Skip to content

Commit 3862551

Browse files
committed
Fix --green retry counter reset after pushing new commits
When --green pushes a fix commit, it should reset the retry counter to 0 since it's a new commit that deserves its own set of retry attempts. Previous behavior: - Attempt 1: Check commit A, fail, fix, push commit B, retryCount = 1 - Attempt 2: Check commit B, fail, fix, push commit C, retryCount = 2 - Attempt 3: Check commit C, fail, give up (retryCount >= maxRetries-1) Fixed behavior: - Attempt 1: Check commit A, fail, fix, push commit B, retryCount = 0 - Attempt 1: Check commit B, fail, fix, push commit C, retryCount = 0 - Attempt 1: Check commit C, fail, fix, push commit D, retryCount = 0 - (continues with proper retry attempts for each new commit) Also adds 15-second wait after pushing to allow new CI run to start.
1 parent 4432576 commit 3862551

File tree

1 file changed

+66
-124
lines changed

1 file changed

+66
-124
lines changed

scripts/claude.mjs

Lines changed: 66 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -3397,7 +3397,15 @@ Let's work through this together to get CI passing.`
33973397
currentSha = newShaResult.stdout.trim()
33983398
pushTime = Date.now()
33993399

3400-
retryCount++
3400+
// Reset retry count for new commit - it deserves its own attempts
3401+
log.substep(
3402+
`New commit ${currentSha.substring(0, 7)}, resetting retry counter`,
3403+
)
3404+
retryCount = 0
3405+
3406+
// Wait for new CI run to start
3407+
log.substep('Waiting 15 seconds for new CI run to start...')
3408+
await new Promise(resolve => setTimeout(resolve, 15_000))
34013409
continue
34023410
}
34033411

@@ -3591,6 +3599,8 @@ Fix all issues by making necessary file changes. Be direct, don't ask questions.
35913599
},
35923600
)
35933601

