fix(test): build startup artifacts for smoke scripts

This commit is contained in:
Vincent Koc
2026-05-24 12:34:13 +02:00
parent 0a8af67c11
commit 3838e450dd
4 changed files with 138 additions and 2 deletions

View File

@@ -7,6 +7,7 @@ Docs: https://docs.openclaw.ai
### Changes
### Fixes
- Tests: make startup memory and startup bench smoke scripts build CLI startup artifacts when run from a fresh source checkout.
- iMessage: mark authorized slash-command turns as text-sourced commands so `/status`, `/new`, and `/restart` acknowledgements return to the source conversation. (#82642) thanks @homer-byte.
- Crabbox: install Corepack shims into the writable hydration `PNPM_HOME` so local AWS runner hydration no longer tries to overwrite `/usr/local/bin/pnpm`.

View File

@@ -1753,11 +1753,11 @@
"test:startup:bench": "node --import tsx scripts/bench-cli-startup.ts",
"test:startup:bench:check": "node scripts/test-cli-startup-bench-budget.mjs",
"test:startup:bench:save": "node --import tsx scripts/bench-cli-startup.ts --preset all --runs 5 --warmup 1 --output .artifacts/cli-startup-bench-all.json",
"test:startup:bench:smoke": "node --import tsx scripts/bench-cli-startup.ts --preset real --case gatewayStatusJson --runs 1 --warmup 0 --output .artifacts/cli-startup-bench-smoke.json",
"test:startup:bench:smoke": "node scripts/ensure-cli-startup-build.mjs && node --import tsx scripts/bench-cli-startup.ts --preset real --case gatewayStatusJson --runs 1 --warmup 0 --output .artifacts/cli-startup-bench-smoke.json",
"test:startup:bench:update": "node scripts/test-update-cli-startup-bench.mjs",
"test:startup:gateway": "node --import tsx scripts/bench-gateway-startup.ts",
"test:restart:gateway": "node --import tsx scripts/bench-gateway-restart.ts",
"test:startup:memory": "node scripts/check-cli-startup-memory.mjs",
"test:startup:memory": "node scripts/ensure-cli-startup-build.mjs && node scripts/check-cli-startup-memory.mjs",
"test:ui": "pnpm ui:i18n:check && pnpm lint:ui:no-raw-window-open && pnpm --dir ui test",
"test:ui:e2e": "node scripts/run-vitest.mjs run --config test/vitest/vitest.ui-e2e.config.ts --configLoader runner",
"test:unit": "pnpm test:unit:fast && node scripts/run-vitest.mjs run --config test/vitest/vitest.unit.config.ts",

View File

@@ -0,0 +1,47 @@
#!/usr/bin/env node
import { spawnSync } from "node:child_process";
import { existsSync } from "node:fs";
import path from "node:path";
import { fileURLToPath, pathToFileURL } from "node:url";
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
const entryCandidates = ["dist/entry.js", "dist/entry.mjs"];
export function hasCliStartupBuild(params = {}) {
const rootDir = params.rootDir ?? repoRoot;
const exists = params.existsSync ?? existsSync;
return entryCandidates.some((relativePath) => exists(path.join(rootDir, relativePath)));
}
export function ensureCliStartupBuild(params = {}) {
const rootDir = params.rootDir ?? repoRoot;
if (hasCliStartupBuild({ rootDir, existsSync: params.existsSync })) {
return { built: false };
}
const nodeExecPath = params.nodeExecPath ?? process.execPath;
const spawn = params.spawnSync ?? spawnSync;
const buildScript = path.join(rootDir, "scripts", "build-all.mjs");
console.error("[cli-startup-build] dist/entry missing; running cliStartup build profile");
const result = spawn(nodeExecPath, [buildScript, "cliStartup"], {
cwd: rootDir,
env: params.env ?? process.env,
stdio: params.stdio ?? "inherit",
});
const status = result.status ?? (result.signal ? 1 : 0);
if (status !== 0) {
throw new Error(`cliStartup build profile failed with exit code ${status}`);
}
return { built: true };
}
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
try {
ensureCliStartupBuild();
} catch (error) {
console.error(error instanceof Error ? error.message : String(error));
process.exit(1);
}
}

View File

@@ -0,0 +1,88 @@
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import path from "node:path";
import { afterEach, describe, expect, it } from "vitest";
import {
ensureCliStartupBuild,
hasCliStartupBuild,
} from "../../scripts/ensure-cli-startup-build.mjs";
const tempRoots: string[] = [];
function makeTempRoot(): string {
const root = mkdtempSync(path.join(tmpdir(), "openclaw-cli-startup-build-"));
tempRoots.push(root);
mkdirSync(path.join(root, "scripts"), { recursive: true });
writeFileSync(path.join(root, "scripts", "build-all.mjs"), "", "utf8");
return root;
}
afterEach(() => {
for (const root of tempRoots.splice(0)) {
rmSync(root, { recursive: true, force: true });
}
});
describe("ensure-cli-startup-build", () => {
it("detects an existing CLI startup build", () => {
const root = makeTempRoot();
mkdirSync(path.join(root, "dist"), { recursive: true });
writeFileSync(path.join(root, "dist", "entry.js"), "export {};\n", "utf8");
expect(hasCliStartupBuild({ rootDir: root })).toBe(true);
});
it("skips the build profile when dist entry output already exists", () => {
const root = makeTempRoot();
mkdirSync(path.join(root, "dist"), { recursive: true });
writeFileSync(path.join(root, "dist", "entry.mjs"), "export {};\n", "utf8");
const result = ensureCliStartupBuild({
rootDir: root,
spawnSync: () => {
throw new Error("unexpected build");
},
});
expect(result).toEqual({ built: false });
});
it("runs the cliStartup build profile when dist entry output is missing", () => {
const root = makeTempRoot();
const calls: unknown[] = [];
const result = ensureCliStartupBuild({
rootDir: root,
nodeExecPath: "/node",
spawnSync: (command, args, options) => {
calls.push({ command, args, options });
return { status: 0 };
},
stdio: "pipe",
});
expect(result).toEqual({ built: true });
expect(calls).toEqual([
{
command: "/node",
args: [path.join(root, "scripts", "build-all.mjs"), "cliStartup"],
options: expect.objectContaining({
cwd: root,
stdio: "pipe",
}),
},
]);
});
it("fails when the cliStartup build profile fails", () => {
const root = makeTempRoot();
expect(() =>
ensureCliStartupBuild({
rootDir: root,
spawnSync: () => ({ status: 1 }),
stdio: "pipe",
}),
).toThrow("cliStartup build profile failed with exit code 1");
});
});