mirror of
https://github.com/openclaw/openclaw.git
synced 2026-02-19 18:39:20 -05:00
refactor(infra): share shell env timeout normalization
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import {
|
||||
getShellPathFromLoginShell,
|
||||
loadShellEnvFallback,
|
||||
resetShellPathCacheForTests,
|
||||
resolveShellEnvFallbackTimeoutMs,
|
||||
shouldEnableShellEnvFallback,
|
||||
} from "./shell-env.js";
|
||||
@@ -71,4 +73,42 @@ describe("shell env fallback", () => {
|
||||
expect(env.DISCORD_BOT_TOKEN).toBe("discord");
|
||||
expect(exec2).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("resolves PATH via login shell and caches it", () => {
|
||||
resetShellPathCacheForTests();
|
||||
const exec = vi.fn(() => Buffer.from("PATH=/usr/local/bin:/usr/bin\0HOME=/tmp\0"));
|
||||
|
||||
const first = getShellPathFromLoginShell({
|
||||
env: {} as NodeJS.ProcessEnv,
|
||||
exec: exec as unknown as Parameters<typeof getShellPathFromLoginShell>[0]["exec"],
|
||||
});
|
||||
const second = getShellPathFromLoginShell({
|
||||
env: {} as NodeJS.ProcessEnv,
|
||||
exec: exec as unknown as Parameters<typeof getShellPathFromLoginShell>[0]["exec"],
|
||||
});
|
||||
|
||||
expect(first).toBe("/usr/local/bin:/usr/bin");
|
||||
expect(second).toBe("/usr/local/bin:/usr/bin");
|
||||
expect(exec).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it("returns null on shell env read failure and caches null", () => {
|
||||
resetShellPathCacheForTests();
|
||||
const exec = vi.fn(() => {
|
||||
throw new Error("exec failed");
|
||||
});
|
||||
|
||||
const first = getShellPathFromLoginShell({
|
||||
env: {} as NodeJS.ProcessEnv,
|
||||
exec: exec as unknown as Parameters<typeof getShellPathFromLoginShell>[0]["exec"],
|
||||
});
|
||||
const second = getShellPathFromLoginShell({
|
||||
env: {} as NodeJS.ProcessEnv,
|
||||
exec: exec as unknown as Parameters<typeof getShellPathFromLoginShell>[0]["exec"],
|
||||
});
|
||||
|
||||
expect(first).toBeNull();
|
||||
expect(second).toBeNull();
|
||||
expect(exec).toHaveBeenCalledOnce();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -6,6 +6,13 @@ const DEFAULT_MAX_BUFFER_BYTES = 2 * 1024 * 1024;
|
||||
let lastAppliedKeys: string[] = [];
|
||||
let cachedShellPath: string | null | undefined;
|
||||
|
||||
function resolveTimeoutMs(timeoutMs: number | undefined): number {
|
||||
if (typeof timeoutMs !== "number" || !Number.isFinite(timeoutMs)) {
|
||||
return DEFAULT_TIMEOUT_MS;
|
||||
}
|
||||
return Math.max(0, timeoutMs);
|
||||
}
|
||||
|
||||
function resolveShell(env: NodeJS.ProcessEnv): string {
|
||||
const shell = env.SHELL?.trim();
|
||||
return shell && shell.length > 0 ? shell : "/bin/sh";
|
||||
@@ -76,10 +83,7 @@ export function loadShellEnvFallback(opts: ShellEnvFallbackOptions): ShellEnvFal
|
||||
return { ok: true, applied: [], skippedReason: "already-has-keys" };
|
||||
}
|
||||
|
||||
const timeoutMs =
|
||||
typeof opts.timeoutMs === "number" && Number.isFinite(opts.timeoutMs)
|
||||
? Math.max(0, opts.timeoutMs)
|
||||
: DEFAULT_TIMEOUT_MS;
|
||||
const timeoutMs = resolveTimeoutMs(opts.timeoutMs);
|
||||
|
||||
const shell = resolveShell(opts.env);
|
||||
|
||||
@@ -146,10 +150,7 @@ export function getShellPathFromLoginShell(opts: {
|
||||
}
|
||||
|
||||
const exec = opts.exec ?? execFileSync;
|
||||
const timeoutMs =
|
||||
typeof opts.timeoutMs === "number" && Number.isFinite(opts.timeoutMs)
|
||||
? Math.max(0, opts.timeoutMs)
|
||||
: DEFAULT_TIMEOUT_MS;
|
||||
const timeoutMs = resolveTimeoutMs(opts.timeoutMs);
|
||||
const shell = resolveShell(opts.env);
|
||||
|
||||
let stdout: Buffer;
|
||||
|
||||
Reference in New Issue
Block a user