fix(update): stop Windows gateways before mutating install

This commit is contained in:
helix4u
2026-06-13 10:46:08 -07:00
committed by Teknium
parent 957a8ffa88
commit 78c11d99e3
2 changed files with 284 additions and 1 deletions
@@ -7,6 +7,7 @@ Windows-specific code paths can be exercised on any host.
from __future__ import annotations
import json
import os
import sys
import types
@@ -446,6 +447,97 @@ def test_quarantine_actionable_warning_when_everything_fails(
assert "Hermes Desktop" in captured or "gateway" in captured.lower()
# ---------------------------------------------------------------------------
# Windows gateway pause/resume before update mutation
# ---------------------------------------------------------------------------
@patch.object(cli_main, "_is_windows", return_value=True)
def test_pause_windows_gateways_for_update_stops_profile_and_unmapped_pids(
_winp,
monkeypatch,
tmp_path,
capsys,
):
import gateway.status as status_mod
import hermes_cli.gateway as gateway_mod
profile_home = tmp_path / "profiles" / "work"
profile_home.mkdir(parents=True)
profile_proc = SimpleNamespace(profile="work", path=profile_home, pid=101)
monkeypatch.setattr(gateway_mod, "find_gateway_pids", lambda **_k: [101, 202])
monkeypatch.setattr(
gateway_mod,
"find_profile_gateway_processes",
lambda **_k: [profile_proc],
)
monkeypatch.setattr(gateway_mod, "_get_restart_drain_timeout", lambda: 0.1)
waited_for = []
def fake_wait(pids, *, timeout):
waited_for.extend(pids)
return set()
monkeypatch.setattr(cli_main, "_wait_for_windows_update_gateway_exit", fake_wait)
terminated = []
monkeypatch.setattr(
status_mod,
"terminate_pid",
lambda pid, force=False: terminated.append((pid, force)),
)
token = cli_main._pause_windows_gateways_for_update()
assert token == {
"resume_needed": True,
"profiles": {"work": 101},
"unmapped_pids": [202],
}
assert waited_for == [101]
assert terminated == [(202, True)]
marker = json.loads((profile_home / ".gateway-planned-stop.json").read_text())
assert marker["target_pid"] == 101
assert marker["stopper_pid"] == os.getpid()
captured = capsys.readouterr().out
assert "Paused gateway profile(s): work" in captured
assert "without profile mapping" in captured
@patch.object(cli_main, "_is_windows", return_value=True)
def test_resume_windows_gateways_after_update_relaunches_paused_profiles(
_winp,
monkeypatch,
capsys,
):
import hermes_cli.gateway as gateway_mod
relaunched = []
monkeypatch.setattr(
gateway_mod,
"launch_detached_profile_gateway_restart",
lambda profile, old_pid: relaunched.append((profile, old_pid)) or True,
)
token = {
"resume_needed": True,
"profiles": {"default": 101, "work": 202},
"unmapped_pids": [],
}
cli_main._resume_windows_gateways_after_update(token)
assert token["resume_needed"] is False
assert relaunched == [("default", 101), ("work", 202)]
assert (
"Restarting Windows gateway profile(s): default, work"
in capsys.readouterr().out
)
# ---------------------------------------------------------------------------
# cmd_update integration — concurrent-instance gate
# ---------------------------------------------------------------------------