From ff8bb24bb288028c8383d23b7920825ae9b953d3 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 11 Jul 2026 21:55:00 -0700 Subject: [PATCH] fix(release): restore pnpm package artifacts (#104975) (cherry picked from commit 0a2a6a2b742e316eaa82ba72d13344f272631e32) --- scripts/package-openclaw-for-docker.mjs | 53 +++++++++++-------- .../package-openclaw-for-docker.e2e.test.ts | 14 +++++ 2 files changed, 46 insertions(+), 21 deletions(-) diff --git a/scripts/package-openclaw-for-docker.mjs b/scripts/package-openclaw-for-docker.mjs index b7c1d5181d67..6761515a080e 100644 --- a/scripts/package-openclaw-for-docker.mjs +++ b/scripts/package-openclaw-for-docker.mjs @@ -135,6 +135,7 @@ export function parseArgs(argv) { outputDir: "", outputName: "", packJson: "", + pnpmPack: false, skipBuild: false, sourceDir: ROOT_DIR, }; @@ -177,6 +178,8 @@ export function parseArgs(argv) { "packJson", readEqualsOptionValue(arg.slice("--pack-json=".length), "--pack-json"), ); + } else if (arg === "--pnpm-pack") { + setOnce(arg, "pnpmPack", true); } else if (arg === "--skip-build") { setOnce(arg, "skipBuild", true); } else if (arg === "--source-dir") { @@ -195,6 +198,9 @@ export function parseArgs(argv) { if (options.outputName) { validateOutputName(options.outputName); } + if (options.packJson && options.pnpmPack) { + throw new Error("--pack-json cannot be combined with --pnpm-pack"); + } return options; } @@ -646,6 +652,10 @@ export async function packOpenClawPackageForDocker(sourceDir, outputDir, options })); const restoreChangelog = options.restoreChangelog ?? restorePackageChangelog; const prepareBundledAiRuntime = options.prepareBundledAiRuntime ?? prepareBundledAiRuntimePackage; + const packTool = options.pnpmPack ? "pnpm" : "npm"; + if (options.packJsonPath && options.pnpmPack) { + throw new Error("packJsonPath cannot be combined with pnpmPack"); + } console.error("==> Packing OpenClaw package"); await prepareChangelog(sourceDir); let packOutput; @@ -653,26 +663,24 @@ export async function packOpenClawPackageForDocker(sourceDir, outputDir, options try { await cleanPackedOpenClawTarballs(outputDir); cleanupBundledAiRuntime = await prepareBundledAiRuntime(sourceDir, outputDir, runCaptureImpl); - const packArgs = [ - "pack", - ...(options.packJsonPath ? ["--json"] : []), - "--silent", - "--ignore-scripts", - "--pack-destination", - outputDir, - ]; - packOutput = await runCaptureImpl( - "npm", - packArgs, - sourceDir, - { - deferForwardedSignalExit: true, - timeoutMs: resolveTimeoutMs( - "OPENCLAW_DOCKER_PACKAGE_PACK_TIMEOUT_MS", - DEFAULT_PACKAGE_PACK_TIMEOUT_MS, - ), - }, - ); + const packArgs = + packTool === "pnpm" + ? ["pack", "--silent", "--config.ignore-scripts=true", "--pack-destination", outputDir] + : [ + "pack", + ...(options.packJsonPath ? ["--json"] : []), + "--silent", + "--ignore-scripts", + "--pack-destination", + outputDir, + ]; + packOutput = await runCaptureImpl(packTool, packArgs, sourceDir, { + deferForwardedSignalExit: true, + timeoutMs: resolveTimeoutMs( + "OPENCLAW_DOCKER_PACKAGE_PACK_TIMEOUT_MS", + DEFAULT_PACKAGE_PACK_TIMEOUT_MS, + ), + }); } finally { try { await cleanupBundledAiRuntime(); @@ -680,7 +688,9 @@ export async function packOpenClawPackageForDocker(sourceDir, outputDir, options await restoreChangelog(sourceDir); } } - let tarball = await newestOpenClawTarball(outputDir, packOutput); + // pnpm reports an absolute destination path. Scan the freshly emptied output directory + // instead of accepting that command output as an artifact path. + let tarball = await newestOpenClawTarball(outputDir, options.pnpmPack ? "" : packOutput); if (options.outputName) { const target = path.join(outputDir, options.outputName); if (target !== tarball) { @@ -729,6 +739,7 @@ async function main() { allowUnreleasedChangelog: options.allowUnreleasedChangelog, outputName: options.outputName, packJsonPath: options.packJson, + pnpmPack: options.pnpmPack, }); console.error("==> Checking OpenClaw package tarball"); diff --git a/test/e2e/qa-lab/runtime/package-openclaw-for-docker.e2e.test.ts b/test/e2e/qa-lab/runtime/package-openclaw-for-docker.e2e.test.ts index 1e7132284827..3bc282abee69 100644 --- a/test/e2e/qa-lab/runtime/package-openclaw-for-docker.e2e.test.ts +++ b/test/e2e/qa-lab/runtime/package-openclaw-for-docker.e2e.test.ts @@ -98,6 +98,7 @@ describe("package-openclaw-for-docker", () => { outputDir: ".artifacts/docker", outputName: "openclaw-current.tgz", packJson: ".artifacts/docker/pack.json", + pnpmPack: false, skipBuild: true, sourceDir: "/repo", }); @@ -132,6 +133,19 @@ describe("package-openclaw-for-docker", () => { } }); + it("rejects pnpm pack with npm metadata output", async () => { + expect(parseArgs(["--pnpm-pack"]).pnpmPack).toBe(true); + expect(() => parseArgs(["--pnpm-pack", "--pack-json", "pack.json"])).toThrow( + "--pack-json cannot be combined with --pnpm-pack", + ); + await expect( + packOpenClawPackageForDocker("/repo", "/out", { + packJsonPath: "pack.json", + pnpmPack: true, + }), + ).rejects.toThrow("packJsonPath cannot be combined with pnpmPack"); + }); + it("rejects package artifact output names that escape the output directory", () => { for (const outputName of [ "../openclaw-current.tgz",