diff --git a/scripts/lib/local-heavy-check-runtime.mjs b/scripts/lib/local-heavy-check-runtime.mjs index 320a8ff84fc..43eeff679f1 100644 --- a/scripts/lib/local-heavy-check-runtime.mjs +++ b/scripts/lib/local-heavy-check-runtime.mjs @@ -6,6 +6,7 @@ import path from "node:path"; const GIB = 1024 ** 3; const DEFAULT_LOCAL_GO_GC = "30"; const DEFAULT_LOCAL_GO_MEMORY_LIMIT = "3GiB"; +const DEFAULT_LOCAL_TSGO_BUILD_INFO_FILE = ".artifacts/tsgo-cache/root.tsbuildinfo"; const DEFAULT_LOCK_TIMEOUT_MS = 10 * 60 * 1000; const DEFAULT_LOCK_POLL_MS = 500; const DEFAULT_LOCK_PROGRESS_MS = 15 * 1000; @@ -26,6 +27,7 @@ export function hasFlag(args, name) { export function applyLocalTsgoPolicy(args, env, hostResources) { const nextEnv = { ...env }; const nextArgs = [...args]; + const defaultProjectRun = nextArgs.length === 0; if (!hasFlag(nextArgs, "--declaration") && !nextArgs.includes("-d")) { insertBeforeSeparator(nextArgs, "--declaration", "false"); @@ -35,6 +37,15 @@ export function applyLocalTsgoPolicy(args, env, hostResources) { return { env: nextEnv, args: nextArgs }; } + if (defaultProjectRun) { + insertBeforeSeparator(nextArgs, "--incremental"); + insertBeforeSeparator( + nextArgs, + "--tsBuildInfoFile", + nextEnv.OPENCLAW_TSGO_BUILD_INFO_FILE ?? DEFAULT_LOCAL_TSGO_BUILD_INFO_FILE, + ); + } + if (shouldThrottleLocalHeavyChecks(nextEnv, hostResources)) { insertBeforeSeparator(nextArgs, "--singleThreaded"); insertBeforeSeparator(nextArgs, "--checkers", "1"); diff --git a/scripts/run-tsgo.mjs b/scripts/run-tsgo.mjs index 5711903e6d3..2e5787b3707 100644 --- a/scripts/run-tsgo.mjs +++ b/scripts/run-tsgo.mjs @@ -1,4 +1,5 @@ import { spawnSync } from "node:child_process"; +import fs from "node:fs"; import path from "node:path"; import { acquireLocalHeavyCheckLockSync, @@ -8,6 +9,10 @@ import { const { args: finalArgs, env } = applyLocalTsgoPolicy(process.argv.slice(2), process.env); const tsgoPath = path.resolve("node_modules", ".bin", "tsgo"); +const tsBuildInfoFile = readFlagValue(finalArgs, "--tsBuildInfoFile"); +if (tsBuildInfoFile) { + fs.mkdirSync(path.dirname(path.resolve(tsBuildInfoFile)), { recursive: true }); +} const releaseLock = acquireLocalHeavyCheckLockSync({ cwd: process.cwd(), env, @@ -29,3 +34,16 @@ try { } finally { releaseLock(); } + +function readFlagValue(args, name) { + for (let index = 0; index < args.length; index++) { + const arg = args[index]; + if (arg === name) { + return args[index + 1]; + } + if (arg.startsWith(`${name}=`)) { + return arg.slice(name.length + 1); + } + } + return undefined; +} diff --git a/test/scripts/local-heavy-check-runtime.test.ts b/test/scripts/local-heavy-check-runtime.test.ts index 6a2b03f5a27..0413af769ce 100644 --- a/test/scripts/local-heavy-check-runtime.test.ts +++ b/test/scripts/local-heavy-check-runtime.test.ts @@ -31,7 +31,16 @@ describe("local-heavy-check-runtime", () => { it("tightens local tsgo runs on constrained hosts", () => { const { args, env } = applyLocalTsgoPolicy([], makeEnv(), CONSTRAINED_HOST); - expect(args).toEqual(["--declaration", "false", "--singleThreaded", "--checkers", "1"]); + expect(args).toEqual([ + "--declaration", + "false", + "--incremental", + "--tsBuildInfoFile", + ".artifacts/tsgo-cache/root.tsbuildinfo", + "--singleThreaded", + "--checkers", + "1", + ]); expect(env.GOGC).toBe("30"); expect(env.GOMEMLIMIT).toBe("3GiB"); }); @@ -77,11 +86,41 @@ describe("local-heavy-check-runtime", () => { it("keeps local tsgo at full speed on roomy hosts in auto mode", () => { const { args, env } = applyLocalTsgoPolicy([], makeEnv(), ROOMY_HOST); - expect(args).toEqual(["--declaration", "false"]); + expect(args).toEqual([ + "--declaration", + "false", + "--incremental", + "--tsBuildInfoFile", + ".artifacts/tsgo-cache/root.tsbuildinfo", + ]); expect(env.GOGC).toBeUndefined(); expect(env.GOMEMLIMIT).toBeUndefined(); }); + it("uses the configured local tsgo build info file", () => { + const { args } = applyLocalTsgoPolicy( + [], + makeEnv({ + OPENCLAW_TSGO_BUILD_INFO_FILE: ".artifacts/custom/tsgo.tsbuildinfo", + }), + ROOMY_HOST, + ); + + expect(args).toEqual([ + "--declaration", + "false", + "--incremental", + "--tsBuildInfoFile", + ".artifacts/custom/tsgo.tsbuildinfo", + ]); + }); + + it("avoids incremental cache reuse for ad hoc tsgo runs", () => { + const { args } = applyLocalTsgoPolicy(["--extendedDiagnostics"], makeEnv(), ROOMY_HOST); + + expect(args).toEqual(["--extendedDiagnostics", "--declaration", "false"]); + }); + it("allows forcing the throttled tsgo policy on roomy hosts", () => { const { args, env } = applyLocalTsgoPolicy( [], @@ -91,7 +130,16 @@ describe("local-heavy-check-runtime", () => { ROOMY_HOST, ); - expect(args).toEqual(["--declaration", "false", "--singleThreaded", "--checkers", "1"]); + expect(args).toEqual([ + "--declaration", + "false", + "--incremental", + "--tsBuildInfoFile", + ".artifacts/tsgo-cache/root.tsbuildinfo", + "--singleThreaded", + "--checkers", + "1", + ]); expect(env.GOGC).toBe("30"); expect(env.GOMEMLIMIT).toBe("3GiB"); });