fix: stop Gateway without source rebuild (#104357)

This commit is contained in:
Peter Steinberger
2026-07-11 02:45:07 -07:00
committed by GitHub
parent b361390356
commit 14a056ac83
3 changed files with 7 additions and 5 deletions
@@ -30,7 +30,7 @@ Keep `/Users/steipete/openclaw` a read-only-to-the-agent deployment mirror: clea
- Every successful update sets `actions.gatewayBuild` and rebuilds exact new `main` before any restart.
- Missing, invalid, or stale build output also forces a build, even when Git did not move.
- A dependency-input change, absent `node_modules`, or missing/invalid build provenance first runs `pnpm install --frozen-lockfile`.
- Stop the managed Gateway immediately before `pnpm build`; never mutate the live `dist` tree while an old Gateway can dynamically import from it. `pnpm build` must leave both canonical stamp heads and `dist/build-info.json.commit` equal to post-update `afterSha`; any missing/mismatched stamp or required artifact blocks restart.
- Stop the managed Gateway immediately before `pnpm build` by invoking the existing `dist/index.js` directly; source launchers can auto-build stale output before dispatching the stop. Never mutate the live `dist` tree while an old Gateway can dynamically import from it. `pnpm build` must leave both canonical stamp heads and `dist/build-info.json.commit` equal to post-update `afterSha`; any missing/mismatched stamp or required artifact blocks restart.
- Only after exact-SHA build proof may it restart the managed Gateway and require `gateway status --deep --require-rpc --json` plus `health --verbose --json`.
- After every managed restart, query Gateway logs through RPC, restrict the audit to entries emitted since that restart began, report warning summaries, and fail the pass on any error/fatal entry. If RPC verification or log retrieval fails, still inspect the local structured log for that restart window. Never accept supervisor or RPC health without this restart-window log audit.
@@ -747,7 +747,9 @@ export function maintainMain(options, dependencies = {}) {
runCommand("pnpm", ["install", "--frozen-lockfile"], update.checkout);
}
if (actions.gatewayBuild) {
runCommand("pnpm", ["openclaw", "gateway", "stop"], update.checkout);
// Use the existing built CLI directly. Source launchers may auto-build a
// stale dist before dispatching `gateway stop`, recreating the live-import race.
runCommand(process.execPath, ["dist/index.js", "gateway", "stop"], update.checkout);
runCommand("pnpm", ["build"], update.checkout);
assertExactBuild(update.checkout, update.afterSha);
const restartStartedAt = restartGateway(runCommand, update.checkout, update.afterSha);
+3 -3
View File
@@ -371,7 +371,7 @@ describe("openclaw live updater", () => {
});
expect(commands.calls).toEqual([
"pnpm install --frozen-lockfile",
"pnpm openclaw gateway stop",
`${process.execPath} dist/index.js gateway stop`,
"pnpm build",
"pnpm openclaw gateway restart",
"pnpm openclaw gateway status --deep --require-rpc --json",
@@ -418,7 +418,7 @@ describe("openclaw live updater", () => {
expect(output.actions.dependencyInstall).toBe(true);
expect(commands.calls).toEqual([
"pnpm install --frozen-lockfile",
"pnpm openclaw gateway stop",
`${process.execPath} dist/index.js gateway stop`,
"pnpm build",
"pnpm openclaw gateway restart",
"pnpm openclaw gateway status --deep --require-rpc --json",
@@ -549,7 +549,7 @@ describe("openclaw live updater", () => {
).toThrow(/build output does not match/u);
expect(calls).toEqual([
"pnpm install --frozen-lockfile",
"pnpm openclaw gateway stop",
`${process.execPath} dist/index.js gateway stop`,
"pnpm build",
]);
});