When a PR originates from a fork, `git fetch origin <branch>` fails because the branch only exists on the fork's remote. Fix: detect cross-repository PRs via the `isCrossRepository` GraphQL field and fetch using `pull/<number>/head:<branch>` refspec instead, which is the standard GitHub mechanism for accessing fork PR branches. Changes: - Add `isCrossRepository` and `headRepository` to PR GraphQL query - Add corresponding fields to GitHubPullRequest type - Branch checkout uses pull ref for fork PRs - Update test fixtures with new fields Co-authored-by: User <user@example.com>
This commit is contained in:
parent
3943183052
commit
c3bf66dbc2
@ -12,6 +12,13 @@ export const PR_QUERY = `
|
|||||||
baseRefName
|
baseRefName
|
||||||
headRefName
|
headRefName
|
||||||
headRefOid
|
headRefOid
|
||||||
|
isCrossRepository
|
||||||
|
headRepository {
|
||||||
|
owner {
|
||||||
|
login
|
||||||
|
}
|
||||||
|
name
|
||||||
|
}
|
||||||
createdAt
|
createdAt
|
||||||
updatedAt
|
updatedAt
|
||||||
lastEditedAt
|
lastEditedAt
|
||||||
|
|||||||
@ -166,9 +166,23 @@ export async function setupBranch(
|
|||||||
// Validate branch names before use to prevent command injection
|
// Validate branch names before use to prevent command injection
|
||||||
validateBranchName(branchName);
|
validateBranchName(branchName);
|
||||||
|
|
||||||
// Execute git commands to checkout PR branch (dynamic depth based on PR size)
|
// For cross-repository (fork) PRs, fetch via the pull ref since the
|
||||||
// Using execFileSync instead of shell template literals for security
|
// branch only exists on the fork's remote, not on origin.
|
||||||
execGit(["fetch", "origin", `--depth=${fetchDepth}`, branchName]);
|
if (prData.isCrossRepository) {
|
||||||
|
console.log(
|
||||||
|
`PR #${entityNumber} is from a fork, fetching via refs/pull/${entityNumber}/head...`,
|
||||||
|
);
|
||||||
|
execGit([
|
||||||
|
"fetch",
|
||||||
|
"origin",
|
||||||
|
`--depth=${fetchDepth}`,
|
||||||
|
`pull/${entityNumber}/head:${branchName}`,
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
// Execute git commands to checkout PR branch (dynamic depth based on PR size)
|
||||||
|
// Using execFileSync instead of shell template literals for security
|
||||||
|
execGit(["fetch", "origin", `--depth=${fetchDepth}`, branchName]);
|
||||||
|
}
|
||||||
execGit(["checkout", branchName, "--"]);
|
execGit(["checkout", branchName, "--"]);
|
||||||
|
|
||||||
console.log(`Successfully checked out PR branch for PR #${entityNumber}`);
|
console.log(`Successfully checked out PR branch for PR #${entityNumber}`);
|
||||||
|
|||||||
@ -57,6 +57,13 @@ export type GitHubPullRequest = {
|
|||||||
baseRefName: string;
|
baseRefName: string;
|
||||||
headRefName: string;
|
headRefName: string;
|
||||||
headRefOid: string;
|
headRefOid: string;
|
||||||
|
isCrossRepository: boolean;
|
||||||
|
headRepository: {
|
||||||
|
owner: {
|
||||||
|
login: string;
|
||||||
|
};
|
||||||
|
name: string;
|
||||||
|
} | null;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
updatedAt?: string;
|
updatedAt?: string;
|
||||||
lastEditedAt?: string;
|
lastEditedAt?: string;
|
||||||
|
|||||||
@ -27,6 +27,8 @@ describe("generatePrompt", () => {
|
|||||||
baseRefName: "main",
|
baseRefName: "main",
|
||||||
headRefName: "feature-branch",
|
headRefName: "feature-branch",
|
||||||
headRefOid: "abc123",
|
headRefOid: "abc123",
|
||||||
|
isCrossRepository: false,
|
||||||
|
headRepository: { owner: { login: "testowner" }, name: "testrepo" },
|
||||||
commits: {
|
commits: {
|
||||||
totalCount: 2,
|
totalCount: 2,
|
||||||
nodes: [
|
nodes: [
|
||||||
|
|||||||
@ -1006,6 +1006,8 @@ describe("fetchGitHubData integration with time filtering", () => {
|
|||||||
baseRefName: "main",
|
baseRefName: "main",
|
||||||
headRefName: "feature",
|
headRefName: "feature",
|
||||||
headRefOid: "abc123",
|
headRefOid: "abc123",
|
||||||
|
isCrossRepository: false,
|
||||||
|
headRepository: { owner: { login: "testowner" }, name: "testrepo" },
|
||||||
createdAt: "2024-01-15T10:00:00Z",
|
createdAt: "2024-01-15T10:00:00Z",
|
||||||
updatedAt: "2024-01-15T12:30:00Z", // Edited after trigger
|
updatedAt: "2024-01-15T12:30:00Z", // Edited after trigger
|
||||||
lastEditedAt: "2024-01-15T12:30:00Z", // Edited after trigger
|
lastEditedAt: "2024-01-15T12:30:00Z", // Edited after trigger
|
||||||
|
|||||||
@ -24,6 +24,8 @@ describe("formatContext", () => {
|
|||||||
baseRefName: "main",
|
baseRefName: "main",
|
||||||
headRefName: "feature/test",
|
headRefName: "feature/test",
|
||||||
headRefOid: "abc123",
|
headRefOid: "abc123",
|
||||||
|
isCrossRepository: false,
|
||||||
|
headRepository: { owner: { login: "testowner" }, name: "testrepo" },
|
||||||
createdAt: "2023-01-01T00:00:00Z",
|
createdAt: "2023-01-01T00:00:00Z",
|
||||||
additions: 50,
|
additions: 50,
|
||||||
deletions: 30,
|
deletions: 30,
|
||||||
|
|||||||
@ -17,6 +17,8 @@ describe("pull_request_target event support", () => {
|
|||||||
baseRefName: "main",
|
baseRefName: "main",
|
||||||
headRefName: "feature-branch",
|
headRefName: "feature-branch",
|
||||||
headRefOid: "abc123",
|
headRefOid: "abc123",
|
||||||
|
isCrossRepository: false,
|
||||||
|
headRepository: { owner: { login: "testowner" }, name: "testrepo" },
|
||||||
commits: {
|
commits: {
|
||||||
totalCount: 2,
|
totalCount: 2,
|
||||||
nodes: [
|
nodes: [
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user