From 2e223300375101558f90b6e78ef9612c55626673 Mon Sep 17 00:00:00 2001 From: Ysopwnable <161784452+N0zoM1z0@users.noreply.github.com> Date: Sun, 11 Oct 2026 19:50:50 +0800 Subject: [PATCH] fix(build): preserve resource controls in strict Turbo tasks (#1809) --- docs/testing.md | 5 ++ .../filesystem/dependencyInstall.test.ts | 47 +++++++++++++++++-- turbo.json | 1 + 3 files changed, 49 insertions(+), 4 deletions(-) diff --git a/docs/testing.md b/docs/testing.md index 7574489b8..fca45ae66 100644 --- a/docs/testing.md +++ b/docs/testing.md @@ -945,6 +945,11 @@ it or select another revision. Source typechecking needs no compiled runtime or generated test metadata. `npm run build:cached` compiles the CLI/MCP runtime and its packaged skill. +Turbo's strict task environment preserves caller-selected `GOMAXPROCS`, +`GOMEMLIMIT`, and `UV_THREADPOOL_SIZE` for resource-constrained builds and +checks. These execution controls do not change artifact content, so changing +their values retains cache reuse. They control individual runtimes; monitor +the complete process family separately when enforcing a total memory budget. `npm run test:prepare` also generates the MCP contract test catalog, product catalog, and portable managed evidence used by the complete suite. Focused tests prepare those extra outputs only when their selected files consume them. diff --git a/tests/boundary/filesystem/dependencyInstall.test.ts b/tests/boundary/filesystem/dependencyInstall.test.ts index 806d91b32..42ad7e564 100644 --- a/tests/boundary/filesystem/dependencyInstall.test.ts +++ b/tests/boundary/filesystem/dependencyInstall.test.ts @@ -141,6 +141,39 @@ describe("dependency install freshness", () => { expect(cached.status, cached.stderr).toBe(0); expect(`${cached.stdout}${cached.stderr}`).toMatch(/cache hit/u); }, 60_000); + + it("preserves caller resource controls in strict cached builds without hashing their values", async () => { + const root = await createBuildCacheFixture(); + const environment = { + ...process.env, + TURBO_ENV_MODE: "strict", + GOMAXPROCS: "1", + GOMEMLIMIT: "384MiB", + UV_THREADPOOL_SIZE: "2", + REA_TEST_UNLISTED_ENV: "filtered", + }; + + const built = await runNpm(root, ["run", "build:cached"], environment); + expect(built.status, `${built.stdout}${built.stderr}`).toBe(0); + expect( + JSON.parse(await readFile(join(root, "resource-controls.json"), "utf8")), + ).toEqual({ + GOMAXPROCS: "1", + GOMEMLIMIT: "384MiB", + UV_THREADPOOL_SIZE: "2", + REA_TEST_UNLISTED_ENV: null, + }); + + const cached = await runTurbo(root, { + ...environment, + GOMAXPROCS: "2", + GOMEMLIMIT: "512MiB", + UV_THREADPOOL_SIZE: "4", + }); + expect(cached.status, `${cached.stdout}${cached.stderr}`).toBe(0); + expect(`${cached.stdout}${cached.stderr}`).toMatch(/cache hit/u); + expect(`${cached.stdout}${cached.stderr}`).not.toMatch(/cache miss/u); + }, 60_000); }); const createBuildCacheFixture = async (): Promise => { @@ -192,6 +225,7 @@ const createBuildCacheFixture = async (): Promise => { await writeFile( join(root, "scripts/cache-fixture-build.mjs"), `import { mkdir, writeFile } from "node:fs/promises"; +await writeFile("resource-controls.json", JSON.stringify(Object.fromEntries(["GOMAXPROCS", "GOMEMLIMIT", "UV_THREADPOOL_SIZE", "REA_TEST_UNLISTED_ENV"].map((name) => [name, process.env[name] ?? null])))); await mkdir("dist", { recursive: true }); await writeFile("dist/cache-fixture.js", "built"); await writeFile("dist/catalogIdentity.js", "export const CATALOG_IDENTITY = { counts: { mcp_tools: 1 } };\\n"); @@ -232,10 +266,13 @@ const createNodeModulesLinks = async (root: string): Promise => { } }; -const runNpm = (cwd: string, arguments_: readonly string[]) => - run("npm", arguments_, cwd); +const runNpm = ( + cwd: string, + arguments_: readonly string[], + environment: NodeJS.ProcessEnv = process.env, +) => run("npm", arguments_, cwd, environment); -const runTurbo = (cwd: string) => +const runTurbo = (cwd: string, environment: NodeJS.ProcessEnv = process.env) => run( process.execPath, [ @@ -245,12 +282,14 @@ const runTurbo = (cwd: string) => "--output-logs=full", ], cwd, + environment, ); const run = ( command: string, arguments_: readonly string[], cwd: string, + environment: NodeJS.ProcessEnv, ): Promise<{ readonly status: number; readonly stdout: string; @@ -259,7 +298,7 @@ const run = ( new Promise((resolve, reject) => { const child = spawn(command, [...arguments_], { cwd, - env: process.env, + env: environment, shell: process.platform === "win32", stdio: ["ignore", "pipe", "pipe"], }); diff --git a/turbo.json b/turbo.json index 5b93503d7..7c0314b24 100644 --- a/turbo.json +++ b/turbo.json @@ -1,5 +1,6 @@ { "$schema": "https://turborepo.dev/schema.json", + "globalPassThroughEnv": ["GOMAXPROCS", "GOMEMLIMIT", "UV_THREADPOOL_SIZE"], "tasks": { "compile": { "dependsOn": ["metadata:check"],