fix: fetch fork PR heads via refs/pull/N/head [LINBEE-28634] - #577
Conversation
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…in tests Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Orca Security Scan Summary
| Status | Check | Issues by priority | |
|---|---|---|---|
| Infrastructure as Code | View in Orca | ||
| OSS Licenses | View in Orca | ||
| SAST | View in Orca | ||
| Secrets | View in Orca | ||
| Vulnerabilities | View in Orca |
There was a problem hiding this comment.
✨ PR Review
The PR correctly solves the fork-PR-head 404 problem by switching from fetching the head branch via the upstream remote to fetching refs/pull/N/head from origin. The sanitisation of pull_request_number is clean and the tests cover both the populated and absent cases. One functional gap deserves attention: when the PR number is absent the resulting refspec is invalid and the fetch silently no-ops.
1 issues detected:
🐞 Bug - An empty `pull_request_number` produces the invalid refspec `refs/pull//head`, which git rejects; the failure is silently swallowed by the `|| echo` fallback, leaving the head branch unfetched and breaking all non-PR invocations. 🛠️
Details: When pull_request_number is empty (e.g. a push event, a workflow_dispatch, or any trigger that does not carry a PR number), the interpolated fetch command becomes:
git fetch … origin $'refs/pull//head:refs/remotes/upstream/<head_ref>'
Git rejects refs/pull//head as an invalid refspec, the command exits non-zero, and the || echo "::warning::" swallows the error. Because the upstream remote is now only ever added but never fetched, the subsequent git checkout -b upstream/<head_ref> upstream/<head_ref> silently fails (|| true), and the head commit is never present in the workspace.
The previous code fetched the head branch from upstream unconditionally, so non-PR invocations still worked.
File: action.yml (107-108)
🛠️ A suggested code correction is included in the review comments.
Generated by LinearB AI and added by gitStream.
AI-generated content may contain inaccuracies. Please verify before using.
💡 Tip: You can customize your AI Review using Guidelines Learn how
There was a problem hiding this comment.
Pull request overview
This PR updates the composite action’s PR head-fetch behavior to work for forked PRs by fetching the PR head ref from the base repository (refs/pull/<N>/head) rather than attempting to fetch from the fork using a base-repo installation token.
Changes:
- Expose
pull_request_numberas an output fromresolve-payload-fields.jsfor use in refspec construction. - Update
action.ymlto fetchrefs/pull/<N>/headfromoriginintorefs/remotes/upstream/<head_ref>so existing checkout logic continues to work. - Extend unit tests to include the new
pull_request_numberoutput.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| scripts/resolve-payload-fields.js | Adds pull_request_number step output for downstream git refspec usage. |
| action.yml | Switches head fetch to refs/pull/<N>/head on origin for fork PR compatibility. |
| tests/resolve-payload-fields.test.ts | Updates expectations to include pull_request_number. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.
Suppressed comments (2)
scripts/resolve-payload-fields.js:162
- The comment says this output is "Digits or ''", but
String(Number(payload.pullRequestNumber) || '')can produce non-digit strings (e.g.Infinity,NaNis handled, or a float like269.5). Since this value is spliced into a git refspec later, it should be strictly validated/normalized to a positive integer string.
// Digits or '': spliced into the fetch refspec without the safe-strings escaping step.
pull_request_number: String(Number(payload.pullRequestNumber) || ''),
action.yml:108
- When
pull_request_numberis empty (non-PR runs or if the payload omits it), this constructsrefs/pull//head:..., causing the fetch to fail and potentially leaving the repo on the base branch. Consider falling back to fetching${{ steps.safe-strings.outputs.head_ref }}fromupstreamwhen no PR number is available.
# refs/pull/N/head is mirrored on the base repo, so a fork PR head needs no fork access.
git fetch --shallow-since="6 months ago" origin $'refs/pull/${{ steps.payload-fields.outputs.pull_request_number }}/head:refs/remotes/upstream/${{ steps.safe-strings.outputs.head_ref }}' || echo "::warning::Failed to fetch head branch. The branch may have been deleted."
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
For a PR opened from a fork, the head branch was fetched from the fork itself with a base-org-scoped installation token, which 404s. GitHub mirrors every PR head under the base repo's own
refs/pull/N/head, so no fork access is needed.LINBEE-28634
action.yml: fetchrefs/pull/N/headfromoriginintorefs/remotes/upstream/<head_ref>, the ref the following checkout lines already consumeresolve-payload-fields.js: exposepull_request_number(digits or empty, safe to splice into the refspec)Validated end to end on a private fork PR and on a same-repo PR: both land on the head sha, all checks green.
✨ PR Description
Purpose: Update the GitHub Action to fetch fork PR heads using mirrored refs on the origin repository.
Main changes:
toStepOutputsto validate and exportpull_request_numberfrom the payloadaction.ymlto fetchrefs/pull/N/headfrom origin instead of fetching from upstreampull_request_numbermapping and positive integer validationChangelog
🐞 Fixes
Generated by LinearB AI and added by gitStream.
AI-generated content may contain inaccuracies. Please verify before using.
💡 Tip: You can customize your AI Description using Guidelines Learn how