mirror of
https://github.com/Comfy-Org/github-workflows.git
synced 2026-11-05 00:17:37 +00:00
[PR #198] [MERGED] fix(workflow-pins): recognize flow-form env, bracket access and env chains as ref uses (BE-8146) #207
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#207
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/198
Author: @mattmillerai
Created: 8/20/2026
Status: ✅ Merged
Merged: 8/21/2026
Merged by: @mattmillerai
Base:
main← Head:matt/be-8146-workflow-pins-ref-uses📝 Commits (4)
4d50e1bfix(workflow-pins): recognize flow-form env, bracket access and env chains as ref uses (BE-8146)0e239d7fix(workflow-pins): close review-flagged gaps in the BE-8146 ref-use widening27e4655merge main into matt/be-8146-workflow-pins-ref-usesaca730fMerge remote-tracking branch 'origin/main' into matt/be-8146-workflow-pins-ref-uses📊 Changes
3 files changed (+901 additions, -42 deletions)
View changed files
📝
.github/workflow-pins/README.md(+42 -1)📝
.github/workflow-pins/check_workflow_pins.py(+429 -41)📝
.github/workflow-pins/tests/test_check_workflow_pins.py(+430 -0)📄 Description
ELI-5
check_workflow_pins.pymakes sure every job that checks this repo out atworkflows_reffirst proves that ref isn't empty — otherwiseactions/checkoutsilently takes the default branch and the job runs mutable scripts under write permissions. The lint found that checkout by pattern-matching the text, and it only knew one way to spell it. Three other perfectly legal spellings made the checkout invisible, so the lint went green over an unguarded checkout. This teaches it those three spellings.The three spellings, and why each failed silently
Each was verified failing open against
mainbefore the fix — the fixture reportsunguarded=[](a clean lint) while carrying an unguarded checkout:env:—env: {WORKFLOWS_REF: ${{ inputs.workflows_ref }}}followed byref: ${{ env.WORKFLOWS_REF }}._ENV_KEY_RErequiredenv:to end its line, so nothing bound the alias and theref:read as no ref use at all.ref: ${{ inputs['workflows_ref'] }}andref: ${{ env['WORKFLOWS_REF'] }}. Every mention regex was dot-access only, thoughinputs['x']is documented Actions expression syntax and interchangeable withinputs.x.BASE: ${{ inputs.workflows_ref }}thenREF: ${{ env.BASE }}, consumed asref: ${{ env.REF }}. The alias scan followed exactly one hop.The
_CONSUMES_*backstop did not cover any of them, and the module's own comment claimed it did ("a flow-styleenv: {…}binds no alias here, which loses nothing the_CONSUMES_*backstop does not already catch"). That comment was false and is corrected in the diff: the backstop only runs whendefaults is None— when the input declaration itself was unparseable — so for a well-formed workflow it never ran at all.What changed
_INPUT_MENTION_BODYnow defines how a workflow can name the input, and every "does this reach the input" pattern is built from it:_REF_USE_BLOCK_RE/_REF_USE_FLOW_RE,_mention_alt, theenv:alias patterns, and the_CONSUMES_*trio (so a bracket-only file with a lost declaration still trips the loud "NOT covering this file" error rather than being a silent skip). The dead, never-referenced_INPUT_MENTION_REis deleted rather than left as a second, narrower spelling of the same concept._env_bindingslearned the flow form. Entries on anenv: {…}line are bounded at the entry boundary ([^,}]) exactly as_REF_USE_FLOW_REbounds its own value, and each entry's start is checked with_outside_quotes, so a,planted inside a quoted scalar cannot bind a decoy name.env_aliasesis a fixpoint instead of a single hop, bounded by the number of names bound anywhere in the file (each pass either adds a name or stops, and every addable name is one of those). An empty alias set short-circuits, because an empty alternation would degenerate toenv\.(?:)\band bind every name in the file.Deliberately asymmetric, and this is the point: all three widen only what counts as a ref use, which can only ever demand a guard, never excuse a missing one. The guard-recognition side (
_GUARD_BINDING_RE) stays block-form and dot-access only, and_FALLBACK_RES— an exemption — stays literal. An unrecognized guard and an unclaimed exemption both fail closed, which is loud. Two tests pin that asymmetry directly (test_the_guard_side_is_NOT_widened_to_the_flow_form,test_bracket_access_NEVER_earns_the_self_pin_exemption).Testing
python3 -m unittest discover -s .github/workflow-pins/tests -p 'test_*.py'— 138 passed, 0 failed (was 118; 20 added).main'scheck_workflow_pins.pyunder the new test file — 9 of the new tests fail, one per behavior this diff adds. The remaining new tests are the "same checkout behind the canonical guard still passes" and negative-boundary halves, which must pass in both directions.python3 .github/workflow-pins/check_workflow_pins.pyagainst this repo's own.github/workflows/— green, 10 workflows, 25 ref checkouts judged, 0 errors (no new errors, as expected: a sweep of all 45 workflow files found 0 using any of the three spellings, so any new error would have meant a regex over-matched).test-workflow-pins.ymlrun locally — a reintroduceddefault:and an unguarded checkout each still exit non-zero.check_dirover the real.github/workflows/is 0.081s;env_aliaseson the 3,308-linegroom.ymlconverges in one extra pass (~9ms).Residual — the part I did NOT fix
The same corpus sweep, pointed at the shapes this diff does not cover, found 0 of 45 workflow files using any of them today. Two remain verified-failing-open, and both are the module's pre-existing line-orientation rather than something this diff introduces (
_REF_USE_FLOW_RE,_STEPS_OUTPUT_FLOW_REand_FALLBACK_RES' flow arm all share it):env: {whose entries continue on later lines, andenv:nested inside a larger flow mapping (- {uses: …, env: {…}}), which_ENV_FLOW_KEY_RE's line-start anchor does not reach.Because that is an unfixed gap on the very file this change is about, no closing keyword is written here and the driving work item stays open to carry it. Teaching the module multi-line flow mappings is a parser-shape change across every flow matcher, not a widening of this one — worth doing on its own, not as a rider here.
One further near-miss was cheap enough to close and is included: Actions permits whitespace inside an index expression, so
inputs[ 'workflows_ref' ]is the same access; the brackets now tolerate it.Judgment calls / deviations from the plan as written
_ENV_ALIAS_REbecame_ENV_ALIAS_RES, a(block, flow)pair produced by a small_env_alias_res(mention)builder. The fixpoint has to build the same pair per pass against a different "reaches" test (env.<known>), so parameterizing it was the alternative to a third hand-written copy of the pattern. Nothing outside the module referenced the old name._REF_USE_BLOCK_RE/_REF_USE_FLOW_REwere widened too, which the plan did not list. They areis_ref_use's defaults when noresis passed; leaving them dot-only would have recreated exactly the "second, narrower spelling of the same concept" the plan objects to for_INPUT_MENTION_RE. In-module behavior is unchanged —ref_checkoutsalways passes_ref_use_res(aliases).test_the_guard_side_is_NOT_widened_to_the_flow_form, asserts the plan's explicit fail-closed design (an unrecognized guard reports its checkout), and that behavior was exercised rather than assumed.main, not from that write-up. Separately,AGENTS.mdis 281 lines and already fails the repo's own 200-line integrity ceiling onmain, untouched by this diff and with no CI caller wired up in this repo; flagging it, not fixing it here.Provenance
check_workflow_pins.pyon this repo's workflows green, 0 errors; bothtest-workflow-pins.ymlCLI smoke tests exit non-zero as expected; cursor-review 194 passed, agents-md-integrity 46 passed, groom 365 passed / 1 skipped_ENV_ALIAS_RErefactored into a(block, flow)pair and_REF_USE_*widened alongside it (neither listed in the plan, both reasoned above); two multi-line/nested flow-mapping spellings verified still failing open and deliberately left out of scope🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.