Skip to content

fix(github): stop feature branches from borrowing unrelated PRs - #27332

Merged
nwparker merged 5 commits into
mainfrom
nwparker/fix-pr-upstream-identity
Oct 11, 2026
Merged

nwparker merged 5 commits into
mainfrom
nwparker/fix-pr-upstream-identity

Conversation

@nwparker

@nwparker nwparker commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor
Files Added Deleted Net
Test 11 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​830 $\color{#cf222e}{\Huge{\mathbf{−}}}$​19 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​811
Prod 12 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​419 $\color{#cf222e}{\Huge{\mathbf{−}}}$​171 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​248

ELI5

A new feature branch should show its own PR, not a release PR belonging to the branch it started from. Old incorrect links should also clear after a refresh.

What Changed

Before, a feature branch tracking origin/develop could show an unrelated develop-to-release PR, including its checks and actions. The incorrect link could survive restarts, and a merged PR could remain cached just because its commit matched the new branch.

The shared lookup now checks each PR's actual head repository and GitHub server, then compares the head branch with that repository's own default. It rejects inferred integration PRs while preserving fork PRs, renamed local branches, explicit links, and detached checkouts. Rejections include the repository and server, so identical PR numbers in different repositories cannot suppress each other. Candidate probing continues after a rejected result.

An optional refresh-result field identifies rejected PR URLs so both renderer caches clear that exact link, even at its merged commit. Manual and background refreshes now share one cache-update implementation. Remote-default caches also refresh after repository invalidation or SSH provider replacement.

Why

Removing upstream discovery would break renamed branches and contributor checkouts; matching only a branch name would hide legitimate fork PRs. Full repository identity distinguishes these cases. Filtering each candidate lets cached-number recovery continue to a valid PR instead of stopping at an unrelated one. Explicit rejection lets the renderer heal an old incorrect link while retaining its existing preservation of legitimate merged PRs.

Default resolution reuses PR metadata and the existing host-owned Git runner, bounded cache, and concurrent-probe handling. An unknown upstream default does not borrow another repository's origin default. When removed tracking leaves a cached PR without a matching remote, one targeted REST lookup reads that PR head repository's own default; unavailable or inconsistent metadata preserves the existing PR.

Linked Issue

Fixes #26948

Visual Proof

N/A — this changes review-data selection and cache invalidation; no rendered components or interaction controls changed. Automated regressions cover manual and background refreshes, both caches, and persisted removal of the incorrect link.

Testing

  • I manually tested these changes locally
  • Automated tests added/updated, or explained why not below

On macOS, manually verified the reported Git branch/upstream setup in a temporary repository. All tests and builds used background-launch mode.

  • GitHub, source-control, relevant IPC routing, renderer PR/hosted-review caches, and response compatibility: 154 files, 1,534 tests passed.
  • Real Git compatibility suite with Apple Git 2.50.1: 30 tests passed. Used TMPDIR=/private/tmp for the existing registration test's macOS temporary-directory symlink assumption.
  • Node and web typechecks, changed-code quality gate, focused lint, formatting, and Electron build passed.

The adversarial review reproduced and fixed eight edge cases: rejection collisions between repository-local PR numbers; recovery stopping at the first invalid repository; stale defaults after SSH provider replacement or repository invalidation; accepting a head from a different repository or GitHub server; preserving a rejected merged integration PR at the current worktree commit; and retaining an integration PR from a different repository after upstream tracking was removed. Regression fixtures route responses by server, repository, and PR number.

Additional coverage protects fork heads with different repository names, different remote defaults, cached feature-PR recovery, removed upstream tracking, missing metadata/remote HEADs, explicit links, detached checkouts, concurrent probes, WSL/SSH separation, and disconnected SSH without local fallback. The real-Git contract covers remote-specific HEAD resolution in the existing Git 2.25.5 / 2.38.1 / 2.49.1 CI matrix. Windows and live SSH were not manually exercised.

Review

Reviewed repository/server identity, rejection and persistence, concurrent refresh ownership, remote cache invalidation, failure behavior, and platform routing. No blocking findings remain in this review. Provider-specific PR matching stays within the GitHub client; the existing source-control resolver owns native, WSL, and SSH Git execution.

The optional no-PR response field preserves mixed-version operation: older clients ignore it and newer clients still accept responses from older hosts. No RPC parameters or stream opcodes change. Head-repository metadata is requested in existing GitHub calls, with no added repository-wide scans. The existing linked-merged-PR divergence check was extracted without changing its behavior.

Agent skill upstream boundary

  • Not applicable, or this change copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.

Notes

Credit to @petersindex for the diagnosis, initial fix, and remote-specific default resolution in #27180. Both original commits retain their authorship, and both follow-up fixes explicitly include Co-authored-by: petersindex <287557875+petersindex@users.noreply.github.com>.

Checklist

  • This PR is focused on correct PR selection and cache recovery
  • I explained what changed and why (ELI5, the user-facing before/after, the mechanism, and why over the alternatives)
  • Before/after screenshots or videos attached for UI changes, or N/A with reason
  • Self-reviewed for correctness, security, and performance
  • Cross-platform, SSH/remote, and path/shortcut impact considered (or N/A)
  • Relevant lint, typechecks, tests, and Electron build pass locally; CI covers the full repository and platform matrix

petersindex and others added 3 commits October 10, 2026 16:08
…acks

A branch made with `git switch -c feature/x origin/develop` tracks the
default branch. When its own PR lookup missed, the tracked-upstream fallback
attached the newest PR whose head is `develop` (an unrelated develop to
release PR) and cached its number, so the wrong link survived restarts.

Drop a match headed by the tracked upstream when that upstream is the default
branch of a repo PRs target. The check runs only after such a match, so normal
polling adds no git calls, and it also heals numbers cached before the fix.

Fixes #26948
… branch

A fork's upstream remote can default to a different branch than origin.
Read refs/remotes/<remote>/HEAD for the tracked remote and fall back to
origin's default only when git never recorded it. Reuses the default-branch
resolver's host routing and cache.
@coderabbitai

coderabbitai Bot commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 9af25450-8d2e-4ce6-b99f-1fba96ab2137


📥 Commits

Reviewing files that changed from the base of the PR and between c7ecf23 and 15b9996.



📒 Files selected for processing (15)
  • src/main/github/client-tracked-upstream-default-branch.test.ts
  • src/main/github/client/lookup/branch-lookup-resolution.ts
  • src/main/github/client/lookup/implicit-default-branch-pr.ts
  • src/main/github/client/lookup/pr-branch-lookup.ts
  • src/main/github/client/lookup/pr-number-lookup.ts
  • src/main/github/client/lookup/pull-request-lookup-data.ts
  • src/main/source-control/repo-default-branch.test.ts
  • src/main/source-control/repo-default-branch.ts
  • src/main/source-control/repo-remote-head-branch.test.ts
  • src/renderer/src/store/github/pr-result-cache.ts
  • src/renderer/src/store/github/pull-request-execution.ts
  • src/renderer/src/store/github/refresh-event-actions.ts
  • src/renderer/src/store/slices/github-pr-rejected-cache.test.ts
  • src/shared/github/pull-request-for-branch-outcome.test.ts
  • src/shared/github/pull-request-refresh-types.ts


Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 5 remain after this review.




📝 Walkthrough
📝 Walkthrough

Walkthrough

The change adds remote-specific Git HEAD branch resolution with shared caching and transport handling. Pull-request lookup data now includes head repository and default-branch metadata. Branch lookup uses that metadata and remote branch information to filter implicit default-branch PR matches, including after fallback-number lookup. No-PR outcomes can carry rejected PR URLs, which refresh paths pass to cache updates. Tests cover remote HEAD resolution, tracked-upstream filtering, cache handling, and pull-request query fields.



Priority: ➖ Normal

Severity of issue fixed: Medium

Merge Risk: 🔵 Low · up to 15b99

When GitHub cannot provide enough PR metadata, an unrelated cached PR may remain visible. The risk is bounded and can be accepted with awareness or addressed before merging.

Pre-merge checks | Passed 4 | Failed 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 22.58% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 31 functions across 23 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check Passed Issue #26948 requires rejection of an unrelated PR found through tracked-upstream lookup and prevention of incorrect cached-PR reuse. The PR adds repository/server identity checks, default-branch matc…
Out of Scope Changes check Passed The changes stay within issue #26948. Remote-specific default-branch resolution and head-repository metadata support the required PR rejection and fork handling. Cache-update refactoring, IPC compatib…
Title check Passed The title clearly and concisely identifies the main change: preventing feature branches from selecting unrelated pull requests.
Description check Passed The description is complete and closely follows the required template. It explains the user impact, implementation, rationale, linked issue, testing, review scope, platform considerations, and checkli…

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR




  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 872d82e9-7a0f-4c0c-9f8c-4b68a1df38ad
📥 Commits

Reviewing files that changed from the base of the PR and between a09dc9a and c7ecf23.

📒 Files selected for processing (14)
  • src/main/github/client-merge-queue-auto-merge.test.ts
  • src/main/github/client-pr-branch-discovery.test.ts
  • src/main/github/client-pr-fallback-number.test.ts
  • src/main/github/client-pr-linked-lookup.test.ts
  • src/main/github/client-tracked-upstream-default-branch.test.ts
  • src/main/github/client-tracked-upstream-fork-owner.test.ts
  • src/main/github/client-tracked-upstream-snapshot.test.ts
  • src/main/github/client/lookup/branch-lookup-resolution.ts
  • src/main/github/client/lookup/implicit-default-branch-pr.ts
  • src/main/github/client/lookup/pull-request-lookup-data.ts
  • src/main/source-control/repo-default-branch.ts
  • src/main/source-control/repo-remote-head-branch.test.ts
  • src/shared/git-default-base-ref.ts
  • src/shared/git-resolution-binary-compatibility.test-cases.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 0 remain after this review.

Comment thread src/main/github/client/lookup/implicit-default-branch-pr.ts
nwparker and others added 2 commits October 10, 2026 16:43
Apply the default-branch policy while probing each repository, so an
integration PR cannot preempt a valid result or suppress the same number
in another repository. Check branch heads by repository and server.

Invalidate remote defaults when their review scope or SSH provider changes.
Report rejected PR URLs through an optional refresh-result field, so merged
integration PRs clear from both caches even at the current worktree head.
Share the manual and coordinator cache update implementation.

Co-authored-by: petersindex <287557875+petersindex@users.noreply.github.com>
Use the existing REST PR mapping to read the head repository's default
branch when no tracked remote or origin can identify it. Require matching
repository and head metadata, and preserve the PR if the lookup fails.

This clears both closed and merged integration PRs cached by a fork
checkout after its upstream tracking is removed.

Co-authored-by: petersindex <287557875+petersindex@users.noreply.github.com>
@nwparker
nwparker merged commit 884575a into main Oct 11, 2026
31 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Workspace links an unrelated closed PR when its branch tracks the base branch

2 participants