ReviewOS

also looking at this

stacks/buddy

feat(ci): let buddy see whose failure it is, and retry the ones worth retrying

#1410
Merged glennmichael123 wants to merge fix/ci-workflow-runs into main
16 files +1092 -14
bin/cli.tsmodified+24-2
Changes to bin/cli.ts
@@ -1,5 +1,6 @@
11#!/usr/bin/env bun
22
3import type { FailureKind } from '../src/ci/classify'
34import type { GitProvider } from '../src/git/provider'
45import type { ReviewFinding } from '../src/review/findings'
56import type { ReviewFormat } from '../src/review/local'
@@ -1355,7 +1356,7 @@ cli
13551356 return
13561357 }
13571358
1358 const { attemptFix } = await import('../src/ci')
1359 const { attemptFix, failsOnBaseBranch } = await import('../src/ci')
13591360 const { parseFixAttempts, upsertFixAttempts } = await import('../src/ci/attempts')
13601361 const { createAiClient } = await import('../src/ai')
13611362
@@ -1368,15 +1369,36 @@ cli
13681369 pullRequest = open.find(candidate => candidate.number === prNumber)
13691370 }
13701371 const priorAttempts = parseFixAttempts(pullRequest?.body)?.attempts ?? 0
1372 const baseBranch = config.repository?.baseBranch ?? 'main'
1373
1374 // Both of these are capability-gated rather than assumed: a provider
1375 // that cannot read a run history still gets the full diagnosis, it just
1376 // cannot tell an inherited failure from a new one.
1377 const canReadRuns = supports(provider, 'ciRuns', 'listWorkflowRuns')
1378 const canRerun = supports(provider, 'ciRuns', 'rerunWorkflowRun')
13711379
13721380 const outcome = await attemptFix({
13731381 log,
13741382 priorAttempts,
13751383 workspace: process.cwd(),
1376 baseBranch: config.repository?.baseBranch ?? 'main',
1384 baseBranch,
13771385 ai: createAiClient(config, logger),
13781386 logger,
13791387 dryRun: Boolean(options.dryRun),
1388 ...(canReadRuns
1389 ? {
1390 checkBase: (kind: FailureKind) => failsOnBaseBranch(
1391 {
1392 listWorkflowRuns: (branch, listOptions) => provider.listWorkflowRuns!(branch, listOptions),
1393 getWorkflowRunLogs: id => provider.getWorkflowRunLogs!(id),
1394 },
1395 baseBranch,
1396 kind,
1397 logger,
1398 ),
1399 }
1400 : {}),
1401 ...(canRerun && runId ? { rerun: () => provider.rerunWorkflowRun!(runId) } : {}),
13801402 regenerateLockfile: async () => {
13811403 const { regenerateLockFile, detectRequiredPackageManagers, getAllLockFilePaths } = await import('../src/utils/lock-file')
13821404 const { commitAndPush } = await import('../src/utils/git')