diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4a716e1..e02d842 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,6 +15,10 @@ on: description: "Build ARM64 image" type: boolean default: false + run_race: + description: "Run Go race detector tests" + type: boolean + default: false env: REGISTRY: ghcr.io @@ -45,18 +49,36 @@ jobs: # services into this job; the build job's purpose is catching # logic regressions in seconds, not standing up a stack. # - # CGO_ENABLED stays at 0 (matches the build above). `-race` - # would catch goroutine data-race regressions but requires - # CGO=1, so we skip it; the test set today is mostly - # math-kernel pure functions where -race adds little. + # CGO_ENABLED stays at 0 (matches the build above). Use the + # manual Race Detector job when reviewing concurrency-sensitive + # changes; it runs with CGO=1 because Go's -race requires CGO. - name: Test run: CGO_ENABLED=0 go test ./... + race: + name: Race Detector + runs-on: ubuntu-latest + if: ${{ github.event_name == 'workflow_dispatch' && inputs.run_race }} + permissions: + contents: read + steps: + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5 + with: + persist-credentials: false + + - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6 + with: + go-version-file: go.mod + cache: true + + - name: Test with race detector + run: CGO_ENABLED=1 go test -race ./... + docker-amd64: name: Docker Build & Push (amd64) needs: build runs-on: ubuntu-latest - if: ${{ github.ref == 'refs/heads/main' && (github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && inputs.build_amd64)) }} + if: ${{ github.ref == 'refs/heads/main' && (github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && inputs.build_amd64 && !inputs.run_race)) }} permissions: contents: read packages: write @@ -97,7 +119,7 @@ jobs: name: Docker Build & Push (arm64) needs: build runs-on: ubuntu-latest - if: ${{ github.event_name == 'workflow_dispatch' && inputs.build_arm64 }} + if: ${{ github.ref == 'refs/heads/main' && github.event_name == 'workflow_dispatch' && inputs.build_arm64 && !inputs.run_race }} permissions: contents: read packages: write diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4028c6e..a81df28 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -25,6 +25,20 @@ Dependencies are managed through normal Go module resolution. Review dependency DB-backed integration tests skip when no Postgres connection is configured. To run them, provide libpq environment variables or `READINESS_TEST_DSN`. Tests create throwaway schemas and drop them during cleanup. +### CI and race detector policy + +The default required-looking CI job is `Build, Vet & Test`. Keep that job name stable unless repository branch protection is updated at the same time. + +Default PR and push CI uses `CGO_ENABLED=0` for build, vet, and tests, matching the production binary. Race detector tests are available as a manual GitHub Actions run: start the `CI` workflow with `run_race=true`. Race-only dispatches do not publish Docker images, even when the image build inputs are left at their defaults. Use this before merging changes that touch tenant management, scheduler goroutines, async AI generation, recompute coordination, Telegram webhook dispatch, or notification loops. + +For local checks on a machine with a CGO toolchain: + +```bash +CGO_ENABLED=1 go test -race ./... +``` + +Branch protection is managed in GitHub repository settings, not in this tree. As of 2026-06-06, the GitHub API reports `main` as not protected. Enabling required checks is a separate admin decision; if enabled, require the `Build, Vet & Test` check first and only require `Race Detector` after deciding that every PR should pay the CGO/race runtime cost. + ## Pull Request Guidelines - Keep behavioral changes focused and explain the data contract they affect. diff --git a/docs/ai-plans/2026-06-06-issue-152-ci-race-detector-branch-protection-policy.html b/docs/ai-plans/2026-06-06-issue-152-ci-race-detector-branch-protection-policy.html new file mode 100644 index 0000000..d55daac --- /dev/null +++ b/docs/ai-plans/2026-06-06-issue-152-ci-race-detector-branch-protection-policy.html @@ -0,0 +1,165 @@ + + + + + Implementation Plan: Issue #152 CI Race Detector and Branch Protection Policy + + + + +
+

Implementation Plan: Issue #152 CI Race Detector and Branch Protection Policy

+

Approved and implemented

+ +
+

Task Summary

+

Record a clear policy for race-detector CI and branch protection, then implement only the parts that are justified now.

+
+ +
+

Current Behavior

+ +
+ +
+

Desired Behavior

+ +
+ +
+

Assumptions And Unknowns

+ +
+ +
+

Files Likely To Change

+ +
+ +
+

Implementation Steps

+
    +
  1. Inspect current branch protection via GitHub API before changing settings.
  2. +
  3. Choose one of three race-detector policies: defer with revisit criteria, manual workflow-only job, or PR job for all branches.
  4. +
  5. If implementing race CI, add a separate Race Detector job using CGO_ENABLED=1 go test -race ./....
  6. +
  7. Keep the existing Build, Vet & Test job name stable unless branch protection is updated at the same time.
  8. +
  9. Document local developer guidance and revisit criteria.
  10. +
  11. If branch protection is approved, update GitHub settings and verify required status checks match actual workflow job names.
  12. +
+
+ +
+

Impact

+ +
+ +
+

Test Plan

+ +
+ +
+

Risks And Edge Cases

+ +
+ +
+

Rollback Plan

+

Remove the race job or switch it back to manual-only. For branch protection, restore the previous protection JSON or remove the newly required check after confirming with the user.

+
+ +
+

Open Questions

+ +
+ +
+

Approval Gate

+

Approved by the user on 2026-06-06. Branch protection settings were inspected but not changed, because settings mutation requires additional explicit approval.

+
+ +
+

Implementation Result

+ +
+ +
+

Verification Run

+ +
+ +
+

Known Limitations

+ +
+
+ +