fix(ci): stop main-push gate self-cancelling via caller-level concurrency - #375
Open
forkwright wants to merge 1 commit into
Open
fix(ci): stop main-push gate self-cancelling via caller-level concurrency#375forkwright wants to merge 1 commit into
forkwright wants to merge 1 commit into
Conversation
…ncelling main-push gates hybrid-gate.yml already declares its own concurrency group (workflow-name + commit sha on push, so distinct commits never collide) and its own comment forbids callers duplicating that key. This file's caller-level block was ref-keyed on push (the PR-number expression falls back to the ref, constant for main), so it reintroduced the exact class the reusable workflow's sha-on-push branch exists to prevent -- one layer up, where the reusable workflow's own fix could not see it. Confirmed live: main-push runs at 7004d73/cf1dd2da/9e8778b4/11f0978f show zero jobs ("workflow file issue"), and three dependabot squash-merges landing seconds apart (60f97de/b5c8071/bebbcd1) show the shared group cancelling the first two runs' full-gate-build mid-run -- main commits merging with no completed compile check. sphragis's gate-attestation.yml already carries the fix (no caller-level block) with the identical WHY. Also drops the pull_request `branches: [main]` filter: that filter matches a PR's BASE branch, so a stacked PR (base = another open PR's branch, not main) would match nothing and get zero gate runs -- not pending, absent. push stays scoped to main, where the base is always resolvable. Documents why doctest_cmd stays empty: every fenced block in a doc comment across the workspace is ```text``` or ```ignore```, never a bare ```rust``` block, so a doctest stage would compile and run zero examples. Part of #262
forkwright
force-pushed
the
fix/262-ci-build-test-workflow
branch
from
August 17, 2026 03:00
87aff42 to
e9fb2f3
Compare
This was referenced Aug 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this fixes
akroasis' only build/test gate is
.github/workflows/gate-attestation.yml, which calls the fleethybrid-gate.ymlreusable workflow. Two prior PRs (#288, #353) already closed most of #262 — areal
fmt/check/clippy/nextestbuild now runs on every PR (including dependabot bumps,confirmed below) and on every push to
main. This PR closes the one piece that regressed afterthose landed:
gate-attestation.ymlcarried its own caller-levelconcurrency:block using${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}. On apusheventpull_request.numberis empty, so that resolves to a plain ref-keyed group — constant formain.hybrid-gate.ymlalready declares its own concurrency group, sha-keyed on pushspecifically to avoid this, and its own comment states callers must not duplicate that key or the
shared group self-cancels.
Verified this was live, not just theoretical, before touching anything (
gh run view --json jobs):7004d734/cf1dd2da/9e8778b4/11f0978f(the runs CI has no build/test workflow — main broke silently under dependabot auto-merge #262's 2026-08-05reopen comment cited) show zero jobs — "This run likely failed because of a workflow file
issue."
60f97de,b5c8071,bebbcd1) show the same live behavior today: the caller-level group cancelled the first tworuns'
full-gate-buildmid-flight (conclusion: "cancelled"), and only the last of the threeever produced a completed compile check. Two of three main-tip commits merged with no
completed CI compile — the exact failure CI has no build/test workflow — main broke silently under dependabot auto-merge #262 exists to close.
sphragis'sgate-attestation.yml(the reusable workflow's other adopter) already carries thefix: no caller-level
concurrency:block at all, with a comment citing the identical reason("sphragis's PRIOR file set this exact key -- dropped here, not carried forward, for that
reason").
What changed
.github/workflows/gate-attestation.yml:concurrency:block. Cancellation authority now belongs solely tohybrid-gate.yml's own group (${{ github.workflow }}-${{ github.event_name == 'push' && github.sha || github.ref }}), which is sha-keyed on push (every commit gets its own group, nonecollide) and PR-number-keyed on
pull_request(a superseded push to the same PR still cancelsits own prior run — behavior unchanged there).
branches: [main]from thepull_request:trigger. Abranches:filter onpull_requestmatches the PR's base, not its head. A stacked PR (base = another open PR'sbranch, not
main) would match nothing and get zero gate runs — not a pending check, anabsent one.
push:stays scoped tomain(that one is always the resolvable target, andscoping it prevents duplicate runs on the same commit).
(dependabot-waived from
full-gate-build; no push-to-main compile check) — both were alreadyclosed upstream (
check-trailerno longer waives bot authors; ci(gate-attestation): build main after squash-merge #353 added the push trigger) butthe comment still claimed them open. Left the accurate current status in its place.
doctest_cmdstays empty:cargo nextestdoes not rundoctests. Checked the workspace — every fenced code block in a doc comment
(
grep -rn '```' crates/) is```text ```or```ignore ```, never a bare```rust ```block, so a doctest stage would compile and execute zero examples. Doctests are genuinely
uncovered, but there is currently nothing for that coverage to catch.
.kanon-lint-baseline.tomlentry forYAML/missing-concurrencyon this file (deliberateabsence, not an oversight — see item 1) — matches this repo's existing practice of baselining
confirmed lint-rule false positives, with the sphragis cross-reference as evidence.
Does / does not verify (asked for explicitly)
Verifies, on every PR and on every push to
main:cargo fmt --check,cargo check --workspace --all-targets --features syntonia/hardware-serial,cargo clippy --workspace --all-targets -- -D warnings,cargo nextest run --workspace --features syntonia/hardware-serial, AI-attribution, and (for a trailer-less tip, which includes everydependabot/squash-merge commit) a real compile+test build — no path that produces a green check
without actually building.
Does not verify: doctests (none exist to run, see item 4 above — revisit if one is ever added);
cargo audit/cargo deny(separatesecurity.yml, unaffected by this PR); thehardware-serialfeature's actual radio hardware behavior (CI has no attached device —
--features syntonia/hardware-serialcompiles and unit-tests the code path, it does not exercise realserial/EEPROM I/O).
Done when (from #262, plus the 2026-08-05 reopen comment)
cargo check --workspacecannot auto-merge"full-gate-buildgates every trailer-less PR; confirmed on dependabot PRs #367/#369/#370, each ran a real 4-5 minfull-gate-buildpass before merge.github/workflows/gate-attestation.yml:59-99; without it, the only remaining group ishybrid-gate.yml's sha-keyed one, so distinct main commits can no longer collide/cancel each otherpushtrigger fire onmainafter merge — the concurrency fix means this branch's own PR-time jobs (gate / full-gate-buildetc.) are the evidence the mechanism now runs to completion; no--admin/docs-only exemption is being invokedNegative fixture
This is a CI-workflow change; there is no local unit to execute the defect against. The negative
evidence is the shipped code's own run history, read directly rather than reproduced:
This exercises the actual defect (concurrency-group collision cancelling a real run), not a
reimplementation — the evidence is GitHub's own run records for the exact file that shipped, and
the fix is verified the same way sphragis's identical fix was: by its absence going forward.
Reviewer note: the class of bug this fix could reproduce
The brief for this fix flagged "the fix carries the same class of defect it was written to
remove" as the thing to fear. Checked directly: could the replacement (no caller-level group,
relying on the reusable workflow's own) still let a main-push commit go unverified?
or without this concurrency block; unrelated to this change.
directly (
forkwright/.github/.github/workflows/hybrid-gate.yml@main, lines 176-178): theconcurrency block is unconditional at the top level of the reusable workflow, not gated behind
any input this caller controls, so this caller cannot regress it by omission.
besides the comment (matches sphragis's own mitigation, which is comment-only too); a mechanical
regression check would need a lint rule that understands "this specific reusable-workflow
contract", which does not exist today. Flagged, not fixed, in a follow-up issue (see below) rather
than invented here as scope creep on a one-file CI fix.
Out of scope, filed separately
Verifying this PR on the local
kanon gate(verda) surfaced two pre-existing, unrelatedkanon lintfindings onorigin/main— confirmed present before this diff touched anything, anduntouched by it:
SHELL/unpinned-actionon thehybrid-gate.yml@mainreference in this same file(
.github/workflows/gate-attestation.yml:106), unpinned to a SHA. Pinning needs picking andverifying a specific upstream commit, a separate review from this concurrency fix.
OIKOS/private-content:CONTRIBUTING.md:8and:18publish the internalkanon.lanforge hostname in a public repo's contributor doc. Unrelated file, unrelated to CI workflow
shape; filed separately rather than expanding this PR's blast radius.
Between them, #377 is why the local
kanon gatecannot currently produce a clean Gate-Passedtrailer for any PR to this repo, including this one —
kanon lint's twoOIKOS/private-contenterrors block the local gate regardless of what a PR touches. This PR relies on the GitHub Actions
required checks (
gate / full-gate-build,cargo audit,cargo deny,osv-scanner,ai-attribution,check-trailer— all green above) as the actual merge gate, per #262's own"Done when": those are real, and #377 does not affect them.
Closes #262