From a5d7896f1bac24ff2439271dfa5cd09bd8defdf8 Mon Sep 17 00:00:00 2001 From: Neil <4138956+nwparker@users.noreply.github.com> Date: Sun, 31 May 2026 06:47:12 -0700 Subject: [PATCH] fix: use base ref details for review creation (#4169) --- .../useCreatePullRequestDialogFields.test.ts | 34 +++++++++++++++++++ .../useCreatePullRequestDialogFields.ts | 25 ++++++++++++-- 2 files changed, 56 insertions(+), 3 deletions(-) create mode 100644 src/renderer/src/components/right-sidebar/useCreatePullRequestDialogFields.test.ts diff --git a/src/renderer/src/components/right-sidebar/useCreatePullRequestDialogFields.test.ts b/src/renderer/src/components/right-sidebar/useCreatePullRequestDialogFields.test.ts new file mode 100644 index 00000000000..d1678f6c5cf --- /dev/null +++ b/src/renderer/src/components/right-sidebar/useCreatePullRequestDialogFields.test.ts @@ -0,0 +1,34 @@ +import { describe, expect, it } from 'vitest' +import { normalizeCreateReviewBaseSearchResults } from './useCreatePullRequestDialogFields' + +describe('normalizeCreateReviewBaseSearchResults', () => { + it('uses detailed local branch names for base refs from arbitrary remotes', () => { + expect( + normalizeCreateReviewBaseSearchResults([ + { + refName: 'mycorp-fork/main', + localBranchName: 'main' + } + ]) + ).toEqual(['main']) + }) + + it('dedupes equivalent base branches found on multiple remotes', () => { + expect( + normalizeCreateReviewBaseSearchResults([ + { + refName: 'origin/main', + localBranchName: 'main' + }, + { + refName: 'upstream/main', + localBranchName: 'main' + }, + { + refName: 'mycorp-fork/release/1.0', + localBranchName: 'release/1.0' + } + ]) + ).toEqual(['main', 'release/1.0']) + }) +}) diff --git a/src/renderer/src/components/right-sidebar/useCreatePullRequestDialogFields.ts b/src/renderer/src/components/right-sidebar/useCreatePullRequestDialogFields.ts index a508063d809..2f7c95eebc8 100644 --- a/src/renderer/src/components/right-sidebar/useCreatePullRequestDialogFields.ts +++ b/src/renderer/src/components/right-sidebar/useCreatePullRequestDialogFields.ts @@ -10,7 +10,7 @@ import { } from '@/runtime/runtime-git-client' import { getRuntimeRepoBaseRefDefault, - searchRuntimeRepoBaseRefs + searchRuntimeRepoBaseRefDetails } from '@/runtime/runtime-repo-client' import { isCustomAgentId, @@ -18,6 +18,7 @@ import { } from '../../../../shared/commit-message-agent-spec' import type { HostedReviewCreationEligibility } from '../../../../shared/hosted-review' import { normalizeHostedReviewBaseRef } from '../../../../shared/hosted-review-refs' +import type { BaseRefSearchResult } from '../../../../shared/types' import { DEFAULT_SOURCE_CONTROL_AI_PR_CREATION_DEFAULTS, normalizeSourceControlAiSettings @@ -71,6 +72,24 @@ export function stripBaseRef(ref: string): string { return normalizeHostedReviewBaseRef(ref) } +export function normalizeCreateReviewBaseSearchResults( + results: readonly BaseRefSearchResult[] +): string[] { + const seen = new Set() + const branches: string[] = [] + for (const result of results) { + // Why: hosted review APIs take branch names, while base search displays + // remote-qualified refs. Detailed search already resolves slashy remotes. + const branch = stripBaseRef((result.localBranchName || result.refName).trim()) + if (!branch || seen.has(branch)) { + continue + } + seen.add(branch) + branches.push(branch) + } + return branches +} + export function useCreatePullRequestDialogFields({ open, repoId, @@ -266,10 +285,10 @@ export function useCreatePullRequestDialogFields({ } let stale = false const timer = window.setTimeout(() => { - void searchRuntimeRepoBaseRefs(settings, repoId, baseQuery.trim(), 20) + void searchRuntimeRepoBaseRefDetails(settings, repoId, baseQuery.trim(), 20) .then((results) => { if (!stale) { - setBaseResults(results.map(stripBaseRef)) + setBaseResults(normalizeCreateReviewBaseSearchResults(results)) setBaseSearchError(null) } })