diff --git a/.github/workflows/pr-policy.yml b/.github/workflows/pr-policy.yml index 5a0d5965..13cdb358 100644 --- a/.github/workflows/pr-policy.yml +++ b/.github/workflows/pr-policy.yml @@ -25,14 +25,14 @@ jobs: 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. + # base SHA that triggered this policy run so reruns are deterministic and + # cannot pick up a newer main-branch policy than the workflow event. 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.event.pull_request.base.sha }} persist-credentials: false - name: Validate pull request evidence diff --git a/scripts/pr-policy.mjs b/scripts/pr-policy.mjs index c26e0e8e..c02736b3 100644 --- a/scripts/pr-policy.mjs +++ b/scripts/pr-policy.mjs @@ -257,6 +257,17 @@ 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\.event\.pull_request\.base\.sha\s*\}\}/, + "PR policy workflow must checkout the event base SHA, not a moving branch ref.", + ); + assert.doesNotMatch( + workflow, + /ref:\s*\$\{\{\s*github\.base_ref\s*\}\}/, + "PR policy workflow must not checkout the moving base branch ref.", + ); console.error("[pr-policy] self-test passed"); }