ci: supersede stale workflow runs with concurrency groups - #1511
ci: supersede stale workflow runs with concurrency groups#1511groupthinking wants to merge 1 commit into
Conversation
Seven PR-triggered workflows had no `concurrency` block, so every push to a branch left its previous run queued instead of cancelling it. A burst of PR activity therefore saturated the Actions concurrency limit with runs whose results nothing would ever read: measured at 21:12Z, 66 runs were live (63 queued behind 3 executing) and 21 of them were superseded duplicates of a run on the same workflow and branch. No PR could reach a green gate, and nothing was actually failing. Group keys avoid two traps: - `pr-checks.yml` runs on `pull_request_target`, where `github.ref` is the *base* branch. A `github.ref` key would put every open PR in one group and have them cancel each other. Keyed on the PR number, as pr-governance.yml already does. - `auto-label.yml` also runs on `issues`, where `github.ref` is likewise the default branch. Keyed on `pull_request.number || issue.number`; PRs and issues share one numbering sequence, so the two cannot collide. `cancel-in-progress` is limited to `pull_request` on the four workflows that also run on push/schedule. A push to main is the record of whether main is green, and a cancelled CodeQL or Security Scan run uploads no SARIF — that would stale the security dashboard silently rather than fail loudly. Verified with actionlint 1.7.7: clean on all seven files. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012S1Fh4RAWUcUbpy2TVtfnR
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important Review skippedAuto reviews are limited based on label configuration. 🏷️ Required labels (at least one) (1)
Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository YAML (base), Repository UI (inherited), Organization UI (inherited) Review profile: ASSERTIVE Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Closing as superseded by #1510 —
|
| #1511 (this) | #1510 | |
|---|---|---|
| Workflows covered | 7 | 14 — adds anthropic-wif-test, api-cost-postgres, auto-assign, branch-cleanup, dependabot-auto-merge, gh-aw-validation, issue-triage |
pull_request_target base-ref trap |
handled per-workflow, by hand, in pr-checks only |
handled structurally by the key itself — github.event.pull_request.number || github.ref prefers the PR number wherever one exists |
No-cancel on main / schedule |
✅ | ✅ |
Both of this PR's distinctive insights are already satisfied by #1510:
- "on
pull_request_targetthe ref is the base branch, so every open PR would share one group" — correct, and fix(ci): add concurrency groups so the Actions queue can drain #1510's key falls back togithub.refonly when there is no PR number, so it never hits this. - "a cancelled run on main or on the weekly schedule uploads no SARIF" — fix(ci): add concurrency groups so the Actions queue can drain #1510 gates
cancel-in-progresson the event being a PR event, same outcome.
So nothing here is lost by closing. Since coverage is what actually drains the queue, the broader diff wins.
dependabot-auto-merge.yml. That should be fixed on #1510 rather than by keeping this PR open.
Reopen if the reconciliation call looks wrong.
Generated by Claude Code
Duplicate of #1510 — and I think #1510 should winThese two were opened ~20 seconds apart by parallel sessions, both fixing the same thing: the Actions queue can't drain. Measured just now via the API, so the premise is real and current:
So this is the root blocker for every open PR: nothing can reach a green CI gate, and the "green" statuses currently visible on #1486 / #1507 / #1485 are Vercel and CodeRabbit-skip, not tests. Why #1510 rather than this one1. The The reasoning here is that
Right goal, but #1510 keys non-PR runs on 2. Coverage: 16 workflows vs 7. This PR covers Given the queue depth, the workflows this PR doesn't touch are a meaningful share of the pressure. Where this PR is right and #1510 should absorb itYour
That's correct and it's a trap #1510 avoids only incidentally (it keys on Suggested resolutionClose this in favour of #1510, moving the Terminal state: Generated by Claude Code |
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Snapshot WarningsEnsure that dependencies are being submitted on PR branches and consider enabling retry-on-snapshot-warnings. See the documentation for more information and troubleshooting advice. Scanned FilesNone |
Canonical issue
Closes # — no issue filed; this was found by the PR-remediation routine while trying to clear the CI gate on #1483 / #1485 / #1486 / #1494. Happy to file one if the repo wants the paper trail.
Outcome
Seven PR-triggered workflows had no
concurrencyblock, so every push to a branch left its previous run queued rather than cancelling it.Measured at 2026-08-07T21:12Z: 66 workflow runs live — 63 queued behind 3 executing. Nothing was failing; nothing could finish either. Every non-draft PR sat at
mergeable_state: unstablewith its checks queued, so no PR could reach a green gate.21 of the 66 were superseded duplicates — a newer run for the same workflow on the same branch already existed, and nothing would ever read the older one's result:
mainclaude/clever-heisenberg-kltzfbclaude/clever-heisenberg-j1yx9lmainmainThat is ~⅓ of the queue reclaimable by configuration alone.
Scope
concurrencyblock onci.yml,codeql-analysis.yml,security.yml,e2e-tests.yml,pr-checks.yml,dependency-review.yml,auto-label.yml. 49 added lines, ~20 of them comments. No job, step, trigger, or permission changed.phase-goal-tracker.ymlandissue-triage.yml, which also showed duplicates. Both areissues-triggered automation outside this PR's PR-gate scope.Two traps in the group keys
Worth a reviewer's eye, because the obvious
${{ github.ref }}key is wrong in both cases:pr-checks.ymlruns onpull_request_target, wheregithub.refis the base branch (refs/heads/main) — not the PR. Agithub.refkey would put every open PR in one group and have them cancel each other, converting a queue problem into a correctness problem. Keyed ongithub.event.pull_request.number, matching whatpr-governance.ymlalready does.auto-label.ymlalso runs onissues, wheregithub.refis likewise the default branch — every issue would collapse into a single group. Keyed onpull_request.number || issue.number. PRs and issues share one numbering sequence on GitHub, so the two branches of that fallback cannot collide.For the five
pull_request-triggered workflowsgithub.refisrefs/pull/<n>/merge, which is already unique per PR.cancel-in-progressis deliberately not uniformtrueonly on the two PR-only workflows (dependency-review,pr-checks). The four that also run onpush/scheduleuse${{ github.event_name == 'pull_request' }}:mainis the record of whether main is green. Cancelling it leaves that unanswered for the commit that landed.This diverges from
coverage.yml/secret-scan.yml, which use an unconditionaltrue. Flagging rather than quietly matching them: those two may want the same treatment, but changing them is not this PR's business.Risk
github.ref. A cancelled required check reports ascancelled, notsuccess, so the failure would be visible at the merge gate rather than silent.git revert. Behaviour returns to unbounded queuing immediately; no state to migrate.Verification
Head
a095dc6.concurrencyblock was read back to confirm the group key and cancel condition resolve as intended per triggering event.on:blocks re-parsed and compared; no workflow gained or lost an event.Production evidence
Not applicable — CI configuration, no runtime or UI surface.
The operational evidence is the queue measurement above, taken from the Actions API rather than inferred: 63 queued / 3 in progress, grouped by
(workflow, branch)to identify the 21 superseded runs.Agent handoff
concurrencyblocksNote for reviewers
Two things this PR does not fix, both found alongside it.
1. The queue is oversubscribed at the source
Nine PRs (#1475–#1497) were opened in an 11-minute window by an automated remediation routine, each firing ~8 workflows. Concurrency groups reclaim the duplicate third; they do not address the burst. If that routine keeps opening PRs at that rate, the queue stays saturated.
2. #1425's CodeRabbit fix did not take — auto-review is still off
This supersedes a vaguer note in the first revision of this description; the mechanism is now pinned.
.coderabbit.yaml:45setslabels: [], added by #1425 (c576b54) specifically to override an inherited org-level required-labels gate. Its comment describes the deadlock exactly: the gate demands one of ~26 labels, a PR opens unlabelled, so the review is skipped and no label is ever applied to un-skip it.The override is not working. CodeRabbit's own run report on this PR (Run ID
60743c8d-31da-4804-8e23-e241981b2918) says:That is the same ~26-label set #1425's comment describes, still armed, with the repo YAML loaded. Evidence it is not merely the draft rule (
drafts: false):Review skipped: excluded by label configurationReview skipped: excluded by label configurationjavascript,testsReview rate limited— passed the gate, hit quotaReview skipped: excluded by label configurationTwo non-draft PRs skipped for labels, and the one non-draft PR that had a matching label got through to a different failure. So the gate is live and
labels: []is not clearing it.Likely cause is the hazard
.coderabbit.yaml's own header warns about (lines 7–10): withinheritance: true, an empty list reads as unset and the inherited value layers back in. The two candidate remedies —inheritance: false, or removing the required-labels list in the Organization UI — both have blast radius beyond this PR (the first drops all org-level config), so I am flagging rather than guessing. Not fixable in-repo either way if it is the org setting.Practical consequence today: any process step that assumes a CodeRabbit review gates these PRs is a no-op, and has been since before #1425 was believed to fix it. Reviews must be requested by hand with
@coderabbitai review.Agent provenance
Produced by a scheduled, unattended PR-remediation routine running under the repo owner's account. Left as a draft; it halts at the human merge-approval gate and requests no auto-merge to protected
main.