From cb5070101e94dd30c3bb2e2fe21d7019c0036ca4 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 18 Jul 2026 08:16:05 +0100 Subject: [PATCH] fix: bound live updater gateway probes (#110509) --- .../scripts/update-main.mjs | 5 +++- test/external-script-modules.d.ts | 6 +++++ test/scripts/openclaw-live-updater.test.ts | 27 +++++++++++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/.agents/skills/openclaw-live-updater/scripts/update-main.mjs b/.agents/skills/openclaw-live-updater/scripts/update-main.mjs index 1c7a36b459ac..61c74956d9ec 100644 --- a/.agents/skills/openclaw-live-updater/scripts/update-main.mjs +++ b/.agents/skills/openclaw-live-updater/scripts/update-main.mjs @@ -38,6 +38,7 @@ const DEFAULT_EXPECTED_ORIGIN = "openclaw/openclaw"; const FULL_SHA_RE = /^[0-9a-f]{40}$/u; const GATEWAY_READINESS_ATTEMPTS = 3; const GATEWAY_READINESS_RETRY_DELAY_MS = 5_000; +const GATEWAY_CLI_TIMEOUT_MS = 30_000; const GATEWAY_STOP_PROOF_ATTEMPTS = 100; const GATEWAY_STOP_PROOF_RETRY_DELAY_MS = 100; const GATEWAY_SUSPEND_TIMEOUT_MS = 10_000; @@ -1013,7 +1014,7 @@ export function parseLaunchctlArguments(output) { : []; } -function runBuiltGatewayCli(checkout, args, deployment, options = {}) { +export function runBuiltGatewayCli(checkout, args, deployment, options = {}) { const observedDeployment = deployment ?? readManagedGatewayLaunchAgent(checkout); const sourceEntrypoint = path.join(checkout, "dist/index.js"); let managedDeployment = observedDeployment; @@ -1105,7 +1106,9 @@ function runBuiltGatewayCli(checkout, args, deployment, options = {}) { cwd: workingDirectory ?? path.dirname(path.dirname(entrypoint)), encoding: "utf8", env, + killSignal: "SIGKILL", stdio: ["ignore", "pipe", options.stderr ?? "inherit"], + timeout: options.timeoutMs ?? GATEWAY_CLI_TIMEOUT_MS, }); } finally { rmSync(overlayPath, { force: true }); diff --git a/test/external-script-modules.d.ts b/test/external-script-modules.d.ts index 4d68f78ea227..82619f989df4 100644 --- a/test/external-script-modules.d.ts +++ b/test/external-script-modules.d.ts @@ -260,6 +260,12 @@ declare module "*openclaw-live-updater/scripts/update-main.mjs" { activeCount: number; blockers: Array<{ kind: string; count: number; message: string }>; }; + export function runBuiltGatewayCli( + checkout: string, + args: string[], + deployment?: GatewayDeployment | null, + options?: { stderr?: "inherit" | "pipe"; timeoutMs?: number }, + ): string; export function verifyGatewayReadiness( runCommand: (command: string, args: string[], checkout: string) => unknown, checkout: string, diff --git a/test/scripts/openclaw-live-updater.test.ts b/test/scripts/openclaw-live-updater.test.ts index 39c6e259c62c..f3b7d2da60d1 100644 --- a/test/scripts/openclaw-live-updater.test.ts +++ b/test/scripts/openclaw-live-updater.test.ts @@ -35,6 +35,7 @@ import { resolveManagedPluginSourceRoots, resolveManagedGatewayEntrypoint, runBuiltGatewayCall, + runBuiltGatewayCli, verifyGatewayReadiness, } from "../../.agents/skills/openclaw-live-updater/scripts/update-main.mjs"; import { @@ -545,6 +546,32 @@ describe("openclaw live updater", () => { ]); }); + test("bounds built Gateway CLI probes and cleans their config overlay", () => { + const { root, mirror } = makeFixture(); + writeBuild(mirror); + const entrypoint = path.join(mirror, "dist/index.js"); + writeFileSync(entrypoint, "setInterval(() => {}, 1_000);\n"); + + expect(() => + runBuiltGatewayCli( + mirror, + ["gateway", "status"], + { + configPath: path.join(root, "openclaw.json"), + entrypoint, + executable: process.execPath, + invocationPrefix: [entrypoint], + port: 18789, + runtime: process.execPath, + }, + { timeoutMs: 100 }, + ), + ).toThrow(); + expect( + readdirSync(root).filter((name) => name.startsWith(".openclaw-live-updater-config-")), + ).toEqual([]); + }); + test("parses ready and busy atomic Gateway suspension responses", () => { const deployment = { entrypoint: "/snapshot/dist/index.js" }; expect(