From 40385bb5c153afa23efbbb750b88f401f6feb3b9 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 8 Aug 2026 09:21:50 -0700 Subject: [PATCH] test(e2e): isolate shared build artifacts (#120628) --- packages/ai/src/package.e2e.test.ts | 7 ++----- test/vitest/vitest.e2e.config.ts | 1 + test/vitest/vitest.e2e.global-setup.ts | 29 ++++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 5 deletions(-) create mode 100644 test/vitest/vitest.e2e.global-setup.ts diff --git a/packages/ai/src/package.e2e.test.ts b/packages/ai/src/package.e2e.test.ts index 97e129f4675a..94c6e61d4920 100644 --- a/packages/ai/src/package.e2e.test.ts +++ b/packages/ai/src/package.e2e.test.ts @@ -271,11 +271,8 @@ describe("@openclaw/ai packed package", () => { } const tempDir = tempDirs.make("openclaw-ai-consumer-"); - await runCommand( - process.execPath, - ["scripts/tsdown-build.mjs", "--config", "tsdown.ai.config.ts"], - { cwd: repoRoot }, - ); + // The E2E global setup owns the exact-head build. Rebuilding this shared + // package here can delete modules beneath concurrently running Gateways. const pack = await runNpmCommand( ["pack", "--ignore-scripts", "--json", "--pack-destination", tempDir], packageRoot, diff --git a/test/vitest/vitest.e2e.config.ts b/test/vitest/vitest.e2e.config.ts index f3960f262af7..5e84b188056f 100644 --- a/test/vitest/vitest.e2e.config.ts +++ b/test/vitest/vitest.e2e.config.ts @@ -39,6 +39,7 @@ export default defineConfig({ ...baseTest, maxWorkers: e2eWorkers, silent: !verboseE2E, + globalSetup: [resolveRepoRootPath("test/vitest/vitest.e2e.global-setup.ts")], setupFiles: [ ...new Set( [...(baseTest.setupFiles ?? []), "test/setup-openclaw-runtime.ts"].map(resolveRepoRootPath), diff --git a/test/vitest/vitest.e2e.global-setup.ts b/test/vitest/vitest.e2e.global-setup.ts new file mode 100644 index 000000000000..8659ade2c045 --- /dev/null +++ b/test/vitest/vitest.e2e.global-setup.ts @@ -0,0 +1,29 @@ +// Builds the shared CLI/package artifacts once before parallel E2E workers +// start long-lived Gateway processes that import those artifacts lazily. +import { execFile } from "node:child_process"; +import { promisify } from "node:util"; + +const execFileAsync = promisify(execFile); + +export default async function setup() { + await execFileAsync(process.execPath, ["scripts/run-node.mjs", "--version"], { + cwd: process.cwd(), + env: { + ...process.env, + OPENCLAW_BUILD_PRIVATE_QA: "1", + OPENCLAW_RUN_NODE_SKIP_DTS_BUILD: "0", + }, + maxBuffer: 8 * 1024 * 1024, + timeout: 300_000, + }); + await execFileAsync( + process.execPath, + ["scripts/tsdown-build.mjs", "--config", "tsdown.ai.config.ts"], + { + cwd: process.cwd(), + env: process.env, + maxBuffer: 8 * 1024 * 1024, + timeout: 300_000, + }, + ); +}