Skip to content

fix(ci): the template that let a commit cancel another commit's run - #53

Merged
catomean merged 1 commit into
mainfrom
fix/ci-strands-commits
Sep 11, 2026
Merged

fix(ci): the template that let a commit cancel another commit's run#53
catomean merged 1 commit into
mainfrom
fix/ci-strands-commits

Conversation

@catomean

Copy link
Copy Markdown
Contributor

28 of 29 repos carry group: ci-${{ github.ref }} with cancel-in-progress: true, because that is what templates/ci/ has always said. It lets a newer merge cancel an older commit's CI run, and every deploy path keys off that run.

It broke two repos today, in the two ways it can break.

fleetcrown — silently. Deploy chains off workflow_run and requires conclusion == 'success'; a cancelled run reports cancelled, so Deploy skipped. Four merges sat on main with every check green, nothing red anywhere, and the box serving the previous build. Each needed a Deploy dispatched by hand, and the only way to notice was comparing the box's build stamp against main's tip. (bitbaum/fleetcrown#662)

hirnli — loudly. Its Deploy waits for CI to pass on the commit it is shipping, found the cancelled run, and failed. That is the better of the two outcomes, because somebody sees it. (bitbaum/hirnli#111)

20:24:07  push              cancelled   84403805
20:24:08  workflow_dispatch success     84403805

Both share a second cause: auto-merge re-arms CI with a dispatch, and under one group-per-branch that dispatch cancels the push run for the same commit.

What changes

  • Both templates key main per commit. Branch behaviour is untouched — the newest push is still the only one that matters there.
  • cicd-hygiene-audit.sh gains ci-strands-commits, so the repos that already copied the old line are found by a sweep instead of by an outage. It fires only where a collision is possible: a group already keyed by github.sha, or one that never cancels, is left alone.

The rule has a test

scripts/ci/test-ci-strands-commits.sh:

bad       FLAGS     ← the shape 28 repos have
fixed     quiet
nocancel  quiet
none      quiet
prose     FLAGS     ← comment mentions github.sha, group does not use it

That last case is the point. Comments are stripped before matching, because a gate a comment can satisfy is not a gate.

Shell syntax checked; both templates parse as YAML.

🤖 Generated with Claude Code

https://claude.ai/code/session_018Z7YRpgsEtNjRqr1usHMQY

Twenty-eight of twenty-nine repos in the fleet carry
`group: ci-${{ github.ref }}` with `cancel-in-progress: true`, because
that is what templates/ci/ has always said. It lets a newer merge cancel
an older commit's CI run, and every deploy path keys off that run.

It broke two repos today, in the two ways it can break:

fleetcrown, silently. Deploy chains off workflow_run and requires
conclusion == success; a cancelled run reports cancelled, so Deploy
skipped. Four merges sat on main with every check green, nothing red
anywhere, and the box serving the previous build. Each needed a Deploy
dispatched by hand, and the only way to notice was to compare the box's
build stamp against main's tip.

hirnli, loudly. Its Deploy waits for CI to pass on the commit it is
shipping, found the cancelled run, and failed — which is the better of the
two outcomes, because somebody sees it.

Both had the same second cause underneath: auto-merge re-arms CI with a
dispatch, and under one group-per-branch that dispatch cancels the push
run for the SAME commit.

So the templates key main per commit, and the hygiene audit gains
ci-strands-commits so the repos that already copied the old line are found
by a sweep rather than by an outage. The rule only fires where a collision
is actually possible: a group already keyed by github.sha, or one that
never cancels, is left alone.

The rule has its own test, including the case that matters — a file whose
COMMENT mentions github.sha while its group does not must still flag.
Comments are stripped before matching, because a gate that a comment can
satisfy is not a gate.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Z7YRpgsEtNjRqr1usHMQY
@catomean
catomean merged commit 9a600f0 into main Sep 11, 2026
1 check passed
@catomean
catomean deleted the fix/ci-strands-commits branch September 11, 2026 20:57
catomean added a commit to bitbaum/substrata that referenced this pull request Sep 11, 2026
The concurrency group was keyed by branch with cancel-in-progress, so a
newer merge cancels an older commit's CI — and every deploy path keys off
that run. One that waits for CI to pass on the commit finds a cancelled run
and stops. One chained on workflow_run sees conclusion=cancelled and skips.

auto-merge also re-arms CI with a dispatch, and under one group-per-branch
that dispatch cancels the push run for the SAME commit.

Measured across the fleet on 2026-09-11: 28 of 39 ci.yml files had this
shape. It broke two repos that day, in the two ways it can break.
fleetcrown failed silently — Deploy skipped, four merges sat on main with
every check green and nothing red while the box served the previous build,
each needing a hand-dispatched deploy. hirnli failed loudly, erroring at
its wait-for-CI step, which is the better outcome because somebody sees it.

Keying main per commit lets both runs finish, so whatever the deploy path
looks for is there. Branch behaviour is unchanged: the newest push is still
the only one that matters there.

The templates this was copied from are fixed in bitbaum/fleet#53, which
also adds a ci-strands-commits rule to the hygiene audit so the remaining
repos are found by a sweep rather than by an outage.


Claude-Session: https://claude.ai/code/session_018Z7YRpgsEtNjRqr1usHMQY

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
catomean added a commit to bitbaum/solon that referenced this pull request Sep 11, 2026
The concurrency group was keyed by branch with cancel-in-progress, so a
newer merge cancels an older commit's CI — and every deploy path keys off
that run. One that waits for CI to pass on the commit finds a cancelled run
and stops. One chained on workflow_run sees conclusion=cancelled and skips.

auto-merge also re-arms CI with a dispatch, and under one group-per-branch
that dispatch cancels the push run for the SAME commit.

Measured across the fleet on 2026-09-11: 28 of 39 ci.yml files had this
shape. It broke two repos that day, in the two ways it can break.
fleetcrown failed silently — Deploy skipped, four merges sat on main with
every check green and nothing red while the box served the previous build,
each needing a hand-dispatched deploy. hirnli failed loudly, erroring at
its wait-for-CI step, which is the better outcome because somebody sees it.

Keying main per commit lets both runs finish, so whatever the deploy path
looks for is there. Branch behaviour is unchanged: the newest push is still
the only one that matters there.

The templates this was copied from are fixed in bitbaum/fleet#53, which
also adds a ci-strands-commits rule to the hygiene audit so the remaining
repos are found by a sweep rather than by an outage.


Claude-Session: https://claude.ai/code/session_018Z7YRpgsEtNjRqr1usHMQY

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
catomean added a commit to bitbaum/botsmann that referenced this pull request Sep 11, 2026
The concurrency group was keyed by branch with cancel-in-progress, so a
newer merge cancels an older commit's CI — and every deploy path keys off
that run. One that waits for CI to pass on the commit finds a cancelled run
and stops. One chained on workflow_run sees conclusion=cancelled and skips.

auto-merge also re-arms CI with a dispatch, and under one group-per-branch
that dispatch cancels the push run for the SAME commit.

Measured across the fleet on 2026-09-11: 28 of 39 ci.yml files had this
shape. It broke two repos that day, in the two ways it can break.
fleetcrown failed silently — Deploy skipped, four merges sat on main with
every check green and nothing red while the box served the previous build,
each needing a hand-dispatched deploy. hirnli failed loudly, erroring at
its wait-for-CI step, which is the better outcome because somebody sees it.

Keying main per commit lets both runs finish, so whatever the deploy path
looks for is there. Branch behaviour is unchanged: the newest push is still
the only one that matters there.

The templates this was copied from are fixed in bitbaum/fleet#53, which
also adds a ci-strands-commits rule to the hygiene audit so the remaining
repos are found by a sweep rather than by an outage.


Claude-Session: https://claude.ai/code/session_018Z7YRpgsEtNjRqr1usHMQY

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
catomean added a commit to bitbaum/datacat that referenced this pull request Sep 11, 2026
The concurrency group was keyed by branch with cancel-in-progress, so a
newer merge cancels an older commit's CI — and every deploy path keys off
that run. One that waits for CI to pass on the commit finds a cancelled run
and stops. One chained on workflow_run sees conclusion=cancelled and skips.

auto-merge also re-arms CI with a dispatch, and under one group-per-branch
that dispatch cancels the push run for the SAME commit.

Measured across the fleet on 2026-09-11: 28 of 39 ci.yml files had this
shape. It broke two repos that day, in the two ways it can break.
fleetcrown failed silently — Deploy skipped, four merges sat on main with
every check green and nothing red while the box served the previous build,
each needing a hand-dispatched deploy. hirnli failed loudly, erroring at
its wait-for-CI step, which is the better outcome because somebody sees it.

Keying main per commit lets both runs finish, so whatever the deploy path
looks for is there. Branch behaviour is unchanged: the newest push is still
the only one that matters there.

The templates this was copied from are fixed in bitbaum/fleet#53, which
also adds a ci-strands-commits rule to the hygiene audit so the remaining
repos are found by a sweep rather than by an outage.


Claude-Session: https://claude.ai/code/session_018Z7YRpgsEtNjRqr1usHMQY

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
catomean added a commit to bitbaum/petvity that referenced this pull request Sep 11, 2026
The concurrency group was keyed by branch with cancel-in-progress, so a
newer merge cancels an older commit's CI — and every deploy path keys off
that run. One that waits for CI to pass on the commit finds a cancelled run
and stops. One chained on workflow_run sees conclusion=cancelled and skips.

auto-merge also re-arms CI with a dispatch, and under one group-per-branch
that dispatch cancels the push run for the SAME commit.

Measured across the fleet on 2026-09-11: 28 of 39 ci.yml files had this
shape. It broke two repos that day, in the two ways it can break.
fleetcrown failed silently — Deploy skipped, four merges sat on main with
every check green and nothing red while the box served the previous build,
each needing a hand-dispatched deploy. hirnli failed loudly, erroring at
its wait-for-CI step, which is the better outcome because somebody sees it.

Keying main per commit lets both runs finish, so whatever the deploy path
looks for is there. Branch behaviour is unchanged: the newest push is still
the only one that matters there.

The templates this was copied from are fixed in bitbaum/fleet#53, which
also adds a ci-strands-commits rule to the hygiene audit so the remaining
repos are found by a sweep rather than by an outage.


Claude-Session: https://claude.ai/code/session_018Z7YRpgsEtNjRqr1usHMQY

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
catomean added a commit to bitbaum/orangecat that referenced this pull request Sep 11, 2026
The concurrency group was keyed by branch with cancel-in-progress, so a
newer merge cancels an older commit's CI — and every deploy path keys off
that run. One that waits for CI to pass on the commit finds a cancelled run
and stops. One chained on workflow_run sees conclusion=cancelled and skips.

auto-merge also re-arms CI with a dispatch, and under one group-per-branch
that dispatch cancels the push run for the SAME commit.

Measured across the fleet on 2026-09-11: 28 of 39 ci.yml files had this
shape. It broke two repos that day, in the two ways it can break.
fleetcrown failed silently — Deploy skipped, four merges sat on main with
every check green and nothing red while the box served the previous build,
each needing a hand-dispatched deploy. hirnli failed loudly, erroring at
its wait-for-CI step, which is the better outcome because somebody sees it.

Keying main per commit lets both runs finish, so whatever the deploy path
looks for is there. Branch behaviour is unchanged: the newest push is still
the only one that matters there.

The templates this was copied from are fixed in bitbaum/fleet#53, which
also adds a ci-strands-commits rule to the hygiene audit so the remaining
repos are found by a sweep rather than by an outage.


Claude-Session: https://claude.ai/code/session_018Z7YRpgsEtNjRqr1usHMQY

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
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