mirror of
https://github.com/getpaseo/paseo.git
synced 2026-11-02 22:52:58 +00:00
fix(forges): retain transferred forks in crowded searches
Resolve the head repository before choosing the bounded fallback so transferred forks keep their pull request association.
This commit is contained in:
@@ -3553,6 +3553,7 @@ describe("ForgeService", () => {
|
||||
const runner = createScriptedRunner([
|
||||
JSON.stringify(other),
|
||||
JSON.stringify(crowd),
|
||||
JSON.stringify({ full_name: "same/wanted" }),
|
||||
JSON.stringify({ owner: { login: "base" }, name: "project", parent: null }),
|
||||
JSON.stringify([{ number: 42, state: "open", head: { repo: { full_name: "same/wanted" } } }]),
|
||||
wanted,
|
||||
@@ -3880,6 +3881,80 @@ describe("ForgeService", () => {
|
||||
).toMatchObject({ number: 42 });
|
||||
});
|
||||
|
||||
it("finds a transferred fork when the branch candidate window is full", async () => {
|
||||
const pr = JSON.parse(
|
||||
currentPullRequestJson({
|
||||
url: "https://github.com/base/repo/pull/42",
|
||||
headRepositoryOwner: { login: "new-fork" },
|
||||
headRepository: { name: "repo" },
|
||||
}),
|
||||
);
|
||||
const unrelated = Array.from({ length: 9 }, (_, i) => ({
|
||||
...pr,
|
||||
number: i + 50,
|
||||
headRepositoryOwner: { login: "other" },
|
||||
}));
|
||||
const runner = createScriptedRunner([
|
||||
JSON.stringify(pr),
|
||||
JSON.stringify([...unrelated, pr]),
|
||||
JSON.stringify({ full_name: "new-fork/repo" }),
|
||||
]);
|
||||
const service = createGitHubService({
|
||||
runner: runner.runner,
|
||||
resolveGhPath: async () => "/usr/bin/gh",
|
||||
});
|
||||
expect(
|
||||
await service.getCurrentPullRequestStatus({
|
||||
cwd: "/repo",
|
||||
headRef: "feature/fork",
|
||||
headRepositoryOwner: "old-fork",
|
||||
headRepositoryPath: "old-fork/repo",
|
||||
}),
|
||||
).toMatchObject({ number: 42, state: "open" });
|
||||
});
|
||||
|
||||
it("uses the canonical fork in the bounded terminal fallback after a transfer", async () => {
|
||||
const pr = JSON.parse(
|
||||
currentPullRequestJson({
|
||||
url: "https://github.com/base/repo/pull/42",
|
||||
state: "MERGED",
|
||||
mergedAt: "2026-01-01T00:00:00Z",
|
||||
headRepositoryOwner: { login: "new-fork" },
|
||||
headRepository: { name: "repo" },
|
||||
}),
|
||||
);
|
||||
const unrelated = Array.from({ length: 9 }, (_, i) => ({
|
||||
...pr,
|
||||
number: i + 50,
|
||||
headRepositoryOwner: { login: "other" },
|
||||
}));
|
||||
const runner = createScriptedRunner([
|
||||
JSON.stringify(pr),
|
||||
JSON.stringify([...unrelated, pr]),
|
||||
JSON.stringify({ full_name: "new-fork/repo" }),
|
||||
JSON.stringify({ owner: { login: "base" }, name: "repo", parent: null }),
|
||||
JSON.stringify([
|
||||
{ number: 42, state: "closed", head: { repo: { full_name: "new-fork/repo" } } },
|
||||
]),
|
||||
JSON.stringify(pr),
|
||||
]);
|
||||
const service = createGitHubService({
|
||||
runner: runner.runner,
|
||||
resolveGhPath: async () => "/usr/bin/gh",
|
||||
});
|
||||
expect(
|
||||
await service.getCurrentPullRequestStatus({
|
||||
cwd: "/repo",
|
||||
headRef: "feature/fork",
|
||||
headRepositoryOwner: "old-fork",
|
||||
headRepositoryPath: "old-fork/repo",
|
||||
}),
|
||||
).toMatchObject({ number: 42, state: "merged" });
|
||||
expect(
|
||||
runner.calls.some((call) => call.args[1]?.includes("head=new-fork%3Afeature%2Ffork")),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it("propagates a failed fork PR lookup instead of reporting no pull request", async () => {
|
||||
const rateLimitError = new GitHubCommandError({
|
||||
args: ["api", "repos/parentOwner/parentRepo/pulls"],
|
||||
|
||||
@@ -3149,9 +3149,6 @@ async function resolveListedPullRequest(
|
||||
headRef: options.headRef,
|
||||
run: options.run,
|
||||
});
|
||||
if (candidates.length >= BATCH_PR_CANDIDATE_LIMIT && options.headRepositoryPath) {
|
||||
return resolveCrowdedPullRequests(options, options.headRepositoryPath);
|
||||
}
|
||||
let match = pickPullRequestCandidate({
|
||||
candidates: viewMatch ? [viewMatch, ...candidates] : candidates,
|
||||
headRef: options.headRef,
|
||||
@@ -3175,6 +3172,11 @@ async function resolveListedPullRequest(
|
||||
repository.full_name &&
|
||||
repository.full_name.toLowerCase() !== options.headRepositoryPath.toLowerCase()
|
||||
) {
|
||||
options = {
|
||||
...options,
|
||||
headRepositoryPath: repository.full_name,
|
||||
headRepositoryOwner: repository.full_name.split("/")[0],
|
||||
};
|
||||
match = pickPullRequestCandidate({
|
||||
candidates: viewMatch ? [viewMatch, ...candidates] : candidates,
|
||||
headRef: options.headRef,
|
||||
@@ -3183,6 +3185,10 @@ async function resolveListedPullRequest(
|
||||
});
|
||||
}
|
||||
}
|
||||
if (candidates.length >= BATCH_PR_CANDIDATE_LIMIT && options.headRepositoryPath) {
|
||||
if (match?.status.state === "open") return match.status;
|
||||
return resolveCrowdedPullRequests(options, options.headRepositoryPath);
|
||||
}
|
||||
return match?.status ?? null;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user