From 2d3181def6b3cc40d43204eaf2e86b085c946424 Mon Sep 17 00:00:00 2001 From: rNoz Date: Sat, 22 Aug 2026 08:53:48 +0200 Subject: [PATCH] fix(wrap): strip -dev from running proxy version in restart check _proxy_needs_version_restart stripped the -dev suffix only from the CLI's own version. A source-built proxy reporting e.g. 0.34.0-dev failed the release regex, normalized to None, and the restart check silently never fired, so stale dev-built proxies were reused forever (observed: a 21-day-old 0.34.0-dev proxy reused by a 0.37.0-dev wrap). Strip the suffix on the running side too, matching the docstring. --- headroom/cli/wrap.py | 11 +++++++++-- tests/test_cli/test_wrap_persistent.py | 22 ++++++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/headroom/cli/wrap.py b/headroom/cli/wrap.py index 638d9e56a..135ae00f9 100644 --- a/headroom/cli/wrap.py +++ b/headroom/cli/wrap.py @@ -3275,9 +3275,16 @@ def _proxy_version(payload: dict[str, Any] | None) -> str | None: def _proxy_needs_version_restart(payload: dict[str, Any] | None) -> bool: """Return True when a running Headroom proxy uses a different package version.""" running_version = _proxy_version(payload) - running_release = _normalize_release_version(running_version) # -dev is a display marker for source builds; compare the base release so a - # dev CLI still restarts a stale proxy on a real version difference. + # dev CLI still restarts a stale proxy on a real version difference. The + # suffix must be stripped from the running version too: with it intact, + # "0.34.0-dev" fails the release regex, normalizes to None, and the check + # below silently never fires for source-built proxies. The scheme is always + # "-dev" (get_version in headroom/_version.py); any future "-rcN" or + # "-dev.N" style would need stripping here as well. + running_release = _normalize_release_version( + running_version.removesuffix("-dev") if running_version is not None else None + ) current_release = _normalize_release_version(_HEADROOM_VERSION.removesuffix("-dev")) return ( running_release is not None diff --git a/tests/test_cli/test_wrap_persistent.py b/tests/test_cli/test_wrap_persistent.py index 740b81afc..a3649b9ed 100644 --- a/tests/test_cli/test_wrap_persistent.py +++ b/tests/test_cli/test_wrap_persistent.py @@ -332,6 +332,28 @@ def test_proxy_version_restart_ignores_non_release_source_labels(monkeypatch) -> assert wrap_cli._proxy_needs_version_restart({"version": "0.29.0"}) is True +def test_proxy_version_restart_strips_dev_suffix_on_both_sides(monkeypatch) -> None: + """A dev-built proxy must be compared by its base release, like the CLI is. + + Regression: "0.34.0-dev" failed the release regex, normalized to None, and + the check never fired, so a stale source-built proxy was silently reused + forever (observed: a 21-day-old 0.34.0-dev proxy reused by a 0.37.0-dev + wrap). + """ + monkeypatch.setattr(wrap_cli, "_HEADROOM_VERSION", "0.37.0-dev") + assert wrap_cli._proxy_needs_version_restart({"version": "0.34.0-dev"}) is True + assert wrap_cli._proxy_needs_version_restart({"version": "0.37.0-dev"}) is False + assert wrap_cli._proxy_needs_version_restart({"version": "0.36.4"}) is True + + monkeypatch.setattr(wrap_cli, "_HEADROOM_VERSION", "0.37.0") + assert wrap_cli._proxy_needs_version_restart({"version": "0.36.4-dev"}) is True + + # Unparseable running versions still never trigger a restart. + assert wrap_cli._proxy_needs_version_restart({"version": "unknown"}) is False + assert wrap_cli._proxy_needs_version_restart(None) is False + assert wrap_cli._proxy_needs_version_restart({}) is False + + def test_ensure_proxy_restarts_ephemeral_proxy_for_openai_api_url_mismatch(monkeypatch) -> None: calls: list[object] = [] health = {