mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 08:20:43 +00:00
fix: tolerate pnpm-backed runtime dependency installs
This commit is contained in:
@@ -465,6 +465,19 @@ export function createNestedNpmInstallEnv(env = process.env) {
|
||||
return nextEnv;
|
||||
}
|
||||
|
||||
export function createBundledRuntimeDependencyInstallEnv(env = process.env) {
|
||||
return {
|
||||
...createNestedNpmInstallEnv(env),
|
||||
npm_config_legacy_peer_deps: "true",
|
||||
npm_config_package_lock: "false",
|
||||
npm_config_save: "false",
|
||||
};
|
||||
}
|
||||
|
||||
export function createBundledRuntimeDependencyInstallArgs(missingSpecs) {
|
||||
return ["install", "--ignore-scripts", ...missingSpecs];
|
||||
}
|
||||
|
||||
function shouldEagerInstallBundledPluginDeps(env = process.env) {
|
||||
return env?.[EAGER_BUNDLED_PLUGIN_DEPS_ENV]?.trim() === "1";
|
||||
}
|
||||
@@ -756,28 +769,21 @@ export function runBundledPluginPostinstall(params = {}) {
|
||||
}
|
||||
|
||||
try {
|
||||
const nestedEnv = createNestedNpmInstallEnv(env);
|
||||
const installEnv = createBundledRuntimeDependencyInstallEnv(env);
|
||||
const npmRunner =
|
||||
params.npmRunner ??
|
||||
resolveNpmRunner({
|
||||
env: nestedEnv,
|
||||
env: installEnv,
|
||||
execPath: params.execPath,
|
||||
existsSync: pathExists,
|
||||
platform: params.platform,
|
||||
comSpec: params.comSpec,
|
||||
npmArgs: [
|
||||
"install",
|
||||
"--omit=dev",
|
||||
"--no-save",
|
||||
"--package-lock=false",
|
||||
"--legacy-peer-deps",
|
||||
...missingSpecs,
|
||||
],
|
||||
npmArgs: createBundledRuntimeDependencyInstallArgs(missingSpecs),
|
||||
});
|
||||
const result = spawn(npmRunner.command, npmRunner.args, {
|
||||
cwd: packageRoot,
|
||||
encoding: "utf8",
|
||||
env: npmRunner.env ?? nestedEnv,
|
||||
env: npmRunner.env ?? installEnv,
|
||||
stdio: "pipe",
|
||||
shell: npmRunner.shell,
|
||||
windowsVerbatimArguments: npmRunner.windowsVerbatimArguments,
|
||||
|
||||
@@ -829,8 +829,11 @@ function runNpmInstall(params) {
|
||||
CI: "1",
|
||||
npm_config_audit: "false",
|
||||
npm_config_fund: "false",
|
||||
npm_config_legacy_peer_deps: "true",
|
||||
npm_config_loglevel: "error",
|
||||
npm_config_package_lock: "false",
|
||||
npm_config_progress: "false",
|
||||
npm_config_save: "false",
|
||||
npm_config_yes: "true",
|
||||
};
|
||||
const result = spawnSync(params.npmRunner.command, params.npmRunner.args, {
|
||||
@@ -1045,16 +1048,7 @@ function installPluginRuntimeDeps(params) {
|
||||
runNpmInstall({
|
||||
cwd: tempInstallDir,
|
||||
npmRunner: resolveNpmRunner({
|
||||
npmArgs: [
|
||||
"install",
|
||||
"--omit=dev",
|
||||
"--no-audit",
|
||||
"--no-fund",
|
||||
"--ignore-scripts",
|
||||
"--legacy-peer-deps",
|
||||
"--package-lock=false",
|
||||
"--silent",
|
||||
],
|
||||
npmArgs: ["install", "--no-audit", "--no-fund", "--ignore-scripts", "--silent"],
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@ import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import {
|
||||
createBundledRuntimeDepsInstallArgs,
|
||||
createBundledRuntimeDepsInstallEnv,
|
||||
ensureBundledPluginRuntimeDeps,
|
||||
installBundledRuntimeDeps,
|
||||
resolveBundledRuntimeDepsNpmRunner,
|
||||
@@ -47,6 +49,26 @@ describe("resolveBundledRuntimeDepsNpmRunner", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("uses package-manager-neutral install args with npm config env", () => {
|
||||
expect(createBundledRuntimeDepsInstallArgs(["acpx@0.5.3"])).toEqual([
|
||||
"install",
|
||||
"--ignore-scripts",
|
||||
"acpx@0.5.3",
|
||||
]);
|
||||
expect(
|
||||
createBundledRuntimeDepsInstallEnv({
|
||||
PATH: "/usr/bin:/bin",
|
||||
npm_config_global: "true",
|
||||
npm_config_prefix: "/opt/homebrew",
|
||||
}),
|
||||
).toEqual({
|
||||
PATH: "/usr/bin:/bin",
|
||||
npm_config_legacy_peer_deps: "true",
|
||||
npm_config_package_lock: "false",
|
||||
npm_config_save: "false",
|
||||
});
|
||||
});
|
||||
|
||||
it("uses the Node-adjacent npm CLI on Windows", () => {
|
||||
const execPath = "C:\\Program Files\\nodejs\\node.exe";
|
||||
const npmCliPath = path.win32.resolve(
|
||||
@@ -126,20 +148,21 @@ describe("installBundledRuntimeDeps", () => {
|
||||
|
||||
expect(spawnSyncMock).toHaveBeenCalledWith(
|
||||
"npm.cmd",
|
||||
[
|
||||
"install",
|
||||
"--prefix",
|
||||
"C:\\openclaw",
|
||||
"--omit=dev",
|
||||
"--no-save",
|
||||
"--package-lock=false",
|
||||
"--ignore-scripts",
|
||||
"--legacy-peer-deps",
|
||||
"acpx@0.5.3",
|
||||
],
|
||||
["install", "--ignore-scripts", "acpx@0.5.3"],
|
||||
expect.objectContaining({
|
||||
cwd: "C:\\openclaw",
|
||||
shell: true,
|
||||
env: expect.objectContaining({
|
||||
npm_config_legacy_peer_deps: "true",
|
||||
npm_config_package_lock: "false",
|
||||
npm_config_save: "false",
|
||||
}),
|
||||
}),
|
||||
);
|
||||
expect(spawnSyncMock).toHaveBeenCalledWith(
|
||||
expect.any(String),
|
||||
expect.any(Array),
|
||||
expect.objectContaining({
|
||||
env: expect.not.objectContaining({
|
||||
npm_config_prefix: expect.any(String),
|
||||
}),
|
||||
|
||||
@@ -187,6 +187,19 @@ function createNestedNpmInstallEnv(env: NodeJS.ProcessEnv): NodeJS.ProcessEnv {
|
||||
return nextEnv;
|
||||
}
|
||||
|
||||
export function createBundledRuntimeDepsInstallEnv(env: NodeJS.ProcessEnv): NodeJS.ProcessEnv {
|
||||
return {
|
||||
...createNestedNpmInstallEnv(env),
|
||||
npm_config_legacy_peer_deps: "true",
|
||||
npm_config_package_lock: "false",
|
||||
npm_config_save: "false",
|
||||
};
|
||||
}
|
||||
|
||||
export function createBundledRuntimeDepsInstallArgs(missingSpecs: readonly string[]): string[] {
|
||||
return ["install", "--ignore-scripts", ...missingSpecs];
|
||||
}
|
||||
|
||||
function resolvePathEnvKey(env: NodeJS.ProcessEnv, platform: NodeJS.Platform): string {
|
||||
if (platform !== "win32") {
|
||||
return "PATH";
|
||||
@@ -457,24 +470,15 @@ export function installBundledRuntimeDeps(params: {
|
||||
missingSpecs: string[];
|
||||
env: NodeJS.ProcessEnv;
|
||||
}): void {
|
||||
const installEnv = createBundledRuntimeDepsInstallEnv(params.env);
|
||||
const npmRunner = resolveBundledRuntimeDepsNpmRunner({
|
||||
env: params.env,
|
||||
npmArgs: [
|
||||
"install",
|
||||
"--prefix",
|
||||
params.installRoot,
|
||||
"--omit=dev",
|
||||
"--no-save",
|
||||
"--package-lock=false",
|
||||
"--ignore-scripts",
|
||||
"--legacy-peer-deps",
|
||||
...params.missingSpecs,
|
||||
],
|
||||
env: installEnv,
|
||||
npmArgs: createBundledRuntimeDepsInstallArgs(params.missingSpecs),
|
||||
});
|
||||
const result = spawnSync(npmRunner.command, npmRunner.args, {
|
||||
cwd: params.installRoot,
|
||||
encoding: "utf8",
|
||||
env: createNestedNpmInstallEnv(npmRunner.env ?? params.env),
|
||||
env: npmRunner.env ?? installEnv,
|
||||
stdio: "pipe",
|
||||
shell: npmRunner.shell ?? false,
|
||||
});
|
||||
|
||||
@@ -2,6 +2,8 @@ import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import {
|
||||
createBundledRuntimeDependencyInstallArgs,
|
||||
createBundledRuntimeDependencyInstallEnv,
|
||||
createNestedNpmInstallEnv,
|
||||
pruneInstalledPackageDist,
|
||||
discoverBundledPluginRuntimeDeps,
|
||||
@@ -47,14 +49,7 @@ async function writePluginPackage(
|
||||
|
||||
describe("bundled plugin postinstall", () => {
|
||||
function createNpmInstallArgs(...packages: string[]) {
|
||||
return [
|
||||
"install",
|
||||
"--omit=dev",
|
||||
"--no-save",
|
||||
"--package-lock=false",
|
||||
"--legacy-peer-deps",
|
||||
...packages,
|
||||
];
|
||||
return createBundledRuntimeDependencyInstallArgs(packages);
|
||||
}
|
||||
|
||||
function createBareNpmRunner(packages: string[]) {
|
||||
@@ -122,6 +117,25 @@ describe("bundled plugin postinstall", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("uses package-manager-neutral runtime install args with npm config env", () => {
|
||||
expect(createBundledRuntimeDependencyInstallArgs(["acpx@0.4.1"])).toEqual([
|
||||
"install",
|
||||
"--ignore-scripts",
|
||||
"acpx@0.4.1",
|
||||
]);
|
||||
expect(
|
||||
createBundledRuntimeDependencyInstallEnv({
|
||||
HOME: "/tmp/home",
|
||||
npm_config_prefix: "/opt/homebrew",
|
||||
}),
|
||||
).toEqual({
|
||||
HOME: "/tmp/home",
|
||||
npm_config_legacy_peer_deps: "true",
|
||||
npm_config_package_lock: "false",
|
||||
npm_config_save: "false",
|
||||
});
|
||||
});
|
||||
|
||||
it("does not install bundled plugin deps outside of source checkouts by default", async () => {
|
||||
const extensionsDir = await createExtensionsDir();
|
||||
const packageRoot = path.dirname(path.dirname(extensionsDir));
|
||||
|
||||
Reference in New Issue
Block a user