






















@@ -385,6 +385,129 @@ describe("runGatewayUpdate", () => {
385385expect(calls).not.toContain("pnpm ui:build");
386386});
387387388+it("uses pnpm highest resolution mode for update installs", async () => {
389+await setupGitCheckout({ packageManager: "pnpm@8.0.0" });
390+await setupUiIndex();
391+const stableTag = "v1.0.1-1";
392+const installEnvs: NodeJS.ProcessEnv[] = [];
393+const doctorNodePath = await resolveStableNodePath(process.execPath);
394+const { runCommand } = createGitInstallRunner({
395+ stableTag,
396+installCommand: "pnpm install",
397+buildCommand: "pnpm build",
398+uiBuildCommand: "pnpm ui:build",
399+doctorCommand: `${doctorNodePath} ${path.join(tempDir, "openclaw.mjs")} doctor --non-interactive --fix`,
400+onCommand: (key, options) => {
401+if (key === "pnpm install") {
402+installEnvs.push(options?.env ?? {});
403+}
404+return undefined;
405+},
406+});
407+408+const result = await runWithCommand(runCommand, { channel: "stable" });
409+410+expect(result.status).toBe("ok");
411+expect(installEnvs).toHaveLength(1);
412+expect(installEnvs[0]).toMatchObject({
413+PNPM_CONFIG_RESOLUTION_MODE: "highest",
414+npm_config_resolution_mode: "highest",
415+pnpm_config_resolution_mode: "highest",
416+});
417+});
418+419+it("uses pnpm highest resolution mode for dev preflight installs", async () => {
420+await setupGitPackageManagerFixture();
421+const upstreamSha = "upstream123";
422+const installEnvs: NodeJS.ProcessEnv[] = [];
423+const doctorNodePath = await resolveStableNodePath(process.execPath);
424+const doctorCommand = `${doctorNodePath} ${path.join(tempDir, "openclaw.mjs")} doctor --non-interactive --fix`;
425+426+const runCommand = async (
427+argv: string[],
428+options?: { env?: NodeJS.ProcessEnv; cwd?: string; timeoutMs?: number },
429+) => {
430+const key = argv.join(" ");
431+if (key === `git -C ${tempDir} rev-parse --show-toplevel`) {
432+return { stdout: tempDir, stderr: "", code: 0 };
433+}
434+if (key === `git -C ${tempDir} rev-parse HEAD`) {
435+return { stdout: "abc123", stderr: "", code: 0 };
436+}
437+if (key === `git -C ${tempDir} rev-parse --abbrev-ref HEAD`) {
438+return { stdout: "main", stderr: "", code: 0 };
439+}
440+if (key === `git -C ${tempDir} status --porcelain -- :!dist/control-ui/`) {
441+return { stdout: "", stderr: "", code: 0 };
442+}
443+if (key === `git -C ${tempDir} rev-parse --abbrev-ref --symbolic-full-name @{upstream}`) {
444+return { stdout: "origin/main", stderr: "", code: 0 };
445+}
446+if (key === `git -C ${tempDir} fetch --all --prune --tags`) {
447+return { stdout: "", stderr: "", code: 0 };
448+}
449+if (key === `git -C ${tempDir} rev-parse @{upstream}`) {
450+return { stdout: upstreamSha, stderr: "", code: 0 };
451+}
452+if (key === `git -C ${tempDir} rev-list --max-count=10 ${upstreamSha}`) {
453+return { stdout: `${upstreamSha}\n`, stderr: "", code: 0 };
454+}
455+if (key === "pnpm --version") {
456+return { stdout: "10.0.0", stderr: "", code: 0 };
457+}
458+if (
459+key.startsWith(`git -C ${tempDir} worktree add --detach /tmp/`) &&
460+key.endsWith(` ${upstreamSha}`) &&
461+preflightPrefixPattern.test(key)
462+) {
463+return { stdout: `HEAD is now at ${upstreamSha}`, stderr: "", code: 0 };
464+}
465+if (
466+key.startsWith("git -C /tmp/") &&
467+preflightPrefixPattern.test(key) &&
468+key.includes(" checkout --detach ") &&
469+key.endsWith(upstreamSha)
470+) {
471+return { stdout: "", stderr: "", code: 0 };
472+}
473+if (key === "pnpm install") {
474+installEnvs.push(options?.env ?? {});
475+return { stdout: "", stderr: "", code: 0 };
476+}
477+if (key === "pnpm build" || key === "pnpm ui:build") {
478+return { stdout: "", stderr: "", code: 0 };
479+}
480+if (
481+key.startsWith(`git -C ${tempDir} worktree remove --force /tmp/`) &&
482+preflightPrefixPattern.test(key)
483+) {
484+return { stdout: "", stderr: "", code: 0 };
485+}
486+if (key === `git -C ${tempDir} worktree prune`) {
487+return { stdout: "", stderr: "", code: 0 };
488+}
489+if (key === `git -C ${tempDir} rebase ${upstreamSha}`) {
490+return { stdout: "", stderr: "", code: 0 };
491+}
492+if (key === doctorCommand) {
493+return { stdout: "", stderr: "", code: 0 };
494+}
495+return { stdout: "", stderr: "", code: 0 };
496+};
497+498+const result = await runWithCommand(runCommand, { channel: "dev" });
499+500+expect(result.status).toBe("ok");
501+expect(installEnvs).toHaveLength(2);
502+for (const env of installEnvs) {
503+expect(env).toMatchObject({
504+PNPM_CONFIG_RESOLUTION_MODE: "highest",
505+npm_config_resolution_mode: "highest",
506+pnpm_config_resolution_mode: "highest",
507+});
508+}
509+});
510+388511it("returns error and stops early when build fails", async () => {
389512await setupGitCheckout({ packageManager: "pnpm@8.0.0" });
390513const stableTag = "v1.0.1-1";
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。