From 067c271712c1f295f76cc32293904721f3dcb36b Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Tue, 21 Jul 2026 13:55:51 +0100 Subject: [PATCH 1/2] fix(ci): SHA-pin pages.yml actions and refresh stale standards pins MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Follow-up to #292, which greened the SPDX arm of `Workflow security linter` and removed the retired scorecard-enforcer.yml. Clearing those revealed the two remaining governance failures. Opened as a new PR off main per the repo's squash-merge convention (.claude/CLAUDE.md). 1. `Workflow security linter` — action pinning pages.yml held the only 4 tag-ref `uses:` in the repo (of 66). It had never actually run -- its single run ever was the BROKEN-M1 startup_failure -- so no linter had ever seen it. actions/checkout -> de0fac2e (v6.0.2), the pin 41 other workflows here already use actions/upload-pages-artifact -> 56afc609 (v3.0.1), = current @v3 actions/deploy-pages -> d6db9016 (v4.0.5), = current @v4 The latter two are pin-only: those SHAs are exactly what the tags resolve to today. checkout moves v4 -> v6.0.2 for repo consistency; pages.yml is the only container job here, so this is the first time that pin runs inside idris2-pack. Preconditions checked before pinning it green: ddraig-ssg is public with Ddraig.idr at root, and Pages is build_type=workflow on boj-server.net. 2. `Check Workflow Staleness` — reusable pin recency The gate allows <=50 commits behind standards HEAD OR <=14 days old; d135b05 was 75 commits / 26 days behind, outside on both arms. Refreshed to 8813ecf, scoped to exactly the two reusables the gate names -- check-workflow-staleness.sh inspects only governance-reusable, hypatia-scan-reusable and scorecard-reusable, which is why mirror.yml sits at the same d135b05 and was NOT flagged. Left alone deliberately. Measured before moving: * governance-reusable: same 10 jobs before and after, so no new required check appears. The three gates that change behaviour were each run locally against this tree -- Guix primary / Nix fallback -> PASS (guix.scm present; the Nix fallback was never required, so the absent flake.nix is a non-issue) Code quality + docs -> PASS (README + LICENSE + CONTRIBUTING) banned languages + Groovy -> 0 tracked .groovy/.gradle files Both fetch their scripts from standards@main rather than from the pin, so these are the scripts CI will actually run. * scorecard-reusable: the whole d135b05..8813ecf diff is an SPDX correction (PMPL-1.0-or-later -> MPL-2.0) plus timeout-minutes: 15. Worth stating because scorecard.yml has no `pull_request` trigger, so this PR's checks do not exercise it; the diff is the evidence, not a green tick. Its first real run is the next push to main. Local verification against the real gate scripts: check-workflow-staleness.sh -> exit 0 66/66 `uses:` SHA-pinned, 25/25 workflows carry SPDX + top-level permissions, all 25 parse as YAML. --- .github/workflows/governance.yml | 2 +- .github/workflows/pages.yml | 8 ++++---- .github/workflows/scorecard.yml | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/governance.yml b/.github/workflows/governance.yml index f143f3c9..d98a84eb 100644 --- a/.github/workflows/governance.yml +++ b/.github/workflows/governance.yml @@ -31,4 +31,4 @@ permissions: jobs: governance: - uses: hyperpolymath/standards/.github/workflows/governance-reusable.yml@d135b05bfc647d0c0fbfedc7e80f37ea50f49236 + uses: hyperpolymath/standards/.github/workflows/governance-reusable.yml@8813ecf2a841335c9dc14c75cc46694722cd6d28 diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index 6168232d..006ab206 100755 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -23,9 +23,9 @@ jobs: image: ghcr.io/stefan-hoeck/idris2-pack@sha256:f0758996a931fb35d9ecb1de273c4d59dabe2a09b433afc7e357f65a08b7e1ff steps: - name: Checkout Site - uses: actions/checkout@v4 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Checkout Ddraig SSG - uses: actions/checkout@v4 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: repository: hyperpolymath/ddraig-ssg path: .ddraig-ssg @@ -42,7 +42,7 @@ jobs: fi ./.ddraig-ssg/build/exec/ddraig build src _site https://hyperpolymath.github.io/${GITHUB_REPOSITORY#*/} - name: Upload artifact - uses: actions/upload-pages-artifact@v3 + uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3.0.1 with: path: '_site' deploy: @@ -55,4 +55,4 @@ jobs: steps: - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v4 + uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5 diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index b67e3b14..0eab2e6f 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -33,4 +33,4 @@ jobs: permissions: security-events: write id-token: write - uses: hyperpolymath/standards/.github/workflows/scorecard-reusable.yml@d135b05bfc647d0c0fbfedc7e80f37ea50f49236 + uses: hyperpolymath/standards/.github/workflows/scorecard-reusable.yml@8813ecf2a841335c9dc14c75cc46694722cd6d28 From 57a11aa0eb2efc3015747478597ffd3a6c6dbb37 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Tue, 21 Jul 2026 13:57:56 +0100 Subject: [PATCH 2/2] fix(ci): SHA-pin the last unpinned action, in pages-deploy.yml `Deploy to Cloudflare Workers` fails on main with: The action actions/checkout@v4 is not allowed in hyperpolymath/boj-server because all actions must be pinned to a full-length commit SHA. This is GitHub's own `sha_pinning_required: true` repo policy, which was deliberately preserved when allowed_actions moved selected -> all. Unlike BROKEN-M1 it is a *correct* refusal: the action really was unpinned. Worth recording how it was found, because two linters missed it. Both the `Workflow security linter` and my local replication of it match `uses:` only at the start of a line (after indentation), so both see - name: Checkout uses: actions/checkout@v4 # caught but not the inline list-item form actually used here: - uses: actions/checkout@v4 # MISSED That single blind spot is why governance reported exactly 4 unpinned actions (all in pages.yml) while the repo in fact had 5, and why the scan undercounted `uses:` lines 66 vs the true 94. GitHub's policy engine caught what the linter could not. The upstream pattern in hyperpolymath/standards has the same gap and should be widened separately; this commit fixes the instance. Pinned to de0fac2e (v6.0.2), the same checkout every other workflow in this repo now uses. Verified with a corrected pattern matching BOTH forms: 0 of 94 `uses:` lines are unpinned. Not addressed here (no CI impact, flagged for follow-up): the deploy step runs `npx wrangler@latest`, which is an unpinned floating dependency in a job that holds CLOUDFLARE_API_TOKEN. --- .github/workflows/pages-deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pages-deploy.yml b/.github/workflows/pages-deploy.yml index 2a56b832..aa7b56da 100644 --- a/.github/workflows/pages-deploy.yml +++ b/.github/workflows/pages-deploy.yml @@ -18,7 +18,7 @@ jobs: deploy: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Deploy site/ to Cloudflare Workers (static assets) run: npx wrangler@latest deploy env: