diff --git a/package.json b/package.json index 546469dfcdf9..635c86dada26 100644 --- a/package.json +++ b/package.json @@ -1943,7 +1943,7 @@ "tsgo:all": "node scripts/run-tsgo.mjs -b tsconfig.projects.json", "tsgo:core": "node scripts/run-tsgo.mjs -p tsconfig.core.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/core.tsbuildinfo", "tsgo:core:all": "node scripts/run-tsgo.mjs -b tsconfig.core.projects.json", - "tsgo:core:test": "node scripts/run-tsgo.mjs -b test/tsconfig/tsconfig.core.test.projects.json", + "tsgo:core:test": "node scripts/run-tsgo-core-test-shards.mjs", "tsgo:extensions": "node scripts/run-tsgo.mjs -p tsconfig.extensions.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/extensions.tsbuildinfo", "tsgo:extensions:all": "node scripts/run-tsgo.mjs -b tsconfig.extensions.projects.json", "tsgo:extensions:test": "node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.extensions.test.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/extensions-test.tsbuildinfo", @@ -1952,10 +1952,10 @@ "tsgo:scripts": "node scripts/run-tsgo.mjs -p tsconfig.scripts.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/scripts.tsbuildinfo", "tsgo:test": "pnpm tsgo:core:test && pnpm tsgo:extensions:test && pnpm tsgo:test:root", "tsgo:test:extensions": "pnpm tsgo:extensions:test", - "tsgo:test:packages": "node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.test.packages.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/test-packages.tsbuildinfo", + "tsgo:test:packages": "node scripts/run-tsgo-core-test-shards.mjs packages", "tsgo:test:root": "node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.test.root.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/test-root.tsbuildinfo", - "tsgo:test:src": "node scripts/run-tsgo.mjs -b test/tsconfig/tsconfig.core.test.src.projects.json", - "tsgo:test:ui": "node scripts/run-tsgo.mjs -b test/tsconfig/tsconfig.core.test.ui.projects.json", + "tsgo:test:src": "node scripts/run-tsgo-core-test-shards.mjs src", + "tsgo:test:ui": "node scripts/run-tsgo-core-test-shards.mjs ui", "tsgo:ui": "node scripts/run-tsgo.mjs -p tsconfig.ui.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/ui.tsbuildinfo", "tui": "node scripts/run-node.mjs tui", "tui:dev": "node --import tsx scripts/run-with-env.mts OPENCLAW_PROFILE=dev -- node scripts/run-node.mjs --dev tui", diff --git a/scripts/lib/tsgo-core-test-shards.mts b/scripts/lib/tsgo-core-test-shards.mts index f554e814013e..48c6ea8e207e 100644 --- a/scripts/lib/tsgo-core-test-shards.mts +++ b/scripts/lib/tsgo-core-test-shards.mts @@ -1,25 +1,43 @@ export const TSGO_CORE_TEST_MAX_ROOTS = 720; export const TSGO_CORE_TEST_SHARDS = [ - { name: "agents-root", config: "test/tsconfig/tsconfig.core.test.agents-root.json" }, - { name: "agents-other", config: "test/tsconfig/tsconfig.core.test.agents-other.json" }, - { name: "gateway", config: "test/tsconfig/tsconfig.core.test.gateway.json" }, - { name: "infra", config: "test/tsconfig/tsconfig.core.test.infra.json" }, - { name: "commands", config: "test/tsconfig/tsconfig.core.test.commands.json" }, + { + name: "agents-root", + group: "src", + config: "test/tsconfig/tsconfig.core.test.agents-root.json", + }, + { + name: "agents-other", + group: "src", + config: "test/tsconfig/tsconfig.core.test.agents-other.json", + }, + { name: "gateway", group: "src", config: "test/tsconfig/tsconfig.core.test.gateway.json" }, + { name: "infra", group: "src", config: "test/tsconfig/tsconfig.core.test.infra.json" }, + { name: "commands", group: "src", config: "test/tsconfig/tsconfig.core.test.commands.json" }, { name: "plugins-platform", + group: "src", config: "test/tsconfig/tsconfig.core.test.plugins-platform.json", }, - { name: "config-cli", config: "test/tsconfig/tsconfig.core.test.config-cli.json" }, - { name: "messaging", config: "test/tsconfig/tsconfig.core.test.messaging.json" }, - { name: "services", config: "test/tsconfig/tsconfig.core.test.services.json" }, - { name: "other", config: "test/tsconfig/tsconfig.core.test.other.json" }, + { + name: "config-cli", + group: "src", + config: "test/tsconfig/tsconfig.core.test.config-cli.json", + }, + { name: "messaging", group: "src", config: "test/tsconfig/tsconfig.core.test.messaging.json" }, + { name: "services", group: "src", config: "test/tsconfig/tsconfig.core.test.services.json" }, + { name: "other", group: "src", config: "test/tsconfig/tsconfig.core.test.other.json" }, { name: "ui-pages-e2e", + group: "ui", config: "test/tsconfig/tsconfig.core.test.ui-pages-e2e.json", }, - { name: "ui-other", config: "test/tsconfig/tsconfig.core.test.ui-other.json" }, - { name: "packages", config: "test/tsconfig/tsconfig.test.packages.json" }, + { name: "ui-other", group: "ui", config: "test/tsconfig/tsconfig.core.test.ui-other.json" }, + { + name: "packages", + group: "packages", + config: "test/tsconfig/tsconfig.test.packages.json", + }, ] as const; export type TsgoCoreTestShard = (typeof TSGO_CORE_TEST_SHARDS)[number]; diff --git a/scripts/run-tsgo-core-test-shards.mjs b/scripts/run-tsgo-core-test-shards.mjs new file mode 100644 index 000000000000..a98c7bd7d183 --- /dev/null +++ b/scripts/run-tsgo-core-test-shards.mjs @@ -0,0 +1,8 @@ +#!/usr/bin/env node + +import { runTsxCliShim } from "./lib/tsx-cli-shim.mjs"; + +await runTsxCliShim(import.meta.url, { + implementation: "./run-tsgo-core-test-shards.mts", + failureTool: "tsgo:core:test", +}); diff --git a/scripts/run-tsgo-core-test-shards.mts b/scripts/run-tsgo-core-test-shards.mts new file mode 100644 index 000000000000..7981a529154d --- /dev/null +++ b/scripts/run-tsgo-core-test-shards.mts @@ -0,0 +1,61 @@ +#!/usr/bin/env node + +// Run bounded test graphs in fresh processes so one shard's checker heap cannot +// accumulate while the next shard loads. Hold one lock across the full sequence. +import { spawnSync } from "node:child_process"; +import path from "node:path"; +import { + acquireLocalHeavyCheckLockSync, + resolveLocalHeavyCheckEnv, +} from "./lib/local-heavy-check-runtime.mts"; +import { signalExitCode } from "./lib/managed-child-process.mts"; +import { resolveRepoRoot } from "./lib/repo-root.mjs"; +import { TSGO_CORE_TEST_SHARDS } from "./lib/tsgo-core-test-shards.mts"; + +const repoRoot = resolveRepoRoot(import.meta.url); +const requestedGroup = process.argv[2]; +const groups: ReadonlySet = new Set(TSGO_CORE_TEST_SHARDS.map((shard) => shard.group)); +if (requestedGroup && !groups.has(requestedGroup)) { + console.error(`Unknown core test shard group: ${requestedGroup}`); + process.exit(1); +} + +const shards = requestedGroup + ? TSGO_CORE_TEST_SHARDS.filter((shard) => shard.group === requestedGroup) + : TSGO_CORE_TEST_SHARDS; +const env = resolveLocalHeavyCheckEnv(process.env); +const releaseLock = + env.OPENCLAW_TSGO_HEAVY_CHECK_LOCK_HELD === "1" + ? () => {} + : acquireLocalHeavyCheckLockSync({ + cwd: repoRoot, + env, + toolName: "tsgo:core:test", + }); + +try { + for (const shard of shards) { + const result = spawnSync( + process.execPath, + [path.join(repoRoot, "scripts/run-tsgo.mjs"), "-b", shard.config, "--builders", "1"], + { + cwd: repoRoot, + env: { ...env, OPENCLAW_TSGO_HEAVY_CHECK_LOCK_HELD: "1" }, + stdio: "inherit", + }, + ); + if (result.error) { + throw result.error; + } + if (result.signal) { + process.exitCode = signalExitCode(result.signal); + break; + } + if (result.status !== 0) { + process.exitCode = result.status ?? 1; + break; + } + } +} finally { + releaseLock(); +} diff --git a/test/tsconfig/tsconfig.core.test.shard.json b/test/tsconfig/tsconfig.core.test.shard.json index 3214eb74db7f..274b710f92a7 100644 --- a/test/tsconfig/tsconfig.core.test.shard.json +++ b/test/tsconfig/tsconfig.core.test.shard.json @@ -1,5 +1,8 @@ { "extends": "./tsconfig.core.test.json", + "compilerOptions": { + "incremental": true + }, "files": [ "../../src/config/sessions/session-entry.test-compat.d.ts", "../../src/infra/host-env-security-policy.d.ts",