diff --git a/.github/workflows/actions.lock b/.github/workflows/actions.lock index ebb88ef7..64a2183d 100644 --- a/.github/workflows/actions.lock +++ b/.github/workflows/actions.lock @@ -35,7 +35,7 @@ workflows: '.github/workflows/ci-pipeline.yml': - 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1' - 'haskell-actions/setup@0f8e8c99d88aeb3fbfd523f1ef2c6f762d10d64d' - - 'hyperpolymath/standards@427eb35c40552d912d8c757518e8326f0d20f597' + - 'hyperpolymath/standards@d55304a01b5260b0511aae0d14ed8b8770b00293' - 'oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6' '.github/workflows/codeql-reusable.yml': - 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1' @@ -109,7 +109,7 @@ workflows: - 'dtolnay/rust-toolchain@683b588c487a69d01f6c6ddf40f036ff682cc2c8' - 'webfactory/ssh-agent@e83874834305fe9a4a2997156cb26c5de65a8555' '.github/workflows/mirror.yml': - - 'hyperpolymath/standards@427eb35c40552d912d8c757518e8326f0d20f597' + - 'hyperpolymath/standards@d55304a01b5260b0511aae0d14ed8b8770b00293' '.github/workflows/no-js-scan.yml': - 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1' '.github/workflows/pages-archive.yml': @@ -239,11 +239,6 @@ dependencies: commit: 'sha1-683b588c487a69d01f6c6ddf40f036ff682cc2c8' owner_id: 1940490 repo_id: 260749683 - 'dtolnay/rust-toolchain@e2a55d2ffb04f378e9626c28d38b36d230d1e12f': - ref: 'v1' - commit: 'sha1-e2a55d2ffb04f378e9626c28d38b36d230d1e12f' - owner_id: 1940490 - repo_id: 260749683 'editorconfig-checker/action-editorconfig-checker@51f63319f592f97930c73d9c46184d20bd206393': ref: 'v3.0.0' commit: 'sha1-51f63319f592f97930c73d9c46184d20bd206393' @@ -269,14 +264,14 @@ dependencies: commit: 'sha1-0f8e8c99d88aeb3fbfd523f1ef2c6f762d10d64d' owner_id: 75048950 repo_id: 623796603 - 'hyperpolymath/standards@427eb35c40552d912d8c757518e8326f0d20f597': - ref: '427eb35c40552d912d8c757518e8326f0d20f597' - commit: 'sha1-427eb35c40552d912d8c757518e8326f0d20f597' + 'hyperpolymath/standards@d55304a01b5260b0511aae0d14ed8b8770b00293': + ref: 'd55304a01b5260b0511aae0d14ed8b8770b00293' + commit: 'sha1-d55304a01b5260b0511aae0d14ed8b8770b00293' owner_id: 6759885 repo_id: 1116521501 uses: - 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1' - - 'dtolnay/rust-toolchain@e2a55d2ffb04f378e9626c28d38b36d230d1e12f' + - 'dtolnay/rust-toolchain@683b588c487a69d01f6c6ddf40f036ff682cc2c8' - 'goto-bus-stop/setup-zig@abea47f85e598557f500fa1fd2ab7464fcb39406' - 'swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6' - 'webfactory/ssh-agent@e83874834305fe9a4a2997156cb26c5de65a8555' diff --git a/.github/workflows/ci-pipeline.yml b/.github/workflows/ci-pipeline.yml index 6b69f765..d0e7dc32 100644 --- a/.github/workflows/ci-pipeline.yml +++ b/.github/workflows/ci-pipeline.yml @@ -319,7 +319,7 @@ jobs: name: Secret scanning # Deliberately NOT gated on `detect`: a repo with no recognised ecosystem # can still be leaking credentials. - uses: hyperpolymath/standards/.github/workflows/secret-scanner-reusable.yml@427eb35c40552d912d8c757518e8326f0d20f597 + uses: hyperpolymath/standards/.github/workflows/secret-scanner-reusable.yml@d55304a01b5260b0511aae0d14ed8b8770b00293 with: runs-on: ${{ inputs.runs-on }} @@ -330,7 +330,7 @@ jobs: name: Rust needs: detect if: ${{ needs.detect.outputs.has_rust == 'true' }} - uses: hyperpolymath/standards/.github/workflows/rust-ci-reusable.yml@427eb35c40552d912d8c757518e8326f0d20f597 + uses: hyperpolymath/standards/.github/workflows/rust-ci-reusable.yml@d55304a01b5260b0511aae0d14ed8b8770b00293 with: runs-on: ${{ inputs.runs-on }} enable_coverage: ${{ inputs.enable_coverage }} diff --git a/.github/workflows/mirror.yml b/.github/workflows/mirror.yml index 9298823f..a80c824e 100644 --- a/.github/workflows/mirror.yml +++ b/.github/workflows/mirror.yml @@ -14,7 +14,7 @@ permissions: jobs: mirror: - uses: hyperpolymath/standards/.github/workflows/mirror-reusable.yml@427eb35c40552d912d8c757518e8326f0d20f597 + uses: hyperpolymath/standards/.github/workflows/mirror-reusable.yml@d55304a01b5260b0511aae0d14ed8b8770b00293 # Exactly the seven optional secrets the callee declares at the # pinned SHA (verified declared ⊇ referenced). Was `secrets: # inherit`, which forwarded every repo/org secret (standards#1108 diff --git a/scripts/relock-standards-pin.sh b/scripts/relock-standards-pin.sh index 34b98887..ecb05431 100755 --- a/scripts/relock-standards-pin.sh +++ b/scripts/relock-standards-pin.sh @@ -70,7 +70,16 @@ PIN_RE='hyperpolymath/standards/\.github/workflows/[A-Za-z0-9._-]+\.ya?ml@[0-9a- shopt -s nullglob wfs=("$WF"/*.yml "$WF"/*.yaml) shopt -u nullglob -pins=$(grep -hoE "$PIN_RE" "${wfs[@]}" 2>/dev/null | sort -u || true) +# standards_pins FILE... — the standards reusable pins that a `uses:` key holds, +# block or flow style (`build: { uses: "…@" }`). Full-line comments are +# skipped: reusables carry commented caller examples (`# uses: …@`) +# that no run resolves, and counting them refused every relock of standards' +# own callers. +standards_pins() { + grep -hvE '^[[:space:]]*#' "$@" 2>/dev/null \ + | grep -oE "(^|[{,[:space:]])uses:[[:space:]]*['\"]?$PIN_RE" | grep -oE "$PIN_RE" +} +pins=$(standards_pins "${wfs[@]}" | sort -u || true) # A short pin (7+ hex) that prefixes TARGET names TARGET: the applier counts it # FRESH and leaves it as written, and the lock keys it by that short ref in a # record of its own, which is left as it is. Only full pins feed TARGET's record. @@ -218,7 +227,7 @@ dangling=$(LC_ALL=C comm -23 "$tmp/edges" "$tmp/recs") # The gates match an entry to a `uses:` by its ref as written, so an entry # re-keyed to TARGET for a workflow that pins a short ref is a desync they reject. for w in "${wfs[@]}"; do - want=$(grep -oE "$PIN_RE" "$w" | sed 's#^hyperpolymath/standards/.*@#hyperpolymath/standards@#' | LC_ALL=C sort -u || true) + want=$(standards_pins "$w" | sed 's#^hyperpolymath/standards/.*@#hyperpolymath/standards@#' | LC_ALL=C sort -u || true) have=$(awk -v k=" '.github/workflows/${w##*/}':" '$0==k{f=1;next} f&&!/^ - /{exit} f' "$tmp/out" \ | grep -oE "'hyperpolymath/standards@[0-9a-fA-F]+'" | tr -d "'" | LC_ALL=C sort -u || true) [ "$want" = "$have" ] || refuse "${w##*/}: lock entries [${have//$'\n'/ }] would not match its pins [${want//$'\n'/ }]" diff --git a/scripts/tests/relock-standards-pin-test.sh b/scripts/tests/relock-standards-pin-test.sh index bdb202fe..69297451 100755 --- a/scripts/tests/relock-standards-pin-test.sh +++ b/scripts/tests/relock-standards-pin-test.sh @@ -180,6 +180,20 @@ cp "$D/actions.lock" "$T/once"; bash "$RELOCK" --to "$NEW" --standards "$S" "$D" cmp -s "$T/once" "$D/actions.lock" || fail "second run changed the lock" echo " PASS idempotent" +# A commented caller example pinned at another commit is not a pin. +D=$(consumer commented-example) +printf '# Caller example:\n# uses: hyperpolymath/standards/.github/workflows/x-reusable.yml@%s\n' "$OLD" >> "$D/caller.yml" +bash "$RELOCK" --to "$NEW" --standards "$S" "$D" >/dev/null 2>&1 || fail "a commented caller example at another commit refused the relock" +grep -q "^ 'hyperpolymath/standards@$NEW':\$" "$D/actions.lock" || fail "commented example: no record for the new pin" +echo " PASS a commented caller example at another commit is not counted as a pin" + +# A flow-style (KYAML) call is still a pin. +D=$(consumer flow-style) +printf 'on: push\njobs: { call: { uses: "hyperpolymath/standards/.github/workflows/x-reusable.yml@%s" } }\n' "$NEW" > "$D/caller.yml" +bash "$RELOCK" --to "$NEW" --standards "$S" "$D" >/dev/null 2>&1 || fail "a flow-style call refused the relock" +grep -q "^ - 'hyperpolymath/standards@$NEW'\$" "$D/actions.lock" || fail "flow-style: workflow entry not re-keyed" +echo " PASS a flow-style call is counted as a pin" + # 3. Refusals leave the lock byte-identical. refuse_case() { # name mutate-command local d; d=$(consumer "$1"); eval "$2"; cp "$d/actions.lock" "$T/before"