From a43df0ac02a1d7e8afce26ff5635dcb657a2ab25 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Tue, 22 Sep 2026 10:40:02 +0100 Subject: [PATCH] fix(ci): repair dead $/ ref and the pin detector blind to it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit signed-push-smoke.yml has been dead at STARTUP on main. Line 56 read `uses: $/.github/actions/signed-push`, which is not valid `uses:` syntax, so the workflow never ran a job. Its last five runs on main are all `failure` and the most recent is 2026-08-24 — a month of silence. `validate-sha-pins.sh` should have caught it and did not. Two defects, the second hiding the first: 1. The selector required a ref to start `[A-Za-z0-9]`. `$` is not alphanumeric, so the line was dropped before any exemption arm saw it. 2. The cure previously attempted for (1) added a SECOND grep inside the same brace group: `{ grep A ... ; grep B ; } < "$file"`. Both greps share one stdin; the first reads it to EOF and the second is handed an exhausted stream. Measured: arm 2 matches line 56 in isolation and emits nothing in place. It was dead code that made the gate look fixed, and its comment asserted "zero matches tree-wide today; this arm is purely prospective" — false the whole time. That comment was mine and this commit retracts it. Cure: one pipeline, first selector widened to any non-blank ref, dead arm deleted. An unknown-shaped ref is now REPORTED; the exemptions (`./`, `../`, `docker://`, 40-hex pins) remain the only way out and each is explicit. A `$/` hit is diagnosed as invalid syntax causing startup death, not as an unpinned ref — the old wording sent the reader hunting a SHA that was never the problem. Mutant kill, both directions, denominator printed each time: defect present -> rc=1, 78 scanned / 92 vendored excluded, 1 finding, reported on signed-push-smoke.yml:56 defect cured -> rc=0, 78 scanned / 92 vendored excluded, 0 findings No new findings on the other 77 files, so the widened selector adds no false positives. `bash -n` clean; the workflow still parses as YAML. Non-destructive: read-only verification only, no auto-fix flags, no source or core logic touched. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01Ji1bq3TypfycfUPAR7hSxR --- .githooks/validate-sha-pins.sh | 55 ++++++++++++++++++------- .github/workflows/signed-push-smoke.yml | 2 +- 2 files changed, 42 insertions(+), 15 deletions(-) diff --git a/.githooks/validate-sha-pins.sh b/.githooks/validate-sha-pins.sh index 63c4266b7..3d5c1ee9d 100755 --- a/.githooks/validate-sha-pins.sh +++ b/.githooks/validate-sha-pins.sh @@ -44,18 +44,32 @@ is_vendored() { case "$1" in *"${VENDORED_MARK}"*) return 0 ;; *) return 1 ;; es # this repo's own composite actions and `docker://` refs are container images, not # actions -- neither is modelled by actions.lock, which keys actions only. UNPINNED_FILTER() { - # `$/...` is NOT valid `uses:` syntax (GitHub Actions has no such thing) — - # `gh actions-lock` REWRITE MODE once invented `uses: $/.github/actions/...` - # and every workflow carrying it died at startup. The alnum-first selector - # below would silently skip such lines, so they are flagged explicitly: - # waving that corruption through is the exact failure this gate exists to - # catch. (Zero matches tree-wide today; this arm is purely prospective.) - { grep -nE '^[[:space:]]*(-[[:space:]]*)?uses:[[:space:]]+[A-Za-z0-9]' \ - | grep -vE 'uses:[[:space:]]+[./]' \ - | grep -vE 'uses:[[:space:]]+docker://' \ - | grep -vE 'uses:[[:space:]]+[^[:space:]@]+@[0-9a-f]{40}([^0-9a-f]|$)' \ - || true; - grep -nE 'uses:[[:space:]]+\$/' || true; } + # ONE pipeline, and the first selector matches any NON-BLANK ref. + # + # Two defects are cured here, and the second hid the first. + # + # 1. The selector used to demand `[A-Za-z0-9]`, so a ref that is not + # alphanumeric was dropped before any later arm saw it. `gh actions-lock` + # REWRITE MODE emits `uses: $/.github/actions/...` (measured; it also + # de-pinned 24 SHAs). `$` is not alphanumeric, so that corruption was + # never reported and a workflow that dies at STARTUP scanned CLEAN. + # + # 2. The cure attempted for (1) was a SECOND grep in the same brace group: + # `{ grep A ... ; grep B ; } < "$file"`. Both greps share one stdin, the + # first reads it to EOF, and the second is handed an exhausted stream. It + # matched in isolation and emitted nothing in place — dead code that made + # the gate look fixed. Its comment claimed "zero matches tree-wide today; + # this arm is purely prospective", which was false: signed-push-smoke.yml + # carried a live `$/` ref the whole time. A second reader of one stdin is + # never a second chance. + # + # An unknown-shaped ref must be REPORTED, never skipped. The exemptions below + # are the only way out, and each one is explicit. + grep -nE '^[[:space:]]*(-[[:space:]]*)?uses:[[:space:]]+[^[:space:]]' \ + | grep -vE 'uses:[[:space:]]+[./]' \ + | grep -vE 'uses:[[:space:]]+docker://' \ + | grep -vE 'uses:[[:space:]]+[^[:space:]@]+@[0-9a-f]{40}([^0-9a-f]|$)' \ + || true } validate_file() { @@ -66,8 +80,21 @@ validate_file() { body="${rec#*:}" body="${body#"${body%%[![:space:]]*}"}" echo "[validate-sha-pins] ERROR: $file:$lineno: ${body}" >&2 - echo " unpinned ref: canon rule 10 wants owner/repo@<40-hex> plus a '# ' comment," >&2 - echo " and a matching key in .github/workflows/actions.lock" >&2 + case "$body" in + *'uses:'*'$/'*) + # Name the real fault. `$/...` is not an unpinned ref, it is not valid + # `uses:` syntax at all, so the workflow dies at STARTUP and no job of + # it ever runs. Reporting it as "unpinned" sends the reader hunting a + # SHA that was never the problem. + echo " invalid ref: a '\$/'-leading ref is not valid uses: syntax and kills the" >&2 + echo " workflow at startup. This is the gh actions-lock rewrite-mode corruption;" >&2 + echo " a local action is written 'uses: ./.github/actions/'." >&2 + ;; + *) + echo " unpinned ref: canon rule 10 wants owner/repo@<40-hex> plus a '# ' comment," >&2 + echo " and a matching key in .github/workflows/actions.lock" >&2 + ;; + esac ERRORS=$((ERRORS + 1)) done < <(UNPINNED_FILTER < "$file") } diff --git a/.github/workflows/signed-push-smoke.yml b/.github/workflows/signed-push-smoke.yml index 00782a22f..a016b5c56 100644 --- a/.github/workflows/signed-push-smoke.yml +++ b/.github/workflows/signed-push-smoke.yml @@ -53,7 +53,7 @@ jobs: git commit -m "test(signed-push): verified-commit smoke [run ${GITHUB_RUN_ID}]" - name: Push the local commit as Verified (via the App) - uses: $/.github/actions/signed-push + uses: ./.github/actions/signed-push with: app-id: ${{ vars.APP_ID }} private-key: ${{ secrets.APP_PRIVATE_KEY }}