fix(web): make continuous handoff self-recovering
This commit is contained in:
@@ -11,8 +11,18 @@ const maxIterations = maxArg >= 0 ? Number(process.argv[maxArg + 1]) : 0;
|
||||
if (!Number.isSafeInteger(maxIterations) || maxIterations < 0) throw new Error("--max-iterations must be a non-negative integer; 0 means unlimited");
|
||||
const commitEnabled = process.argv.includes("--commit");
|
||||
const pushEnabled = process.argv.includes("--push");
|
||||
if (pushEnabled && !commitEnabled) throw new Error("--push requires --commit");
|
||||
const pushRetryArg = process.argv.indexOf("--push-retries");
|
||||
const pushRetries = pushRetryArg >= 0 ? Number(process.argv[pushRetryArg + 1]) : 6;
|
||||
if (!Number.isSafeInteger(pushRetries) || pushRetries < 0) throw new Error("--push-retries must be a non-negative integer");
|
||||
const shellQuote = (value) => `'${value.replaceAll("'", "'\\''")}'`;
|
||||
|
||||
function waitMs(milliseconds) {
|
||||
if (milliseconds <= 0) return;
|
||||
const wait = new Int32Array(new SharedArrayBuffer(4));
|
||||
Atomics.wait(wait, 0, 0, milliseconds);
|
||||
}
|
||||
|
||||
function command(command, logPath) {
|
||||
const result = spawnSync("bash", ["-lc", command], { cwd: root, encoding: "utf8", maxBuffer: 16 * 1024 * 1024 });
|
||||
const output = `${result.stdout ?? ""}${result.stderr ?? ""}`;
|
||||
@@ -78,8 +88,23 @@ while (maxIterations === 0 || iterations < maxIterations) {
|
||||
const commitResult = command(`git diff --cached --quiet || git commit -m "chore(web): continuous handoff ${before.task}"`, `tests/golden/${before.task}/continuous-commit-result.log`);
|
||||
if (commitResult.code !== 0) throw new Error(`${before.task} commit failed; log=tests/golden/${before.task}/continuous-commit-result.log`);
|
||||
if (pushEnabled) {
|
||||
const push = command("git push origin main", `tests/golden/${before.task}/continuous-push.log`);
|
||||
if (push.code !== 0) throw new Error(`${before.task} push failed; log=tests/golden/${before.task}/continuous-push.log`);
|
||||
let pushed = false;
|
||||
for (let attempt = 0; attempt <= pushRetries; attempt += 1) {
|
||||
const pushLog = attempt === 0
|
||||
? `tests/golden/${before.task}/continuous-push.log`
|
||||
: `tests/golden/${before.task}/continuous-push-attempt-${attempt + 1}.log`;
|
||||
const push = command("git push origin main", pushLog);
|
||||
const pushVerification = command(
|
||||
"local_head=$(git rev-parse --verify HEAD) && remote_head=$(git ls-remote --refs origin refs/heads/main | awk '$2 == \"refs/heads/main\" { print $1; exit }') && printf 'local_head=%s remote_head=%s\\n' \"$local_head\" \"$remote_head\" && test -n \"$remote_head\" && test \"$local_head\" = \"$remote_head\"",
|
||||
`tests/golden/${before.task}/continuous-push-verify.log`,
|
||||
);
|
||||
if (pushVerification.code === 0) {
|
||||
pushed = true;
|
||||
break;
|
||||
}
|
||||
if (attempt < pushRetries) waitMs(Math.min(30000, 1000 * 2 ** attempt));
|
||||
}
|
||||
if (!pushed) throw new Error(`${before.task} remote push verification failed after ${pushRetries + 1} attempts; log=tests/golden/${before.task}/continuous-push-verify.log`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user