diff --git a/scripts/check-openclaw-package-tarball.mjs b/scripts/check-openclaw-package-tarball.mjs index 16419e6af80c..96b9d7265062 100644 --- a/scripts/check-openclaw-package-tarball.mjs +++ b/scripts/check-openclaw-package-tarball.mjs @@ -258,6 +258,8 @@ function collectRequiredBundledWorkspaceDependencyErrors( } const phaseTimingsEnabled = process.env.OPENCLAW_PACKAGE_TARBALL_CHECK_TIMINGS !== "0"; +// Self-contained artifacts can exceed Node's 1 MiB spawnSync output default. +const TAR_LIST_MAX_BUFFER_BYTES = 64 * 1024 * 1024; function runPhase(label, action) { const startedAt = performance.now(); try { @@ -273,11 +275,12 @@ function runPhase(label, action) { const list = runPhase("tar list", () => spawnSync("tar", ["-tf", tarball], { encoding: "utf8", + maxBuffer: TAR_LIST_MAX_BUFFER_BYTES, stdio: ["ignore", "pipe", "pipe"], }), ); if (list.status !== 0) { - fail(`tar -tf failed for ${tarball}: ${list.stderr || list.status}`); + fail(`tar -tf failed for ${tarball}: ${list.stderr || list.error?.message || list.status}`); } const extractDir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-package-tarball-")); diff --git a/test/scripts/check-openclaw-package-tarball.test.ts b/test/scripts/check-openclaw-package-tarball.test.ts index 9b98d7448f6a..e6ab4311f873 100644 --- a/test/scripts/check-openclaw-package-tarball.test.ts +++ b/test/scripts/check-openclaw-package-tarball.test.ts @@ -17,6 +17,7 @@ import { PACKAGE_INSTALL_GUARD_RELATIVE_PATH } from "../../scripts/lib/package-d import { WORKSPACE_TEMPLATE_PACK_PATHS } from "../../scripts/lib/workspace-bootstrap-smoke.mjs"; const CHECK_SCRIPT = "scripts/check-openclaw-package-tarball.mjs"; +const NODE_DEFAULT_SPAWN_MAX_BUFFER_BYTES = 1024 * 1024; const FLAT_PLUGIN_SDK_DECLARATION = "dist/plugin-sdk/provider-entry.d.ts"; const DEEP_PLUGIN_SDK_DECLARATION = "dist/plugin-sdk/src/plugin-sdk/provider-entry.d.ts"; const AI_RUNTIME_PACKAGE_JSON = JSON.stringify({ @@ -140,6 +141,36 @@ describe("check-openclaw-package-tarball", () => { expect(extra.stderr).not.toContain("OpenClaw package tarball does not exist"); }); + it("accepts tarballs whose entry list exceeds Node's default spawn buffer", () => { + const longNameSuffix = "x".repeat(80); + const largeEntryList = Object.fromEntries( + Array.from({ length: 8_000 }, (_, index) => [ + `dist/control-ui/assets/large-entry-list/asset-${String(index).padStart(5, "0")}-${longNameSuffix}.txt`, + "", + ]), + ); + + withTarball( + ["dist/index.js"], + { "dist/index.js": "export {};\n", ...largeEntryList }, + (tarball) => { + const listing = spawnSync("tar", ["-tf", tarball], { + encoding: "utf8", + maxBuffer: NODE_DEFAULT_SPAWN_MAX_BUFFER_BYTES * 2, + }); + expect(listing.status, listing.stderr).toBe(0); + expect(Buffer.byteLength(listing.stdout)).toBeGreaterThan( + NODE_DEFAULT_SPAWN_MAX_BUFFER_BYTES, + ); + + const result = spawnSync("node", [CHECK_SCRIPT, tarball], { encoding: "utf8" }); + + expect(result.status, result.stderr).toBe(0); + expect(result.stdout).toContain("OpenClaw package tarball integrity passed."); + }, + ); + }); + it.runIf(process.platform !== "win32")( "removes the extract dir when tar extraction fails", () => {