From 8895b0f119ecd06d540a72316a3cea98cd95203f Mon Sep 17 00:00:00 2001 From: teknium1 <127238744+teknium1@users.noreply.github.com> Date: Wed, 23 Sep 2026 03:18:54 -0700 Subject: [PATCH] fix(update): an in-gateway cron update no longer exits STALE for the gateway it runs inside MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `hermes update --yes` from a cron job inside the gateway takes the #100179 ancestor branch (`_drain_or_signal_gateway_for_update` -> self-restart request, fire-and-forget) — the gateway can only restart after the updater exits. The post-restart fleet matrix then saw that same gateway on the pre-update code_sha, printed STALE + "Update not complete" and exited 1 on every nightly run (#119597). The restart phase now records the pids that accepted a self-restart (`_GatewayRestartOutcome.self_restart_pending_pids`, threaded from the systemd, manual and launchd paths) and `collect_fleet_versions(self_restart_pending=)` turns exactly those rows into `restart_pending` — rendered as "restart pending (deferred until this process exits)" and excluded from the stale_or_down verdict. Every other stale/down gateway keeps its verdict; the same pid without the recorded acceptance is still STALE. The receipt keeps the row's old sha, so the next `hermes update` / CLI startup hint still verifies the restart landed via the live fleet (`_receipt_reports_stale_runtime` -> `_live_fleet_covers_receipt`). Closes #119597 --- hermes_cli/update_cmd_fleet.py | 66 ++++++++--- hermes_cli/update_receipt.py | 30 ++++- .../test_fleet_matrix_self_restart_pending.py | 104 ++++++++++++++++++ 3 files changed, 182 insertions(+), 18 deletions(-) create mode 100644 tests/hermes_cli/test_fleet_matrix_self_restart_pending.py diff --git a/hermes_cli/update_cmd_fleet.py b/hermes_cli/update_cmd_fleet.py index e0ddca4d60..0151384a75 100644 --- a/hermes_cli/update_cmd_fleet.py +++ b/hermes_cli/update_cmd_fleet.py @@ -975,7 +975,9 @@ def _warn_incomplete_gateway_fleet_restart(failed_units: list) -> None: print(" launchctl kickstart -k gui/$UID/