Skip to content

Commit 90c36c8

Browse files
committed
fix(component): align external package with channel
1 parent 90aef6b commit 90c36c8

2 files changed

Lines changed: 65 additions & 9 deletions

File tree

custom_components/ha_mcp_tools/embedded_server.py

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -861,7 +861,7 @@ async def _async_externally_managed_package_version(self) -> str:
861861
calls Home Assistant's requirements manager, UV, or the config-entry
862862
marker writers used by manual and automatic installs.
863863
"""
864-
installed_version: str | None = await self._hass.async_add_executor_job(
864+
importable_version: str | None = await self._hass.async_add_executor_job(
865865
_installed_ha_mcp_version
866866
)
867867
stable_version: str | None = await self._hass.async_add_executor_job(
@@ -870,12 +870,22 @@ async def _async_externally_managed_package_version(self) -> str:
870870
dev_version: str | None = await self._hass.async_add_executor_job(
871871
_installed_dist_version, DIST_NAME_DEV
872872
)
873+
target_dist = dist_for_channel(self._channel)
874+
target_version = (
875+
stable_version if target_dist == DIST_NAME_STABLE else dev_version
876+
)
877+
other_dist = (
878+
DIST_NAME_DEV if target_dist == DIST_NAME_STABLE else DIST_NAME_STABLE
879+
)
880+
other_version = (
881+
dev_version if target_dist == DIST_NAME_STABLE else stable_version
882+
)
873883

874-
if installed_version is None:
884+
if importable_version is None:
875885
raise EmbeddedServerError(
876886
"Home Assistant was started with skip_pip enabled, so HA-MCP "
877887
"will not install the externally managed server package. Use "
878-
"the system package manager to install ha-mcp "
888+
f"the system package manager to install {target_dist} "
879889
f"{MIN_EMBEDDED_SERVER_VERSION} or newer, then reload this "
880890
"integration.",
881891
kind="package",
@@ -892,9 +902,20 @@ async def _async_externally_managed_package_version(self) -> str:
892902
kind="package",
893903
)
894904

895-
if not _is_compatible_embedded_version(installed_version):
905+
if target_version is None:
896906
raise EmbeddedServerError(
897-
f"The externally managed ha-mcp {installed_version} is "
907+
f"The configured {self._channel} channel expects {target_dist}, "
908+
f"but only {other_dist} {other_version} is installed while "
909+
"skip_pip is enabled. Use the system package manager to install "
910+
f"{target_dist} {MIN_EMBEDDED_SERVER_VERSION} or newer, or "
911+
f"change the HA-MCP release channel to match {other_dist}, then "
912+
"reload this integration.",
913+
kind="package",
914+
)
915+
916+
if not _is_compatible_embedded_version(target_version):
917+
raise EmbeddedServerError(
918+
f"The externally managed {target_dist} {target_version} is "
898919
"incompatible while skip_pip is enabled; this in-process "
899920
f"component requires {MIN_EMBEDDED_SERVER_VERSION} or newer. "
900921
"Upgrade it with the system package manager, then reload this "
@@ -903,11 +924,13 @@ async def _async_externally_managed_package_version(self) -> str:
903924
)
904925

905926
_LOGGER.info(
906-
"HA-MCP externally managed server package ready (version %s; "
907-
"skip_pip enabled)",
908-
installed_version,
927+
"HA-MCP externally managed %s package ready (version %s; "
928+
"skip_pip enabled, channel %s)",
929+
target_dist,
930+
target_version,
931+
self._channel,
909932
)
910-
return installed_version
933+
return target_version
911934

912935
async def _async_remove_legacy_target(
913936
self, target_dist: str, installed_version: str | None

tests/src/unit/test_embedded_server.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,39 @@ async def test_skip_pip_uses_compatible_externally_managed_package(
447447
assert version == "7.12.1"
448448
assert entry.data == data
449449

450+
@pytest.mark.parametrize(
451+
("channel", "installed_dist", "installed_version", "expected_dist"),
452+
[
453+
(
454+
CHANNEL_STABLE,
455+
DIST_NAME_DEV,
456+
"7.12.1.dev1",
457+
DIST_NAME_STABLE,
458+
),
459+
(CHANNEL_DEV, DIST_NAME_STABLE, "7.12.1", DIST_NAME_DEV),
460+
],
461+
)
462+
async def test_skip_pip_rejects_package_from_other_channel(
463+
self,
464+
tmp_path,
465+
monkeypatch,
466+
channel,
467+
installed_dist,
468+
installed_version,
469+
expected_dist,
470+
):
471+
mgr, hass, _entry = _manager(tmp_path, options={OPT_CHANNEL: channel})
472+
hass.config.skip_pip = True
473+
versions = {installed_dist: installed_version}
474+
monkeypatch.setattr(es, "_installed_ha_mcp_version", lambda: installed_version)
475+
monkeypatch.setattr(es, "_installed_dist_version", versions.get)
476+
477+
with pytest.raises(
478+
es.EmbeddedServerError,
479+
match=rf"configured {channel} channel expects {expected_dist}.*{installed_dist}",
480+
):
481+
await mgr._async_ensure_package()
482+
450483
async def test_skip_pip_reports_missing_externally_managed_package(
451484
self, tmp_path, monkeypatch
452485
):

0 commit comments

Comments
 (0)