fix: stage npm updates under global root · openclaw/openclaw@2186080
shakkernerd
·
2026-04-27
·
via Recent Commits to openclaw:main
| Original file line number | Diff line number | Diff line change |
|---|
@@ -66,6 +66,16 @@ describe("inferUpdateFailureHints", () => {
|
66 | 66 | expect(hints.join("\n")).toContain("npm config set prefix ~/.local"); |
67 | 67 | }); |
68 | 68 | |
| 69 | +it("returns EACCES hint for staged package permission failures", () => { |
| 70 | +const result = makeResult( |
| 71 | +"global install stage", |
| 72 | +"EACCES: permission denied, mkdtemp '/usr/local/lib/node_modules/.openclaw-update-stage-'", |
| 73 | +); |
| 74 | +const hints = inferUpdateFailureHints(result); |
| 75 | +expect(hints.join("\n")).toContain("EACCES"); |
| 76 | +expect(hints.join("\n")).toContain("npm config set prefix ~/.local"); |
| 77 | +}); |
| 78 | + |
69 | 79 | it("returns native optional dependency hint for node-gyp failures", () => { |
70 | 80 | const result = makeResult("global update", "node-pre-gyp ERR!\nnode-gyp rebuild failed"); |
71 | 81 | const hints = inferUpdateFailureHints(result); |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -78,8 +78,10 @@ export function inferUpdateFailureHints(result: UpdateRunResult): string[] {
|
78 | 78 | |
79 | 79 | const stderr = normalizeLowercaseStringOrEmpty(failedStep.stderrTail); |
80 | 80 | const hints: string[] = []; |
| 81 | +const isGlobalPackageInstallStep = |
| 82 | +failedStep.name.startsWith("global update") || failedStep.name.startsWith("global install"); |
81 | 83 | |
82 | | -if (failedStep.name.startsWith("global update") && stderr.includes("eacces")) { |
| 84 | +if (isGlobalPackageInstallStep && stderr.includes("eacces")) { |
83 | 85 | hints.push( |
84 | 86 | "Detected permission failure (EACCES). Re-run with a writable global prefix or sudo (for system-managed Node installs).", |
85 | 87 | ); |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -66,6 +66,7 @@ describe("runGlobalPackageUpdateSteps", () => {
|
66 | 66 | if (!stagePrefix) { |
67 | 67 | throw new Error("missing staged prefix"); |
68 | 68 | } |
| 69 | +expect(path.dirname(stagePrefix)).toBe(globalRoot); |
69 | 70 | await writePackageRoot( |
70 | 71 | path.join(stagePrefix, "lib", "node_modules", "openclaw"), |
71 | 72 | "2.0.0", |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -62,7 +62,8 @@ async function createStagedNpmInstall(
|
62 | 62 | if (!targetLayout) { |
63 | 63 | return null; |
64 | 64 | } |
65 | | -const prefix = await fs.mkdtemp(path.join(targetLayout.prefix, ".openclaw-update-stage-")); |
| 65 | +await fs.mkdir(targetLayout.globalRoot, { recursive: true }); |
| 66 | +const prefix = await fs.mkdtemp(path.join(targetLayout.globalRoot, ".openclaw-update-stage-")); |
66 | 67 | const layout = resolveNpmGlobalPrefixLayoutFromPrefix(prefix); |
67 | 68 | return { |
68 | 69 | prefix, |
|
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。