test(ci): skip unrelated Bun launcher builds (#122333)

Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
Peter Steinberger
2026-08-11 16:21:44 -07:00
committed by GitHub
parent b3cb8f7ab2
commit 25f7fc0ec5
5 changed files with 20 additions and 185 deletions
+1 -1
View File
@@ -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
+2 -174
View File
@@ -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<string> {
async function addCompiledMjsEntryFixture(fixtureRoot: string): Promise<void> {
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<void> {
});
}
async function makeLauncherProbeFixture(
fixtureRoots: string[],
probeSource: string,
): Promise<string> {
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<void> {
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<void> {
);
}
async function addLauncherRuntimeMock(
fixtureRoot: string,
params: { nodeVersion: string; platform: NodeJS.Platform },
): Promise<string> {
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<T>(filePath: string, timeoutMs: number): Promise<T> {
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#<ref>");
});
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-");
+4
View File
@@ -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 || '' }}",
+8 -5
View File
@@ -61,13 +61,16 @@ describe("vitest E2E global setup", () => {
);
});
it("uses an exact-run prebuilt dist without rebuilding it", async () => {
const runCommand = vi.fn<SetupCommandRunner>();
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<SetupCommandRunner>();
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-"));
+5 -5
View File
@@ -30,9 +30,9 @@ export async function runE2eGlobalSetup(
runCommand: SetupCommandRunner = runE2eSetupCommand,
env: NodeJS.ProcessEnv = process.env,
): Promise<void> {
// 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(" ")}`);
}