ci: bound every job and cancel superseded PR runs - #75
Conversation
Every job without a `timeout-minutes` now has one sized to its observed runtime (a hung `npm ci`, QEMU build or CodeQL database step previously ran to the 360-minute default). Workflows that run on pull_request gained a concurrency group that cancels a superseded PR run but lets push and schedule runs finish, so a default-branch result is never dropped.
sprayberry-redline
left a comment
There was a problem hiding this comment.
Automated review from the Sprayberry Labs fleet code reviewer.
Reviewed by the GPT gating lane (gating review).
Verdict: Approve — no blocking issues found in the workflow timeout and PR-run concurrency changes.
What's good: I checked all seven changed workflow hunks. The timeouts are job-scoped and preserve the existing job logic; the concurrency groups use the workflow plus ref, while cancellation is limited to pull_request events, so push and scheduled default-branch runs are not cancelled. GitHub checks are green (CodeQL, analysis, docker-build, test, and triage).
I did not run the repository test suite locally, per review environment policy; CI was used as the test signal.
sprayberry-secondread
left a comment
There was a problem hiding this comment.
Automated review from the Sprayberry Labs fleet code reviewer.
Reviewed by the Claude second-opinion lane (second opinion, non-gating; the gating review is posted separately).
Verdict: one medium-severity concurrency issue relative to the stated promise to preserve push and schedule runs.
Medium: non-PR runs can still be dropped from the pending queue
.github/workflows/build.yml:20-21 (also .github/workflows/ci.yml:14-15 and .github/workflows/codeql.yml:17-18):
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}GitHub concurrency groups allow one running and one pending run; a new pending run replaces the existing pending run even when cancel-in-progress is false. For example, while main push A is running, main pushes B and C arrive: C cancels pending B. In CodeQL, a scheduled run and pushes to main also share a group, so a pending scheduled run can be replaced by a push. This contradicts the added comment and PR description that non-PR results are never dropped. The false expression protects the running job, not the queue.
Suggested fix: keep a shared group only for PR runs and use a unique run ID for other events, in all three workflows.
concurrency:
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.run_id }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}What's good / scope
The timeout additions are small, job-scoped changes without alterations to step logic or permissions. I read the complete seven-file diff and trigger/job context for the build, CI, CodeQL, fuzzing, release and Scorecard workflows. Current PR checks pass: test, docker-build, CodeQL analysis and triage. I did not run a local test suite or exercise queued-run cancellation; the finding follows GitHub Actions concurrency semantics. Release, fuzzing and Scorecard timeout behavior is not demonstrated by these PR checks.
Every job without a
timeout-minutesnow has one sized to its observed runtime (a hungnpm ci, QEMU build or CodeQL database step previously ran to the 360-minute default). Workflows that run on pull_request gained a concurrency group that cancels a superseded PR run but lets push and schedule runs finish, so a default-branch result is never dropped.release.yml: the multi-arch QEMU publish job now has 45 minutes;build.yml's boot smoke 20.Not changed: any step's logic; the upload-sarif pin (already current).
docker-buildwas added to the ruleset's required checks separately: it is the only job that boots the image and checks/healthzand the fail-closed redaction header, and it was not required.