diff --git a/homeassistant/components/homeassistant_alerts/__init__.py b/homeassistant/components/homeassistant_alerts/__init__.py index 82631d58ec5..7012111ed61 100644 --- a/homeassistant/components/homeassistant_alerts/__init__.py +++ b/homeassistant/components/homeassistant_alerts/__init__.py @@ -21,7 +21,6 @@ from homeassistant.helpers.issue_registry import ( from homeassistant.helpers.start import async_at_start from homeassistant.helpers.typing import ConfigType from homeassistant.helpers.update_coordinator import DataUpdateCoordinator -from homeassistant.util.yaml import parse_yaml DOMAIN = "homeassistant_alerts" UPDATE_INTERVAL = timedelta(hours=3) @@ -46,35 +45,14 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: # Fetch alert to get title + description try: response = await async_get_clientsession(hass).get( - f"https://alerts.home-assistant.io/alerts/{alert.filename}", + f"https://alerts.home-assistant.io/alerts/{alert.alert_id}.json", timeout=aiohttp.ClientTimeout(total=10), ) except asyncio.TimeoutError: _LOGGER.warning("Error fetching %s: timeout", alert.filename) continue - alert_content = await response.text() - alert_parts = alert_content.split("---") - - if len(alert_parts) != 3: - _LOGGER.warning( - "Error parsing %s: unexpected metadata format", alert.filename - ) - continue - - try: - alert_info = parse_yaml(alert_parts[1]) - except ValueError as err: - _LOGGER.warning("Error parsing %s metadata: %s", alert.filename, err) - continue - - if not isinstance(alert_info, dict) or "title" not in alert_info: - _LOGGER.warning("Error in %s metadata: title not found", alert.filename) - continue - - alert_title = alert_info["title"] - alert_content = alert_parts[2].strip() - + alert_content = await response.json() async_create_issue( hass, DOMAIN, @@ -84,8 +62,8 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: severity=IssueSeverity.WARNING, translation_key="alert", translation_placeholders={ - "title": alert_title, - "description": alert_content, + "title": alert_content["title"], + "description": alert_content["content"], }, ) active_alerts[issue_id] = alert.date_updated @@ -118,6 +96,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: class IntegrationAlert: """Issue Registry Entry.""" + alert_id: str integration: str filename: str date_updated: str | None @@ -197,9 +176,10 @@ class AlertUpdateCoordinator(DataUpdateCoordinator[dict[str, IntegrationAlert]]) continue integration_alert = IntegrationAlert( + alert_id=alert["id"], integration=integration["package"], filename=alert["filename"], - date_updated=alert.get("date_updated"), + date_updated=alert.get("updated"), ) result[integration_alert.issue_id] = integration_alert diff --git a/tests/components/homeassistant_alerts/fixtures/alerts_1.json b/tests/components/homeassistant_alerts/fixtures/alerts_1.json index 0f480f66b31..4462f7020d2 100644 --- a/tests/components/homeassistant_alerts/fixtures/alerts_1.json +++ b/tests/components/homeassistant_alerts/fixtures/alerts_1.json @@ -1,5 +1,6 @@ [ { + "id": "aladdin_connect", "title": "Aladdin Connect is turning off their previous connection method", "created": "2022-07-14T06:00:00.000Z", "integrations": [ @@ -15,6 +16,7 @@ "alert_url": "https://alerts.home-assistant.io/#aladdin_connect.markdown" }, { + "id": "dark_sky", "title": "Dark Sky API closed for new users", "created": "2020-03-31T14:40:00.000Z", "integrations": [ @@ -31,6 +33,7 @@ "alert_url": "https://alerts.home-assistant.io/#dark_sky.markdown" }, { + "id": "hassio", "title": "Supervisor November beta issue impacting users on Home Assistant beta/dev channels", "created": "2022-11-16T06:00:00.000Z", "integrations": [ @@ -51,6 +54,7 @@ "alert_url": "https://alerts.home-assistant.io/#hassio.markdown" }, { + "id": "hikvision", "title": "Hikvision Security Vulnerability", "created": "2021-09-20T22:08:00.000Z", "integrations": [ @@ -68,6 +72,7 @@ } }, { + "id": "hive_us", "title": "Hive shutting down North American Servers", "created": "2021-11-13T13:58:00.000Z", "integrations": [ @@ -83,6 +88,7 @@ "alert_url": "https://alerts.home-assistant.io/#hive_us.markdown" }, { + "id": "homematicip_cloud", "title": "HomematicIP (EQ-3) blocks public IP addresses, if access to the Cloud is too frequent.", "created": "2020-12-20T12:00:00.000Z", "integrations": [ @@ -103,6 +109,7 @@ "alert_url": "https://alerts.home-assistant.io/#homematicip_cloud.markdown" }, { + "id": "logi_circle", "title": "Logitech no longer accepting API applications", "created": "2022-05-16T12:00:00.000Z", "integrations": [ @@ -119,6 +126,7 @@ "alert_url": "https://alerts.home-assistant.io/#logi_circle.markdown" }, { + "id": "neato", "title": "New Neato Botvacs Do Not Support Existing API", "created": "2021-12-20T13:27:00.000Z", "integrations": [ @@ -134,6 +142,7 @@ "alert_url": "https://alerts.home-assistant.io/#neato.markdown" }, { + "id": "nest", "title": "Nest Desktop Auth Deprecation", "created": "2022-05-12T14:04:00.000Z", "integrations": [ @@ -149,6 +158,7 @@ } }, { + "id": "senseme", "title": "Haiku Firmware Update Protocol Change", "created": "2022-04-05T00:00:00.000Z", "integrations": [ @@ -163,6 +173,7 @@ } }, { + "id": "sochain", "title": "The SoChain integration is disabled due to a dependency conflict", "created": "2022-02-01T00:00:00.000Z", "integrations": [ @@ -177,6 +188,7 @@ } }, { + "id": "yeelight", "title": "Yeelight-manufactured Xiaomi-branded devices removed Local Control", "created": "2021-03-29T06:00:00.000Z", "integrations": [ diff --git a/tests/components/homeassistant_alerts/fixtures/alerts_2.json b/tests/components/homeassistant_alerts/fixtures/alerts_2.json index 2941d9da143..55f8f5ffae1 100644 --- a/tests/components/homeassistant_alerts/fixtures/alerts_2.json +++ b/tests/components/homeassistant_alerts/fixtures/alerts_2.json @@ -1,5 +1,6 @@ [ { + "id": "dark_sky", "title": "Dark Sky API closed for new users", "created": "2020-03-31T14:40:00.000Z", "integrations": [ @@ -16,6 +17,7 @@ "alert_url": "https://alerts.home-assistant.io/#dark_sky.markdown" }, { + "id": "hikvision", "title": "Hikvision Security Vulnerability", "created": "2021-09-20T22:08:00.000Z", "integrations": [ @@ -33,6 +35,7 @@ } }, { + "id": "hive_us", "title": "Hive shutting down North American Servers", "created": "2021-11-13T13:58:00.000Z", "integrations": [ @@ -48,6 +51,7 @@ "alert_url": "https://alerts.home-assistant.io/#hive_us.markdown" }, { + "id": "homematicip_cloud", "title": "HomematicIP (EQ-3) blocks public IP addresses, if access to the Cloud is too frequent.", "created": "2020-12-20T12:00:00.000Z", "integrations": [ @@ -68,6 +72,7 @@ "alert_url": "https://alerts.home-assistant.io/#homematicip_cloud.markdown" }, { + "id": "logi_circle", "title": "Logitech no longer accepting API applications", "created": "2022-05-16T12:00:00.000Z", "integrations": [ @@ -84,6 +89,7 @@ "alert_url": "https://alerts.home-assistant.io/#logi_circle.markdown" }, { + "id": "neato", "title": "New Neato Botvacs Do Not Support Existing API", "created": "2021-12-20T13:27:00.000Z", "integrations": [ @@ -99,6 +105,7 @@ "alert_url": "https://alerts.home-assistant.io/#neato.markdown" }, { + "id": "nest", "title": "Nest Desktop Auth Deprecation", "created": "2022-05-12T14:04:00.000Z", "integrations": [ @@ -114,6 +121,7 @@ } }, { + "id": "senseme", "title": "Haiku Firmware Update Protocol Change", "created": "2022-04-05T00:00:00.000Z", "integrations": [ @@ -128,6 +136,7 @@ } }, { + "id": "sochain", "title": "The SoChain integration is disabled due to a dependency conflict", "created": "2022-02-01T00:00:00.000Z", "integrations": [ @@ -142,6 +151,7 @@ } }, { + "id": "yeelight", "title": "Yeelight-manufactured Xiaomi-branded devices removed Local Control", "created": "2021-03-29T06:00:00.000Z", "integrations": [ diff --git a/tests/components/homeassistant_alerts/fixtures/alerts_no_integrations.json b/tests/components/homeassistant_alerts/fixtures/alerts_no_integrations.json index 25ce79d7e7c..5b798b3cd53 100644 --- a/tests/components/homeassistant_alerts/fixtures/alerts_no_integrations.json +++ b/tests/components/homeassistant_alerts/fixtures/alerts_no_integrations.json @@ -1,5 +1,6 @@ [ { + "id": "dark_sky", "title": "Dark Sky API closed for new users", "created": "2020-03-31T14:40:00.000Z", "integrations": [ @@ -16,6 +17,7 @@ "alert_url": "https://alerts.home-assistant.io/#dark_sky.markdown" }, { + "id": "hikvision", "title": "Hikvision Security Vulnerability", "created": "2021-09-20T22:08:00.000Z", "filename": "hikvision.markdown", diff --git a/tests/components/homeassistant_alerts/fixtures/alerts_no_package.json b/tests/components/homeassistant_alerts/fixtures/alerts_no_package.json index bcc0a0223ee..de506b0a2d4 100644 --- a/tests/components/homeassistant_alerts/fixtures/alerts_no_package.json +++ b/tests/components/homeassistant_alerts/fixtures/alerts_no_package.json @@ -1,5 +1,6 @@ [ { + "id": "dark_sky", "title": "Dark Sky API closed for new users", "created": "2020-03-31T14:40:00.000Z", "integrations": [ @@ -16,6 +17,7 @@ "alert_url": "https://alerts.home-assistant.io/#dark_sky.markdown" }, { + "id": "hikvision", "title": "Hikvision Security Vulnerability", "created": "2021-09-20T22:08:00.000Z", "integrations": [ diff --git a/tests/components/homeassistant_alerts/test_init.py b/tests/components/homeassistant_alerts/test_init.py index 41fdff425b3..cb1f5f169fe 100644 --- a/tests/components/homeassistant_alerts/test_init.py +++ b/tests/components/homeassistant_alerts/test_init.py @@ -17,15 +17,11 @@ from tests.common import assert_lists_same, async_fire_time_changed, load_fixtur from tests.test_util.aiohttp import AiohttpClientMocker -def stub_alert(aioclient_mock, filename): +def stub_alert(aioclient_mock, alert_id): """Stub an alert.""" aioclient_mock.get( - f"https://alerts.home-assistant.io/alerts/{filename}", - text=f"""--- -title: Title for {filename} ---- -Content for {filename} -""", + f"https://alerts.home-assistant.io/alerts/{alert_id}.json", + json={"title": f"Title for {alert_id}", "content": f"Content for {alert_id}"}, ) @@ -42,50 +38,50 @@ async def setup_repairs(hass): "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"), - ("homematicip_cloud.markdown", "homematicip_cloud"), - ("logi_circle.markdown", "logi_circle"), - ("neato.markdown", "neato"), - ("nest.markdown", "nest"), - ("senseme.markdown", "senseme"), - ("sochain.markdown", "sochain"), + ("aladdin_connect", "aladdin_connect"), + ("dark_sky", "darksky"), + ("hassio", "hassio"), + ("hikvision", "hikvision"), + ("hikvision", "hikvisioncam"), + ("hive_us", "hive"), + ("homematicip_cloud", "homematicip_cloud"), + ("logi_circle", "logi_circle"), + ("neato", "neato"), + ("nest", "nest"), + ("senseme", "senseme"), + ("sochain", "sochain"), ], ), ( "2022.8.0", {"version": "2022.11.1"}, [ - ("dark_sky.markdown", "darksky"), - ("hikvision.markdown", "hikvision"), - ("hikvision.markdown", "hikvisioncam"), - ("hive_us.markdown", "hive"), - ("homematicip_cloud.markdown", "homematicip_cloud"), - ("logi_circle.markdown", "logi_circle"), - ("neato.markdown", "neato"), - ("nest.markdown", "nest"), - ("senseme.markdown", "senseme"), - ("sochain.markdown", "sochain"), + ("dark_sky", "darksky"), + ("hikvision", "hikvision"), + ("hikvision", "hikvisioncam"), + ("hive_us", "hive"), + ("homematicip_cloud", "homematicip_cloud"), + ("logi_circle", "logi_circle"), + ("neato", "neato"), + ("nest", "nest"), + ("senseme", "senseme"), + ("sochain", "sochain"), ], ), ( "2021.10.0", None, [ - ("aladdin_connect.markdown", "aladdin_connect"), - ("dark_sky.markdown", "darksky"), - ("hikvision.markdown", "hikvision"), - ("hikvision.markdown", "hikvisioncam"), - ("homematicip_cloud.markdown", "homematicip_cloud"), - ("logi_circle.markdown", "logi_circle"), - ("neato.markdown", "neato"), - ("nest.markdown", "nest"), - ("senseme.markdown", "senseme"), - ("sochain.markdown", "sochain"), + ("aladdin_connect", "aladdin_connect"), + ("dark_sky", "darksky"), + ("hikvision", "hikvision"), + ("hikvision", "hikvisioncam"), + ("homematicip_cloud", "homematicip_cloud"), + ("logi_circle", "logi_circle"), + ("neato", "neato"), + ("nest", "nest"), + ("senseme", "senseme"), + ("sochain", "sochain"), ], ), ), @@ -153,17 +149,17 @@ async def test_alerts( "domain": "homeassistant_alerts", "ignored": False, "is_fixable": False, - "issue_id": f"{alert}_{integration}", + "issue_id": f"{alert_id}.markdown_{integration}", "issue_domain": integration, "learn_more_url": None, "severity": "warning", "translation_key": "alert", "translation_placeholders": { - "title": f"Title for {alert}", - "description": f"Content for {alert}", + "title": f"Title for {alert_id}", + "description": f"Content for {alert_id}", }, } - for alert, integration in expected_alerts + for alert_id, integration in expected_alerts ] } @@ -175,15 +171,15 @@ async def test_alerts( "2022.7.0", "alerts_no_integrations.json", [ - ("dark_sky.markdown", "darksky"), + ("dark_sky", "darksky"), ], ), ( "2022.7.0", "alerts_no_package.json", [ - ("dark_sky.markdown", "darksky"), - ("hikvision.markdown", "hikvision"), + ("dark_sky", "darksky"), + ("hikvision", "hikvision"), ], ), ), @@ -204,7 +200,7 @@ async def test_bad_alerts( text=fixture_content, ) for alert in json.loads(fixture_content): - stub_alert(aioclient_mock, alert["filename"]) + stub_alert(aioclient_mock, alert["id"]) activated_components = ( "darksky", @@ -234,17 +230,17 @@ async def test_bad_alerts( "domain": "homeassistant_alerts", "ignored": False, "is_fixable": False, - "issue_id": f"{alert}_{integration}", + "issue_id": f"{alert_id}.markdown_{integration}", "issue_domain": integration, "learn_more_url": None, "severity": "warning", "translation_key": "alert", "translation_placeholders": { - "title": f"Title for {alert}", - "description": f"Content for {alert}", + "title": f"Title for {alert_id}", + "description": f"Content for {alert_id}", }, } - for alert, integration in expected_alerts + for alert_id, integration in expected_alerts ] } @@ -279,60 +275,60 @@ async def test_no_alerts( "2022.7.0", "alerts_1.json", [ - ("aladdin_connect.markdown", "aladdin_connect"), - ("dark_sky.markdown", "darksky"), - ("hikvision.markdown", "hikvision"), - ("hikvision.markdown", "hikvisioncam"), - ("hive_us.markdown", "hive"), - ("homematicip_cloud.markdown", "homematicip_cloud"), - ("logi_circle.markdown", "logi_circle"), - ("neato.markdown", "neato"), - ("nest.markdown", "nest"), - ("senseme.markdown", "senseme"), - ("sochain.markdown", "sochain"), + ("aladdin_connect", "aladdin_connect"), + ("dark_sky", "darksky"), + ("hikvision", "hikvision"), + ("hikvision", "hikvisioncam"), + ("hive_us", "hive"), + ("homematicip_cloud", "homematicip_cloud"), + ("logi_circle", "logi_circle"), + ("neato", "neato"), + ("nest", "nest"), + ("senseme", "senseme"), + ("sochain", "sochain"), ], "alerts_2.json", [ - ("dark_sky.markdown", "darksky"), - ("hikvision.markdown", "hikvision"), - ("hikvision.markdown", "hikvisioncam"), - ("hive_us.markdown", "hive"), - ("homematicip_cloud.markdown", "homematicip_cloud"), - ("logi_circle.markdown", "logi_circle"), - ("neato.markdown", "neato"), - ("nest.markdown", "nest"), - ("senseme.markdown", "senseme"), - ("sochain.markdown", "sochain"), + ("dark_sky", "darksky"), + ("hikvision", "hikvision"), + ("hikvision", "hikvisioncam"), + ("hive_us", "hive"), + ("homematicip_cloud", "homematicip_cloud"), + ("logi_circle", "logi_circle"), + ("neato", "neato"), + ("nest", "nest"), + ("senseme", "senseme"), + ("sochain", "sochain"), ], ), ( "2022.7.0", "alerts_2.json", [ - ("dark_sky.markdown", "darksky"), - ("hikvision.markdown", "hikvision"), - ("hikvision.markdown", "hikvisioncam"), - ("hive_us.markdown", "hive"), - ("homematicip_cloud.markdown", "homematicip_cloud"), - ("logi_circle.markdown", "logi_circle"), - ("neato.markdown", "neato"), - ("nest.markdown", "nest"), - ("senseme.markdown", "senseme"), - ("sochain.markdown", "sochain"), + ("dark_sky", "darksky"), + ("hikvision", "hikvision"), + ("hikvision", "hikvisioncam"), + ("hive_us", "hive"), + ("homematicip_cloud", "homematicip_cloud"), + ("logi_circle", "logi_circle"), + ("neato", "neato"), + ("nest", "nest"), + ("senseme", "senseme"), + ("sochain", "sochain"), ], "alerts_1.json", [ - ("aladdin_connect.markdown", "aladdin_connect"), - ("dark_sky.markdown", "darksky"), - ("hikvision.markdown", "hikvision"), - ("hikvision.markdown", "hikvisioncam"), - ("hive_us.markdown", "hive"), - ("homematicip_cloud.markdown", "homematicip_cloud"), - ("logi_circle.markdown", "logi_circle"), - ("neato.markdown", "neato"), - ("nest.markdown", "nest"), - ("senseme.markdown", "senseme"), - ("sochain.markdown", "sochain"), + ("aladdin_connect", "aladdin_connect"), + ("dark_sky", "darksky"), + ("hikvision", "hikvision"), + ("hikvision", "hikvisioncam"), + ("hive_us", "hive"), + ("homematicip_cloud", "homematicip_cloud"), + ("logi_circle", "logi_circle"), + ("neato", "neato"), + ("nest", "nest"), + ("senseme", "senseme"), + ("sochain", "sochain"), ], ), ), @@ -355,7 +351,7 @@ async def test_alerts_change( text=fixture_1_content, ) for alert in json.loads(fixture_1_content): - stub_alert(aioclient_mock, alert["filename"]) + stub_alert(aioclient_mock, alert["id"]) activated_components = ( "aladdin_connect", @@ -396,17 +392,17 @@ async def test_alerts_change( "domain": "homeassistant_alerts", "ignored": False, "is_fixable": False, - "issue_id": f"{alert}_{integration}", + "issue_id": f"{alert_id}.markdown_{integration}", "issue_domain": integration, "learn_more_url": None, "severity": "warning", "translation_key": "alert", "translation_placeholders": { - "title": f"Title for {alert}", - "description": f"Content for {alert}", + "title": f"Title for {alert_id}", + "description": f"Content for {alert_id}", }, } - for alert, integration in expected_alerts_1 + for alert_id, integration in expected_alerts_1 ], ) @@ -417,7 +413,7 @@ async def test_alerts_change( text=fixture_2_content, ) for alert in json.loads(fixture_2_content): - stub_alert(aioclient_mock, alert["filename"]) + stub_alert(aioclient_mock, alert["id"]) future = now + UPDATE_INTERVAL + timedelta(seconds=1) async_fire_time_changed(hass, future) @@ -436,16 +432,16 @@ async def test_alerts_change( "domain": "homeassistant_alerts", "ignored": False, "is_fixable": False, - "issue_id": f"{alert}_{integration}", + "issue_id": f"{alert_id}.markdown_{integration}", "issue_domain": integration, "learn_more_url": None, "severity": "warning", "translation_key": "alert", "translation_placeholders": { - "title": f"Title for {alert}", - "description": f"Content for {alert}", + "title": f"Title for {alert_id}", + "description": f"Content for {alert_id}", }, } - for alert, integration in expected_alerts_2 + for alert_id, integration in expected_alerts_2 ], )