Skip to content

ci: Run mutation testing in parallel and gate merges through CI gate - #237

Merged
bitbiter-dev merged 3 commits into
masterfrom
ci/parallelize-gates
Oct 15, 2026
Merged

bitbiter-dev merged 3 commits into
masterfrom
ci/parallelize-gates

Conversation

@bitbiter-dev

Copy link
Copy Markdown
Owner

Why

Stryker was ~72% of the single Build & Test job (7m04s–7m30s of ~10m20s), and both Docker builds waited behind it, so the required checks took ~12 min.

What

Job When needs
Checks always – (build, test, coverage, format, helper scripts, schema check)
Mutation always – (Stryker, report, badge/high-water payloads)
Docker — API/Worker PRs, and dispatch without push_to_registry Checks — build only, no push
CI gate if: always() Checks, Mutation, Docker
Publish image — API/Worker master, v* tags, dispatch with push_to_registry CI gate
Publish quality reports master Checks, Mutation (runs even if the mutation gate fails)
Deploy quality reports to Pages master Publish quality reports
Schema diagram always – (no longer waits)
  • Expected PR gate: ~8.5 min (Stryker is the floor; Checks → Docker finishes at ~5 min).
  • No image is pushed before everything is green. Pushing only happens after CI gate, on master and tags alike.
  • scripts/ci-gate.sh (tested by ci-gate.test.sh, test-first) holds the gate's rule. GitHub treats a skipped required check as passing, so every need must succeed. The one exception is the PR-only Docker build, which may be skipped outside pull requests.
  • Jobs downstream of the gate check needs.<job>.result explicitly. The implicit success() also sees the transitively skipped PR Docker job, so without the explicit check they would be skipped on every push.
  • contents: write only exists in the master-only publish job. PR jobs get a read token.
  • cancel-in-progress applies to PRs only, so every master commit finishes its image push and high-water advance.

Considered and rejected: Checks/Mutation as direct required checks (every job rename would need a protection change), keeping the name Build & Test, letting Docker push right after Checks, a separate format job, and NuGet caching (restore is ~5 s, and setup-dotnet caching needs lock files).

⚠️ Rollout

This PR no longer reports Build & Test, so it stays blocked until the required checks are swapped. Immediately before merging, once every check on this PR is green:

gh api -X PATCH repos/bitbiter-dev/anichron/branches/master/protection/required_status_checks --input - <<'JSON'
{"strict":true,"checks":[{"context":"CI gate","app_id":15368},{"context":"CodeQL","app_id":57789}]}
JSON

Open PRs (#236, #228, #229) pick up the new workflow when they are next brought up to date, which strict already forces.

Verification

  • actionlint is clean on all workflows. All helper-script suites pass, including the new ci-gate.test.sh.
  • /code-review: no correctness findings. The dispatch smoke-build regression it flagged is fixed.
  • The real proof is this PR's own run: compare its wall clock with the ~12 min baseline.

🤖 Generated with Claude Code

bitbiter-dev and others added 3 commits October 15, 2026 19:25
Stryker was ~72% of the single Build & Test job, and the Docker builds
waited behind it, so the required checks took ~12 min. Checks (build,
test, coverage, format, helper scripts, schema) and Mutation now run in
parallel; PR Docker builds follow Checks and finish long before Stryker.
Expected PR gate: ~8.5 min.

- CI gate (if: always()) needs Checks, Mutation and Docker; its rule
  lives in scripts/ci-gate.sh, tested by ci-gate.test.sh. A skipped
  required check counts as passing on GitHub, so every need must
  succeed; only the PR Docker builds may be skipped, and only outside
  pull requests.
- Images are pushed only by Publish image, after CI gate, so no edge,
  sha, version or latest tag can exist for a commit whose checks or
  mutation score failed. Jobs downstream of the gate check
  needs.<job>.result explicitly, because the implicit success() also
  sees the transitively skipped PR Docker job.
- Badges, high-water mark and Pages move to a master-only publish job,
  the only job holding contents: write; the badge and mark payloads
  travel from Mutation as the mutation-state artifact.
- Schema diagram no longer waits for anything.
- cancel-in-progress applies to pull requests only, so every master
  commit finishes its pushes and its high-water advance.

Considered and rejected: Checks/Mutation as direct required checks
(every job rename becomes a protection change), keeping the name
Build & Test, letting Docker push right after Checks, a separate format
job, and NuGet caching (restore is ~5 s, setup-dotnet caching needs
lock files).

Requires swapping the required checks to "CI gate" and "CodeQL"
immediately before merging.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	graphify-out/GRAPH_REPORT.md
#	graphify-out/graph.json
@bitbiter-dev
bitbiter-dev merged commit 6137372 into master Oct 15, 2026
11 checks passed
@bitbiter-dev
bitbiter-dev deleted the ci/parallelize-gates branch October 15, 2026 06:45
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.

1 participant