fix(update): require applied gateway restarts

Require Control UI updates to observe a real gateway process replacement, surface skipped/error update outcomes, and verify the running gateway version after restart.\n\nAdds update.status restart-sentinel plumbing, docs, generated protocol model updates, and changelog attribution.\n\nLocal verification:\n- pnpm test src/gateway/server-methods/update.test.ts src/cli/gateway-cli/run-loop.test.ts src/infra/restart-sentinel.test.ts src/infra/process-respawn.test.ts src/infra/update-runner.test.ts ui/src/ui/app-gateway.node.test.ts ui/src/ui/controllers/config.test.ts\n- git diff --check\n- pnpm exec oxfmt --check --threads=1 CHANGELOG.md docs/gateway/protocol.md docs/gateway/configuration.md docs/web/control-ui.md\n- pnpm docs:check-mdx
This commit is contained in:
Samuel Rodda
2026-04-27 18:37:43 +09:30
committed by GitHub
parent b74f35ee6f
commit 6c252cc54c
41 changed files with 1265 additions and 54 deletions

View File

@@ -1078,6 +1078,30 @@ describe("update-cli", () => {
).toContain("Low disk space near");
});
it("refuses package updates from inside the gateway service process", async () => {
mockPackageInstallStatus(createCaseDir("openclaw-update"));
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(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({