diff --git a/scripts/lib/format-generated-module.mjs b/scripts/lib/format-generated-module.mjs index bfd65997d63..64989c18956 100644 --- a/scripts/lib/format-generated-module.mjs +++ b/scripts/lib/format-generated-module.mjs @@ -1,5 +1,6 @@ import { spawnSync } from "node:child_process"; import fs from "node:fs"; +import os from "node:os"; import path from "node:path"; export function formatGeneratedModule(source, { repoRoot, outputPath, errorLabel }) { @@ -8,27 +9,33 @@ export function formatGeneratedModule(source, { repoRoot, outputPath, errorLabel resolvedRepoRoot, path.isAbsolute(outputPath) ? path.relative(resolvedRepoRoot, outputPath) : outputPath, ); - const formatterPath = path.relative(resolvedRepoRoot, resolvedOutputPath) || resolvedOutputPath; const directFormatterPath = path.join(resolvedRepoRoot, "node_modules", ".bin", "oxfmt"); const useDirectFormatter = process.platform !== "win32" && fs.existsSync(directFormatterPath); const command = useDirectFormatter ? directFormatterPath : "pnpm"; - const args = useDirectFormatter - ? ["--stdin-filepath", formatterPath] - : ["exec", "oxfmt", "--stdin-filepath", formatterPath]; - const formatter = spawnSync(command, args, { - cwd: resolvedRepoRoot, - input: source, - encoding: "utf8", - // Windows requires a shell to launch package-manager shim scripts reliably. - ...(process.platform === "win32" ? { shell: true } : {}), - }); - if (formatter.status !== 0) { - const details = - formatter.stderr?.trim() || - formatter.stdout?.trim() || - formatter.error?.message || - "unknown formatter failure"; - throw new Error(`failed to format generated ${errorLabel}: ${details}`); + const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-generated-format-")); + const tempOutputPath = path.join(tempDir, path.basename(resolvedOutputPath)); + + try { + fs.writeFileSync(tempOutputPath, source, "utf8"); + const args = useDirectFormatter + ? ["--write", tempOutputPath] + : ["exec", "oxfmt", "--write", tempOutputPath]; + const formatter = spawnSync(command, args, { + cwd: resolvedRepoRoot, + encoding: "utf8", + // Windows requires a shell to launch package-manager shim scripts reliably. + ...(process.platform === "win32" ? { shell: true } : {}), + }); + if (formatter.status !== 0) { + const details = + formatter.stderr?.trim() || + formatter.stdout?.trim() || + formatter.error?.message || + "unknown formatter failure"; + throw new Error(`failed to format generated ${errorLabel}: ${details}`); + } + return fs.readFileSync(tempOutputPath, "utf8"); + } finally { + fs.rmSync(tempDir, { recursive: true, force: true }); } - return formatter.stdout; } diff --git a/scripts/test-parallel.mjs b/scripts/test-parallel.mjs index e46a8255078..e2b442eaaa6 100644 --- a/scripts/test-parallel.mjs +++ b/scripts/test-parallel.mjs @@ -55,6 +55,10 @@ const cleanupTempArtifacts = () => { if (tempArtifactDir === null) { return; } + if (process.env.OPENCLAW_TEST_KEEP_TEMP_ARTIFACTS === "1") { + console.error(`[test-parallel] keeping temp artifacts at ${tempArtifactDir}`); + return; + } fs.rmSync(tempArtifactDir, { recursive: true, force: true }); tempArtifactDir = null; }; @@ -455,12 +459,13 @@ const channelIsolatedEntries = channelIsolatedFiles.map((file) => ({ name: `${path.basename(file, ".test.ts")}-channels-isolated`, args: ["vitest", "run", "--config", "vitest.channels.config.ts", "--pool=forks", file], })); -const defaultUnitFastLaneCount = isCI && !isWindows ? 3 : 1; +const defaultUnitFastLaneCount = testProfile === "low" ? 8 : isCI && !isWindows ? 3 : 1; const unitFastLaneCount = Math.max( 1, parseEnvNumber("OPENCLAW_TEST_UNIT_FAST_LANES", defaultUnitFastLaneCount), ); -const defaultUnitFastBatchTargetMs = isCI && !isWindows ? 45_000 : 0; +const defaultUnitFastBatchTargetMs = + testProfile === "low" ? 10_000 : isCI && !isWindows ? 45_000 : 0; const unitFastBatchTargetMs = parseEnvNumber( "OPENCLAW_TEST_UNIT_FAST_BATCH_TARGET_MS", defaultUnitFastBatchTargetMs, @@ -1665,7 +1670,10 @@ if (serialPrefixRuns.length > 0) { if (failedSerialPrefix !== undefined) { process.exit(failedSerialPrefix); } - const deferredRunConcurrency = isMacMiniProfile ? 3 : testProfile === "low" ? 2 : undefined; + // Low-profile runs favor stability over overlap once we leave the shared + // unit-fast batches; the isolated memory-heavy lanes can still trip over + // each other when two singleton Vitest processes overlap. + const deferredRunConcurrency = isMacMiniProfile ? 3 : testProfile === "low" ? 1 : undefined; const failedDeferredParallel = isMacMiniProfile ? await runEntriesWithLimit(deferredParallelRuns, passthroughOptionArgs, deferredRunConcurrency) : deferredRunConcurrency