From 58d216b0cf99af1f41d918ee907985b2ae35b42c Mon Sep 17 00:00:00 2001 From: bthornto Date: Thu, 13 Aug 2026 06:02:47 -0700 Subject: [PATCH 1/2] ci(sonar): resolve fork PR numbers by head OID in finalize workflow_run.pull_requests and commits/{sha}/pulls are empty for fork PR heads, so Sonar never re-analyzed those PRs. Fall back to matching an open PR by headRefOid. Co-authored-by: Cursor --- .github/workflows/finalize.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/finalize.yml b/.github/workflows/finalize.yml index 21bead22..e929b5a2 100644 --- a/.github/workflows/finalize.yml +++ b/.github/workflows/finalize.yml @@ -77,6 +77,15 @@ jobs: --jq '.[0].number // empty') fi + # Fork PR head SHAs are often missing from the commits/{sha}/pulls API + # and workflow_run.pull_requests. Match an open PR by head OID instead. + if [[ ! "${PR_NUMBER}" =~ ^[0-9]+$ ]]; then + PR_NUMBER=$(gh pr list --repo "${REPO}" --state open --limit 100 \ + --json number,headRefOid \ + --jq ".[] | select(.headRefOid == \"${HEAD_SHA}\") | .number" \ + | head -n1) + fi + if [[ ! "${PR_NUMBER}" =~ ^[0-9]+$ ]]; then echo "::error::Unable to resolve a trusted PR number for head SHA ${HEAD_SHA}" exit 1 From c8dca47130faef2eefcb17dc36817ff5f1397fad Mon Sep 17 00:00:00 2001 From: bthornto Date: Thu, 13 Aug 2026 06:14:32 -0700 Subject: [PATCH 2/2] ci(sonar): resolve fork PRs by head owner:branch and exact SHA Avoid listing open PRs with a limit/head -n1. Use the pulls API head filter from trusted workflow_run metadata and require exactly one OID match. Co-authored-by: Cursor --- .github/workflows/finalize.yml | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/.github/workflows/finalize.yml b/.github/workflows/finalize.yml index e929b5a2..83879901 100644 --- a/.github/workflows/finalize.yml +++ b/.github/workflows/finalize.yml @@ -64,6 +64,8 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} HEAD_SHA: ${{ github.event.workflow_run.head_sha }} + HEAD_BRANCH: ${{ github.event.workflow_run.head_branch }} + HEAD_REPOSITORY: ${{ github.event.workflow_run.head_repository.full_name }} REPO: ${{ github.repository }} # Trusted GitHub payload — not PR-controlled artifact content PR_NUMBER: ${{ github.event.workflow_run.pull_requests[0].number }} @@ -78,12 +80,24 @@ jobs: fi # Fork PR head SHAs are often missing from the commits/{sha}/pulls API - # and workflow_run.pull_requests. Match an open PR by head OID instead. + # and workflow_run.pull_requests. Resolve via trusted head owner:branch, + # then require an exact head OID match (fail if 0 or >1). if [[ ! "${PR_NUMBER}" =~ ^[0-9]+$ ]]; then - PR_NUMBER=$(gh pr list --repo "${REPO}" --state open --limit 100 \ - --json number,headRefOid \ - --jq ".[] | select(.headRefOid == \"${HEAD_SHA}\") | .number" \ - | head -n1) + if [[ -z "${HEAD_BRANCH}" || -z "${HEAD_REPOSITORY}" ]]; then + echo "::error::Missing workflow_run head_branch/head_repository for SHA ${HEAD_SHA}" + exit 1 + fi + HEAD_OWNER="${HEAD_REPOSITORY%%/*}" + MATCHES=$(gh api \ + -H "Accept: application/vnd.github+json" \ + "repos/${REPO}/pulls?state=open&head=${HEAD_OWNER}:${HEAD_BRANCH}" \ + --jq "[.[] | select(.head.sha == \"${HEAD_SHA}\") | .number]") + MATCH_COUNT=$(jq 'length' <<< "${MATCHES}") + if [[ "${MATCH_COUNT}" -ne 1 ]]; then + echo "::error::Expected exactly one open PR for ${HEAD_OWNER}:${HEAD_BRANCH}@${HEAD_SHA}, found ${MATCH_COUNT}: ${MATCHES}" + exit 1 + fi + PR_NUMBER=$(jq -r '.[0]' <<< "${MATCHES}") fi if [[ ! "${PR_NUMBER}" =~ ^[0-9]+$ ]]; then