Repository navigation
Load PR details in forked repositories - #7513
brennanb2025 wants to merge 4 commits into
Conversation
getOwnerRepo previously only checked origin, causing all PR operations (viewing, commenting, merging, checks, etc.) to fail in fork repos where the PR actually lives in the upstream canonical repo. Change getOwnerRepo to resolve upstream-first (matching the pre-existing getIssueOwnerRepo behaviour), and add getOriginOwnerRepo for the two callers that specifically need the fork origin remote: - createGitHubPullRequest (head repo is the fork) - getRepoUpstream (fork detection) getIssueOwnerRepo is kept as a backwards-compatible alias. Fixes #7331 Co-Authored-By: Claude <noreply@anthropic.com>
resolvePrWorkItemSource resolved the raw origin candidate via getOwnerRepo, which is now upstream-first. For fork repos that collapsed originCandidate onto upstreamCandidate, hiding the issue-source selector in the renderer. Resolve it via getOriginOwnerRepo so the raw origin remote is preserved, and refresh two comments that still claimed PR lookups target origin. Co-Authored-By: Claude <noreply@anthropic.com> Co-authored-by: Orca <help@stably.ai>
The fork toggle regression fix (originCandidate must resolve via the raw origin remote, not upstream-first getOwnerRepo) had no pinning coverage: the client tests aliased getOriginOwnerRepo to the same vi.fn as getOwnerRepo, so reverting the fix left every test green. gh-utils' cache-separation test also mocked identical origin/upstream values, so a cache-key mixing regression would pass undetected. - Give getOriginOwnerRepo a dedicated mock in client-issue-source.test.ts and client-work-items.test.ts, delegating to getOwnerRepoMock by default so existing origin-candidate setups keep working unchanged. - Add a regression test asserting originCandidate resolves via raw origin and differs from upstreamCandidate; verified it fails when the originCandidate fix is reverted. - Restore real origin-vs-upstream cache separation coverage in gh-utils.test.ts with distinct values and direct getOriginOwnerRepo coverage. Co-Authored-By: Claude <noreply@anthropic.com> Co-authored-by: Orca <help@stably.ai>
Round-2 review follow-ups on the branch's own test edits: - gh-utils WSL cache-separation test used a non-matching "not found" error, so the upstream miss took the transient (uncached) path and the "cached hit" call silently re-probed; the git-process count pin had also been dropped. Use the real "No such remote" wording so the stable negative-cache path is exercised, and restore toHaveBeenCalledTimes(4) to guard against git-spawn churn. - Reset getOriginOwnerRepoMock in client.test.ts beforeEach blocks so a stale queued once-value cannot leak between getRepoUpstream tests. Co-Authored-By: Claude <noreply@anthropic.com> Co-authored-by: Orca <help@stably.ai>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (9)
📝 WalkthroughWalkthroughThis PR introduces a new Changes
Related PRs: None identified. Suggested labels: area:github, refactor, tests Suggested reviewers: Reviewer with GitHub client and remote-resolution expertise.
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…#9384) On a fork checkout (origin=fork, upstream=parent) PR details failed to load because getOwnerRepo() resolved only the origin remote while GitHub PRs live on the upstream parent. Make getOwnerRepo() prefer upstream (mirroring getIssueOwnerRepo), and pin the call sites that genuinely need the checkout's own origin identity (getRepoSlug, getRepoUpstream, createGitHubPullRequest, resolvePrWorkItemSource) to the origin-only primitive. Lands the fix community-identified in #7332 and hardened in #7513. Closes #7331 Co-authored-by: fsdwen <1214772+fsdwen@users.noreply.github.com> Co-authored-by: brennanb2025 <79079362+brennanb2025@users.noreply.github.com>
|
Thanks @brennanb2025 for hardening the community fix with the extra test coverage. The upstream-first change landed on main in #9384 (commit 4930c87), rebased against current main with the call-site audit (one behavioral difference from this branch: |
…stablyai#9384) On a fork checkout (origin=fork, upstream=parent) PR details failed to load because getOwnerRepo() resolved only the origin remote while GitHub PRs live on the upstream parent. Make getOwnerRepo() prefer upstream (mirroring getIssueOwnerRepo), and pin the call sites that genuinely need the checkout's own origin identity (getRepoSlug, getRepoUpstream, createGitHubPullRequest, resolvePrWorkItemSource) to the origin-only primitive. Lands the fix community-identified in stablyai#7332 and hardened in stablyai#7513. Closes stablyai#7331 Co-authored-by: fsdwen <1214772+fsdwen@users.noreply.github.com> Co-authored-by: brennanb2025 <79079362+brennanb2025@users.noreply.github.com>
What changes
PR details now load in forked repositories. Previously, opening a PR in a repo where
originpoints to a fork andupstreampoints to the canonical repo showed "Unable to load details for this GitHub item."Root cause:
getOwnerRepo()resolved only theoriginremote, so PR lookups queried the fork (where the PR does not exist) instead ofupstream(where fork-contribution PRs live). Issue lookups already resolvedupstream-first, which is why issues worked but PRs did not.This builds on and hardens community PR #7332 (by @fsdwen) — that PR is left open and unmodified; this one carries its commit plus review fixes so it can be considered as a reviewed, test-hardened unit.
Approach
getOwnerRepo()now resolvesupstream-first and falls back toorigin, matching the existinggetIssueOwnerRepo()behavior. All ~20 PR-detail call sites that usegetOwnerRepo()benefit automatically.getOriginOwnerRepo()for the callers that genuinely need the fork'sorigin:createGitHubPullRequest(head repo is the fork),getRepoUpstream(fork detection), andresolvePrWorkItemSource(raw origin candidate).getIssueOwnerRepo()retained as a backwards-compatible alias.Takeover review — what was wrong and what this fixes
The original PR switched only two callers to the origin-specific resolver and missed one, plus left stale comments and thin test coverage. This PR adds:
resolvePrWorkItemSourceresolved itsoriginCandidatevia the now-upstream-firstgetOwnerRepo. For a fork that collapsedoriginCandidate === upstreamCandidate, and the renderer's fork detection (!sameGitHubOwnerRepo(originCandidate, upstreamCandidate)) then hid the issue-source (origin/upstream) selector on fork repos. Now resolved viagetOriginOwnerRepo, preserving the type contract thatoriginCandidateis the raworiginremote.work-item-details.ts,client.ts) that still claimed PR lookups targetorigin.getOriginOwnerRepoa dedicated mock (distinct fromgetOwnerRepo) plus a regression test that fails if theoriginCandidatefix is reverted; distinct origin/upstream values in the cache-separation test; realistic missing-remote error wording so the negative-cache path is exercised and the git-spawn-count guard restored; andgetOriginOwnerRepoMockresets.Completeness & headline behavior
gh:workItemDetails) actually uses.Known tradeoff (conscious decision for the reviewer)
The
upstream-first flip is a global heuristic. It fixes the common fork-contribution case (PR lives onupstream) but introduces a mirror-image edge case: because the details dialog re-derives a PR's repo by number, a fork-internal PR whose number also exists onupstreamwould now resolve to the upstream item. The root-cause-correct fix is to thread the already-known PR owner/repo through the details IPC + runtime RPC + detail helpers so PR details never re-guess by number — a cross-cutting change beyond this bug fix. Net effect here is still positive (common case fixed, rare collision regressed). Flagging so this is merged as a conscious decision; theprRepo-threading follow-up can be tracked separately.Validation
npx vitest run src/main/github→ 296 passed (22 files; +1 regression test).npx tsgo --noEmit -p config/tsconfig.node.json→ clean.upstreamprobe is bounded by the existing per-runtime/path/remote owner-repo cache (30s positive / 5min negative TTL) with in-flight coalescing, so non-fork repos add negligible git churn.connectionId/localGitOptionsplumbing (unchanged); GitLab/other providers are untouched (GitHub-remote-resolution only).Not merged.
Fixes #7331
🤖 Generated with Claude Code
Made with Orca 🐋