From d9486c683b804e232fee7b6907d562f7639910b0 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 25 Apr 2026 20:08:13 +0100 Subject: [PATCH] fix: stabilize macos npm update smoke --- extensions/bonjour/src/advertiser.test.ts | 7 ++++--- extensions/bonjour/src/advertiser.ts | 11 +++++++---- scripts/e2e/parallels-npm-update-smoke.sh | 4 ++++ 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/extensions/bonjour/src/advertiser.test.ts b/extensions/bonjour/src/advertiser.test.ts index 089cbd0056b..7888a9b6c01 100644 --- a/extensions/bonjour/src/advertiser.test.ts +++ b/extensions/bonjour/src/advertiser.test.ts @@ -484,12 +484,12 @@ describe("gateway bonjour advertiser", () => { expect(createService).toHaveBeenCalledTimes(2); expect(advertise).toHaveBeenCalledTimes(2); expect(destroy).toHaveBeenCalledTimes(1); - expect(shutdown).toHaveBeenCalledTimes(1); + expect(shutdown).not.toHaveBeenCalled(); expect(events).toEqual(["advertise:1", "destroy", "advertise:2"]); await started.stop(); expect(destroy).toHaveBeenCalledTimes(2); - expect(shutdown).toHaveBeenCalledTimes(2); + expect(shutdown).toHaveBeenCalledTimes(1); }); it("treats probing-to-announcing churn as one unhealthy window", async () => { @@ -527,9 +527,10 @@ describe("gateway bonjour advertiser", () => { expect(createService).toHaveBeenCalledTimes(2); expect(advertise).toHaveBeenCalledTimes(3); expect(destroy).toHaveBeenCalledTimes(1); - expect(shutdown).toHaveBeenCalledTimes(1); + expect(shutdown).not.toHaveBeenCalled(); await started.stop(); + expect(shutdown).toHaveBeenCalledTimes(1); }); it("normalizes hostnames with domains for service names", async () => { diff --git a/extensions/bonjour/src/advertiser.ts b/extensions/bonjour/src/advertiser.ts index c2972ca8873..e2be9b082d2 100644 --- a/extensions/bonjour/src/advertiser.ts +++ b/extensions/bonjour/src/advertiser.ts @@ -233,8 +233,9 @@ export async function startGatewayBonjourAdvertiser( gatewayTxt.sshPort = String(opts.sshPort ?? 22); } + const responder = getResponder(); + function createCycle(): BonjourCycle { - const responder = getResponder(); const services: Array<{ label: string; svc: BonjourService }> = []; const gateway = responder.createService({ @@ -259,7 +260,7 @@ export async function startGatewayBonjourAdvertiser( return { responder, services, cleanupUnhandledRejection }; } - async function stopCycle(cycle: BonjourCycle | null) { + async function stopCycle(cycle: BonjourCycle | null, opts?: { shutdownResponder?: boolean }) { if (!cycle) { return; } @@ -271,7 +272,9 @@ export async function startGatewayBonjourAdvertiser( } } try { - await cycle.responder.shutdown(); + if (opts?.shutdownResponder) { + await cycle.responder.shutdown(); + } } catch { /* ignore */ } finally { @@ -442,7 +445,7 @@ export async function startGatewayBonjourAdvertiser( } catch { // ignore } - await stopCycle(cycle); + await stopCycle(cycle, { shutdownResponder: true }); restoreConsoleLog(); }, }; diff --git a/scripts/e2e/parallels-npm-update-smoke.sh b/scripts/e2e/parallels-npm-update-smoke.sh index 6c55dd58793..efbafd46b00 100755 --- a/scripts/e2e/parallels-npm-update-smoke.sh +++ b/scripts/e2e/parallels-npm-update-smoke.sh @@ -1659,6 +1659,10 @@ stop_openclaw_gateway_processes() { # host can observe new plugin metadata mid-update and abort config validation. scrub_future_plugin_entries stop_openclaw_gateway_processes +# The baseline updater process may run its post-install doctor through the old +# host while new bundled plugin metadata is already on disk. Keep this +# same-guest update hop focused on core/package migration; post-update smoke +# below starts the fresh gateway with bundled plugins enabled. OPENCLAW_DISABLE_BUNDLED_PLUGINS=1 /opt/homebrew/bin/openclaw update --tag "$update_target" --yes --json # Same-guest npm upgrades can leave the old gateway process holding the old # bundled plugin host version. Stop it before post-update config commands.