ci: gates read workflows with yq (Y-1), then KYAML pilot (Y-3) - #1115
Merged
Merged
Conversation
YAML-POLICY Y-1: a verdict about a workflow must come from a parser.
Each of these gates read `uses:`/`permissions:` by line grep, which only
sees block style. On a KYAML workflow they either falsely failed (the
quote and comma were captured into the ref) or went blind (a pin inside
`{ uses: ... }` was never seen):
- validate-actions-lock.sh, lock-selfcheck.sh, check-action-pins-resolve.sh,
update-actions-lock.sh: refs come from yq; an unparseable file fails
closed instead of contributing zero refs.
- check-workflow-duplicate-keys.sh: flow documents are normalised with
yq -P before the line scanner runs (yq keeps duplicates, so the
scanner still sees them).
- governance-reusable.yml: top-level permissions via yq has("permissions"),
with a warned grep fallback on a runner without yq.
- Mustfile actions-sha-pinned: optional quote/comma in the pattern.
- lock-selfcheck.sh: its existing MPL-2.0 SPDX line moves from line 41
to line 2 so the staged SPDX hook sees it (identifier unchanged).
Known answers on main's block-style tree: identical ref sets for
validate-actions-lock (29) and lock-selfcheck (111 pairs);
check-action-pins-resolve drops exactly two `# uses:` comment examples
that never execute. New KYAML cases and mutants fail against the old
scripts and pass against the new ones.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W5CoaksP2Bg21HpDCgFgwS
The pre-commit/pre-push permissions hook grepped `^permissions:`, which
never matches a KYAML workflow (every key sits inside `{ ... }`), so a
KYAML file that does declare permissions was rejected. Ask yq
has("permissions") instead; an unparseable file is an error, not a
pass. Without yq the grep is kept with a warning -- it can only
false-fail KYAML, never false-pass.
Known answer: identical output to the old hook on all 58 of main's
workflows. scripts/tests/validate-permissions-test.sh: 6/6; the old
hook fails its KYAML positive case.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W5CoaksP2Bg21HpDCgFgwS
Single-file pilot of YAML-POLICY Y-3, produced verbatim by `yq -p yaml -o kyaml '.'` (yq v4.53.3). Not the #1023 scope ruling. Verified locally: - data-equal: sort_keys JSON of block and KYAML forms cmp-identical - idempotent: re-emitting the KYAML is byte-identical - tools/yaml-comment-proof (#1021): kyaml arm PASS, 26/26 comments preserved, 0 moved, 0 dropped; 8 blank lines lost (cosmetic) - the gates fixed in the previous commits read it correctly (validate-actions-lock, validate-permissions, duplicate keys, governance permissions check, Mustfile pin pattern) Not proven: GitHub's runtime parse of this reusable needs a caller run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W5CoaksP2Bg21HpDCgFgwS
Contributor
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 26 minutes. View limit detailsLimit details: You’ve used the included review currently available. Review configuration: ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Advanced Run ID: 📒 Files selected for processing (14)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
hyperpolymath
enabled auto-merge (squash)
October 1, 2026 17:59
governance / Workflow security linter runs the duplicate-key checker from a standards checkout pinned at 317101e, not this PR's fixed copy, so the KYAML file false-fails until the fix is on main and the pin is bumped. The pilot moves to a follow-up PR (branch feat/kyaml-pilot-provisioning-convert) that bumps the pin and converts the file together. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W5CoaksP2Bg21HpDCgFgwS
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
YAML-POLICY Y-1: the gates that judge a workflow now get their verdict from a YAML parser (yq) instead of a line grep.
This is a single-file pilot. It is not the scope ruling in #1023 (KYAML step 4/6). It adds evidence for that ruling and for #1022. The comment proof is #1021's harness.
Why the gates had to come first
On a KYAML workflow, each of these gates either falsely failed a correct file (the quote and comma ended up inside the captured ref, or
^permissions:never matched) or went blind (it never saw auses:inside{ … }):.githooks/validate-actions-lock.sh…@sha",).githooks/validate-permissions.sh(pre-commit and pre-push)^permissions:)has("permissions"); falls back to grep with a warning if yq is missingscripts/lock-selfcheck.shUNEXAMINED, not consistentscripts/check-action-pins-resolve.shscripts/update-actions-lock.sh(reusable coverage)run:-body decoyscripts/check-workflow-duplicate-keys.shyq -Pbefore the scangovernance-reusable.ymlpermissions checkactions-sha-pinnedEvidence
Known answers on main's block-style tree:
validate-actions-lockandlock-selfcheckproduce identical ref sets: 29 refs and 111 pairs.validate-permissionsgives identical output on all 58 workflows.check-action-pins-resolvedrops exactly two# uses:comment examples, which never execute.Mutant suites. Each was run against the new and the old script:
scripts/tests/validate-actions-lock-test.sh(new)scripts/tests/lock-selfcheck-test.sh(new)scripts/tests/validate-permissions-test.sh(new)scripts/tests/check-workflow-duplicate-keys-test.sh(+5 KYAML cases)scripts/tests/update-actions-lock-test.sh(+3 KYAML / decoy cases)run:decoyscripts/tests/check-action-pins-resolve-test.shThe full
scripts/run-shell-test-suite.shpasses (66 files). Docstring scan over the range: 8/8 documented.Pilot conversion:
sort_keysJSON of the block and KYAML forms iscmp-identical.tools/yaml-comment-proof(KYAML step 2/6 — comment-preservation proof (shared by Y-2 and Y-3) #1021) kyaml arm: PASS, 26/26 comments preserved, 0 moved, 0 dropped. 8 blank lines are lost; this is cosmetic.job.workflow_shafalse positive (actionlint 1.7.7), the same as on main.gh actions-lock --no-fix. Its one finding (thesigned-push-smoke.ymllocal action) is identical on main.Not proven: GitHub's runtime parse of this reusable. That needs a caller run. #1020 showed that Actions parses KYAML in general.
Known Y-1 gaps outside this PR
These are filed as findings, not fixed here:
scripts/check-lockfile-drift.sh:86: the regex can't match the opening", so it silently skips a KYAML workflow. This runs only from the estate detectorlockfile-drift-detect.yml, not as a PR gate..githooks/validate-sha-pins.sh: catches an unpinned quoted ref (checked with a planted mutant). It would, however, false-fail a quoted local action ("./x") and is blind to a one-line{ uses: … }. yq never emits that form, and the pilot has no local action.pin_integrity.ex:56don't recognise a quoteduses:. That is in the hypatia repo.🤖 Generated with Claude Code
https://claude.ai/code/session_01W5CoaksP2Bg21HpDCgFgwS