diff --git a/tools/release-candidate.ts b/tools/release-candidate.ts index 170ca43..a1cdea8 100644 --- a/tools/release-candidate.ts +++ b/tools/release-candidate.ts @@ -165,6 +165,7 @@ export async function waitGreen(sha: string, timeoutMin: number, graceMin = 20): for (;;) { const s = await status(sha); if (s.state === 'green') { say(`candidate ${sha.slice(0, 10)} is green (run ${s.record.run}${s.record.reusedFrom ? `, CI and acceptance of ${s.record.reusedFrom.sha.slice(0, 10)}` : ''})`); return s; } + if (s.state === 'red' && s.cancelledOnly) fail(`commit ${sha.slice(0, 10)}: ${s.failed.join(', ')} were cancelled in ${s.run} (Forgejo cancels a branch's older run when a newer commit is pushed: never push to main while a release runs). Nothing was released: move the tag to origin/main and continue: git tag -f v && git push -f origin refs/tags/v && bun tools/release.ts --resume --yes`); if (s.state === 'red') fail(`commit ${sha.slice(0, 10)} is red: ${s.failed.join(', ')} failed in ${s.run}. Fix it and push; nothing is released from a red commit.`); if (s.state === 'none' && Date.now() - t0 > graceMin * 60_000) fail(`commit ${sha.slice(0, 10)} has no ci run on ${BASE}/${REPO}/actions after ${graceMin} min: push it to main (ci.yml makes the candidate), or free the runners (a queued run gets no task until one is free)`); if (Date.now() > end) fail(`timeout after ${timeoutMin} min waiting for the candidate of ${sha.slice(0, 10)}${s.state === 'pending' ? `: ${s.run} still has ${s.running.join(', ') || 'the record upload'}` : ''}`);