From d01126cf3c5cf7492f41517392e7bce29744e88c Mon Sep 17 00:00:00 2001 From: Leonid <127580858+bashrusakh@users.noreply.github.com> Date: Sat, 11 Jul 2026 22:37:33 +1100 Subject: [PATCH] fix(ui): pass sourceRepo to PR/issue context calls for fork workflows (#2090) (#2091) Fixes GitHub PR/issue context endpoints returning 404 when working from a fork because they resolved the repo from origin remote only. - Pass sourceRepo: status?.repo ?? null to all prContext() calls in PullRequestSection.tsx (5 call sites) - Pass sourceRepo: args.pr.sourceRepo ?? null / args.issue.sourceRepo ?? null to NewWorktreeDialog.tsx (3 call sites: prContext, issueGet, issueComments) - Add status?.repo to dependency arrays to prevent stale closures The prStatus endpoint already resolves the correct repo through the fork network; this change wires it through to the downstream API calls. Closes #2090 Co-authored-by: bashrusakh --- .../components/session/NewWorktreeDialog.tsx | 5 +++-- .../views/git/PullRequestSection.tsx | 18 ++++++++++-------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/packages/ui/src/components/session/NewWorktreeDialog.tsx b/packages/ui/src/components/session/NewWorktreeDialog.tsx index 1d6ddb34..cda33b7b 100644 --- a/packages/ui/src/components/session/NewWorktreeDialog.tsx +++ b/packages/ui/src/components/session/NewWorktreeDialog.tsx @@ -496,12 +496,12 @@ export function NewWorktreeDialog({ return; } - const issueRes = await github.issueGet(projectDirectory, args.issue.number); + const issueRes = await github.issueGet(projectDirectory, args.issue.number, { sourceRepo: args.issue.sourceRepo ?? null }); if (issueRes.connected === false || !issueRes.repo || !issueRes.issue) { throw new Error('Failed to load issue context'); } - const commentsRes = await github.issueComments(projectDirectory, args.issue.number); + const commentsRes = await github.issueComments(projectDirectory, args.issue.number, { sourceRepo: args.issue.sourceRepo ?? null }); if (commentsRes.connected === false) { throw new Error('Failed to load issue comments'); } @@ -542,6 +542,7 @@ export function NewWorktreeDialog({ } const prContext = await github.prContext(projectDirectory, args.pr.number, { + sourceRepo: args.pr.sourceRepo ?? null, includeDiff: args.includeDiff, includeCheckDetails: false, }); diff --git a/packages/ui/src/components/views/git/PullRequestSection.tsx b/packages/ui/src/components/views/git/PullRequestSection.tsx index 560f02fe..3639a26c 100644 --- a/packages/ui/src/components/views/git/PullRequestSection.tsx +++ b/packages/ui/src/components/views/git/PullRequestSection.tsx @@ -517,7 +517,7 @@ export const PullRequestSection: React.FC<{ setHydratingPrBodyKey(hydrationKey); let cancelled = false; - void github.prContext(directory, pr.number, { includeDiff: false, includeCheckDetails: false }) + void github.prContext(directory, pr.number, { includeDiff: false, includeCheckDetails: false, sourceRepo: status?.repo ?? null }) .then((ctx) => { if (cancelled) { return; @@ -550,7 +550,7 @@ export const PullRequestSection: React.FC<{ return () => { cancelled = true; }; - }, [directory, github, pr, prStatusKey, updatePrStatus]); + }, [directory, github, pr, prStatusKey, status?.repo, updatePrStatus]); React.useEffect(() => { if (!pr) { @@ -590,6 +590,7 @@ export const PullRequestSection: React.FC<{ const ctx = await github.prContext(directory, pr.number, { includeDiff: false, includeCheckDetails: true, + sourceRepo: status?.repo ?? null, }); setCheckDetails(ctx); } catch (e) { @@ -598,7 +599,7 @@ export const PullRequestSection: React.FC<{ } finally { setIsLoadingCheckDetails(false); } - }, [directory, github, pr, t]); + }, [directory, github, pr, status?.repo, t]); const openCommentsDialog = React.useCallback(async () => { if (!github?.prContext) { @@ -613,6 +614,7 @@ export const PullRequestSection: React.FC<{ const ctx = await github.prContext(directory, pr.number, { includeDiff: false, includeCheckDetails: false, + sourceRepo: status?.repo ?? null, }); setCommentsDetails(ctx); } catch (e) { @@ -621,7 +623,7 @@ export const PullRequestSection: React.FC<{ } finally { setIsLoadingCommentsDetails(false); } - }, [directory, github, pr, t]); + }, [directory, github, pr, status?.repo, t]); const formatTimestamp = React.useCallback((value?: string) => { if (!value) return ''; @@ -886,7 +888,7 @@ export const PullRequestSection: React.FC<{ } try { - const context = await github.prContext(directory, pr.number, { includeDiff: false, includeCheckDetails: true }); + const context = await github.prContext(directory, pr.number, { includeDiff: false, includeCheckDetails: true, sourceRepo: status?.repo ?? null }); const runs = context.checkRuns ?? []; const failed = runs.filter((r) => { const conclusion = typeof r.conclusion === 'string' ? r.conclusion.toLowerCase() : ''; @@ -926,7 +928,7 @@ export const PullRequestSection: React.FC<{ const message = e instanceof Error ? e.message : String(e); toast.error(t('gitView.pr.toast.loadChecksFailed'), { description: message }); } - }, [directory, dispatchSyntheticPrompt, github, pr, resolveChatDispatchTarget, setActiveMainTab, t]); + }, [directory, dispatchSyntheticPrompt, github, pr, resolveChatDispatchTarget, setActiveMainTab, status?.repo, t]); const sendCommentsToChat = React.useCallback(async () => { setActiveMainTab('chat'); @@ -942,7 +944,7 @@ export const PullRequestSection: React.FC<{ } try { - const context = await github.prContext(directory, pr.number, { includeDiff: false, includeCheckDetails: false }); + const context = await github.prContext(directory, pr.number, { includeDiff: false, includeCheckDetails: false, sourceRepo: status?.repo ?? null }); const issueComments = context.issueComments ?? []; const reviewComments = context.reviewComments ?? []; const total = issueComments.length + reviewComments.length; @@ -965,7 +967,7 @@ export const PullRequestSection: React.FC<{ const message = e instanceof Error ? e.message : String(e); toast.error(t('gitView.pr.toast.loadPrCommentsFailed'), { description: message }); } - }, [directory, dispatchSyntheticPrompt, github, pr, resolveChatDispatchTarget, setActiveMainTab, t]); + }, [directory, dispatchSyntheticPrompt, github, pr, resolveChatDispatchTarget, setActiveMainTab, status?.repo, t]); const sendSingleCommentToChat = React.useCallback(async (comment: TimelineCommentItem) => { setCommentsDialogOpen(false);