fix(homeassistant): detect the supervised launch through is_supervised_gateway_launch

gateway.restart already answers "was this gateway launched by a generated
service" (HERMES_SUPERVISED_CHILD or launchd's XPC_SERVICE_NAME, so a plist
that predates the marker still counts); the hint reuses it instead of a
second env read. The negative branch (plain unreachable host without a
supervisor) is now an unmarked test so the Linux lane keeps covering the
function; the macOS-only test holds the positive branch.
This commit is contained in:
kshitijk4poor
2026-09-21 17:10:21 +05:30
committed by kshitij
parent eda2432cce
commit 7b660e66ee
2 changed files with 15 additions and 12 deletions

View File

@@ -7,7 +7,6 @@ import asyncio
import errno
import json
import logging
import os
import sys
import time
import uuid
@@ -21,6 +20,7 @@ except ImportError:
AIOHTTP_AVAILABLE = False
aiohttp = None # type: ignore[assignment]
from gateway.restart import is_supervised_gateway_launch
from gateway.config import Platform, PlatformConfig
from gateway.platforms.base import gateway_trust_env, BasePlatformAdapter, SendResult
from gateway.platforms.event import MessageEvent, MessageType
@@ -70,12 +70,12 @@ _TRIGGERED = ("cleared", "triggered") # binary_sensor wording, indexed by ``sta
def _connect_error_detail(exc: BaseException) -> str:
"""Annotate macOS Local Network Privacy denials so launchd HA failures are actionable (#71206).
Only a launchd-supervised gateway on macOS (``HERMES_SUPERVISED_CHILD`` is set by the generated plist)
can be denied this way; the same errno elsewhere is a genuinely unreachable host.
Only a supervised (launchd) gateway on macOS can be denied this way; the same errno from a
Terminal-run gateway or on another OS is a genuinely unreachable host.
"""
text = str(exc)
os_error = getattr(exc, "os_error", None) or exc.__cause__ or exc
if (sys.platform == "darwin" and os.environ.get("HERMES_SUPERVISED_CHILD")
if (sys.platform == "darwin" and is_supervised_gateway_launch()
and getattr(os_error, "errno", None) == errno.EHOSTUNREACH):
return (
f"{text} — macOS Local Network Privacy is blocking this launchd gateway from the LAN. "

View File

@@ -321,22 +321,25 @@ class TestWsUrlConstruction:
class TestLocalNetworkConnectHint:
@pytest.mark.macos_only
def test_ehostunreach_under_launchd_names_the_remedy(self, monkeypatch):
"""Only the launchd-supervised gateway can be denied by Local Network Privacy; the same errno from a
Terminal-run gateway is a genuinely unreachable host and must not be blamed on macOS (#71206)."""
def test_ehostunreach_outside_launchd_is_a_plain_unreachable_host(self, monkeypatch):
"""The same errno from a Terminal-run gateway (or another OS) must not be blamed on macOS."""
from plugins.platforms.homeassistant.adapter import _connect_error_detail
err = OSError(errno.EHOSTUNREACH, "No route to host")
monkeypatch.delenv("HERMES_SUPERVISED_CHILD", raising=False)
monkeypatch.delenv("XPC_SERVICE_NAME", raising=False)
err = OSError(errno.EHOSTUNREACH, "No route to host")
assert _connect_error_detail(err) == str(err)
assert _connect_error_detail(RuntimeError("auth failed")) == "auth failed"
@pytest.mark.macos_only
def test_ehostunreach_under_launchd_names_the_remedy(self, monkeypatch):
"""Only the launchd-supervised gateway can be denied by Local Network Privacy (#71206)."""
from plugins.platforms.homeassistant.adapter import _connect_error_detail
monkeypatch.setenv("HERMES_SUPERVISED_CHILD", "1")
err = OSError(errno.EHOSTUNREACH, "No route to host")
detail = _connect_error_detail(err)
assert detail.startswith(str(err))
assert "Local Network" in detail
assert "hermes gateway install" in detail
assert "71206" in detail
# Unrelated failures stay untouched.
assert _connect_error_detail(RuntimeError("auth failed")) == "auth failed"