Skip to content

ci: add GitHub Actions build/test + ASan/UBSan (fix cmake test build) - #43

Merged
gabsow merged 4 commits into
RedisBloom:masterfrom
redis-performance:ci-github-actions-sanitizers
Jul 29, 2026
Merged

ci: add GitHub Actions build/test + ASan/UBSan (fix cmake test build)#43
gabsow merged 4 commits into
RedisBloom:masterfrom
redis-performance:ci-github-actions-sanitizers

Conversation

@fcostaoliveira

@fcostaoliveira fcostaoliveira commented Jul 27, 2026

Copy link
Copy Markdown
Collaborator

What

Adds real build/test CI, since none currently runs on PRs (CircleCI reports no status; only Hound + Cursor Bugbot run), and fixes the cmake unit-test build so ctest works.

  • .github/workflows/ci.yml
    • build-and-test: cmake build + ctest on gcc and clang.
    • sanitizers: build td_test with ASan + UBSan and run it (leak detection on; allocator_may_return_null=1 so an oversized capacity request exercises the allocation-failure path instead of aborting).
  • cmake test-build fix (tests/CMakeLists.txt): minunit.h calls clock_gettime(), which the top-level -std=c99 hides unless _POSIX_C_SOURCE is defined on the command line before any header. Without it, building td_test fails with unknown type name 'clockid_t', so ctest never runs. Fixed via target_compile_definitions(td_test PRIVATE _POSIX_C_SOURCE=200809L).

Why

Complements #41 (the capacity-narrowing guard): with ASan/UBSan CI in place, integer-narrowing / overflow regressions like the one #41 fixes are caught automatically. Kept intentionally separate and small so #41 stays a focused change.

Verified locally

  • ctest passes on gcc and clang (was previously failing to build).
  • ASan + UBSan run clean (no UB, no leaks).

🤖 Generated with Claude Code


Note

Low Risk
CI and test-target compile-definition changes only; no runtime library or security logic is modified.

Overview
Introduces GitHub Actions CI on push to master and on pull requests, with read-only workflow permissions and checkout without persisted credentials.

The build-and-test job configures a Release build with tests enabled, builds with gcc and clang, and runs ctest. A separate sanitizers job uses clang with a Debug build, ASan/UBSan compile/link flags, and runs the full test suite via ctest (leak detection plus allocator_may_return_null for large allocation failure paths).

tests/CMakeLists.txt adds _POSIX_C_SOURCE=200809L on the td_test target so minunit.h can use clock_gettime() when the project’s -std=c99 would otherwise break the unit test build.

Reviewed by Cursor Bugbot for commit 8bf0dd7. Bugbot is set up for automated code reviews on this repo. Configure here.

There is currently no build/test CI running on PRs (CircleCI does not report a
status; only Hound and Cursor Bugbot run), so regressions in the library or the
unit tests can land unnoticed.

- Add .github/workflows/ci.yml:
  * build-and-test: cmake build + ctest on gcc and clang.
  * sanitizers: build td_test with -fsanitize=address,undefined and run it
    (leak detection on; allocator_may_return_null=1 so an oversized capacity
    request exercises the allocation-failure path instead of aborting).
- Fix the cmake unit-test build: minunit.h uses clock_gettime(), which the
  top-level "-std=c99" hides unless _POSIX_C_SOURCE is defined on the command
  line before any header. Without this, `ctest` fails to build td_test with
  "unknown type name 'clockid_t'". Add the define via target_compile_definitions.

Both jobs verified green locally (gcc+clang ctest pass; ASan+UBSan clean).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@gabsow gabsow left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The build/test and sanitizer jobs look good, but I found one workflow-security blocker before approval.

This repository currently has default_workflow_permissions: write. The new workflow runs pull-request-controlled code without overriding that default, and actions/checkout@v4 persists its token credentials by default. A test or build step could therefore access a write-capable token in same-repository PR runs.

Please scope the workflow explicitly:

permissions:
  contents: read

And preferably avoid leaving even the read token in the checkout after the fetch:

- uses: actions/checkout@v4
  with:
    persist-credentials: false

Once that is added, the PR looks ready for approval.

Address review: the repo default is default_workflow_permissions: write, and
actions/checkout@v4 persists its token, so pull-request-controlled build/test
steps could reach a write-capable token in same-repo PR runs. Scope the workflow
to `permissions: contents: read` and set `persist-credentials: false` on checkout.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@fcostaoliveira

Copy link
Copy Markdown
Collaborator Author

Thanks — addressed in facdfb3. Scoped the workflow to permissions: contents: read and set persist-credentials: false on both actions/checkout@v4 steps, so PR-controlled build/test steps never see a write-capable token. CI re-running.

@gabsow gabsow left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed facdfb3. The previous blocker is resolved: the workflow now uses read-only permissions and neither checkout step persists credentials. The GCC, Clang, and sanitizer jobs are green. Approved.

@gabsow

gabsow commented Jul 27, 2026

Copy link
Copy Markdown
Collaborator

You can merge this one

The sanitizer job compiled and ran only td_test, so other test targets (e.g.
td_capacity_test, td_sort_complexity_test) were not covered by ASan/UBSan.
Build the suite with sanitizer flags through CMake and run it via CTest, so
every registered test target is covered automatically. A non-Release build
avoids the top-level -std=c99 that hides POSIX clock_gettime() in minunit.h.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

Reviewed by Cursor Bugbot for commit 6054d44. Configure here.

Comment thread .github/workflows/ci.yml
The project defaults CMAKE_BUILD_TYPE to Release, whose top-level -std=c99 hides
POSIX clock_gettime() in minunit.h, so a default-type sanitizer build would only
compile targets that carry a _POSIX_C_SOURCE define. Pin the sanitizer job to
Debug so every registered test target compiles and runs under ASan/UBSan.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

@gabsow
gabsow merged commit 21bfb00 into RedisBloom:master Jul 29, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants