diff --git a/homeassistant/components/analytics/analytics.py b/homeassistant/components/analytics/analytics.py index 5bb1836928c..2e53d9c03d5 100644 --- a/homeassistant/components/analytics/analytics.py +++ b/homeassistant/components/analytics/analytics.py @@ -113,8 +113,10 @@ class Analytics: if stored: self._data = stored - if self.supervisor: - supervisor_info = hassio.get_supervisor_info(self.hass) + if ( + self.supervisor + and (supervisor_info := hassio.get_supervisor_info(self.hass)) is not None + ): if not self.onboarded: # User have not configured analytics, get this setting from the supervisor if supervisor_info[ATTR_DIAGNOSTICS] and not self.preferences.get( diff --git a/homeassistant/components/hassio/__init__.py b/homeassistant/components/hassio/__init__.py index 467d1e878b9..581ed0e3292 100644 --- a/homeassistant/components/hassio/__init__.py +++ b/homeassistant/components/hassio/__init__.py @@ -271,7 +271,7 @@ def get_store(hass): @callback @bind_hass -def get_supervisor_info(hass): +def get_supervisor_info(hass: HomeAssistant) -> dict[str, Any] | None: """Return Supervisor information. Async friendly. @@ -719,7 +719,7 @@ class HassioDataUpdateCoordinator(DataUpdateCoordinator): raise UpdateFailed(f"Error on Supervisor API: {err}") from err new_data: dict[str, Any] = {} - supervisor_info = get_supervisor_info(self.hass) + supervisor_info = get_supervisor_info(self.hass) or {} addons_info = get_addons_info(self.hass) addons_stats = get_addons_stats(self.hass) addons_changelogs = get_addons_changelogs(self.hass) diff --git a/homeassistant/components/hassio/system_health.py b/homeassistant/components/hassio/system_health.py index d8d29f44d68..795d1e325fb 100644 --- a/homeassistant/components/hassio/system_health.py +++ b/homeassistant/components/hassio/system_health.py @@ -27,7 +27,7 @@ async def system_health_info(hass: HomeAssistant): supervisor_info = get_supervisor_info(hass) healthy: bool | dict[str, str] - if supervisor_info.get("healthy"): + if supervisor_info is not None and supervisor_info.get("healthy"): healthy = True else: healthy = { @@ -36,7 +36,7 @@ async def system_health_info(hass: HomeAssistant): } supported: bool | dict[str, str] - if supervisor_info.get("supported"): + if supervisor_info is not None and supervisor_info.get("supported"): supported = True else: supported = { @@ -70,7 +70,7 @@ async def system_health_info(hass: HomeAssistant): information["installed_addons"] = ", ".join( f"{addon['name']} ({addon['version']})" - for addon in supervisor_info.get("addons", []) + for addon in (supervisor_info or {}).get("addons", []) ) return information diff --git a/homeassistant/components/homeassistant_alerts/__init__.py b/homeassistant/components/homeassistant_alerts/__init__.py index ed7957407a8..82631d58ec5 100644 --- a/homeassistant/components/homeassistant_alerts/__init__.py +++ b/homeassistant/components/homeassistant_alerts/__init__.py @@ -9,6 +9,7 @@ import logging import aiohttp from awesomeversion import AwesomeVersion, AwesomeVersionStrategy +from homeassistant.components.hassio import get_supervisor_info, is_hassio from homeassistant.const import __version__ from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.aiohttp_client import async_get_clientsession @@ -142,6 +143,7 @@ class AlertUpdateCoordinator(DataUpdateCoordinator[dict[str, IntegrationAlert]]) __version__, ensure_strategy=AwesomeVersionStrategy.CALVER, ) + self.supervisor = is_hassio(self.hass) async def _async_update_data(self) -> dict[str, IntegrationAlert]: response = await async_get_clientsession(self.hass).get( @@ -170,6 +172,23 @@ class AlertUpdateCoordinator(DataUpdateCoordinator[dict[str, IntegrationAlert]]) if self.ha_version >= resolved_in_version: continue + if self.supervisor and "supervisor" in alert: + if (supervisor_info := get_supervisor_info(self.hass)) is None: + continue + + if "affected_from_version" in alert["supervisor"]: + affected_from_version = AwesomeVersion( + alert["supervisor"]["affected_from_version"], + ) + if supervisor_info["version"] < affected_from_version: + continue + if "resolved_in_version" in alert["supervisor"]: + resolved_in_version = AwesomeVersion( + alert["supervisor"]["resolved_in_version"], + ) + if supervisor_info["version"] >= resolved_in_version: + continue + for integration in alert["integrations"]: if "package" not in integration: continue diff --git a/tests/components/homeassistant_alerts/fixtures/alerts_1.json b/tests/components/homeassistant_alerts/fixtures/alerts_1.json index 381a31d7a5d..0f480f66b31 100644 --- a/tests/components/homeassistant_alerts/fixtures/alerts_1.json +++ b/tests/components/homeassistant_alerts/fixtures/alerts_1.json @@ -30,6 +30,26 @@ "filename": "dark_sky.markdown", "alert_url": "https://alerts.home-assistant.io/#dark_sky.markdown" }, + { + "title": "Supervisor November beta issue impacting users on Home Assistant beta/dev channels", + "created": "2022-11-16T06:00:00.000Z", + "integrations": [ + { + "package": "hassio" + } + ], + "homeassistant": { + "package": "homeassistant", + "affected_from_version": "0.41" + }, + "supervisor": { + "package": "supervisor", + "affected_from_version": "2022.11.0", + "resolved_in_version": "2022.11.1" + }, + "filename": "hassio.markdown", + "alert_url": "https://alerts.home-assistant.io/#hassio.markdown" + }, { "title": "Hikvision Security Vulnerability", "created": "2021-09-20T22:08:00.000Z", diff --git a/tests/components/homeassistant_alerts/test_init.py b/tests/components/homeassistant_alerts/test_init.py index 6b8cb7bf475..41fdff425b3 100644 --- a/tests/components/homeassistant_alerts/test_init.py +++ b/tests/components/homeassistant_alerts/test_init.py @@ -36,13 +36,15 @@ async def setup_repairs(hass): @pytest.mark.parametrize( - "ha_version, expected_alerts", + "ha_version, supervisor_info, expected_alerts", ( ( "2022.7.0", + {"version": "2022.11.0"}, [ ("aladdin_connect.markdown", "aladdin_connect"), ("dark_sky.markdown", "darksky"), + ("hassio.markdown", "hassio"), ("hikvision.markdown", "hikvision"), ("hikvision.markdown", "hikvisioncam"), ("hive_us.markdown", "hive"), @@ -56,6 +58,7 @@ async def setup_repairs(hass): ), ( "2022.8.0", + {"version": "2022.11.1"}, [ ("dark_sky.markdown", "darksky"), ("hikvision.markdown", "hikvision"), @@ -71,6 +74,7 @@ async def setup_repairs(hass): ), ( "2021.10.0", + None, [ ("aladdin_connect.markdown", "aladdin_connect"), ("dark_sky.markdown", "darksky"), @@ -91,6 +95,7 @@ async def test_alerts( hass_ws_client, aioclient_mock: AiohttpClientMocker, ha_version, + supervisor_info, expected_alerts, ) -> None: """Test creating issues based on alerts.""" @@ -119,9 +124,18 @@ async def test_alerts( for domain in activated_components: hass.config.components.add(domain) + if supervisor_info is not None: + hass.config.components.add("hassio") + with patch( "homeassistant.components.homeassistant_alerts.__version__", ha_version, + ), patch( + "homeassistant.components.homeassistant_alerts.is_hassio", + return_value=supervisor_info is not None, + ), patch( + "homeassistant.components.homeassistant_alerts.get_supervisor_info", + return_value=supervisor_info, ): assert await async_setup_component(hass, DOMAIN, {})