fix(install): inject execPath for nvm detection in service env builder

This commit is contained in:
GodsBoy 2026-03-17 17:35:46 +02:00
parent ec459def07
commit 4c8fd51664
2 changed files with 40 additions and 11 deletions

View File

@ -458,16 +458,18 @@ describe("buildNodeServiceEnvironment", () => {
});
describe("shared Node TLS env defaults", () => {
// Pass an explicit non-nvm execPath so tests are deterministic regardless of
// whether the test runner itself runs under nvm.
const builders = [
{
name: "gateway service env",
build: (env: Record<string, string | undefined>, platform?: NodeJS.Platform) =>
buildServiceEnvironment({ env, port: 18789, platform }),
buildServiceEnvironment({ env, port: 18789, platform, execPath: "/usr/bin/node" }),
},
{
name: "node service env",
build: (env: Record<string, string | undefined>, platform?: NodeJS.Platform) =>
buildNodeServiceEnvironment({ env, platform }),
buildNodeServiceEnvironment({ env, platform, execPath: "/usr/bin/node" }),
},
] as const;
@ -536,16 +538,25 @@ describe("resolveLinuxSystemCaBundle", () => {
});
describe("shared Node TLS env — Linux nvm detection", () => {
const nvmExecPath = "/home/user/.nvm/versions/node/v22.22.0/bin/node";
const nonNvmExecPath = "/usr/bin/node";
const builders = [
{
name: "gateway service env",
build: (env: Record<string, string | undefined>, platform?: NodeJS.Platform) =>
buildServiceEnvironment({ env, port: 18789, platform }),
build: (
env: Record<string, string | undefined>,
platform?: NodeJS.Platform,
execPath?: string,
) => buildServiceEnvironment({ env, port: 18789, platform, execPath }),
},
{
name: "node service env",
build: (env: Record<string, string | undefined>, platform?: NodeJS.Platform) =>
buildNodeServiceEnvironment({ env, platform }),
build: (
env: Record<string, string | undefined>,
platform?: NodeJS.Platform,
execPath?: string,
) => buildNodeServiceEnvironment({ env, platform, execPath }),
},
] as const;
@ -555,7 +566,19 @@ describe("shared Node TLS env — Linux nvm detection", () => {
it.each(builders)(
"$name defaults NODE_EXTRA_CA_CERTS on Linux when NVM_DIR is set",
({ build }) => {
const env = build({ HOME: "/home/user", NVM_DIR: "/home/user/.nvm" }, "linux");
const env = build(
{ HOME: "/home/user", NVM_DIR: "/home/user/.nvm" },
"linux",
nonNvmExecPath,
);
expect(env.NODE_EXTRA_CA_CERTS).toBe(expectedCaBundle);
},
);
it.each(builders)(
"$name defaults NODE_EXTRA_CA_CERTS on Linux when execPath is under nvm",
({ build }) => {
const env = build({ HOME: "/home/user" }, "linux", nvmExecPath);
expect(env.NODE_EXTRA_CA_CERTS).toBe(expectedCaBundle);
},
);
@ -563,7 +586,7 @@ describe("shared Node TLS env — Linux nvm detection", () => {
it.each(builders)(
"$name does not default NODE_EXTRA_CA_CERTS on Linux without nvm",
({ build }) => {
const env = build({ HOME: "/home/user" }, "linux");
const env = build({ HOME: "/home/user" }, "linux", nonNvmExecPath);
expect(env.NODE_EXTRA_CA_CERTS).toBeUndefined();
},
);
@ -578,6 +601,7 @@ describe("shared Node TLS env — Linux nvm detection", () => {
NODE_EXTRA_CA_CERTS: "/custom/ca-bundle.crt",
},
"linux",
nvmExecPath,
);
expect(env.NODE_EXTRA_CA_CERTS).toBe("/custom/ca-bundle.crt");
},

View File

@ -291,10 +291,12 @@ export function buildServiceEnvironment(params: {
launchdLabel?: string;
platform?: NodeJS.Platform;
extraPathDirs?: string[];
/** Override process.execPath for nvm detection (testing). */
execPath?: string;
}): Record<string, string | undefined> {
const { env, port, launchdLabel, extraPathDirs } = params;
const platform = params.platform ?? process.platform;
const sharedEnv = resolveSharedServiceEnvironmentFields(env, platform, extraPathDirs);
const sharedEnv = resolveSharedServiceEnvironmentFields(env, platform, extraPathDirs, params.execPath);
const profile = env.OPENCLAW_PROFILE;
const resolvedLaunchdLabel =
launchdLabel || (platform === "darwin" ? resolveGatewayLaunchAgentLabel(profile) : undefined);
@ -316,10 +318,12 @@ export function buildNodeServiceEnvironment(params: {
env: Record<string, string | undefined>;
platform?: NodeJS.Platform;
extraPathDirs?: string[];
/** Override process.execPath for nvm detection (testing). */
execPath?: string;
}): Record<string, string | undefined> {
const { env, extraPathDirs } = params;
const platform = params.platform ?? process.platform;
const sharedEnv = resolveSharedServiceEnvironmentFields(env, platform, extraPathDirs);
const sharedEnv = resolveSharedServiceEnvironmentFields(env, platform, extraPathDirs, params.execPath);
const gatewayToken =
env.OPENCLAW_GATEWAY_TOKEN?.trim() || env.CLAWDBOT_GATEWAY_TOKEN?.trim() || undefined;
return {
@ -359,6 +363,7 @@ function resolveSharedServiceEnvironmentFields(
env: Record<string, string | undefined>,
platform: NodeJS.Platform,
extraPathDirs: string[] | undefined,
execPath?: string,
): SharedServiceEnvironmentFields {
const stateDir = env.OPENCLAW_STATE_DIR;
const configPath = env.OPENCLAW_CONFIG_PATH;
@ -374,7 +379,7 @@ function resolveSharedServiceEnvironmentFields(
env.NODE_EXTRA_CA_CERTS ??
(platform === "darwin"
? "/etc/ssl/cert.pem"
: platform === "linux" && isNvmNode(env)
: platform === "linux" && isNvmNode(env, execPath ?? process.execPath)
? resolveLinuxSystemCaBundle()
: undefined);
const nodeUseSystemCa = env.NODE_USE_SYSTEM_CA ?? (platform === "darwin" ? "1" : undefined);