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 <bashrusakh@users.noreply.github.com>
This commit is contained in:
Leonid
2026-07-11 14:37:33 +03:00
committed by GitHub
co-authored by bashrusakh
parent cd1ffa8b66
commit d01126cf3c
2 changed files with 13 additions and 10 deletions
@@ -496,12 +496,12 @@ export function NewWorktreeDialog({
return; 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) { if (issueRes.connected === false || !issueRes.repo || !issueRes.issue) {
throw new Error('Failed to load issue context'); 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) { if (commentsRes.connected === false) {
throw new Error('Failed to load issue comments'); throw new Error('Failed to load issue comments');
} }
@@ -542,6 +542,7 @@ export function NewWorktreeDialog({
} }
const prContext = await github.prContext(projectDirectory, args.pr.number, { const prContext = await github.prContext(projectDirectory, args.pr.number, {
sourceRepo: args.pr.sourceRepo ?? null,
includeDiff: args.includeDiff, includeDiff: args.includeDiff,
includeCheckDetails: false, includeCheckDetails: false,
}); });
@@ -517,7 +517,7 @@ export const PullRequestSection: React.FC<{
setHydratingPrBodyKey(hydrationKey); setHydratingPrBodyKey(hydrationKey);
let cancelled = false; 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) => { .then((ctx) => {
if (cancelled) { if (cancelled) {
return; return;
@@ -550,7 +550,7 @@ export const PullRequestSection: React.FC<{
return () => { return () => {
cancelled = true; cancelled = true;
}; };
}, [directory, github, pr, prStatusKey, updatePrStatus]); }, [directory, github, pr, prStatusKey, status?.repo, updatePrStatus]);
React.useEffect(() => { React.useEffect(() => {
if (!pr) { if (!pr) {
@@ -590,6 +590,7 @@ export const PullRequestSection: React.FC<{
const ctx = await github.prContext(directory, pr.number, { const ctx = await github.prContext(directory, pr.number, {
includeDiff: false, includeDiff: false,
includeCheckDetails: true, includeCheckDetails: true,
sourceRepo: status?.repo ?? null,
}); });
setCheckDetails(ctx); setCheckDetails(ctx);
} catch (e) { } catch (e) {
@@ -598,7 +599,7 @@ export const PullRequestSection: React.FC<{
} finally { } finally {
setIsLoadingCheckDetails(false); setIsLoadingCheckDetails(false);
} }
}, [directory, github, pr, t]); }, [directory, github, pr, status?.repo, t]);
const openCommentsDialog = React.useCallback(async () => { const openCommentsDialog = React.useCallback(async () => {
if (!github?.prContext) { if (!github?.prContext) {
@@ -613,6 +614,7 @@ export const PullRequestSection: React.FC<{
const ctx = await github.prContext(directory, pr.number, { const ctx = await github.prContext(directory, pr.number, {
includeDiff: false, includeDiff: false,
includeCheckDetails: false, includeCheckDetails: false,
sourceRepo: status?.repo ?? null,
}); });
setCommentsDetails(ctx); setCommentsDetails(ctx);
} catch (e) { } catch (e) {
@@ -621,7 +623,7 @@ export const PullRequestSection: React.FC<{
} finally { } finally {
setIsLoadingCommentsDetails(false); setIsLoadingCommentsDetails(false);
} }
}, [directory, github, pr, t]); }, [directory, github, pr, status?.repo, t]);
const formatTimestamp = React.useCallback((value?: string) => { const formatTimestamp = React.useCallback((value?: string) => {
if (!value) return ''; if (!value) return '';
@@ -886,7 +888,7 @@ export const PullRequestSection: React.FC<{
} }
try { 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 runs = context.checkRuns ?? [];
const failed = runs.filter((r) => { const failed = runs.filter((r) => {
const conclusion = typeof r.conclusion === 'string' ? r.conclusion.toLowerCase() : ''; 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); const message = e instanceof Error ? e.message : String(e);
toast.error(t('gitView.pr.toast.loadChecksFailed'), { description: message }); 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 () => { const sendCommentsToChat = React.useCallback(async () => {
setActiveMainTab('chat'); setActiveMainTab('chat');
@@ -942,7 +944,7 @@ export const PullRequestSection: React.FC<{
} }
try { 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 issueComments = context.issueComments ?? [];
const reviewComments = context.reviewComments ?? []; const reviewComments = context.reviewComments ?? [];
const total = issueComments.length + reviewComments.length; const total = issueComments.length + reviewComments.length;
@@ -965,7 +967,7 @@ export const PullRequestSection: React.FC<{
const message = e instanceof Error ? e.message : String(e); const message = e instanceof Error ? e.message : String(e);
toast.error(t('gitView.pr.toast.loadPrCommentsFailed'), { description: message }); 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) => { const sendSingleCommentToChat = React.useCallback(async (comment: TimelineCommentItem) => {
setCommentsDialogOpen(false); setCommentsDialogOpen(false);