mirror of
https://github.com/Comfy-Org/github-workflows.git
synced 2026-11-05 00:17:37 +00:00
[PR #264] [MERGED] feat(bump-callers): refuse a Skip-caller-bump skip while the fleet owes a catch-up #267
Labels
No labels
cursor-review-catalog-drift
groom
groom
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Comfy-Org/github-workflows#267
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/Comfy-Org/github-workflows/pull/264
Author: @mattmillerai
Created: 9/5/2026
Status: ✅ Merged
Merged: 9/5/2026
Merged by: @mattmillerai
Base:
main← Head:matt/be-10008-owed-bump-gate📝 Commits (1)
0f6af87feat(bump-callers): refuse a Skip-caller-bump skip while the fleet owes a catch-up (BE-10008)📊 Changes
17 files changed (+912 additions, -30 deletions)
View changed files
📝
.github/bump-callers/README.md(+44 -7)📝
.github/bump-callers/preflight.sh(+290 -23)📝
.github/bump-callers/tests/test_paths_contract.sh(+55 -0)📝
.github/bump-callers/tests/test_preflight.sh(+393 -0)📝
.github/workflows/bump-agents-md-callers.yml(+10 -0)📝
.github/workflows/bump-area-label-callers.yml(+10 -0)📝
.github/workflows/bump-assign-reviewers-callers.yml(+10 -0)📝
.github/workflows/bump-auto-label-callers.yml(+10 -0)📝
.github/workflows/bump-coderabbit-config-callers.yml(+10 -0)📝
.github/workflows/bump-cursor-review-callers.yml(+10 -0)📝
.github/workflows/bump-detect-unreviewed-merge-callers.yml(+10 -0)📝
.github/workflows/bump-groom-callers.yml(+10 -0)📝
.github/workflows/bump-linear-ticket-callers.yml(+10 -0)📝
.github/workflows/bump-pr-derisk-callers.yml(+10 -0)📝
.github/workflows/bump-pr-risk-callers.yml(+10 -0)📝
.github/workflows/bump-pr-size-callers.yml(+10 -0)📝
.github/workflows/bump-public-repo-hygiene-callers.yml(+10 -0)📄 Description
ELI-5
A
Skip-caller-bump: truetrailer lets a docs-only commit inside a watched surface say "don't fan a churn SHA-bump PR out to every caller for this." The gate that honors it looked only at the push in front of it. But a bump run is also the catch-up for an earlier watched change whose own run never bumped — it failed at the token mint or insidebump-callers.sh, it was cancelled, or it never started at all because GitHub evaluates apaths:filter against only the first 300 changed files of a push. Declining today's docs push declined that catch-up too, and callers sat on a stale SHA with nothing red anywhere. That was the gate's ownKNOWN LIMITcomment and the bump-callers README's §"Known limit". This closes it: before honoring a trailer, the preflight now checks whether the fleet still owes a bump, and refuses the skip if it does.Not hypothetical —
bump-cursor-review-callers.ymlhas ~23 runs in retained history whoseBump SHA in caller reposstep endedfailure, andbump-groom-callers.ymlhas acancelledrun that produced zero jobs. Each of those is a watched change that reached no caller until some later behavioral bump happened along.What changed
.github/bump-callers/preflight.sh— afleet_owes_bumpprobe, called from theskip_caller_bump_requestedacceptance path, before the skip'semit false. It answers the question the push payload cannot, from this fleet's own Actions run history — the.github/groom/interval.pypattern: derivable with onlyactions: readon the ambient token, so no new secret and no writable store, and fail-open by construction.GITHUB_WORKFLOW_REF+GITHUB_REPOSITORY, list this workflow's successful runs onmain, newest first, one bounded page (30), and take the first whose job carries a step named exactlyBump SHA in caller reposwith conclusionsuccess. That step isskippedon a declined run andsuccesson a real bump — the entire discriminator.pushandworkflow_dispatchruns both count (a dispatch recovery bump is as much of a catch-up as a push one). The endpoint is that run'shead_sha, not the SHA it pinned: a re-pointed run had already proved its surface unchanged up to its pin target, so the difference can only add commits to the range, i.e. it errs toward bumping.HEAD, restricted to the watched surface, checking each commit's message with the one shared$SKIP_TRAILER_JQtrailer definition. Per commit, not as a content diff — that is what lets an earlier, legitimately-skipped trailered push keep being excused by its own trailer instead of poisoning every later skip.::notice::naming the oldest owed commit: catch-up owed for<sha>, whose own run never bumped.The
gh apireads sit in their own tiny functions with no--jq, so the suite can stubghwith canned JSON. The watched-surface pathspec choice (WATCHED_PATHSPECS, elseWATCHED+WATCHED_ASSETS) was hoisted out of the hand-off guard into onesurface_pathspecshelper both readers now call — a second hand-rolled copy would let the two disagree about which commits count on exactly the input (an excluding fleet) where that changes the verdict.All 13
bump-*-callers.ymlentrypoints —permissions:gainsactions: read, and the preflight step'senv:gainsGH_TOKEN: ${{ github.token }}. Both read-only, and both well ahead of the org-wide write token, which is still minted only after and only if the preflight says proceed..github/bump-callers/tests/test_paths_contract.sh— asserts, per entrypoint, that it names its bump step exactlyOWED_BUMP_STEP_NAME(read out ofpreflight.sh, not restated), that it grantsactions: readat the workflow level (and declares no job-levelpermissions:block that would replace it), and that its preflight step wiresgithub.token. All three fail silently green: break any one and the trailer quietly stops being honored forever, in the safe direction, with nothing red..github/bump-callers/README.md— §"Known limit" replaced by §"The owed-bump check", plus its residuals and the two new env rows.Riskiest line, and why it is safe
if skip_caller_bump_requested && ! fleet_owes_bump; then— the whole feature turns on one added condition in front of an existing skip. It is safe in the direction that matters:fleet_owes_bumpreturns "owes" (refuse the skip) for every indeterminate answer — nogh, nojq, an Actions API error, no qualifying run inside the scan bound, an unreadable jobs payload, a failed deepening fetch, an endpoint that is not an ancestor ofHEAD, a range pastSKIP_TRAILER_RANGE_MAX. So the check can only ever narrow a skip, never widen one; its worst bug is status-quo churn (a bump that could have been skipped), which is the behavior that existed before the trailer did. And the&&short-circuit means aworkflow_dispatchrun, or any untrailered push, never reaches the probe at all — the documented recovery path is untouched and spends no API call.Everything under it is
||-guarded so nothing aborts under the file'sset -euo pipefail, andowed_untrailered_commitshape-checks the sha it extracts before it is interpolated anywhere.How this was verified
Hermetic suites (throwaway bare repos, a canned
ghon PATH, no network):bash .github/bump-callers/tests/test_preflight.sh— 445 passed, 0 failed (was 392; +53). New cases: a catch-up owed by an untrailered watched commit newer than the last bumping run (proceed=true + the naming notice); the all-trailered control (proceed=false); per-commit excusal across two trailered pushes, then the same range with one untrailered commit spliced in; an unwatched untrailered commit owing nothing;:(exclude)honored for the pr-risk-shaped fleet in both directions; the--depth=1production checkout deepening and still producing a real answer both ways;workflow_dispatchand untrailered pushes short-circuiting with no notice at all; and the whole fail-open surface — API error, a history where nothing bumped, a declined run listed ahead of a real one, a dispatch recovery bump as the endpoint, empty history, missingGITHUB_WORKFLOW_REF/GITHUB_REPOSITORY, an endpoint absent from this history, and noghon PATH at all (a curated PATH holding only the binaries the script shells out to, so it measures an absent binary rather than a failing one).bash .github/bump-callers/tests/test_paths_contract.sh— 110 passed, 0 failed (was 70; +40). Negative-checked by hand: renaming the bump step in one entrypoint, deletingactions: readfrom a second andGH_TOKENfrom a third produced exactly three failures and no others; restoring them returned to green.bash .github/bump-callers/tests/test_bump_callers.sh— 437 passed, 0 failed (untouched).shellcheck -xoverbump-callers.sh,preflight.shand all three suites — clean.python3 .github/workflow-pins/check_workflow_pins.py— OK, 11 workflows, 0 exempt.python3 .github/agents-md-integrity/check_agents_md.py --root .— passed (2 pre-existing warnings, unchanged). All 13 edited entrypoints re-parsed with PyYAML:permissions == {contents: read, actions: read}andGH_TOKENpresent in the preflight step's env.Read-only checks against the real Actions API, because the probe's premises are claims about production data and no unit test can falsify them (all non-mutating
gh apireads):branch=main&status=success&per_page=Nand returns newest-first.Bump SHA in caller repos, withconclusion: "success"on runs that bumped (e.g.33667061259,33220810341).if:-gated steps really do reportconclusion: "skipped"in this repo's own jobs payloads (confirmed across several recent runs of other workflows), which is the half of the discriminator the bump fleets have no retained example of — see Residual.bump-cursor-review-callers.ymlruns whose bump step endedfailure, and acancelledbump-groom-callers.ymlrun (30936094387) with zero jobs — the shape(.jobs // [])[]guards against.status=successcorrectly excludes all of them.Negative-claim falsification. This diff adds a refusal path, so the premise worth falsifying is "the preflight cannot see whether an earlier run bumped." I went and looked rather than asserting it: the Actions run-history reads above are exactly that capability, they work, and the change uses them instead of shipping a dead end. The trailer's own capability is preserved, not removed —
owed_none,owed_percommitandowed_unwatchedall still produceproceed=false, andworkflow_dispatchstill overrides unconditionally.Provenance
Residual
Not fixed / not exercised here, written to stand on its own:
skippedhalf of the discriminator has no retained example on a bump fleet. The probe treats a run as "bumped" only when theBump SHA in caller reposstep's conclusion is exactlysuccess. Thesuccessside is confirmed against real runs; theskippedside is confirmed only generically — I swept the last 30 successful runs of all 13 fleets and none has a declined-but-green run, so I confirmedskippedonif:-gated steps in other workflows of this repo instead. The probe's safety does not depend on the exact value (anything other thansuccessreads as "did not bump", which walks back and, at worst, bumps), but if Actions ever reportedsuccessfor anif:-skipped step the probe would take a declined run as the left endpoint and wrongly conclude nothing is owed. Worth a one-line assertion the first time a fleet legitimately declines.actions: readorGH_TOKEN. Documented in both the script and the README; the contract test covers the third case, nothing covers the first two, and nothing goes red when they happen.bump-*-callers.ymlrun opens SHA-bump PRs in consumer repos, so I did not trigger one — verification is the hermetic harness plus the read-only API queries above. The first production exercise will be whichever fleet next sees a trailered push.git ls-remote/fetch behaviour on the normal path is newly load-bearing. The probe is the first thing inpreflight.shthat needs real history on the non-stale path, so it may now rungit fetch --unshallowon runs that previously never fetched. Bounded by this repo's own history and by the jobs' existingtimeout-minutes, and covered by theowed_shallowcase, but it is new work on the hot path.2026-08-27T14:44:29Z, branchmatt/be-9571-skip-caller-bump-trailer), which was the stated precondition, but agh apiread of that individual review comment hit GitHub's secondary rate limit twice and I did not read its text. The design implemented here comes from the task brief, not from that thread, so if the thread raised a constraint the brief did not carry, it is not reflected here.🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.