

















@@ -1,5 +1,5 @@
11import { spawnSync } from "node:child_process";
2-import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
2+import { chmodSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
33import { tmpdir } from "node:os";
44import path from "node:path";
55import { afterEach, describe, expect, it } from "vitest";
@@ -36,6 +36,17 @@ function runHelper(script: string) {
3636});
3737}
383839+function getPackageManagerHelperBlock(): string {
40+const script = readFileSync(scriptPath, "utf8");
41+const start = script.indexOf("PNPM_CMD=()");
42+const end = script.indexOf("merge_framework_machos()");
43+44+expect(start).toBeGreaterThanOrEqual(0);
45+expect(end).toBeGreaterThan(start);
46+47+return script.slice(start, end);
48+}
49+3950afterEach(() => {
4051for (const dir of tempDirs.splice(0)) {
4152rmSync(dir, { recursive: true, force: true });
@@ -50,11 +61,71 @@ describe("package-mac-app plist stamping", () => {
5061script.indexOf('if [[ -z "${APP_BUILD:-}" ]]'),
5162);
526353-expect(installBlock).toContain("pnpm install --frozen-lockfile");
64+expect(installBlock).toContain("run_pnpm install --frozen-lockfile");
5465expect(installBlock).toContain("--config.node-linker=hoisted");
5566expect(installBlock).not.toContain("--no-frozen-lockfile");
5667});
576869+it("falls back to corepack pnpm when the pnpm shim is absent", () => {
70+const helperBlock = getPackageManagerHelperBlock();
71+const tempRoot = mkdtempSync(path.join(tmpdir(), "openclaw-package-pnpm-root-"));
72+const toolsDir = mkdtempSync(path.join(tmpdir(), "openclaw-package-pnpm-tools-"));
73+const logPath = path.join(tempRoot, "corepack.log");
74+tempDirs.push(tempRoot, toolsDir);
75+76+const corepackPath = path.join(toolsDir, "corepack");
77+writeFileSync(
78+corepackPath,
79+[
80+"#!/usr/bin/env bash",
81+"set -euo pipefail",
82+"printf '%s|%s\\n' \"$PWD\" \"$*\" >> \"$OPENCLAW_TEST_LOG\"",
83+"if [[ \"${1:-}\" == \"pnpm\" && \"${2:-}\" == \"--version\" ]]; then",
84+" echo '11.2.2'",
85+"fi",
86+"",
87+].join("\n"),
88+"utf8",
89+);
90+chmodSync(corepackPath, 0o755);
91+92+const result = runHelper(`
93+ set -euo pipefail
94+ ROOT_DIR=${JSON.stringify(tempRoot)}
95+ OPENCLAW_TEST_LOG=${JSON.stringify(logPath)}
96+ export OPENCLAW_TEST_LOG
97+ PATH=${JSON.stringify(`${toolsDir}:/usr/bin:/bin`)}
98+ ${helperBlock}
99+ run_pnpm install --frozen-lockfile --config.node-linker=hoisted
100+ run_pnpm build
101+ `);
102+103+expect(result.status).toBe(0);
104+expect(readFileSync(logPath, "utf8").trim().split("\n")).toEqual([
105+`${tempRoot}|pnpm --version`,
106+`${tempRoot}|pnpm install --frozen-lockfile --config.node-linker=hoisted`,
107+`${tempRoot}|pnpm build`,
108+]);
109+});
110+111+it("fails with an actionable error when neither pnpm nor corepack pnpm is available", () => {
112+const helperBlock = getPackageManagerHelperBlock();
113+const tempRoot = mkdtempSync(path.join(tmpdir(), "openclaw-package-pnpm-root-"));
114+const toolsDir = mkdtempSync(path.join(tmpdir(), "openclaw-package-pnpm-tools-"));
115+tempDirs.push(tempRoot, toolsDir);
116+117+const result = runHelper(`
118+ set -euo pipefail
119+ ROOT_DIR=${JSON.stringify(tempRoot)}
120+ PATH=${JSON.stringify(`${toolsDir}:/usr/bin:/bin`)}
121+ ${helperBlock}
122+ run_pnpm build
123+ `);
124+125+expect(result.status).toBe(1);
126+expect(result.stderr).toContain("pnpm is not on PATH and corepack pnpm is unavailable");
127+});
128+58129it("does not kill unrelated OpenClaw processes during packaging", () => {
59130const script = readFileSync(scriptPath, "utf8");
60131const stopBlock = script.slice(
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。