mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 08:50:43 +00:00
fix: preserve wrapper env during gateway reinstall
This commit is contained in:
@@ -30,13 +30,22 @@ const resolveGatewayAuthMock = vi.hoisted(() =>
|
||||
);
|
||||
const resolveSecretRefValuesMock = vi.hoisted(() => vi.fn());
|
||||
const randomTokenMock = vi.hoisted(() => vi.fn(() => "generated-token"));
|
||||
const buildGatewayInstallPlanMock = vi.hoisted(() =>
|
||||
vi.fn(async () => ({
|
||||
programArguments: ["openclaw", "gateway", "run"],
|
||||
workingDirectory: "/tmp",
|
||||
environment: {},
|
||||
})),
|
||||
);
|
||||
const createInstallPlanFixture = vi.hoisted(() => {
|
||||
return async (params?: { wrapperPath?: string; env?: Record<string, string | undefined> }) => {
|
||||
const environment: Record<string, string | undefined> = {};
|
||||
if (params?.wrapperPath || params?.env?.OPENCLAW_WRAPPER) {
|
||||
environment.OPENCLAW_WRAPPER = params.wrapperPath ?? params.env?.OPENCLAW_WRAPPER;
|
||||
}
|
||||
return {
|
||||
programArguments: params?.wrapperPath
|
||||
? [params.wrapperPath, "gateway", "run"]
|
||||
: ["openclaw", "gateway", "run"],
|
||||
workingDirectory: "/tmp",
|
||||
environment,
|
||||
};
|
||||
};
|
||||
});
|
||||
const buildGatewayInstallPlanMock = vi.hoisted(() => vi.fn(createInstallPlanFixture));
|
||||
const parsePortMock = vi.hoisted(() => vi.fn(() => null));
|
||||
const isGatewayDaemonRuntimeMock = vi.hoisted(() => vi.fn(() => true));
|
||||
const installDaemonServiceAndEmitMock = vi.hoisted(() => vi.fn(async () => {}));
|
||||
@@ -108,6 +117,11 @@ vi.mock("../../commands/daemon-install-helpers.js", () => ({
|
||||
buildGatewayInstallPlan: buildGatewayInstallPlanMock,
|
||||
}));
|
||||
|
||||
vi.mock("../../daemon/program-args.js", () => ({
|
||||
OPENCLAW_WRAPPER_ENV_KEY: "OPENCLAW_WRAPPER",
|
||||
resolveOpenClawWrapperPath: async (value: string | undefined) => value?.trim() || undefined,
|
||||
}));
|
||||
|
||||
vi.mock("./shared.js", () => ({
|
||||
parsePort: parsePortMock,
|
||||
createDaemonInstallActionContext: (jsonFlag: unknown) => {
|
||||
@@ -188,6 +202,7 @@ describe("runDaemonInstall", () => {
|
||||
installDaemonServiceAndEmitMock.mockReset();
|
||||
service.isLoaded.mockReset();
|
||||
service.stage.mockReset();
|
||||
service.readCommand.mockReset();
|
||||
resetRuntimeCapture();
|
||||
actionState.warnings.length = 0;
|
||||
actionState.emitted.length = 0;
|
||||
@@ -211,11 +226,7 @@ describe("runDaemonInstall", () => {
|
||||
});
|
||||
resolveSecretRefValuesMock.mockResolvedValue(new Map());
|
||||
randomTokenMock.mockReturnValue("generated-token");
|
||||
buildGatewayInstallPlanMock.mockResolvedValue({
|
||||
programArguments: ["openclaw", "gateway", "run"],
|
||||
workingDirectory: "/tmp",
|
||||
environment: {},
|
||||
});
|
||||
buildGatewayInstallPlanMock.mockImplementation(createInstallPlanFixture);
|
||||
parsePortMock.mockReturnValue(null);
|
||||
isGatewayDaemonRuntimeMock.mockReturnValue(true);
|
||||
installDaemonServiceAndEmitMock.mockResolvedValue(undefined);
|
||||
@@ -402,6 +413,50 @@ describe("runDaemonInstall", () => {
|
||||
expect(actionState.emitted.at(-1)).toMatchObject({ result: "already-installed" });
|
||||
});
|
||||
|
||||
it("preserves wrapper env from an installed but unloaded service during forced reinstall", async () => {
|
||||
service.isLoaded.mockResolvedValue(false);
|
||||
service.readCommand.mockResolvedValue({
|
||||
programArguments: ["/usr/local/bin/openclaw-doppler", "gateway", "run"],
|
||||
environment: {
|
||||
OPENCLAW_WRAPPER: "/usr/local/bin/openclaw-doppler",
|
||||
},
|
||||
} as never);
|
||||
|
||||
await runDaemonInstall({ json: true, force: true });
|
||||
|
||||
expect(service.readCommand).toHaveBeenCalledTimes(1);
|
||||
expect(buildGatewayInstallPlanMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
wrapperPath: "/usr/local/bin/openclaw-doppler",
|
||||
existingEnvironment: expect.objectContaining({
|
||||
OPENCLAW_WRAPPER: "/usr/local/bin/openclaw-doppler",
|
||||
}),
|
||||
env: expect.objectContaining({
|
||||
OPENCLAW_WRAPPER: "/usr/local/bin/openclaw-doppler",
|
||||
}),
|
||||
}),
|
||||
);
|
||||
expect(installDaemonServiceAndEmitMock).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("reinstalls when wrapper command matches but wrapper env is missing", async () => {
|
||||
service.isLoaded.mockResolvedValue(true);
|
||||
service.readCommand.mockResolvedValue({
|
||||
programArguments: ["/usr/local/bin/openclaw-doppler", "gateway", "run"],
|
||||
environment: {},
|
||||
} as never);
|
||||
|
||||
await runDaemonInstall({
|
||||
json: true,
|
||||
wrapper: "/usr/local/bin/openclaw-doppler",
|
||||
});
|
||||
|
||||
expect(installDaemonServiceAndEmitMock).toHaveBeenCalledTimes(1);
|
||||
expect(actionState.warnings).toContain(
|
||||
"Gateway service OPENCLAW_WRAPPER differs from the current wrapper install plan; refreshing the install.",
|
||||
);
|
||||
});
|
||||
|
||||
it("reinstalls when the embedded gateway token differs from the install plan", async () => {
|
||||
service.isLoaded.mockResolvedValue(true);
|
||||
service.readCommand.mockResolvedValue({
|
||||
|
||||
@@ -135,10 +135,8 @@ export async function runDaemonInstall(opts: DaemonInstallOptions) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (loaded) {
|
||||
existingServiceCommand = await service.readCommand(process.env).catch(() => null);
|
||||
existingServiceEnv = existingServiceCommand?.environment;
|
||||
}
|
||||
existingServiceCommand = await service.readCommand(process.env).catch(() => null);
|
||||
existingServiceEnv = existingServiceCommand?.environment;
|
||||
const installEnv = mergeInstallInvocationEnv({
|
||||
env: process.env,
|
||||
existingServiceEnv,
|
||||
@@ -294,6 +292,15 @@ async function getGatewayServiceAutoRefreshMessage(params: {
|
||||
) {
|
||||
return "Gateway service command differs from the current wrapper install plan; refreshing the install.";
|
||||
}
|
||||
const plannedWrapperPath = normalizeOptionalString(
|
||||
plannedInstall.environment[OPENCLAW_WRAPPER_ENV_KEY],
|
||||
);
|
||||
const currentWrapperPath = normalizeOptionalString(
|
||||
currentCommand.environment?.[OPENCLAW_WRAPPER_ENV_KEY],
|
||||
);
|
||||
if (plannedWrapperPath !== currentWrapperPath) {
|
||||
return `Gateway service ${OPENCLAW_WRAPPER_ENV_KEY} differs from the current wrapper install plan; refreshing the install.`;
|
||||
}
|
||||
}
|
||||
const currentExecPath = currentCommand.programArguments[0]?.trim();
|
||||
if (!currentExecPath) {
|
||||
|
||||
Reference in New Issue
Block a user