3602+
let pushedNewCommit = false
3603+
35943604
if (fixStatusResult.stdout.trim()) {
35953605
log.progress('Committing CI fixes')
35963606

@@ -3602,72 +3612,28 @@ Fix all issues by making necessary file changes. Be direct, don't ask questions.
36023612
.join(', ')
36033613
log.substep(`Changed files: ${changedFiles}`)
36043614

3605-
// Use Claude to create proper commits (logical groupings, no AI attribution)
3606-
const commitPrompt = `Review the changes and create commits with logical groupings.
3607-
3608-
Changed files: ${changedFiles}
3609-
3610-
Requirements:
3611-
- Create one or more commits as needed for logical grouping
3612-
- No AI attribution in commit messages
3613-
- Follow conventional commit style from the repo
3614-
- Be concise and descriptive
3615-
3616-
Commit the changes now.`
3615+
// Stage all changes
3616+
await runCommand('git', ['add', '.'], { cwd: rootPath })
36173617

3618-
const commitTmpFile = path.join(
3618+
// Generate commit message using Claude (non-interactive)
3619+
log.progress('Generating CI fix commit message with Claude')
3620+
const commitMessage = await generateCommitMessage(
3621+
claudeCmd,
36193622
rootPath,
3620-
`.claude-commit-${Date.now()}.txt`,
3623+
opts,
36213624
)
3622-
await fs.writeFile(commitTmpFile, commitPrompt, 'utf8')
3623-
3624-
const commitArgs = prepareClaudeArgs([], opts)
3625-
const commitArgsStr = commitArgs.join(' ')
3626-
const commitCommand = commitArgsStr
3627-
? `${claudeCmd} ${commitArgsStr}`
3628-
: claudeCmd
3625+
log.substep(`Commit message: ${commitMessage}`)
36293626

3630-
let commitScriptCmd
3631-
if (WIN32) {
3632-
const winptyCheck = await runCommandWithOutput('where', ['winpty'])
3633-
if (winptyCheck.exitCode === 0) {
3634-
commitScriptCmd = `winpty ${commitCommand} < "${commitTmpFile}"`
3635-
} else {
3636-
commitScriptCmd = `${commitCommand} < "${commitTmpFile}"`
3637-
}
3638-
} else {
3639-
commitScriptCmd = `script -q /dev/null sh -c '${commitCommand} < "${commitTmpFile}"'`
3627+
// Commit with generated message
3628+
const commitArgs = ['commit', '-m', commitMessage]
3629+
if (useNoVerify) {
3630+
commitArgs.push('--no-verify')
36403631
}
3641-
3642-
const commitExitCode = await new Promise((resolve, _reject) => {
3643-
const child = spawn(commitScriptCmd, [], {
3644-
stdio: 'inherit',
3645-
cwd: rootPath,
3646-
shell: true,
3647-
})
3648-
3649-
const sigintHandler = () => {
3650-
child.kill('SIGINT')
3651-
resolve(130)
3652-
}
3653-
process.on('SIGINT', sigintHandler)
3654-
3655-
child.on('exit', code => {
3656-
process.off('SIGINT', sigintHandler)
3657-
resolve(code || 0)
3658-
})
3659-
3660-
child.on('error', () => {
3661-
process.off('SIGINT', sigintHandler)
3662-
resolve(1)
3663-
})
3632+
const commitResult = await runCommandWithOutput('git', commitArgs, {
3633+
cwd: rootPath,
36643634
})
36653635

3666-
try {
3667-
await fs.unlink(commitTmpFile)
3668-
} catch {}
3669-
3670-
if (commitExitCode === 0) {
3636+
if (commitResult.exitCode === 0) {
36713637
// Push the commits
36723638
await runCommand('git', ['push'], { cwd: rootPath })
36733639
log.done('Pushed fix commits')
@@ -3682,12 +3648,28 @@ Commit the changes now.`
36823648
)
36833649
currentSha = newShaResult.stdout.trim()
36843650
pushTime = Date.now()
3651+
pushedNewCommit = true
3652+
3653+
// Reset retry count for new commit - it deserves its own attempts
3654+
log.substep(
3655+
`New commit ${currentSha.substring(0, 7)}, resetting retry counter`,
3656+
)
3657+
retryCount = 0
3658+
3659+
// Wait for new CI run to start
3660+
log.substep('Waiting 15 seconds for new CI run to start...')
3661+
await new Promise(resolve => setTimeout(resolve, 15_000))
36853662
} else {
3686-
log.warn(`Claude commit failed with exit code ${commitExitCode}`)
3663+
log.warn(
3664+
`Git commit failed: ${commitResult.stderr || commitResult.stdout}`,
3665+
)
36873666
}
36883667
}
36893668

3690-
retryCount++
3669+
// Only increment retry count if we didn't push a new commit
3670+
if (!pushedNewCommit) {
3671+
retryCount++
3672+
}
36913673
} else {
36923674
log.error(`CI still failing after ${maxRetries} attempts`)
36933675
log.substep(
@@ -3920,79 +3902,39 @@ Fix the issue by making necessary file changes. Be direct, don't ask questions.`
39203902
.join(', ')
39213903
log.substep(`Changed files: ${changedFiles}`)
39223904

3923-
// Use Claude to create proper commits (logical groupings, no AI attribution)
3924-
const commitPrompt = `Review the changes and create commits with logical groupings.
3925-
3926-
Changed files: ${changedFiles}
3905+
// Stage all changes
3906+
await runCommand('git', ['add', '.'], { cwd: rootPath })
39273907

3928-
Requirements:
3929-
- Create one or more commits as needed for logical grouping
3930-
- No AI attribution in commit messages
3931-
- Follow conventional commit style from the repo
3932-
- Be concise and descriptive
3933-
3934-
Commit the changes now.`
3935-
3936-
const commitTmpFile = path.join(
3908+
// Generate commit message using Claude (non-interactive)
3909+
log.progress(
3910+
`Generating commit message for ${job.name} fix with Claude`,
3911+
)
3912+
const commitMessage = await generateCommitMessage(
3913+
claudeCmd,
39373914
rootPath,
3938-
`.claude-commit-${Date.now()}.txt`,
3915+
opts,
39393916
)
3940-
await fs.writeFile(commitTmpFile, commitPrompt, 'utf8')
3941-
3942-
const commitArgs = prepareClaudeArgs([], opts)
3943-
const commitArgsStr = commitArgs.join(' ')
3944-
const commitCommand = commitArgsStr
3945-
? `${claudeCmd} ${commitArgsStr}`
3946-
: claudeCmd
3917+
log.substep(`Commit message: ${commitMessage}`)
39473918

3948-
let commitScriptCmd
3949-
if (WIN32) {
3950-
const winptyCheck = await runCommandWithOutput('where', [
3951-
'winpty',
3952-
])
3953-
if (winptyCheck.exitCode === 0) {
3954-
commitScriptCmd = `winpty ${commitCommand} < "${commitTmpFile}"`
3955-
} else {
3956-
commitScriptCmd = `${commitCommand} < "${commitTmpFile}"`
3957-
}
3958-
} else {
3959-
commitScriptCmd = `script -q /dev/null sh -c '${commitCommand} < "${commitTmpFile}"'`
3919+
// Commit with generated message
3920+
const commitArgs = ['commit', '-m', commitMessage]
3921+
if (useNoVerify) {
3922+
commitArgs.push('--no-verify')
39603923
}
3961-
3962-
const commitExitCode = await new Promise((resolve, _reject) => {
3963-
const child = spawn(commitScriptCmd, [], {
3964-
stdio: 'inherit',
3924+
const commitResult = await runCommandWithOutput(
3925+
'git',
3926+
commitArgs,
3927+
{
39653928
cwd: rootPath,
3966-
shell: true,
3967-
})
3968-
3969-
const sigintHandler = () => {
3970-
child.kill('SIGINT')
3971-
resolve(130)
3972-
}
3973-
process.on('SIGINT', sigintHandler)
3974-
3975-
child.on('exit', code => {
3976-
process.off('SIGINT', sigintHandler)
3977-
resolve(code || 0)
3978-
})
3979-
3980-
child.on('error', () => {
3981-
process.off('SIGINT', sigintHandler)
3982-
resolve(1)
3983-
})
3984-
})
3985-
3986-
try {
3987-
await fs.unlink(commitTmpFile)
3988-
} catch {}
3929+
},
3930+
)
39893931

3990-
if (commitExitCode === 0) {
3932+
if (commitResult.exitCode === 0) {
39913933
log.done(`Committed fix for ${job.name}`)
39923934
hasPendingCommits = true
39933935
} else {
39943936
log.warn(
3995-
`Claude commit failed with exit code ${commitExitCode}`,
3937+
`Git commit failed: ${commitResult.stderr || commitResult.stdout}`,
39963938
)
39973939
}
39983940
} else {

0 commit comments

Comments
 (0)