From 3548685fda6ed11e6246a3e7c22308dfeb9565b3 Mon Sep 17 00:00:00 2001 From: Serhii Vecherenko Date: Fri, 24 Jul 2026 09:51:46 -0700 Subject: [PATCH 1/3] fix(git-review): refresh PR data after commit and create actions --- .../GitReviewSidebar/GitReviewSidebar.tsx | 1 - .../parts/useGitReviewActions.ts | 17 +++++++++++++--- .../parts/useSourceBranchData.ts | 20 +++++++------------ 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/GitReviewSidebar.tsx b/src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/GitReviewSidebar.tsx index b2a142269..f0d905137 100644 --- a/src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/GitReviewSidebar.tsx +++ b/src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/GitReviewSidebar.tsx @@ -142,7 +142,6 @@ export function GitReviewSidebar(props: { project, effectiveBranch, effectivePrKey, - worktreePath, isGitHub, ghAvailable, preferredSourceBranch: prBaseBranch, diff --git a/src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/useGitReviewActions.ts b/src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/useGitReviewActions.ts index 41dbd8168..473e5eba1 100644 --- a/src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/useGitReviewActions.ts +++ b/src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/useGitReviewActions.ts @@ -235,7 +235,11 @@ export function useGitReviewActions(args: UseGitReviewActionsArgs) { // callers that chain further work — e.g. the combined "Commit & Create PR" // action — only proceed when there's actually something pushed to open a PR // against. - async function handleCommit(addAll: boolean, pushAfter = false): Promise { + async function handleCommit( + addAll: boolean, + pushAfter = false, + skipDelayedRefresh = false, + ): Promise { setIsCommitting(true); try { let message = commitMessage.trim(); @@ -300,7 +304,12 @@ export function useGitReviewActions(args: UseGitReviewActionsArgs) { // GitHub takes a beat to register the new commits — refreshing // immediately fetches a stale PR snapshot. Delay so the post-push // refresh picks up fresh state. - setTimeout(() => onRefresh(), 1500); + // When the caller chains a PR creation (skipDelayedRefresh), the + // delayed refresh would race with handleCreatePr's setPrData and + // overwrite it with a stale null from ghGetPrForBranch. + if (!skipDelayedRefresh) { + setTimeout(() => onRefresh(), 1500); + } } finally { setIsSyncing(false); } @@ -642,6 +651,7 @@ export function useGitReviewActions(args: UseGitReviewActionsArgs) { useGitStore.getState().setPrData(effectivePrKey, pr); } patch(storeKey, { prTitle: "", prBody: "", prGen: null }); + onRefresh(); } catch (err) { console.error("[git] create PR failed", err); toast.danger(friendlyError(err)); @@ -655,9 +665,10 @@ export function useGitReviewActions(args: UseGitReviewActionsArgs) { // opens the dialog), so this stays a single uninterrupted action regardless // of the prCreateMode setting. async function handleCommitAndCreatePr(addAll: boolean): Promise { - const committed = await handleCommit(addAll, true); + const committed = await handleCommit(addAll, true, true); if (!committed) return; await handleCreatePr(false); + onRefresh(); } async function handleGeneratePrSummary(): Promise { diff --git a/src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/useSourceBranchData.ts b/src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/useSourceBranchData.ts index 07f621337..314308b14 100644 --- a/src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/useSourceBranchData.ts +++ b/src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/useSourceBranchData.ts @@ -8,7 +8,6 @@ export function useSourceBranchData(params: { project: { location: ProjectLocation }; effectiveBranch: string | undefined; effectivePrKey: string | undefined; - worktreePath: string | undefined; isGitHub: boolean; ghAvailable: boolean; /** When set (e.g. PR base), overrides the inferred source branch. */ @@ -19,7 +18,6 @@ export function useSourceBranchData(params: { project, effectiveBranch, effectivePrKey, - worktreePath, isGitHub, ghAvailable, preferredSourceBranch, @@ -92,9 +90,13 @@ export function useSourceBranchData(params: { refreshKey, ]); - // Fetch PR data for non-worktree mode (worktree PR data is polled elsewhere) + // Fetch PR data on mount / refreshKey change for both worktree and + // non-worktree modes. Worktree PR data is also polled by the periodic + // refreshGitProject cycle, but that cycle may not have run yet when the + // panel is first opened — leaving the PR section blank after a "commit & + // create PR" action or when reopening the panel. useEffect(() => { - if (worktreePath || !isGitHub || !ghAvailable || !effectiveBranch || !effectivePrKey) return; + if (!isGitHub || !ghAvailable || !effectiveBranch || !effectivePrKey) return; let isActive = true; readBridge() .ghGetPrForBranch({ projectLocation: project.location, branch: effectiveBranch }) @@ -106,15 +108,7 @@ export function useSourceBranchData(params: { return () => { isActive = false; }; - }, [ - worktreePath, - isGitHub, - ghAvailable, - effectiveBranch, - effectivePrKey, - project.location, - refreshKey, - ]); + }, [isGitHub, ghAvailable, effectiveBranch, effectivePrKey, project.location, refreshKey]); return { sourceBranchLoading }; } From 1243d03c54b2328b3635443fb40c0100a3a988d1 Mon Sep 17 00:00:00 2001 From: Serhii Vecherenko Date: Fri, 24 Jul 2026 09:54:41 -0700 Subject: [PATCH 2/3] fix(git-review): delay post-push PR refreshes further --- .../parts/GitReviewSidebar/parts/useGitReviewActions.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/useGitReviewActions.ts b/src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/useGitReviewActions.ts index 473e5eba1..feb3c9ea4 100644 --- a/src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/useGitReviewActions.ts +++ b/src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/parts/useGitReviewActions.ts @@ -308,7 +308,7 @@ export function useGitReviewActions(args: UseGitReviewActionsArgs) { // delayed refresh would race with handleCreatePr's setPrData and // overwrite it with a stale null from ghGetPrForBranch. if (!skipDelayedRefresh) { - setTimeout(() => onRefresh(), 1500); + setTimeout(() => onRefresh(), 2000); } } finally { setIsSyncing(false); @@ -399,7 +399,7 @@ export function useGitReviewActions(args: UseGitReviewActionsArgs) { // GitHub takes a beat to register the new commits — refreshing // immediately fetches a stale PR snapshot (mergeable/checks not // yet updated). Delay so the post-push refresh picks up fresh state. - setTimeout(() => onRefresh(), 1500); + setTimeout(() => onRefresh(), 2000); } else { captureProductEvent("git.sync_action", { action: "sync", @@ -434,7 +434,7 @@ export function useGitReviewActions(args: UseGitReviewActionsArgs) { if (key === "push") { refreshPrAfterPush(); applyStatusOptimistic((s) => ({ ...s, ahead: 0 })); - setTimeout(() => onRefresh(), 1500); + setTimeout(() => onRefresh(), 2000); return; } onRefresh(); From 08d6341216465821f4a0618fa08020c0be6da740 Mon Sep 17 00:00:00 2001 From: Serhii Vecherenko Date: Fri, 24 Jul 2026 10:24:37 -0700 Subject: [PATCH 3/3] test(git-review): mock pull request lookup bridge --- .../parts/GitReviewSidebar/GitReviewSidebar.test.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/GitReviewSidebar.test.tsx b/src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/GitReviewSidebar.test.tsx index d2deceae3..aa2db1c0c 100644 --- a/src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/GitReviewSidebar.test.tsx +++ b/src/renderer/views/GitReviewOverlay/parts/GitReviewSidebar/GitReviewSidebar.test.tsx @@ -17,6 +17,7 @@ const bridgeMock = vi.hoisted(() => ({ vi.fn< () => Promise<{ sourceBranch: string | null; commitsAhead: number; sourceAhead: number }> >(), + ghGetPrForBranch: vi.fn<() => Promise>(), generateCommitMessage: vi.fn<() => Promise<{ message: string }>>(), })); @@ -239,6 +240,7 @@ describe("GitReviewSidebar", () => { bridgeMock.gitCommit.mockResolvedValue(undefined); bridgeMock.gitFetch.mockResolvedValue(undefined); bridgeMock.gitGetWorktreeSourceBranch.mockImplementation(() => new Promise(() => {})); + bridgeMock.ghGetPrForBranch.mockResolvedValue(null); bridgeMock.generateCommitMessage.mockResolvedValue({ message: "generated" }); useGitStore.setState({ ghAvailable: {},