From b435a85a4bc3568dfabb12af35cd7d6ccafe42c0 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sat, 18 Jul 2026 16:06:29 +0000 Subject: [PATCH] fix(ci): checkout PR policy from github.workflow_sha Use the workflow revision for pull_request_target policy checkout so reruns stay deterministic without pinning stale pull_request.base.sha trees that can miss scripts/pr-policy.mjs on older PRs. Co-authored-by: BigSimmo --- .github/workflows/pr-policy.yml | 11 ++++++----- scripts/pr-policy.mjs | 16 ++++++++++++++++ 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pr-policy.yml b/.github/workflows/pr-policy.yml index 5a0d59652..1322bdcc7 100644 --- a/.github/workflows/pr-policy.yml +++ b/.github/workflows/pr-policy.yml @@ -24,15 +24,16 @@ jobs: if: github.event_name == 'merge_group' run: echo "PR metadata was validated before merge-queue entry." - # pull_request_target runs trusted base-branch code. Checkout the current - # tip of the base branch (not a potentially stale base.sha) so the policy - # script is always available even when the PR was opened before the script - # was added to main. Never execute the PR head or persist credentials. + # pull_request_target runs trusted workflow-revision code. Checkout + # github.workflow_sha (not a moving base_ref tip, and not a potentially + # stale pull_request.base.sha from an older PR) so the policy script is + # always the exact revision that triggered this run. Never execute the PR + # head or persist credentials. - name: Checkout trusted policy if: github.event_name == 'pull_request_target' uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: - ref: ${{ github.base_ref }} + ref: ${{ github.workflow_sha }} persist-credentials: false - name: Validate pull request evidence diff --git a/scripts/pr-policy.mjs b/scripts/pr-policy.mjs index c26e0e8ea..26d1f5130 100644 --- a/scripts/pr-policy.mjs +++ b/scripts/pr-policy.mjs @@ -257,6 +257,22 @@ function selfTest() { const template = readFileSync(new URL("../.github/pull_request_template.md", import.meta.url), "utf8"); for (const item of requiredClinicalGovernanceItems) assert.match(template, new RegExp(`- \\[ \\] ${item.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`)); + const workflow = readFileSync(new URL("../.github/workflows/pr-policy.yml", import.meta.url), "utf8"); + assert.match( + workflow, + /ref:\s*\$\{\{\s*github\.workflow_sha\s*\}\}/, + "PR policy workflow must checkout github.workflow_sha for a deterministic trusted tree.", + ); + assert.doesNotMatch( + workflow, + /ref:\s*\$\{\{\s*github\.base_ref\s*\}\}/, + "PR policy workflow must not checkout the moving base branch ref.", + ); + assert.doesNotMatch( + workflow, + /ref:\s*\$\{\{\s*github\.event\.pull_request\.base\.sha\s*\}\}/, + "PR policy workflow must not checkout a potentially stale pull_request.base.sha.", + ); console.error("[pr-policy] self-test passed"); }