diff --git a/.github/workflows/ui-preview-deploy.yml b/.github/workflows/ui-preview-deploy.yml index abd46ae96a..5414420b68 100644 --- a/.github/workflows/ui-preview-deploy.yml +++ b/.github/workflows/ui-preview-deploy.yml @@ -24,6 +24,7 @@ permissions: contents: read actions: read # download the build artifact from the triggering run deployments: write # record the preview Deployment Reviewbot reads + pull-requests: read # resolve the (often fork) PR for this build by matching head SHA concurrency: group: ui-preview-deploy-${{ github.event.workflow_run.head_sha }} @@ -187,16 +188,31 @@ jobs: const url = ${{ toJSON(steps.upload.outputs.preview_url) }}; // Trust only the GitHub-set head_sha — never fork-supplied data. const sha = context.payload.workflow_run.head_sha; - // Resolve the PR from the head commit. workflow_run.pull_requests is EMPTY for fork PRs, - // so look it up from the commit (the base repo holds the fork head as refs/pull/N/head). - const assoc = await github.rest.repos.listPullRequestsAssociatedWithCommit({ - owner: context.repo.owner, - repo: context.repo.repo, - commit_sha: sha, - }); const slug = `${context.repo.owner}/${context.repo.repo}`; - const open = assoc.data.find((p) => p.state === "open" && p.base.repo.full_name === slug); - const prNumber = open?.number ?? context.payload.workflow_run.pull_requests?.[0]?.number; + // Resolve the PR for this build. Both signals below are EMPTY for fork PRs (the common case + // here): workflow_run.pull_requests is empty for cross-repo runs, and the commit→PR + // association API doesn't index a fork-head commit from the base repo. So we ALSO match the + // open PR whose head points at this exact build SHA — head.sha is GitHub-set (the base repo + // tracks the fork head as refs/pull/N/head), so it's safe to trust even for forks. + let prNumber = context.payload.workflow_run.pull_requests?.[0]?.number; + if (!prNumber) { + const assoc = await github.rest.repos.listPullRequestsAssociatedWithCommit({ + owner: context.repo.owner, + repo: context.repo.repo, + commit_sha: sha, + }); + prNumber = assoc.data.find((p) => p.state === "open" && p.base.repo.full_name === slug)?.number; + } + if (!prNumber) { + // Fork-safe fallback: scan open PRs for the one whose head is this build's commit. + const openPrs = await github.paginate(github.rest.pulls.list, { + owner: context.repo.owner, + repo: context.repo.repo, + state: "open", + per_page: 100, + }); + prNumber = openPrs.find((p) => p.head.sha === sha)?.number; + } if (!prNumber) { core.setFailed(`Could not resolve an open PR for ${sha} — skipping deployment record.`); return;