edsger 0.42.0 → 0.42.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -53,8 +53,25 @@ export async function resolveStandalonePR(options) {
53
53
  pull_number: prInfo.prNumber,
54
54
  });
55
55
  const headRef = prData.head.ref;
56
- // Clone repo and checkout PR branch
57
- const repoPath = prepareWorkspace(owner, repo, headRef, prInfo.prNumber, githubToken, verbose);
56
+ // Determine clone source: fork PRs need to clone from the fork repo.
57
+ // head.repo is null when the fork has been deleted — treat as fork with deleted source.
58
+ const isFork = !prData.head.repo ||
59
+ prData.head.repo.full_name !== prData.base.repo.full_name;
60
+ const forkDeleted = !prData.head.repo;
61
+ const cloneOwner = isFork && !forkDeleted ? prData.head.repo.owner.login : owner;
62
+ const cloneRepo = isFork && !forkDeleted ? prData.head.repo.name : repo;
63
+ if (isFork && verbose) {
64
+ logInfo(forkDeleted
65
+ ? `Fork PR detected but fork repo has been deleted, will use PR ref from ${owner}/${repo}`
66
+ : `Fork PR detected: cloning from ${cloneOwner}/${cloneRepo} instead of ${owner}/${repo}`);
67
+ }
68
+ // Clone repo and checkout PR branch.
69
+ // For fork PRs, pass fallback info so prepareWorkspace can fetch the PR ref
70
+ // from upstream if the fork branch is unavailable.
71
+ // For deleted forks, clone upstream directly and always use PR ref fallback.
72
+ const repoPath = prepareWorkspace(cloneOwner, cloneRepo, headRef, prInfo.prNumber, githubToken, verbose, isFork
73
+ ? { upstreamOwner: owner, upstreamRepo: repo }
74
+ : undefined);
58
75
  try {
59
76
  // Run Claude Agent SDK to evaluate and fix comments
60
77
  const systemPrompt = createResolveSystemPrompt();
@@ -10,11 +10,17 @@ export declare function buildCredentialArgs(token: string): string[];
10
10
  * Get the workspace path for a PR resolve operation.
11
11
  */
12
12
  export declare function getResolveWorkspacePath(prNumber: number): string;
13
+ export interface ForkFallbackInfo {
14
+ upstreamOwner: string;
15
+ upstreamRepo: string;
16
+ }
13
17
  /**
14
18
  * Clone or reuse a repo for PR resolve.
19
+ * For fork PRs, clones from the fork repo. If the fork branch is unavailable,
20
+ * falls back to fetching the PR ref from the upstream repo.
15
21
  * Returns the workspace path.
16
22
  */
17
- export declare function prepareWorkspace(owner: string, repo: string, headRef: string, prNumber: number, token: string, verbose?: boolean): string;
23
+ export declare function prepareWorkspace(owner: string, repo: string, headRef: string, prNumber: number, token: string, verbose?: boolean, forkFallback?: ForkFallbackInfo): string;
18
24
  /**
19
25
  * Push changes from workspace back to remote.
20
26
  */
@@ -27,9 +27,11 @@ export function getResolveWorkspacePath(prNumber) {
27
27
  }
28
28
  /**
29
29
  * Clone or reuse a repo for PR resolve.
30
+ * For fork PRs, clones from the fork repo. If the fork branch is unavailable,
31
+ * falls back to fetching the PR ref from the upstream repo.
30
32
  * Returns the workspace path.
31
33
  */
32
- export function prepareWorkspace(owner, repo, headRef, prNumber, token, verbose) {
34
+ export function prepareWorkspace(owner, repo, headRef, prNumber, token, verbose, forkFallback) {
33
35
  const repoPath = getResolveWorkspacePath(prNumber);
34
36
  const repoUrl = `https://github.com/${owner}/${repo}.git`;
35
37
  const gitCredentialArgs = buildCredentialArgs(token);
@@ -66,16 +68,41 @@ export function prepareWorkspace(owner, repo, headRef, prNumber, token, verbose)
66
68
  }
67
69
  else {
68
70
  logInfo(`Cloning ${owner}/${repo} (branch: ${headRef})...`);
69
- execFileSync('git', [
70
- ...gitCredentialArgs,
71
- 'clone',
72
- '--branch',
73
- headRef,
74
- '--single-branch',
75
- repoUrl,
76
- repoPath,
77
- ], { stdio: 'pipe' });
78
- logSuccess(`Cloned to ${repoPath}`);
71
+ try {
72
+ execFileSync('git', [
73
+ ...gitCredentialArgs,
74
+ 'clone',
75
+ '--branch',
76
+ headRef,
77
+ '--single-branch',
78
+ repoUrl,
79
+ repoPath,
80
+ ], { stdio: 'pipe' });
81
+ logSuccess(`Cloned to ${repoPath}`);
82
+ }
83
+ catch (error) {
84
+ // If clone fails and this is a fork PR, fall back to upstream PR ref
85
+ if (forkFallback) {
86
+ logInfo(`Fork branch not available, falling back to PR ref from ${forkFallback.upstreamOwner}/${forkFallback.upstreamRepo}`);
87
+ const upstreamUrl = `https://github.com/${forkFallback.upstreamOwner}/${forkFallback.upstreamRepo}.git`;
88
+ execFileSync('git', [...gitCredentialArgs, 'clone', upstreamUrl, repoPath], { stdio: 'pipe' });
89
+ // Fetch the PR ref and check it out
90
+ execFileSync('git', [
91
+ ...gitCredentialArgs,
92
+ 'fetch',
93
+ 'origin',
94
+ `pull/${prNumber}/head:${headRef}`,
95
+ ], { cwd: repoPath, stdio: 'pipe' });
96
+ execSync(`git checkout ${headRef}`, {
97
+ cwd: repoPath,
98
+ stdio: 'pipe',
99
+ });
100
+ logSuccess(`Cloned via PR ref to ${repoPath}`);
101
+ }
102
+ else {
103
+ throw error;
104
+ }
105
+ }
79
106
  }
80
107
  // Configure git user for commits
81
108
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "edsger",
3
- "version": "0.42.0",
3
+ "version": "0.42.1",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "edsger": "dist/index.js"