diff --git a/changelog.d/fixes/6908-standalone-head-response-guard.md b/changelog.d/fixes/6908-standalone-head-response-guard.md new file mode 100644 index 000000000000..3bb36703a60f --- /dev/null +++ b/changelog.d/fixes/6908-standalone-head-response-guard.md @@ -0,0 +1 @@ +- **fix(cli):** ship `head-response-guard.cjs` into the standalone bundle — `server-ws.mjs` imported it without a matching `EXTRA_MODULE_ENTRIES` entry, so every `build:release` dist crashed at boot with `ERR_MODULE_NOT_FOUND`; a new regression test derives the required sidecars from `server-ws.mjs` imports (#6908) diff --git a/scripts/build/assembleStandalone.mjs b/scripts/build/assembleStandalone.mjs index 6ee88d58a7f7..b0d8892b2740 100644 --- a/scripts/build/assembleStandalone.mjs +++ b/scripts/build/assembleStandalone.mjs @@ -22,6 +22,7 @@ * scripts/dev/standalone-server-ws.mjs -> outDir/server-ws Y Y - SHARED (extra module) * scripts/dev/peer-stamp.mjs -> outDir/peer-stamp.mjs Y Y - SHARED (extra module) * scripts/dev/responses-ws-proxy.mjs -> outDir/responses-ws- Y Y - SHARED (extra module) + * scripts/dev/head-response-guard.cjs -> outDir/head-respons Y Y - SHARED (extra module) * scripts/build/runtime-env.mjs -> outDir/build/runtime-env Y - - SHARED (extra module) * scripts/build/bootstrap-env.mjs -> outDir/build/bootstrap- Y - - SHARED (extra module) * scripts/dev/healthcheck.mjs -> outDir/healthcheck.mjs Y - - SHARED (extra module) @@ -139,6 +140,11 @@ const EXTRA_MODULE_ENTRIES = [ src: ["scripts", "dev", "http-method-guard.cjs"], dest: ["http-method-guard.cjs"], }, + { + label: "HEAD response guard (server-ws.mjs dependency)", + src: ["scripts", "dev", "head-response-guard.cjs"], + dest: ["head-response-guard.cjs"], + }, { label: "responses-ws-proxy (server-ws.mjs dependency)", src: ["scripts", "dev", "responses-ws-proxy.mjs"], diff --git a/tests/unit/build/assemble-standalone.test.ts b/tests/unit/build/assemble-standalone.test.ts index a5c039ed13f6..9fefa5890ea3 100644 --- a/tests/unit/build/assemble-standalone.test.ts +++ b/tests/unit/build/assemble-standalone.test.ts @@ -159,3 +159,28 @@ test("the TPROXY addon source is skipped gracefully when it was not built (non-L ); fs.rmSync(tmp, { recursive: true, force: true }); }); + +// Regression guard (#deploy 2026-07-11): server-ws.mjs gained an import of +// head-response-guard.cjs without a matching EXTRA_MODULE_ENTRIES entry, so every +// build:release bundle crashed at boot with ERR_MODULE_NOT_FOUND. This test derives +// the requirement from the source itself: EVERY relative import in +// standalone-server-ws.mjs must be shipped into the bundle by the extra-module sync. +test("every relative import of standalone-server-ws.mjs is shipped into the bundle", async () => { + const repoRoot = path.resolve(new URL(".", import.meta.url).pathname, "../../.."); + const serverWsSrc = fs.readFileSync( + path.join(repoRoot, "scripts/dev/standalone-server-ws.mjs"), + "utf8" + ); + const relImports = [...serverWsSrc.matchAll(/from\s+"\.\/([^"]+)"/g)].map((m) => m[1]); + assert.ok(relImports.length > 0, "server-ws.mjs has relative imports to check"); + + const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "assemble-serverws-")); + await syncStandaloneExtraModules(repoRoot, fs.promises, { log() {} }, tmp); + for (const imp of relImports) { + assert.ok( + fs.existsSync(path.join(tmp, imp)), + `server-ws.mjs imports ./${imp} but EXTRA_MODULE_ENTRIES does not ship it — the bundle would crash at boot (ERR_MODULE_NOT_FOUND)` + ); + } + fs.rmSync(tmp, { recursive: true, force: true }); +});