Keep fork PR badges visible in worktrees

This commit is contained in:
Mohamed Boudra
2026-06-02 15:38:27 +07:00
parent f1a20a9fe9
commit 07ace19b69
4 changed files with 151 additions and 15 deletions
@@ -13,7 +13,6 @@ import {
type GitHubCommandRunner,
type GitHubCommandRunnerOptions,
type GitHubCurrentPullRequestStatus,
type GitHubReadOptions,
} from "./github-service.js";
import { CheckoutPrStatusResponseSchema } from "@getpaseo/protocol/messages";
@@ -186,7 +185,7 @@ function githubStatusFacts(
}
function recordCurrentPullRequestStatusReads(service: ReturnType<typeof createGitHubService>) {
const reads: GitHubReadOptions[] = [];
const reads: Parameters<typeof service.getCurrentPullRequestStatus>[0][] = [];
const getCurrentPullRequestStatus = service.getCurrentPullRequestStatus.bind(service);
service.getCurrentPullRequestStatus = vi.fn(async (options) => {
reads.push(options);
@@ -662,6 +661,41 @@ describe("GitHubService", () => {
service.dispose?.();
});
it("retained fork PR status polls keep the head repository owner", async () => {
const runner = createRunner([
currentPullRequestJson({
headRefName: "open-button-targets-active-file",
headRepositoryOwner: { login: "fork-owner" },
}),
]);
const service = createGitHubService({
ttlMs: 0,
runner: runner.runner,
resolveGhPath: async () => "/usr/bin/gh",
});
const reads = recordCurrentPullRequestStatusReads(service);
const subscription = service.retainCurrentPullRequestStatusPoll?.({
cwd: "/repo",
headRef: "open-button-targets-active-file",
headRepositoryOwner: "fork-owner",
});
await vi.advanceTimersByTimeAsync(0);
expect(reads).toEqual([
expect.objectContaining({
cwd: "/repo",
headRef: "open-button-targets-active-file",
headRepositoryOwner: "fork-owner",
reason: "self-heal-github",
}),
]);
expect(currentPullRequestStatusCalls(runner.calls)).toHaveLength(1);
subscription?.unsubscribe();
service.dispose?.();
});
it("polls PR status at slow cadence after stable checks", async () => {
let now = 0;
const runner = createRunner([
+15 -2
View File
@@ -642,6 +642,7 @@ export interface GitHubService {
retainCurrentPullRequestStatusPoll?(options: {
cwd: string;
headRef: string;
headRepositoryOwner?: string;
onStatus?: (status: GitHubCurrentPullRequestStatus | null) => void;
onError?: (error: unknown) => void;
}): { unsubscribe: () => void };
@@ -720,6 +721,7 @@ interface InFlightCacheEntry {
interface GitHubPollTarget {
cwd: string;
headRef: string;
headRepositoryOwner?: string;
retainCount: number;
timer: NodeJS.Timeout | null;
latestStatus: GitHubCurrentPullRequestStatus | null;
@@ -813,17 +815,25 @@ export function createGitHubService(options: CreateGitHubServiceOptions = {}): G
}
}
function getPollTargetKey(target: { cwd: string; headRef: string }): string {
function getPollTargetKey(target: {
cwd: string;
headRef: string;
headRepositoryOwner?: string;
}): string {
return buildCacheKey({
cwd: target.cwd,
method: "getCurrentPullRequestStatus",
args: { headRef: target.headRef },
args: {
headRef: target.headRef,
headRepositoryOwner: target.headRepositoryOwner,
},
});
}
function updatePollTargetAfterSuccess(update: {
cwd: string;
headRef: string;
headRepositoryOwner?: string;
status: GitHubCurrentPullRequestStatus | null;
notify: boolean;
}): void {
@@ -872,6 +882,7 @@ export function createGitHubService(options: CreateGitHubServiceOptions = {}): G
await api.getCurrentPullRequestStatus({
cwd: target.cwd,
headRef: target.headRef,
headRepositoryOwner: target.headRepositoryOwner,
reason: "self-heal-github",
});
} catch (error) {
@@ -1027,6 +1038,7 @@ export function createGitHubService(options: CreateGitHubServiceOptions = {}): G
updatePollTargetAfterSuccess({
cwd: input.cwd,
headRef: input.headRef,
headRepositoryOwner: input.headRepositoryOwner,
status,
notify: input.reason === "self-heal-github",
});
@@ -1241,6 +1253,7 @@ export function createGitHubService(options: CreateGitHubServiceOptions = {}): G
target = {
cwd: input.cwd,
headRef: input.headRef,
headRepositoryOwner: input.headRepositoryOwner,
retainCount: 0,
timer: null,
latestStatus: null,