feat(FN-3262): harden CLI native bundle externalization with tests
The merge adds Step 2 of the native externalization hardening for the CLI package, including a minor changeset for `@runfusion/fusion` and tests validating bundle output and package configuration behavior. The changes strengthen the contract governing how native modules are handled during the build Fusion-Task-Id: FN-3262
This commit is contained in:
5
.changeset/fn-3262-cli-native-build-hardening.md
Normal file
5
.changeset/fn-3262-cli-native-build-hardening.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@runfusion/fusion": patch
|
||||
---
|
||||
|
||||
Hardened CLI packaging against native module build regressions by asserting `dockerode`/`ssh2`/`cpu-features` remain externalized in tsup bundle config, preventing native `.node` artifact strings from being inlined into the bundle, and declaring `dockerode` as a runtime dependency for published installs.
|
||||
@@ -57,6 +57,7 @@
|
||||
"dependencies": {
|
||||
"@mariozechner/pi-ai": "^0.72.1",
|
||||
"@mariozechner/pi-coding-agent": "^0.72.1",
|
||||
"dockerode": "^4.0.12",
|
||||
"express": "^5.1.0",
|
||||
"ink": "^6.8.0",
|
||||
"ink-spinner": "^5.0.0",
|
||||
|
||||
@@ -80,6 +80,14 @@ describe("CLI bundle output", () => {
|
||||
expect(tsupConfig).toContain("cpSync(dashboardClientSrc, dashboardClientDest, { recursive: true });");
|
||||
});
|
||||
|
||||
it("keeps native module loaders externalized in tsup config", () => {
|
||||
const tsupConfig = readFileSync(tsupConfigPath, "utf-8");
|
||||
|
||||
expect(tsupConfig).toContain('"dockerode"');
|
||||
expect(tsupConfig).toContain('"ssh2"');
|
||||
expect(tsupConfig).toContain('"cpu-features"');
|
||||
});
|
||||
|
||||
it("loads sqlite from Node built-ins and never from bare sqlite npm package", () => {
|
||||
const content = readFileSync(bundlePath, "utf-8");
|
||||
// The bundle must resolve sqlite through Node's built-in module.
|
||||
@@ -89,6 +97,12 @@ describe("CLI bundle output", () => {
|
||||
expect(content).not.toMatch(/from\s+["']sqlite["'][^s]/);
|
||||
});
|
||||
|
||||
it("does not inline native artifact filenames into the bundled CLI", () => {
|
||||
const content = readFileSync(bundlePath, "utf-8");
|
||||
expect(content).not.toContain("sshcrypto.node");
|
||||
expect(content).not.toContain("cpufeatures.node");
|
||||
});
|
||||
|
||||
it("provides require via createRequire banner", () => {
|
||||
const content = readFileSync(bundlePath, "utf-8");
|
||||
// Banner should inject createRequire for ESM CJS interop
|
||||
|
||||
@@ -78,6 +78,14 @@ describe("CLI package.json publishing config", () => {
|
||||
const deps = Object.keys(pkg.dependencies || {});
|
||||
expect(deps).toContain("ioredis");
|
||||
});
|
||||
|
||||
it("declares dockerode as a runtime dependency when kept external in CLI bundling", () => {
|
||||
const deps = Object.keys(pkg.dependencies || {});
|
||||
const devDeps = Object.keys(pkg.devDependencies || {});
|
||||
|
||||
expect(deps).toContain("dockerode");
|
||||
expect(devDeps).not.toContain("dockerode");
|
||||
});
|
||||
});
|
||||
|
||||
describe("Scoped @fusion/* packages publishing config", () => {
|
||||
|
||||
Reference in New Issue
Block a user