Skip to content

Commit 8dc2bf0

Browse files
fix(ci): checkout the event SHA in governance jobs (re-enable PR-time enforcement) (#442)
## Summary Fixes the estate-wide governance failure where **8 of 10 jobs in `governance-reusable.yml` die at checkout on every PR** with: ``` fatal: couldn't find remote ref refs/pull/<n>/merge ``` (This is the `refs/pull/<n>/merge` item flagged as out-of-scope in #441 — now resolved with owner approval.) ## Root cause `governance.yml` triggers on `pull_request` and calls `governance-reusable.yml` via `workflow_call`. Inside a **reusable** workflow, `github.ref` inherits the caller's PR ref, which on a `pull_request` event is the *named merge ref* `refs/pull/<n>/merge`. The 8 jobs that pass `ref: ${{ github.ref }}` to `actions/checkout` therefore ask it to `git fetch refs/pull/<n>/merge` — a named ref checkout cannot resolve — and fail at the checkout step. The two jobs that **omit** an explicit `ref:` (`workflow-staleness`, `validate-hypatia-baseline`) use checkout's default and were unaffected — exactly matching the observed **8/10**. **Consequence today:** governance is effectively **ungated on PRs** — only `push`-to-`main` runs enforce. ## Fix Pin the 8 caller-repo checkouts to **`ref: ${{ github.sha }}`** — the concrete event commit (the PR merge commit on `pull_request`, the pushed commit on `push`). It resolves to the *same* commit `refs/pull/<n>/merge` points at, but is always fetchable. A short comment at each site explains why `github.ref` must not be used here. - Affected jobs: `language-policy`, `package-policy`, `security-policy`, `quality`, `wellknown`, `workflow-lint`, `trusted-base`, `licence-consistency`. - The 3 secondary `repository: hyperpolymath/standards` + `ref: main` checkouts (which fetch the check scripts) are **untouched**. - Content/enforcement semantics are preserved: the diff-based step (`quality`'s trufflehog) already uses explicit `github.sha` / `github.event.pull_request.base.sha`, independent of the checkout ref. ## Blast radius (owner-acknowledged) This **re-enables PR-time governance enforcement across every repo** consuming the reusable workflow. PRs that were silently passing (because the jobs never ran) may now surface real governance violations. Approved by owner 2026-06-27. ## Verification - `python3 -c "import yaml; yaml.safe_load(...)"` → **YAML OK**. - Structural check: 13 checkout steps total — 2 bare (unchanged), 8 now `ref: ${{ github.sha }}`, 3 standards-checkout `ref: main` (unchanged). No `ref: ${{ github.ref }}` remains. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- _Generated by [Claude Code](https://claude.ai/code/session_01MJdfXv5E5gwGD2yaJq8jRM)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent e9c8888 commit 8dc2bf0

1 file changed

Lines changed: 72 additions & 8 deletions

File tree

.github/workflows/governance-reusable.yml

Lines changed: 72 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,15 @@ jobs:
128128
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
129129
with:
130130
repository: ${{ github.repository }}
131-
ref: ${{ github.ref }}
131+
# Pin to the concrete event SHA (the PR merge commit on
132+
# pull_request, the pushed commit on push). Do NOT use
133+
# `ref: ${{ github.ref }}`: in a reusable workflow called from a
134+
# pull_request, github.ref is the named merge ref
135+
# `refs/pull/<n>/merge`, which actions/checkout cannot fetch
136+
# ("couldn't find remote ref refs/pull/<n>/merge") — it broke 8/10
137+
# governance jobs on every PR estate-wide. github.sha resolves to the
138+
# same merge commit but is always fetchable.
139+
ref: ${{ github.sha }}
132140

133141
# Estate language policy bans Python with no exceptions (CLAUDE.md
134142
# Language Policy; SaltStack exception removed 2026-01-03). The
@@ -464,7 +472,15 @@ jobs:
464472
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
465473
with:
466474
repository: ${{ github.repository }}
467-
ref: ${{ github.ref }}
475+
# Pin to the concrete event SHA (the PR merge commit on
476+
# pull_request, the pushed commit on push). Do NOT use
477+
# `ref: ${{ github.ref }}`: in a reusable workflow called from a
478+
# pull_request, github.ref is the named merge ref
479+
# `refs/pull/<n>/merge`, which actions/checkout cannot fetch
480+
# ("couldn't find remote ref refs/pull/<n>/merge") — it broke 8/10
481+
# governance jobs on every PR estate-wide. github.sha resolves to the
482+
# same merge commit but is always fetchable.
483+
ref: ${{ github.sha }}
468484
- name: Enforce Guix primary / Nix fallback
469485
run: |
470486
HAS_GUIX=$(find . -name "*.scm" -o -name ".guix-channel" -o -name "guix.scm" 2>/dev/null | head -1)
@@ -492,7 +508,15 @@ jobs:
492508
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
493509
with:
494510
repository: ${{ github.repository }}
495-
ref: ${{ github.ref }}
511+
# Pin to the concrete event SHA (the PR merge commit on
512+
# pull_request, the pushed commit on push). Do NOT use
513+
# `ref: ${{ github.ref }}`: in a reusable workflow called from a
514+
# pull_request, github.ref is the named merge ref
515+
# `refs/pull/<n>/merge`, which actions/checkout cannot fetch
516+
# ("couldn't find remote ref refs/pull/<n>/merge") — it broke 8/10
517+
# governance jobs on every PR estate-wide. github.sha resolves to the
518+
# same merge commit but is always fetchable.
519+
ref: ${{ github.sha }}
496520
- name: Security checks
497521
run: |
498522
FAILED=false
@@ -723,7 +747,15 @@ jobs:
723747
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
724748
with:
725749
repository: ${{ github.repository }}
726-
ref: ${{ github.ref }}
750+
# Pin to the concrete event SHA (the PR merge commit on
751+
# pull_request, the pushed commit on push). Do NOT use
752+
# `ref: ${{ github.ref }}`: in a reusable workflow called from a
753+
# pull_request, github.ref is the named merge ref
754+
# `refs/pull/<n>/merge`, which actions/checkout cannot fetch
755+
# ("couldn't find remote ref refs/pull/<n>/merge") — it broke 8/10
756+
# governance jobs on every PR estate-wide. github.sha resolves to the
757+
# same merge commit but is always fetchable.
758+
ref: ${{ github.sha }}
727759
- name: Check file permissions
728760
run: |
729761
find . -type f -perm /111 -name "*.sh" | head -10 || true
@@ -772,7 +804,15 @@ jobs:
772804
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
773805
with:
774806
repository: ${{ github.repository }}
775-
ref: ${{ github.ref }}
807+
# Pin to the concrete event SHA (the PR merge commit on
808+
# pull_request, the pushed commit on push). Do NOT use
809+
# `ref: ${{ github.ref }}`: in a reusable workflow called from a
810+
# pull_request, github.ref is the named merge ref
811+
# `refs/pull/<n>/merge`, which actions/checkout cannot fetch
812+
# ("couldn't find remote ref refs/pull/<n>/merge") — it broke 8/10
813+
# governance jobs on every PR estate-wide. github.sha resolves to the
814+
# same merge commit but is always fetchable.
815+
ref: ${{ github.sha }}
776816
- name: RFC 9116 security.txt validation
777817
run: |
778818
SECTXT=""
@@ -830,7 +870,15 @@ jobs:
830870
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
831871
with:
832872
repository: ${{ github.repository }}
833-
ref: ${{ github.ref }}
873+
# Pin to the concrete event SHA (the PR merge commit on
874+
# pull_request, the pushed commit on push). Do NOT use
875+
# `ref: ${{ github.ref }}`: in a reusable workflow called from a
876+
# pull_request, github.ref is the named merge ref
877+
# `refs/pull/<n>/merge`, which actions/checkout cannot fetch
878+
# ("couldn't find remote ref refs/pull/<n>/merge") — it broke 8/10
879+
# governance jobs on every PR estate-wide. github.sha resolves to the
880+
# same merge commit but is always fetchable.
881+
ref: ${{ github.sha }}
834882
- name: Check SPDX headers + permissions
835883
run: |
836884
failed=0
@@ -874,7 +922,15 @@ jobs:
874922
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
875923
with:
876924
repository: ${{ github.repository }}
877-
ref: ${{ github.ref }}
925+
# Pin to the concrete event SHA (the PR merge commit on
926+
# pull_request, the pushed commit on push). Do NOT use
927+
# `ref: ${{ github.ref }}`: in a reusable workflow called from a
928+
# pull_request, github.ref is the named merge ref
929+
# `refs/pull/<n>/merge`, which actions/checkout cannot fetch
930+
# ("couldn't find remote ref refs/pull/<n>/merge") — it broke 8/10
931+
# governance jobs on every PR estate-wide. github.sha resolves to the
932+
# same merge commit but is always fetchable.
933+
ref: ${{ github.sha }}
878934
path: caller
879935
- name: Checkout standards (for the check script)
880936
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
@@ -897,7 +953,15 @@ jobs:
897953
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
898954
with:
899955
repository: ${{ github.repository }}
900-
ref: ${{ github.ref }}
956+
# Pin to the concrete event SHA (the PR merge commit on
957+
# pull_request, the pushed commit on push). Do NOT use
958+
# `ref: ${{ github.ref }}`: in a reusable workflow called from a
959+
# pull_request, github.ref is the named merge ref
960+
# `refs/pull/<n>/merge`, which actions/checkout cannot fetch
961+
# ("couldn't find remote ref refs/pull/<n>/merge") — it broke 8/10
962+
# governance jobs on every PR estate-wide. github.sha resolves to the
963+
# same merge commit but is always fetchable.
964+
ref: ${{ github.sha }}
901965
path: caller
902966
- name: Checkout standards (for the check script)
903967
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0

0 commit comments

Comments
 (0)