fix(doctor): bound launchctl environment probes (#109115)

This commit is contained in:
Alix-007
2026-07-16 09:08:55 -07:00
committed by GitHub
parent 14bb0b4e52
commit 59fa034fcb
2 changed files with 48 additions and 2 deletions
@@ -1,7 +1,16 @@
// Doctor launchctl environment tests cover macOS gateway platform warnings for env overrides.
import fs from "node:fs";
import { describe, expect, it, vi } from "vitest";
import { beforeEach, describe, expect, it, vi } from "vitest";
import type { OpenClawConfig } from "../config/config.js";
const processMocks = vi.hoisted(() => ({
runExec: vi.fn(),
}));
vi.mock("../process/exec.js", () => ({
runExec: processMocks.runExec,
}));
import {
collectMacGatewayPlatformWarnings,
noteMacLaunchctlGatewayEnvOverrides,
@@ -17,6 +26,10 @@ function requireNoteCall(noteFn: { mock: { calls: unknown[][] } }, index = 0): u
}
describe("noteMacLaunchctlGatewayEnvOverrides", () => {
beforeEach(() => {
processMocks.runExec.mockReset().mockResolvedValue({ stdout: "", stderr: "" });
});
it("collects clear unsetenv instructions for token override", async () => {
const noteFn = vi.fn();
const getenv = vi.fn(async (name: string) =>
@@ -118,6 +131,34 @@ describe("noteMacLaunchctlGatewayEnvOverrides", () => {
expect(getenv).not.toHaveBeenCalled();
expect(noteFn).not.toHaveBeenCalled();
});
it("bounds launchctl getenv calls and ignores timeout failures", async () => {
const noteFn = vi.fn();
processMocks.runExec.mockRejectedValue(new Error("timed out"));
const cfg = {
gateway: {
auth: {
token: "config-token",
},
},
} as OpenClawConfig;
await noteMacLaunchctlGatewayEnvOverrides(cfg, { platform: "darwin", noteFn });
expect(processMocks.runExec).toHaveBeenNthCalledWith(
1,
"/bin/launchctl",
["getenv", "OPENCLAW_GATEWAY_TOKEN"],
{ logOutput: false, timeoutMs: 5_000 },
);
expect(processMocks.runExec).toHaveBeenNthCalledWith(
2,
"/bin/launchctl",
["getenv", "OPENCLAW_GATEWAY_PASSWORD"],
{ logOutput: false, timeoutMs: 5_000 },
);
expect(noteFn).not.toHaveBeenCalled();
});
});
describe("noteMacStaleOpenClawUpdateLaunchdJobs", () => {
+6 -1
View File
@@ -12,6 +12,8 @@ import { resolveGatewayService, type GatewayService } from "../daemon/service.js
import { runExec } from "../process/exec.js";
import { shortenHomePath } from "../utils.js";
const DOCTOR_LAUNCHCTL_TIMEOUT_MS = 5_000;
function resolveHomeDir(): string {
return process.env.HOME ?? os.homedir();
}
@@ -104,7 +106,10 @@ export async function noteMacStaleOpenClawUpdateLaunchdJobs(deps?: {
async function launchctlGetenv(name: string): Promise<string | undefined> {
try {
const result = await runExec("/bin/launchctl", ["getenv", name], { logOutput: false });
const result = await runExec("/bin/launchctl", ["getenv", name], {
logOutput: false,
timeoutMs: DOCTOR_LAUNCHCTL_TIMEOUT_MS,
});
const value = normalizeOptionalString(result.stdout) ?? "";
return value.length > 0 ? value : undefined;
} catch {