@ravshansbox/pi-next-issue 1.0.5 → 1.0.7

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ravshansbox/pi-next-issue",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
4
4
  "description": "Pi extension that works through GitHub issues in the background",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/src/git.ts CHANGED
@@ -81,8 +81,8 @@ export async function push(cwd: string, remote: string, branch: string): Promise
81
81
  await must('git', ['push', '-u', remote, `HEAD:refs/heads/${branch}`], { cwd });
82
82
  }
83
83
 
84
- export async function discard(cwd: string): Promise<void> {
85
- await must('git', ['reset', '--hard', '@{upstream}'], { cwd });
84
+ export async function discard(cwd: string, remote: string, branch: string): Promise<void> {
85
+ await must('git', ['reset', '--hard', `${remote}/${branch}`], { cwd });
86
86
  await must('git', ['clean', '-fd'], { cwd });
87
87
  }
88
88
 
package/src/github.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { setTimeout as sleep } from 'node:timers/promises';
2
2
  import { must, run } from './exec.ts';
3
- import { LABELS, STOP_LABELS, type ChecksResult, type Issue } from './runner.ts';
3
+ import { LABELS, STOP_LABELS, type ChecksResult, type Issue, type MergeResult } from './runner.ts';
4
4
 
5
5
  export type Repo = { root: string; slug: string };
6
6
 
@@ -247,25 +247,31 @@ export async function merge(
247
247
  pr: number,
248
248
  timeoutMs: number,
249
249
  signal: AbortSignal,
250
- ): Promise<boolean> {
250
+ ): Promise<MergeResult> {
251
251
  const before = await gh(repo, ['pr', 'view', String(pr), '--json', 'state', '--jq', '.state']);
252
252
  if (before === 'MERGED') {
253
- return true;
253
+ return { merged: true };
254
254
  }
255
255
  const result = await run('gh', ['pr', 'merge', String(pr), '--squash', '--repo', repo.slug], {
256
256
  cwd: repo.root,
257
257
  });
258
258
  if (result.code !== 0) {
259
- return false;
259
+ return {
260
+ merged: false,
261
+ reason: result.stderr.trim().slice(-2000) || `gh pr merge failed with code ${result.code}`,
262
+ };
260
263
  }
261
264
  const deadline = Date.now() + timeoutMs;
262
265
  for (;;) {
263
266
  const state = await gh(repo, ['pr', 'view', String(pr), '--json', 'state', '--jq', '.state']);
264
267
  if (state === 'MERGED') {
265
- return true;
268
+ return { merged: true };
266
269
  }
267
- if (state === 'CLOSED' || Date.now() >= deadline) {
268
- return false;
270
+ if (state === 'CLOSED') {
271
+ return { merged: false, reason: 'the pull request was closed' };
272
+ }
273
+ if (Date.now() >= deadline) {
274
+ return { merged: false, reason: 'the merge did not finish in time' };
269
275
  }
270
276
  await sleep(Math.min(POLL_MS, deadline - Date.now()), undefined, { signal });
271
277
  }
package/src/ports.ts CHANGED
@@ -17,7 +17,7 @@ export async function createPorts(root: string, config: Config): Promise<Ports>
17
17
  worktree: (issue, branch) => git.worktree(root, config.remote, base, issue, branch),
18
18
  commit: (cwd, message) => git.commit(cwd, message),
19
19
  push: (cwd, branch) => git.push(cwd, config.remote, branch),
20
- discard: (cwd) => git.discard(cwd),
20
+ discard: (cwd, branch) => git.discard(cwd, config.remote, branch),
21
21
  diff: (cwd) => git.diff(cwd, config.remote, base),
22
22
  openPr: (branch, title, body) => github.openPr(repo, branch, base, title, body),
23
23
  checks: async (pr, cwd, signal) =>
package/src/runner.ts CHANGED
@@ -46,13 +46,13 @@ export type Ports = {
46
46
  worktree(issue: number, branch: string): Promise<string>;
47
47
  commit(cwd: string, message: string): Promise<boolean>;
48
48
  push(cwd: string, branch: string): Promise<void>;
49
- discard(cwd: string): Promise<void>;
49
+ discard(cwd: string, branch: string): Promise<void>;
50
50
  diff(cwd: string): Promise<string>;
51
51
  openPr(branch: string, title: string, body: string): Promise<number>;
52
52
  checks(pr: number, cwd: string, signal: AbortSignal): Promise<ChecksResult>;
53
53
  failedLogs(pr: number): Promise<string>;
54
54
  commentOnPr(pr: number, body: string): Promise<void>;
55
- merge(pr: number, signal: AbortSignal): Promise<boolean>;
55
+ merge(pr: number, signal: AbortSignal): Promise<MergeResult>;
56
56
  cleanup(issue: number, branch: string, cwd: string): Promise<void>;
57
57
  work(task: AgentTask): Promise<string>;
58
58
  review(task: AgentTask): Promise<Verdict | undefined>;
@@ -64,6 +64,8 @@ export type Ports = {
64
64
  unlock(): Promise<void>;
65
65
  };
66
66
 
67
+ export type MergeResult = { merged: true } | { merged: false; reason: string };
68
+
67
69
  export type Outcome = 'merged' | 'needs-human';
68
70
 
69
71
  export type Status = 'idle' | 'running' | 'stopping' | 'finished' | 'stopped' | 'failed';
@@ -292,7 +294,7 @@ export class Runner {
292
294
  cwd,
293
295
  reviewPrompt(issue, comments, diff, state.earlier),
294
296
  );
295
- await ports.discard(cwd);
297
+ await ports.discard(cwd, state.branch);
296
298
  if (verdict === undefined) {
297
299
  return needsHuman('the reviewer gave no verdict');
298
300
  }
@@ -330,8 +332,9 @@ export class Runner {
330
332
  }
331
333
  case 'merge': {
332
334
  this.stage('merge');
333
- if (!(await ports.merge(pr(), this.controller.signal))) {
334
- return needsHuman(`pull request #${pr()} could not be merged`);
335
+ const result = await ports.merge(pr(), this.controller.signal);
336
+ if (!result.merged) {
337
+ return needsHuman(`pull request #${pr()} could not be merged: ${result.reason}`);
335
338
  }
336
339
  await ports.setLabel(number, LABELS.done, [LABELS.inProgress]);
337
340
  await ports.cleanup(number, state.branch, cwd);