perf(cli): skip native-binary build tests by default

The build-exe and build-exe-cross suites invoke `bun build` in beforeAll
hooks and pegged CPU for ~6 min on every test run (one cached-on-miss
build plus three unconditional cross-target builds). Move them to a
dedicated vitest project, skip them unless CI=1 or FUSION_TEST_BUILD_EXE=1
is set, and add cache guards so CI re-runs skip rebuilds when the target
binary already exists. With build-exe out of the default cli run, the
main config can enable fileParallelism.

Run on demand via `pnpm --filter @runfusion/fusion test:build-exe`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsxdsm
2026-04-23 22:34:05 -07:00
parent 5f7cba63d6
commit fcf47d2c77
5 changed files with 67 additions and 10 deletions

View File

@@ -42,7 +42,8 @@
"build:exe": "bun run build.ts",
"build:exe:all": "bun run build.ts --all",
"typecheck": "tsc --noEmit",
"test": "vitest run --silent=passed-only --reporter=dot"
"test": "vitest run --silent=passed-only --reporter=dot",
"test:build-exe": "FUSION_TEST_BUILD_EXE=1 vitest run --config vitest.build-exe.config.ts --silent=passed-only --reporter=dot"
},
"dependencies": {
"@fusion/pi-claude-cli": "workspace:*",

View File

@@ -38,9 +38,15 @@ function nativeTarget(): string | null {
return `bun-${platform}-${arch}`;
}
describe("build-exe-cross: single target", () => {
// Cross-compiling native binaries pegs CPU for ~60s per target. Skip by
// default locally; opt in with FUSION_TEST_BUILD_EXE=1 or run on CI.
const SHOULD_RUN_BUILD_EXE =
Boolean(process.env.FUSION_TEST_BUILD_EXE) || Boolean(process.env.CI);
describe.skipIf(!SHOULD_RUN_BUILD_EXE)("build-exe-cross: single target", () => {
beforeAll(() => {
// Build for linux-x64 specifically
const bin = join(distDir, "fn-linux-x64");
if (existsSync(bin)) return;
execSync("bun run build.ts --target bun-linux-x64", {
cwd: cliRoot,
stdio: "pipe",
@@ -59,8 +65,10 @@ describe("build-exe-cross: single target", () => {
});
});
describe("build-exe-cross: windows target has .exe extension", () => {
describe.skipIf(!SHOULD_RUN_BUILD_EXE)("build-exe-cross: windows target has .exe extension", () => {
beforeAll(() => {
const bin = join(distDir, "fn-windows-x64.exe");
if (existsSync(bin)) return;
execSync("bun run build.ts --target bun-windows-x64", {
cwd: cliRoot,
stdio: "pipe",
@@ -75,8 +83,12 @@ describe("build-exe-cross: windows target has .exe extension", () => {
});
});
describe("build-exe-cross: --all builds all platforms", () => {
describe.skipIf(!SHOULD_RUN_BUILD_EXE)("build-exe-cross: --all builds all platforms", () => {
beforeAll(() => {
const allBuilt = SUPPORTED_TARGETS.every((target) =>
existsSync(join(distDir, expectedBinaryName(target))),
);
if (allBuilt) return;
execSync("bun run build.ts --all", {
cwd: cliRoot,
stdio: "pipe",
@@ -147,8 +159,11 @@ describe("build-exe-cross: --all builds all platforms", () => {
}, 60_000);
});
describe("build-exe-cross: default (no args) backward compatibility", () => {
describe.skipIf(!SHOULD_RUN_BUILD_EXE)("build-exe-cross: default (no args) backward compatibility", () => {
beforeAll(() => {
const defaultName = process.platform === "win32" ? "fn.exe" : "fn";
const bin = join(distDir, defaultName);
if (existsSync(bin)) return;
execSync("bun run build.ts", {
cwd: cliRoot,
stdio: "pipe",

View File

@@ -61,7 +61,12 @@ async function stopChildProcess(child: ChildProcess | null): Promise<void> {
});
}
describe("build-exe", () => {
// Native-binary build tests are expensive (~2 min of pegged CPU). Skip by
// default locally; opt in with FUSION_TEST_BUILD_EXE=1 or run on CI.
const SHOULD_RUN_BUILD_EXE =
Boolean(process.env.FUSION_TEST_BUILD_EXE) || Boolean(process.env.CI);
describe.skipIf(!SHOULD_RUN_BUILD_EXE)("build-exe", () => {
beforeAll(() => {
// Build the executable (skip if already built to speed up re-runs)
if (!existsSync(outBinary)) {

View File

@@ -0,0 +1,34 @@
import { defineConfig } from "vitest/config";
import { resolve } from "node:path";
// Separate project for the native-binary build tests. These invoke `bun build`
// and can peg CPU for minutes. They are skipped by default (see skipIf guards
// inside the test files) and run via `pnpm test:build-exe` or when CI=1 /
// FUSION_TEST_BUILD_EXE=1 is set.
//
// fileParallelism is false here because both suites write to packages/cli/dist/
// and would race each other in parallel workers.
export default defineConfig({
resolve: {
alias: [
{ find: /^@fusion\/core\/gh-cli$/, replacement: resolve(__dirname, "../core/src/gh-cli.ts") },
{ find: /^@fusion\/core$/, replacement: resolve(__dirname, "../core/src/index.ts") },
{ find: /^@fusion\/dashboard\/planning$/, replacement: resolve(__dirname, "../dashboard/src/planning.ts") },
{ find: /^@fusion\/dashboard$/, replacement: resolve(__dirname, "../dashboard/src/index.ts") },
{ find: /^@fusion\/engine$/, replacement: resolve(__dirname, "../engine/src/index.ts") },
{ find: /^@fusion\/test-utils$/, replacement: resolve(__dirname, "../core/src/__test-utils__/workspace.ts") },
],
},
test: {
include: ["src/__tests__/build-exe*.test.ts"],
setupFiles: [
"./src/__tests__/setup-test-isolation.ts",
resolve(__dirname, "../core/src/__test-utils__/vitest-setup.ts"),
],
globalSetup: [resolve(__dirname, "../core/src/__test-utils__/vitest-teardown.ts")],
fileParallelism: false,
testTimeout: 360_000,
hookTimeout: 360_000,
},
});

View File

@@ -23,6 +23,10 @@ export default defineConfig({
},
test: {
include: ["src/**/*.test.ts"],
// build-exe + build-exe-cross live in their own vitest project
// (see vitest.build-exe.config.ts) so the rest of the CLI suite can
// run with file parallelism enabled.
exclude: ["**/node_modules/**", "**/dist/**", "src/__tests__/build-exe*.test.ts"],
setupFiles: [
"./src/__tests__/setup-test-isolation.ts",
resolve(__dirname, "../core/src/__test-utils__/vitest-setup.ts"),
@@ -30,9 +34,7 @@ export default defineConfig({
globalSetup: [resolve(__dirname, "../core/src/__test-utils__/vitest-teardown.ts")],
maxWorkers,
poolOptions: { threads: { minThreads: 1, maxThreads: maxWorkers }, forks: { minForks: 1, maxForks: maxWorkers } },
// build-exe and build-exe-cross suites both operate on packages/cli/dist/
// and can race when run in parallel workers.
fileParallelism: false,
fileParallelism: true,
coverage: {
enabled: false,
reporter: ["text", "html", "json"],