mirror of
https://github.com/Comfy-Org/github-workflows.git
synced 2026-11-05 00:17:37 +00:00
[PR #197] [MERGED] fix(workflow-pins): stop the step-output reader failing compliant if: spellings (BE-8130) #204
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#204
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/197
Author: @mattmillerai
Created: 8/20/2026
Status: ✅ Merged
Merged: 8/21/2026
Merged by: @mattmillerai
Base:
main← Head:matt/be-8130-step-output-reader-spellings📝 Commits (1)
f481ca5fix(workflow-pins): stop the step-output reader failing compliant spellings (BE-8130)📊 Changes
3 files changed (+107 additions, -6 deletions)
View changed files
📝
.github/workflow-pins/README.md(+3 -2)📝
.github/workflow-pins/check_workflow_pins.py(+30 -4)📝
.github/workflow-pins/tests/test_check_workflow_pins.py(+74 -0)📄 Description
ELI-5
check_workflow_pins.pynow follows aref:through a step output (#195, BE-8130), socursor-review.yml's never-fail ledger checkout is linted instead of invisible. The multi-model review panel on that PR found the reader is narrower than the shapes it has to read: three ways of writing a checkout that IS compliant were reported as violations, and one way of writing an evasive one slipped past. A lint that fails the remedy it just recommended is a lint people learn to route around, so this widens the reader — and only the reader. Every coverage rule is unchanged.What changed
Four fixes, each mirroring a precedent already in this file rather than inventing a rule.
- if:on the list-marker line was never seen._skips_on_empty_outputscanned only lines at the step's key column, so a step written- if: steps.x.outputs.ref != ''had its guard ignored and a correctly guarded checkout was reported unguarded. Normalize the marker exactly as_binding_step_idalready does to read anid:off it.!=had to be surrounded by spaces. Actions accepts…outputs.ref!=''; the lint failed it. Spacing around!=is now normalized to one space either side. Nothing else is normalized, so an OR-widened condition and anif:on a different output stay refused however they are spaced — both pinned by tests._STEPS_OUTPUT_FLOW_RE.searchtook the leftmost[{,]entry boundary, and a comma inside a quoted scalar meets it:with: {path: "x, ref: ${{ steps.other.outputs.ref }}", ref: "${{ steps.resolve_ref.outputs.ref }}"}resolved toother, which holds noresolversentry, so the real checkout was dropped out of coverage entirely. It now keeps looking past a match inside quotes, via the_outside_quoteshelper_pins_to_job_workflow_shaalready applies to its own flow match. That function stops at a quoted match; stopping here would lose the site, so this one iterates.env:"bindsworkflows_ref", which is wider than what the code detects. It now says "in one of the two literal spellings below" — the spellings the preconditions block already lists.Two tests that passed vacuously now assert what they name:
test_a_resolver_below_its_consumer_is_never_creditedfiltered onguarded, which an empty site list satisfies, so it could not distinguish "reported as unguarded" from "dropped and never seen". It now pins the site list and documents that today the site is dropped, though at runtime that output is guaranteed''and the checkout takes the default branch. Left as-is deliberately — see below._binding_step_id's own list-marker normalization had no test at all; deleting it kept the suite green. Found by mutation while checking the fix above.Verification
python3 -m unittest discover -s .github/workflow-pins/tests -p 'test_*.py'— 123 passed, 0 failed (118 onmain).python3 .github/workflow-pins/check_workflow_pins.py— green: 10 workflows, every ref checkout guarded, 0 exempt.default:→ exit 1, unguarded checkout → exit 1.if:→test_the_if_on_the_list_marker_line_is_seen;!=spacing →test_a_tightly_spaced_if_passes; the decoy fix →test_a_quoted_sibling_cannot_plant_a_decoy_step_output;_binding_step_id's marker rewrite →test_the_id_on_the_list_marker_line_registers_the_resolver.Deliberately NOT fixed here
The panel's other findings are coverage-rule changes, not reader changes, and each needs a judgment this PR does not make. They are recorded for follow-up rather than folded in:
_GUARD_BINDING_REmatch (8/8 reviewers), so a step reaching the input any other way — a different env name,|| 'main', a job-levelenv:— registers nothing and its consumer drops out of coverage. This is the "Known residual" #195 named when it landed asRefs BE-8130rather thanCloses; BE-8130 stays open for it. Fixing it fail-closed would demand an empty-refif:of checkouts whose ref is a mutable branch by construction, which is the different judgment #195 declined to make.<id>— a typo, another job, or declared below its consumer — is dropped rather than reported, though the runtime value is then guaranteed''. Distinguishing it from the legitimately out-of-scope case (an earlier step that exists and never touchesworkflows_ref) needs a per-job pre-scan of step ids. The test above now makes the gap visible in the suite.if:, butis_guard_stepproves only that the step rejects an empty input — never that the value it writes to$GITHUB_OUTPUTis non-empty. The BE-8130 error text actively recommends that route.ref: ${{ steps.x.outputs.ref || 'main' }}matches none of the three step-output patterns and names no input either, so it records nothing — a mutable ref with no coverage.Refs BE-8130
Provenance
python3 -m unittest discover -s .github/workflow-pins/tests -p 'test_*.py': 123 passed, 0 failed;python3 .github/workflow-pins/check_workflow_pins.py: green (10 workflows, every ref checkout guarded, 0 exempt); both CI smoke tests run by hand (reintroduced default → exit 1, unguarded checkout → exit 1); 4 mutation checks, one per new test, each failing exactly the test that names it🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.