Skip to content

ci: cancel superseded runs instead of banking one per commit - #496

Merged
thedancingdeveloper merged 1 commit into
devfrom
ci/cancel-superseded
Sep 1, 2026
Merged

ci: cancel superseded runs instead of banking one per commit#496
thedancingdeveloper merged 1 commit into
devfrom
ci/cancel-superseded

Conversation

@thedancingdeveloper

Copy link
Copy Markdown
Contributor

Merge bursts previously banked one CI run and one image build per pushed commit on the small self-hosted pool. This makes cancellation safe and then switches to newest-wins:

  • ci.yml: pushes now classify as a change to everything (PRs keep merge-base classification), which restores the "a replacing run covers a superseded one" property that made cancelling unsafe before — the before..sha gap that let two failures reach dev is documented in the concurrency comment. Group is per ref, cancel-in-progress: true.
  • build.yml: newest-wins per ref. Only the newest commit of a burst gets images — the commit anything would deploy. Ref stays in the key so fast-forwarded dev/main/prod never evict each other.
  • codeql.yml: cancel on all events (was PR-only); a whole-tree scan is always covered by its replacement.
  • e2e.yml unchanged: runs queue because two stacks would race the same loopback port.
  • tests/test_deploy.py pins the invariant pair: newest-wins keying and classify-everything-on-push must change together.

Cost accepted: a docs-only push runs the full matrix (docs.yml remains the cheap gate), and superseded commits get no sha- image.

Verification: pytest tests/test_deploy.py (79 passed), ruff, YAML parse of all three workflows.

🤖 Generated with Claude Code

https://claude.ai/code/session_0161etTkUPyRoUXnHQ8xgKUu

Push runs to dev/main/prod previously kept one CI and one build run per
commit, because cancelling was unsafe: ci.yml classified a push by
before..sha, so a cancelled run's files were checked by nothing, ever (two
escapes reached dev that way), and a cancelled build left no sha- image.

Make cancellation safe instead of avoiding it: a push now classifies as a
change to everything, so a replacing run fully covers a superseded one, and
ci.yml, build.yml and codeql.yml switch to newest-wins per ref
(cancel-in-progress: true). The ref stays in every group so dev/main/prod —
the same commit after a fast-forward release — never evict each other, and
PRs group by their own merge ref. e2e.yml keeps queueing: two stacks would
race the same loopback port.

The cost accepted: a docs-only push now runs the full matrix (docs.yml
remains the cheap path-filtered gate), and only the newest commit of a merge
burst gets images — which is the commit anything would deploy.

tests/test_deploy.py pins the pairing: newest-wins keying and
classify-everything-on-push must move together.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0161etTkUPyRoUXnHQ8xgKUu
@thedancingdeveloper
thedancingdeveloper merged commit a5cf579 into dev Sep 1, 2026
14 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.

1 participant