fix(update): block live gateway without service definition

This commit is contained in:
masonxhuang
2026-05-02 00:52:28 +08:00
committed by Mason Huang
parent e2892c3940
commit 0ef9caee56
2 changed files with 45 additions and 2 deletions

View File

@@ -1286,6 +1286,10 @@ describe("update-cli", () => {
it("allows package updates from inherited gateway service env when the managed gateway is not running", async () => {
mockPackageInstallStatus(createCaseDir("openclaw-update"));
serviceReadRuntime.mockResolvedValueOnce({
status: "stopped",
state: "stopped",
});
await withEnvAsync(
{
@@ -1375,6 +1379,39 @@ describe("update-cli", () => {
);
});
it("refuses package updates from inherited gateway service env when the service definition is missing but runtime is live", async () => {
mockPackageInstallStatus(createCaseDir("openclaw-update"));
serviceReadCommand.mockResolvedValue(null);
serviceReadRuntime.mockResolvedValueOnce({
status: "running",
pid: 4242,
state: "running",
});
await withEnvAsync(
{
OPENCLAW_SERVICE_MARKER: "openclaw",
OPENCLAW_SERVICE_KIND: "gateway",
},
async () => {
await updateCommand({ yes: true });
},
);
expect(defaultRuntime.error).toHaveBeenCalledWith(
expect.stringContaining(
"Package updates cannot run from inside the gateway service process.",
),
);
expect(defaultRuntime.exit).toHaveBeenCalledWith(1);
expect(serviceStop).not.toHaveBeenCalled();
expect(runGatewayUpdate).not.toHaveBeenCalled();
expect(runCommandWithTimeout).not.toHaveBeenCalledWith(
["npm", "i", "-g", "openclaw@latest", "--no-fund", "--no-audit", "--loglevel=error"],
expect.any(Object),
);
});
it("blocks package updates when the target requires a newer Node runtime", async () => {
mockPackageInstallStatus(createCaseDir("openclaw-update"));
vi.mocked(fetchNpmPackageTargetStatus).mockResolvedValue({

View File

@@ -181,11 +181,17 @@ async function maybeStopManagedServiceBeforePackageUpdate(params: {
return { stopped: false, inspected: false, runtimeInspected: false, running: false };
}
const runtimeInspected = Boolean(serviceState.runtime);
if (!serviceState.installed) {
return { stopped: false, inspected: true, runtimeInspected: true, running: false };
return {
stopped: false,
inspected: true,
runtimeInspected,
running: serviceState.running,
serviceEnv: serviceState.env,
};
}
const runtimeInspected = Boolean(serviceState.runtime);
if (!params.shouldRestart) {
if (!params.jsonMode && serviceState.running) {
defaultRuntime.log(