Files
rea/tests/fixtures/processFinalization.mjs
T
Ysopwnable 428eee00fd ci: keep validation fresh and preserve failed-shard reports (#2210)
Run the existing README consistency and Python producer guards from their
CI owners. Execute full local validation fresh while preserving cached
preparation, and permit scoped reuse of earlier portable build entries.

Collect failed-shard diagnostics before enforcing success and publish
compact, portable timing history only after a complete successful merge.
Preserve installer truncation failure across supported Bash versions.

Keep cancellation tests focused on the called MCP tool, observe server
progress before timing target readiness, and retain delayed-startup,
cancellation, cleanup, and live follow-up request assertions.

Validation: all 32 CI jobs and the separate Go lane passed; 935 files,
9,630 cases, 9,544 passed, 86 skipped, zero failed. Controlled regressions
and fault/restoration probes are recorded in PR #2210.

Refs #2190.

Assisted-by: Kogasa (gensokyo-skills:kogasa-surprise-testing)
2026-10-12 23:42:47 +08:00

58 lines
2.0 KiB
JavaScript

import { spawn } from "node:child_process";
import { mkdirSync, writeFileSync } from "node:fs";
import { join } from "node:path";
import { setTimeout as delay } from "node:timers/promises";
import { fileURLToPath } from "node:url";
// Writes a periodic report, then behaves by mode:
// - "cooperative": stays alive; SIGTERM prints a line, writes a final report
// and exits cleanly.
// - "ignoring": stays alive and swallows SIGTERM and SIGINT, so only SIGKILL
// ends the process.
// - "delayed-ignoring": installs those handlers after a slow startup.
// - "exits": exits on its own at once.
// - "descendant": cooperates while leaving a SIGTERM-ignoring child for owned cleanup.
// An optional third argument is the exit code a cooperative finalizer uses.
const [mode, directory, finalExitCode = "0"] = process.argv.slice(2);
// Make the cancellation case exercise startup beyond its old 300 ms capture
// window deterministically, rather than relying on a busy CI runner.
if (mode === "delayed-ignoring") await delay(500);
writeFileSync(join(directory, "pid.txt"), String(process.pid));
writeFileSync(
join(directory, "periodic.json"),
JSON.stringify({ phase: "periodic" }),
);
if (mode === "exits") process.exit(0);
if (mode === "descendant") {
const childDirectory = join(directory, "descendant");
mkdirSync(childDirectory);
spawn(
process.execPath,
[fileURLToPath(import.meta.url), "ignoring", childDirectory],
{ detached: true, stdio: "ignore" },
);
}
if (mode === "ignoring" || mode === "delayed-ignoring") {
process.on("SIGTERM", () => {
writeFileSync(join(directory, "sigterm-received"), "received");
});
process.on("SIGINT", () => undefined);
} else {
process.on("SIGTERM", () => {
writeFileSync(join(directory, "sigterm-received"), "received");
process.stdout.write("finalized\n");
writeFileSync(
join(directory, "final.json"),
JSON.stringify({ phase: "final" }),
);
process.exit(Number(finalExitCode));
});
}
setInterval(() => undefined, 1_000);