fix(server): fall back PR status queries for fine-grained tokens

Fixes #926
This commit is contained in:
ezra
2026-05-13 17:52:13 +08:00
committed by GitHub
parent 65d14d4433
commit 72293f7f4f
2 changed files with 190 additions and 42 deletions
+38 -14
View File
@@ -236,8 +236,9 @@ query PullRequestCheckoutTarget($owner: String!, $name: String!, $number: Int!)
}
}`;
const CURRENT_PR_STATUS_FIELDS =
"number,url,title,state,isDraft,baseRefName,headRefName,mergedAt,statusCheckRollup,reviewDecision,mergeable,headRepositoryOwner";
const CURRENT_PR_STATUS_BASE_FIELDS =
"number,url,title,state,isDraft,baseRefName,headRefName,mergedAt,reviewDecision,mergeable,headRepositoryOwner";
const CURRENT_PR_STATUS_FIELDS = `${CURRENT_PR_STATUS_BASE_FIELDS},statusCheckRollup`;
const PULL_REQUEST_TIMELINE_QUERY = `
query PullRequestTimeline($owner: String!, $name: String!, $number: Int!) {
@@ -1314,6 +1315,13 @@ function isNoPullRequestFoundError(error: unknown): boolean {
return text.includes("no pull requests found");
}
function isStatusCheckRollupPermissionError(error: unknown): boolean {
if (!(error instanceof GitHubCommandError)) {
return false;
}
return error.stderr.toLowerCase().includes("statuscheckrollup");
}
async function resolveCurrentPullRequestView(options: {
cwd: string;
headRef: string;
@@ -1370,8 +1378,10 @@ async function tryCurrentPullRequestView(options: {
run: (args: string[], options: GitHubCommandRunnerOptions) => Promise<string>;
}): Promise<ResolvedPullRequestCandidate | null> {
try {
const stdout = await options.run(["pr", "view", "--json", CURRENT_PR_STATUS_FIELDS], {
const stdout = await runCurrentPullRequestStatusCommand({
cwd: options.cwd,
run: options.run,
args: ["pr", "view"],
});
return parseCurrentPullRequestCandidate(stdout, options.headRef);
} catch (error) {
@@ -1392,18 +1402,13 @@ async function listCurrentPullRequestCandidates(options: {
if (options.repo) {
args.push("--repo", options.repo);
}
args.push(
"--state",
"all",
"--head",
options.headRef,
"--json",
CURRENT_PR_STATUS_FIELDS,
"--limit",
"10",
);
args.push("--state", "all", "--head", options.headRef, "--limit", "10");
try {
const stdout = await options.run(args, { cwd: options.cwd });
const stdout = await runCurrentPullRequestStatusCommand({
cwd: options.cwd,
run: options.run,
args,
});
return parseCurrentPullRequestCandidateList(stdout, options.headRef);
} catch (error) {
if (isNoPullRequestFoundError(error)) {
@@ -1413,6 +1418,25 @@ async function listCurrentPullRequestCandidates(options: {
}
}
async function runCurrentPullRequestStatusCommand(options: {
cwd: string;
run: (args: string[], options: GitHubCommandRunnerOptions) => Promise<string>;
args: string[];
}): Promise<string> {
try {
return await options.run([...options.args, "--json", CURRENT_PR_STATUS_FIELDS], {
cwd: options.cwd,
});
} catch (error) {
if (!isStatusCheckRollupPermissionError(error)) {
throw error;
}
return options.run([...options.args, "--json", CURRENT_PR_STATUS_BASE_FIELDS], {
cwd: options.cwd,
});
}
}
async function getGitHubRepoView(options: {
cwd: string;
run: (args: string[], options: GitHubCommandRunnerOptions) => Promise<string>;