mirror of
https://github.com/Comfy-Org/github-workflows.git
synced 2026-11-05 00:17:37 +00:00
[PR #134] [MERGED] fix(bump-callers): validate roster entries and fail on un-bumpable callers (BE-6471) #145
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#145
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/134
Author: @mattmillerai
Created: 8/5/2026
Status: ✅ Merged
Merged: 8/12/2026
Merged by: @mattmillerai
Base:
main← Head:matt/be-6471-roster-validation📝 Commits (6)
ef8aa14fix(bump-callers): validate roster entries and fail on un-bumpable callers (BE-6471)239a32afix(bump-callers): close the review panel's gaps in the roster validation (BE-6471)331c1d4fix(bump-callers): close round-2 review findings on the roster gate (BE-6471)76cc890fix(bump-callers): close round-3 review findings on the roster gate (BE-6471)65eb430Merge origin/main into matt/be-6471-roster-validation60467dcfix(bump-callers): reconcile merge — drop stale BE-6015 tests, fix doc drift (BE-6471)📊 Changes
4 files changed (+1137 additions, -157 deletions)
View changed files
📝
.github/bump-callers/README.md(+83 -0)📝
.github/bump-callers/bump-callers.sh(+430 -99)📝
.github/bump-callers/tests/test_bump_callers.sh(+617 -51)📝
AGENTS.md(+7 -7)📄 Description
ELI-5
A config list tells our robot which repos to keep up to date. The robot trusted that list completely: it never checked that an entry named a real Comfy-Org repo or a real workflow file, and when an entry pointed somewhere with nothing to update, the robot cheerfully logged "already up to date" and went green — forever. This makes the robot check the list before it touches anything, and say "I can't move this one" instead of pretending it's fine.
What this does
Three changes, all in
bump-callers.shplus its tests. No entrypoint workflow is touched (one bumper, not several).1. Roster entry validation, before any API call. Every field reaches a privileged sink —
repois interpolated into eachgh api repos/<repo>/…write andgh pr create --repo,filebecomes the path committed into the caller's tree,labelgoes togh pr create --label— all under an org-wide app token (owner: Comfy-Org, contents + pull-requests + issues write, norepositories:narrowing). The roster is an Actions variable, editable outside code review, so roster-edit access currently converts into bot-authored commits, branch force-moves and labelled PRs in any org repo the app is installed on.repomust now match^Comfy-Org/[A-Za-z0-9._-]+$(and not be a bare dot segment),filemust match^\.github/workflows/[A-Za-z0-9._-]+\.ya?ml$— the class excludes/, so../traversal cannot appear — andlabelmust be a string with no|and no newline. One jq pass emits every violation, so an entry breaking two rules reports both.The
labelrule closes a real delimiter bug: entries are carried internally asrepo|file|label|wire_bottuples and read back withcut -d'|' -f3, so a pipe-bearing label truncated at the pipe and bled its tail intowire_bot— silently flagging for identity wiring an entry that never asked for it. The dedup comment that assumed pipe-bearing labels were representable is corrected in the same commit.Errors name the entry's zero-based index and the violated rule, never the value. Masking has not been applied at that point in the script, and this repo's run logs are public.
2. An un-bumpable caller file fails the run. A file that carries no pin this fleet can address rewrites to itself, so the content-equality check reported it as
already at <short> — skippingand the job exited green — indefinitely, for a roster entry that is simply wrong. Each file is now checked before the rewrite, using the same regexes the rewrite uses so the two cannot drift apart. Two shapes trip it: noComfy-Org/github-workflowspin at all, or (via the sibling-tightened address) a file whose onlygithub-workflowsuses:belongs to a different fleet's reusable.3. End-of-run accounting. Offenders are warned per file and tallied into one
::error::after the whole fleet has been processed, then the job exits 1. Failing at the end rather than at the offending file preserves the fan-out — one bad entry never blocks another repo's bump, matching howFAILEDalready behaves. Only the count is printed; the per-file warnings carry the (masked) repo and the path.Judgment calls — please read these two
The ticket's rule for part 2 was written against a stale base, and I did not implement it as literally specified. BE-6467 verified against
main@e4a8f7c(Aug 3, 18:56) and specified that a recognisable pin must be a 40-hex SHA. #79 / BE-4662 merged the next morning (Aug 4, 10:55) and re-anchored the rewrite to the pin token rather than to 40-hex-ness — so a caller on@v1is now self-healed to the new SHA. Requiring a full SHA here would therefore hard-fail exactly the floating-tag callers the fleet exists to drag back onto immutable pins, which is a regression against #79's intent. The check requires an addressable pin of any literal ref shape instead, and there is a test asserting the@v1self-heal stays green. The ticket's test case 1 (floating tag → warning + exit 1) is consequently not implemented as written; the genuinely-undetectable case it was reaching for — a roster entry pointing at a file with no pin of ours — is covered instead.Overlap with open PR #107 (BE-6015). #107 implements the same "un-bumpable caller" idea, from the pre-#79 base, and is currently
CONFLICTINGwith main. Its checks require a 40-hex pin, which is the rule #79 superseded. I have not touched it. Recommend reconciling: either close it in favour of this, or rebase it and keep only the parts this does not cover (its# main @/ placeholder-specific test fixtures are still useful). Flagging rather than deciding, since it is not mine to close.Falsification — I went and looked, I did not just test my own premise
This diff's user-facing outcome denies a capability (it turns previously-green runs red), so internal tests only assert my own premise. I checked it against production instead:
CURSOR_REVIEW_CALLERS19,AGENTS_MD_CALLERS17,GROOM_CALLERS9,AUTO_LABEL_CALLERS5,ASSIGN_REVIEWERS_CALLERS3,PR_SIZE_CALLERS1 = 54 entries);PR_RISK_CALLERSandDETECT_UNREVIEWED_MERGE_CALLERSdo not exist yet, as documented. Ran the exact jq against all 54: zero violations. No live fleet breaks.continues before the new check, so they never reach it. Net: zero real callers would trip the new hard-fail today.Testing
shellcheck -x .github/bump-callers/bump-callers.sh .github/bump-callers/tests/test_bump_callers.sh— clean.bash .github/bump-callers/tests/test_bump_callers.sh— 235 passed, 0 failed (was 175; all 175 pre-existing assertions pass unchanged, including theALLOW_EMPTYseeded-empty no-op and the malformed-variable hard-fail).Comfy-Org/.githubstill valid); non-workflowfile;.github/workflows/../evil.ymltraversal; pipe-bearing label; an entry breaking two rules reporting both; every legitimate roster shape still validating and bumping; each rejection asserting the offending value is never echoed and that it bailed before the mask loop;@v1self-heal stays green; a file with no pin of ours failing with the aggregate tally; a sibling-fleet-only file; and one un-bumpable entry not blocking a healthy repo's bump in the same run (theghstub gained a small per-repo fixture override for that last one).Round 2 — the review panel's ten findings (
331c1d4)Two High, one Medium, four Low, two Nits, plus the README follow-on. All ten
addressed; each thread carries the detail.
The two High ones were live defects, not hardening:
comfy-org/xcase-insensitively is correct, but nothing folded the spelling,so the byte-exact repo grouping produced two
REPOSentries andbump_reporan twice — the second force-PATCHing the shared bump branch off the first's
commit. Green run, half a bump. The owner is canonicalized on the way in and
repos are grouped (and their entries collected) case-insensitively.
workflows_ref:could vouch for a file. Theuses:-pinrequirement was gated on
GW_HAS_SIBLING, which derives from acase-sensitive grep — so a caller spelled
GitHub-Workflows, or one whoseuses:had been removed, left the flag at 0, took the relaxed address, andhad this fleet's SHA stamped onto its assets ref by the unaddressed rule 2,
invisibly to the address-filtered assertion. The requirement is unconditional
now, which also makes the README bullet true as written.
The rest: a rejected path's label no longer folds onto the healthy file's PR;
the label rule bars commas (cobra CSV-splits
--label) and all controlcharacters (bash's
readeats a NUL) rather than just|/CR/LF; the siblingaddress anchors the filename to its leading
/solegacy-groom.ymlis nottreated as
groom.yml; the caller's default-branch name no longer reaches thesepublic logs; the tally counts caller files and excludes repos that failed
wholesale; and the two doc nits.
One thing the fixes surfaced:
SHA_ADDRis consumed both bygrep -Eand as ased
/…/address, so adding the/closed the address early and silentlydisabled the rewrite. There is now a separate escaped
SHA_ADDR_SEDfor the sedside. The existing
multireusabletest caught it, which is the argument for itexisting.
Falsification, again
Same reasoning as the first round — this diff still denies a capability, so the
new tests only assert my own premise. Re-checked against production:
GW_USESgrep, sameSHA_ADDR, same comment-stripping, sameADDR_RE) over all 51 caller filesin the six seeded rosters: 51 pass, 0 rejected. The roster's three 404s from
round 1 have since been cleaned up.
"",ciorCore— nothing livetrips the tightened label rule.
latent; it was also one roster edit away, which is the threat model this PR is
about.
Testing
shellcheck -x— clean.bash .github/bump-callers/tests/test_bump_callers.sh— 299 passed, 0failed (was 235).
fails there, so none of them pass vacuously.
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.