fix(web): make continuous handoff self-recovering
Some checks failed
M6 deployable RC / quick (push) Has been cancelled
M6 deployable RC / chromium (push) Has been cancelled
M6 deployable RC / release (push) Has been cancelled

This commit is contained in:
mes123456
2026-08-30 14:05:10 +08:00
parent b215aa7227
commit 51d313357c
4 changed files with 305 additions and 45 deletions

View File

@@ -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`);
}
}
}