Files
openclaw/scripts/run-tsgo-core-test-shards.mts
Peter Steinberger bf9b25ab7e fix(gateway): prevent control-plane polling stalls (#124891)
* fix(gateway): avoid repeated control-plane scans

* fix(tooling): allow concurrent worktree validation

* fix(ci): refresh protocol and runner inputs

* perf(ui): defer hidden session refreshes

* fix(ui): resolve session refresh lint failure

* fix(update): preserve pre-cache update channel

* fix(update): normalize cached update channel

* fix(gateway): lifecycle-cache update install identity

* fix(ui): preserve manual history retry after layout scroll

* test(codex): repair side-question tool schema fixture
2026-08-16 20:58:27 -07:00

87 lines
2.9 KiB
TypeScript

#!/usr/bin/env node
// Run bounded test graphs in fresh processes so one shard's checker heap cannot
// accumulate while the next shard loads.
import { spawn, type ChildProcess } from "node:child_process";
import path from "node:path";
import { resolveLocalCheckEnv } from "./lib/local-check-runtime.mts";
import { signalExitCode } from "./lib/managed-child-process.mts";
import { resolveRepoRoot } from "./lib/repo-root.mjs";
import {
selectTsgoCoreTestShards,
selectTsgoCoreTestStripe,
} from "./lib/tsgo-core-test-shards.mts";
const repoRoot = resolveRepoRoot(import.meta.url);
// CI stripes split the serial shard sequence across parallel jobs; the
// stripe union is exactly the full shard list, so coverage is unchanged.
const stripeFlagIndex = process.argv.indexOf("--stripe");
let shards;
if (stripeFlagIndex >= 0) {
const stripeSpec = process.argv[stripeFlagIndex + 1] ?? "";
shards = selectTsgoCoreTestStripe(stripeSpec);
if (!shards) {
console.error(`Invalid core test stripe (expected i/n): ${stripeSpec}`);
process.exit(1);
}
} else {
const requestedGroup = process.argv[2];
shards = selectTsgoCoreTestShards(requestedGroup);
if (!shards) {
console.error(`Unknown core test shard group: ${requestedGroup}`);
process.exit(1);
}
}
// Each graph is a serial single-project build, so tsgo gains little past four
// cores; CI stripe jobs opt into overlapping fresh child processes to use the
// idle cores. Local runs stay serial to keep the heap-bounded default.
const concurrencyFlagIndex = process.argv.indexOf("--concurrency");
let concurrency = 1;
if (concurrencyFlagIndex >= 0) {
const rawConcurrency = process.argv[concurrencyFlagIndex + 1] ?? "";
concurrency = Number(rawConcurrency);
if (!Number.isInteger(concurrency) || concurrency < 1 || concurrency > 4) {
console.error(`Invalid shard concurrency (expected 1-4): ${rawConcurrency}`);
process.exit(1);
}
}
const env = resolveLocalCheckEnv(process.env);
function runShard(config: string): Promise<number> {
return new Promise((resolve, reject) => {
const child: ChildProcess = spawn(
process.execPath,
[path.join(repoRoot, "scripts/run-tsgo.mjs"), "-b", config, "--builders", "1"],
{
cwd: repoRoot,
env,
stdio: "inherit",
},
);
child.on("error", reject);
child.on("exit", (code, signal) => {
resolve(signal ? signalExitCode(signal) : (code ?? 1));
});
});
}
const queue = [...shards];
let failureCode = 0;
const workers = Array.from({ length: Math.min(concurrency, queue.length) }, async () => {
for (;;) {
const shard = queue.shift();
// Stop draining after the first failure so the exit stays prompt.
if (!shard || failureCode !== 0) {
return;
}
const code = await runShard(shard.config);
if (code !== 0 && failureCode === 0) {
failureCode = code;
}
}
});
await Promise.all(workers);
if (failureCode !== 0) {
process.exitCode = failureCode;
}