From 25f7fc0ec5db6fd734054e4b306d1fae0e366a63 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Tue, 11 Aug 2026 16:21:44 -0700 Subject: [PATCH] test(ci): skip unrelated Bun launcher builds (#122333) Co-authored-by: Amp --- .github/workflows/ci.yml | 2 +- test/openclaw-launcher.e2e.test.ts | 176 +------------------ test/scripts/ci-workflow-guards.test.ts | 4 + test/scripts/vitest-e2e-global-setup.test.ts | 13 +- test/vitest/vitest.e2e.global-setup.ts | 10 +- 5 files changed, 20 insertions(+), 185 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0eb240614d4a..f079319a7f6a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1842,7 +1842,7 @@ jobs: fi ;; bun-launcher) - OPENCLAW_TEST_BUN_LAUNCHER=1 pnpm test test/openclaw-launcher.e2e.test.ts + OPENCLAW_E2E_SKIP_BUILD=1 OPENCLAW_TEST_BUN_LAUNCHER=1 pnpm test test/openclaw-launcher.e2e.test.ts ;; *) echo "Unsupported checks-fast task: $TASK" >&2 diff --git a/test/openclaw-launcher.e2e.test.ts b/test/openclaw-launcher.e2e.test.ts index 3369403d51fc..0e02ef18dbb3 100644 --- a/test/openclaw-launcher.e2e.test.ts +++ b/test/openclaw-launcher.e2e.test.ts @@ -4,7 +4,7 @@ import { once } from "node:events"; import fs from "node:fs/promises"; import path from "node:path"; import { pathToFileURL } from "node:url"; -import { build } from "esbuild"; +import { build as esbuild } from "esbuild"; import { afterEach, describe, expect, it } from "vitest"; import { cleanupTempDirs, makeTempDir } from "./helpers/temp-dir.js"; @@ -20,7 +20,7 @@ async function makeLauncherFixture(fixtureRoots: string[]): Promise { async function addCompiledMjsEntryFixture(fixtureRoot: string): Promise { const sourceRoot = path.resolve(process.cwd(), "src"); - await build({ + await esbuild({ bundle: true, entryPoints: [path.join(sourceRoot, "entry.ts")], format: "esm", @@ -41,26 +41,6 @@ async function addCompiledMjsEntryFixture(fixtureRoot: string): Promise { }); } -async function makeLauncherProbeFixture( - fixtureRoots: string[], - probeSource: string, -): Promise { - const fixtureRoot = await makeLauncherFixture(fixtureRoots); - const launcherPath = path.join(fixtureRoot, "openclaw.mjs"); - const launcher = await fs.readFile(launcherPath, "utf8"); - const bootstrapStart = "\nif (!waitingForCompileCacheRespawn) {"; - const bootstrapIndex = launcher.indexOf(bootstrapStart); - if (bootstrapIndex < 0) { - throw new Error("openclaw launcher bootstrap block was not found"); - } - await fs.writeFile( - launcherPath, - `${launcher.slice(0, bootstrapIndex)}\n${probeSource}\n`, - "utf8", - ); - return fixtureRoot; -} - async function addSourceTreeMarker(fixtureRoot: string): Promise { await fs.mkdir(path.join(fixtureRoot, "src"), { recursive: true }); await fs.writeFile(path.join(fixtureRoot, "src", "entry.ts"), "export {};\n", "utf8"); @@ -83,26 +63,6 @@ async function addCompileCacheProbe(fixtureRoot: string): Promise { ); } -async function addLauncherRuntimeMock( - fixtureRoot: string, - params: { nodeVersion: string; platform: NodeJS.Platform }, -): Promise { - const mockPath = path.join(fixtureRoot, "mock-launcher-runtime.mjs"); - await fs.writeFile( - mockPath, - [ - "Object.defineProperty(process, 'platform', {", - ` value: ${JSON.stringify(params.platform)},`, - "});", - "Object.defineProperty(process.versions, 'node', {", - ` value: ${JSON.stringify(params.nodeVersion)},`, - "});", - ].join("\n"), - "utf8", - ); - return mockPath; -} - async function waitForJsonFile(filePath: string, timeoutMs: number): Promise { const deadline = Date.now() + timeoutMs; let lastError: unknown; @@ -188,10 +148,6 @@ describe("openclaw launcher", () => { }); it("keeps the bootstrap Node range aligned with the package engine", async () => { - const packageJsonRaw = await fs.readFile(path.resolve(process.cwd(), "package.json"), "utf8"); - const packageJson = JSON.parse(packageJsonRaw) as { engines?: { node?: string } }; - expect(packageJson.engines?.node).toBe(">=22.22.3 <23 || >=24.15.0 <25 || >=25.9.0"); - const fixtureRoot = await makeLauncherFixture(fixtureRoots); await fs.writeFile( path.join(fixtureRoot, "dist", "entry.js"), @@ -291,36 +247,6 @@ describe("openclaw launcher", () => { ); }); - it("runs the CLI under Bun when the runtime provides node:sqlite", async () => { - const fixtureRoot = await makeLauncherFixture(fixtureRoots); - await fs.writeFile( - path.join(fixtureRoot, "dist", "entry.js"), - 'process.stdout.write("bun-runtime-entry\\n");\n', - "utf8", - ); - const mockRuntime = path.join(fixtureRoot, "mock-bun-sqlite-runtime.mjs"); - await fs.writeFile( - mockRuntime, - // Simulates Bun >=1.4 (Rust rewrite): bun-branded runtime with node:sqlite - // available; Node's own getBuiltinModule answers the launcher probe. - "Object.defineProperty(process.versions, 'bun', { value: '1.4.0' });", - "utf8", - ); - - const result = spawnSync( - process.execPath, - ["--import", pathToFileURL(mockRuntime).href, path.join(fixtureRoot, "openclaw.mjs")], - { - cwd: fixtureRoot, - env: launcherEnv(), - encoding: "utf8", - }, - ); - - expect(result.status).toBe(0); - expect(result.stdout).toContain("bun-runtime-entry"); - }); - it("surfaces transitive entry import failures instead of masking them as missing dist", async () => { const fixtureRoot = await makeLauncherFixture(fixtureRoots); await fs.writeFile( @@ -372,57 +298,6 @@ describe("openclaw launcher", () => { expect(result.stderr).toContain("--profile requires a value"); }); - it("treats Bun direct optional import misses as direct launcher misses", async () => { - const fixtureRoot = await makeLauncherProbeFixture( - fixtureRoots, - [ - "const result = {", - " direct: isDirectModuleNotFoundError(", - " { message: `Cannot find module './dist/warning-filter.js' from '${fileURLToPath(import.meta.url)}'` },", - " './dist/warning-filter.js',", - " ),", - " directWithCode: isDirectModuleNotFoundError(", - " { code: 'ERR_MODULE_NOT_FOUND', message: `Cannot find module './dist/warning-filter.js' from '${fileURLToPath(import.meta.url)}'` },", - " './dist/warning-filter.js',", - " ),", - " transitive: isDirectModuleNotFoundError(", - " { message: \"Cannot find module './nested.js' from '/pkg/openclaw/dist/entry.js'\" },", - " './dist/entry.js',", - " ),", - " sameSpecifierTransitive: isDirectModuleNotFoundError(", - " { message: \"Cannot find module './dist/entry.js' from '/pkg/openclaw/dist/entry.js'\" },", - " './dist/entry.js',", - " ),", - " nonModuleUrl: isDirectModuleNotFoundError(", - " { message: 'boom', url: new URL('./dist/warning-filter.js', import.meta.url).href },", - " './dist/warning-filter.js',", - " ),", - " nonModulePath: isDirectModuleNotFoundError(", - " { message: `Cannot find module '${fileURLToPath(new URL('./dist/warning-filter.js', import.meta.url))}'` },", - " './dist/warning-filter.js',", - " ),", - "};", - "process.stdout.write(`${JSON.stringify(result)}\\n`);", - ].join("\n"), - ); - - const result = spawnSync(process.execPath, [path.join(fixtureRoot, "openclaw.mjs")], { - cwd: fixtureRoot, - env: launcherEnv(), - encoding: "utf8", - }); - - expect(result.status).toBe(0); - expect(JSON.parse(result.stdout)).toEqual({ - direct: true, - directWithCode: true, - nonModulePath: false, - nonModuleUrl: false, - sameSpecifierTransitive: false, - transitive: false, - }); - }); - it.runIf(process.env.OPENCLAW_TEST_BUN_LAUNCHER === "1" && hasBunRuntime())( "gates the real Bun runtime on node:sqlite availability", async () => { @@ -796,21 +671,6 @@ describe("openclaw launcher", () => { expect(result.stderr).toContain("github:openclaw/openclaw#"); }); - it("keeps compile cache off for source-checkout launchers", async () => { - const fixtureRoot = await makeLauncherFixture(fixtureRoots); - await addSourceTreeMarker(fixtureRoot); - await addCompileCacheProbe(fixtureRoot); - - const result = spawnSync(process.execPath, [path.join(fixtureRoot, "openclaw.mjs")], { - cwd: fixtureRoot, - env: launcherEnv(), - encoding: "utf8", - }); - - expect(result.status).toBe(0); - expect(result.stdout).toBe("cache:disabled;respawn:0"); - }); - it("respawns source-checkout launchers without inherited NODE_COMPILE_CACHE", async () => { const fixtureRoot = await makeLauncherFixture(fixtureRoots); await addGitMarker(fixtureRoot); @@ -1101,38 +961,6 @@ describe("openclaw launcher", () => { expect(result.stdout).not.toContain(path.join(runCwd, "openclaw")); }); - it("keeps compile cache enabled for unaffected packaged launcher runtimes", async () => { - const cases: Array<{ nodeVersion: string; platform: NodeJS.Platform }> = [ - { nodeVersion: "24.15.0", platform: "win32" }, - { nodeVersion: "22.22.3", platform: "linux" }, - { nodeVersion: "25.9.0", platform: "darwin" }, - ]; - - for (const runtime of cases) { - const fixtureRoot = await makeLauncherFixture(fixtureRoots); - const tmpRoot = makeTempDir(fixtureRoots, "openclaw-launcher-tmp-"); - const mockRuntime = await addLauncherRuntimeMock(fixtureRoot, runtime); - await addCompileCacheProbe(fixtureRoot); - - const result = spawnSync( - process.execPath, - ["--import", pathToFileURL(mockRuntime).href, path.join(fixtureRoot, "openclaw.mjs")], - { - cwd: fixtureRoot, - env: launcherEnv({ - TMP: tmpRoot, - TEMP: tmpRoot, - TMPDIR: tmpRoot, - }), - encoding: "utf8", - }, - ); - - expect(result.status).toBe(0); - expect(result.stdout).toBe("cache:enabled;respawn:0"); - } - }); - it("enables compile cache for packaged launchers", async () => { const fixtureRoot = await makeLauncherFixture(fixtureRoots); const tmpRoot = makeTempDir(fixtureRoots, "openclaw-launcher-tmp-"); diff --git a/test/scripts/ci-workflow-guards.test.ts b/test/scripts/ci-workflow-guards.test.ts index 6a89bec10e22..55e003945a75 100644 --- a/test/scripts/ci-workflow-guards.test.ts +++ b/test/scripts/ci-workflow-guards.test.ts @@ -5020,6 +5020,10 @@ printf '%s\n' "\${CURL_SUCCESS_IP:-203.0.113.7}" expect(checksFastRun.run).toContain("max-lines-ratchet)"); expect(checksFastRun.run).toContain("coercion-helpers)"); expect(checksFastRun.run).toContain("pnpm check:coercion-helpers"); + expect(checksFastRun.run).toContain("bun-launcher)"); + expect(checksFastRun.run).toContain( + "OPENCLAW_E2E_SKIP_BUILD=1 OPENCLAW_TEST_BUN_LAUNCHER=1 pnpm test test/openclaw-launcher.e2e.test.ts", + ); expect(checksFastRun.run).toContain('has_package_script "check:max-lines-ratchet"'); expect(checksFastRun.env.RATCHET_PR_HEAD_SHA).toBe( "${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || '' }}", diff --git a/test/scripts/vitest-e2e-global-setup.test.ts b/test/scripts/vitest-e2e-global-setup.test.ts index 33df8cfca545..b6fd8678bc53 100644 --- a/test/scripts/vitest-e2e-global-setup.test.ts +++ b/test/scripts/vitest-e2e-global-setup.test.ts @@ -61,13 +61,16 @@ describe("vitest E2E global setup", () => { ); }); - it("uses an exact-run prebuilt dist without rebuilding it", async () => { - const runCommand = vi.fn(); + it.each(["OPENCLAW_E2E_SKIP_BUILD", "OPENCLAW_E2E_USE_PREBUILT_DIST"] as const)( + "skips rebuilding when %s is set", + async (envName) => { + const runCommand = vi.fn(); - await runE2eGlobalSetup(runCommand, { OPENCLAW_E2E_USE_PREBUILT_DIST: "1" }); + await runE2eGlobalSetup(runCommand, { [envName]: "1" }); - expect(runCommand).not.toHaveBeenCalled(); - }); + expect(runCommand).not.toHaveBeenCalled(); + }, + ); posixIt("forwards output and SIGTERM through the runner process group", async () => { const fixtureDir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-e2e-setup-group-")); diff --git a/test/vitest/vitest.e2e.global-setup.ts b/test/vitest/vitest.e2e.global-setup.ts index 6ca8391c1c97..f26b4c9304da 100644 --- a/test/vitest/vitest.e2e.global-setup.ts +++ b/test/vitest/vitest.e2e.global-setup.ts @@ -30,9 +30,9 @@ export async function runE2eGlobalSetup( runCommand: SetupCommandRunner = runE2eSetupCommand, env: NodeJS.ProcessEnv = process.env, ): Promise { - // Exact-run CI artifact consumers already have the complete built surface. - // Rebuilding here would discard that provenance and duplicate the slow step. - if (env.OPENCLAW_E2E_USE_PREBUILT_DIST === "1") { + // Some focused suites bring their own fixtures, while exact-run artifact consumers already + // have the complete built surface. In both cases rebuilding here would duplicate slow work. + if (env.OPENCLAW_E2E_SKIP_BUILD === "1" || env.OPENCLAW_E2E_USE_PREBUILT_DIST === "1") { return; } const commands = [ @@ -49,8 +49,8 @@ export async function runE2eGlobalSetup( env, }, ]; - for (const { args, env } of commands) { - const status = await runCommand(args, env); + for (const { args, env: commandEnv } of commands) { + const status = await runCommand(args, commandEnv); if (status !== 0) { throw new Error(`E2E setup command failed with exit code ${status}: ${args.join(" ")}`); }