mirror of
https://github.com/home-assistant/core.git
synced 2025-07-24 05:37:44 +00:00
Add deprecation issues for supervised and core installation methods (#145323)
Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
This commit is contained in:
parent
b8a96d2a76
commit
a2b02537a6
@ -4,7 +4,7 @@ import asyncio
|
||||
from collections.abc import Callable, Coroutine
|
||||
import itertools as it
|
||||
import logging
|
||||
from typing import Any
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
@ -31,14 +31,22 @@ from homeassistant.core import (
|
||||
split_entity_id,
|
||||
)
|
||||
from homeassistant.exceptions import HomeAssistantError, Unauthorized, UnknownUser
|
||||
from homeassistant.helpers import config_validation as cv, recorder, restore_state
|
||||
from homeassistant.helpers import (
|
||||
config_validation as cv,
|
||||
issue_registry as ir,
|
||||
recorder,
|
||||
restore_state,
|
||||
)
|
||||
from homeassistant.helpers.entity_component import async_update_entity
|
||||
from homeassistant.helpers.importlib import async_import_module
|
||||
from homeassistant.helpers.issue_registry import IssueSeverity
|
||||
from homeassistant.helpers.service import (
|
||||
async_extract_config_entry_ids,
|
||||
async_extract_referenced_entity_ids,
|
||||
async_register_admin_service,
|
||||
)
|
||||
from homeassistant.helpers.signal import KEY_HA_STOP
|
||||
from homeassistant.helpers.system_info import async_get_system_info
|
||||
from homeassistant.helpers.template import async_load_custom_templates
|
||||
from homeassistant.helpers.typing import ConfigType
|
||||
|
||||
@ -81,6 +89,11 @@ SCHEMA_RESTART = vol.Schema({vol.Optional(ATTR_SAFE_MODE, default=False): bool})
|
||||
|
||||
SHUTDOWN_SERVICES = (SERVICE_HOMEASSISTANT_STOP, SERVICE_HOMEASSISTANT_RESTART)
|
||||
|
||||
DEPRECATION_URL = (
|
||||
"https://www.home-assistant.io/blog/2025/05/22/"
|
||||
"deprecating-core-and-supervised-installation-methods-and-32-bit-systems/"
|
||||
)
|
||||
|
||||
|
||||
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: # noqa: C901
|
||||
"""Set up general services related to Home Assistant."""
|
||||
@ -386,6 +399,83 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: # noqa:
|
||||
hass.data[DATA_EXPOSED_ENTITIES] = exposed_entities
|
||||
async_set_stop_handler(hass, _async_stop)
|
||||
|
||||
info = await async_get_system_info(hass)
|
||||
|
||||
installation_type = info["installation_type"][15:]
|
||||
deprecated_method = installation_type in {
|
||||
"Core",
|
||||
"Supervised",
|
||||
}
|
||||
arch = info["arch"]
|
||||
if arch == "armv7":
|
||||
if installation_type == "OS":
|
||||
# Local import to avoid circular dependencies
|
||||
# We use the import helper because hassio
|
||||
# may not be loaded yet and we don't want to
|
||||
# do blocking I/O in the event loop to import it.
|
||||
if TYPE_CHECKING:
|
||||
# pylint: disable-next=import-outside-toplevel
|
||||
from homeassistant.components import hassio
|
||||
else:
|
||||
hassio = await async_import_module(
|
||||
hass, "homeassistant.components.hassio"
|
||||
)
|
||||
os_info = hassio.get_os_info(hass)
|
||||
assert os_info is not None
|
||||
issue_id = "deprecated_os_"
|
||||
board = os_info.get("board")
|
||||
if board in {"rpi3", "rpi4"}:
|
||||
issue_id += "aarch64"
|
||||
elif board in {"tinker", "odroid-xu4", "rpi2"}:
|
||||
issue_id += "armv7"
|
||||
ir.async_create_issue(
|
||||
hass,
|
||||
DOMAIN,
|
||||
issue_id,
|
||||
breaks_in_ha_version="2025.12.0",
|
||||
learn_more_url=DEPRECATION_URL,
|
||||
is_fixable=False,
|
||||
severity=IssueSeverity.WARNING,
|
||||
translation_key=issue_id,
|
||||
translation_placeholders={
|
||||
"installation_guide": "https://www.home-assistant.io/installation/",
|
||||
},
|
||||
)
|
||||
elif installation_type == "Container":
|
||||
ir.async_create_issue(
|
||||
hass,
|
||||
DOMAIN,
|
||||
"deprecated_container_armv7",
|
||||
breaks_in_ha_version="2025.12.0",
|
||||
learn_more_url=DEPRECATION_URL,
|
||||
is_fixable=False,
|
||||
severity=IssueSeverity.WARNING,
|
||||
translation_key="deprecated_container_armv7",
|
||||
)
|
||||
deprecated_architecture = False
|
||||
if arch in {"i386", "armhf"} or (arch == "armv7" and deprecated_method):
|
||||
deprecated_architecture = True
|
||||
if deprecated_method or deprecated_architecture:
|
||||
issue_id = "deprecated"
|
||||
if deprecated_method:
|
||||
issue_id += "_method"
|
||||
if deprecated_architecture:
|
||||
issue_id += "_architecture"
|
||||
ir.async_create_issue(
|
||||
hass,
|
||||
DOMAIN,
|
||||
issue_id,
|
||||
breaks_in_ha_version="2025.12.0",
|
||||
learn_more_url=DEPRECATION_URL,
|
||||
is_fixable=False,
|
||||
severity=IssueSeverity.WARNING,
|
||||
translation_key=issue_id,
|
||||
translation_placeholders={
|
||||
"installation_type": installation_type,
|
||||
"arch": arch,
|
||||
},
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
|
@ -90,6 +90,30 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"deprecated_method": {
|
||||
"title": "Deprecation notice: Installation method",
|
||||
"description": "This system is using the {installation_type} installation type, which has been deprecated and will become unsupported following the release of Home Assistant 2025.12. While you can continue using your current setup after that point, we strongly recommend migrating to a supported installation method."
|
||||
},
|
||||
"deprecated_method_architecture": {
|
||||
"title": "Deprecation notice",
|
||||
"description": "This system is using the {installation_type} installation type, and 32-bit hardware (`{arch}`), both of which have been deprecated and will no longer be supported after the release of Home Assistant 2025.12."
|
||||
},
|
||||
"deprecated_architecture": {
|
||||
"title": "Deprecation notice: 32-bit architecture",
|
||||
"description": "This system uses 32-bit hardware (`{arch}`), which has been deprecated and will no longer receive updates after the release of Home Assistant 2025.12. As your hardware is no longer capable of running newer versions of Home Assistant, you will need to migrate to new hardware."
|
||||
},
|
||||
"deprecated_container_armv7": {
|
||||
"title": "[%key:component::homeassistant::issues::deprecated_architecture::title%]",
|
||||
"description": "This system is running on a 32-bit operating system (`armv7`), which has been deprecated and will no longer receive updates after the release of Home Assistant 2025.12. Check if your system is capable of running a 64-bit operating system. If not, you will need to migrate to new hardware."
|
||||
},
|
||||
"deprecated_os_aarch64": {
|
||||
"title": "[%key:component::homeassistant::issues::deprecated_architecture::title%]",
|
||||
"description": "This system is running on a 32-bit operating system (`armv7`), which has been deprecated and will no longer receive updates after the release of Home Assistant 2025.12. To continue using Home Assistant on this hardware, you will need to install a 64-bit operating system. Please refer to our [installation guide]({installation_guide})."
|
||||
},
|
||||
"deprecated_os_armv7": {
|
||||
"title": "[%key:component::homeassistant::issues::deprecated_architecture::title%]",
|
||||
"description": "This system is running on a 32-bit operating system (`armv7`), which has been deprecated and will no longer receive updates after the release of Home Assistant 2025.12. As your hardware is no longer capable of running newer versions of Home Assistant, you will need to migrate to new hardware."
|
||||
}
|
||||
},
|
||||
"system_health": {
|
||||
|
@ -10,6 +10,7 @@ from homeassistant import config, core as ha
|
||||
from homeassistant.components.homeassistant import (
|
||||
ATTR_ENTRY_ID,
|
||||
ATTR_SAFE_MODE,
|
||||
DOMAIN as HOMEASSISTANT_DOMAIN,
|
||||
SERVICE_CHECK_CONFIG,
|
||||
SERVICE_HOMEASSISTANT_RESTART,
|
||||
SERVICE_HOMEASSISTANT_STOP,
|
||||
@ -32,7 +33,7 @@ from homeassistant.const import (
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError, Unauthorized
|
||||
from homeassistant.helpers import entity, entity_registry as er
|
||||
from homeassistant.helpers import entity, entity_registry as er, issue_registry as ir
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from tests.common import (
|
||||
@ -637,3 +638,187 @@ async def test_reload_all(
|
||||
assert len(core_config) == 1
|
||||
assert len(themes) == 1
|
||||
assert len(jinja) == 1
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"installation_type",
|
||||
[
|
||||
"Home Assistant Core",
|
||||
"Home Assistant Supervised",
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize(
|
||||
"arch",
|
||||
[
|
||||
"i386",
|
||||
"armhf",
|
||||
"armv7",
|
||||
],
|
||||
)
|
||||
async def test_deprecated_installation_issue_32bit_method(
|
||||
hass: HomeAssistant,
|
||||
issue_registry: ir.IssueRegistry,
|
||||
installation_type: str,
|
||||
arch: str,
|
||||
) -> None:
|
||||
"""Test deprecated installation issue."""
|
||||
with patch(
|
||||
"homeassistant.components.homeassistant.async_get_system_info",
|
||||
return_value={
|
||||
"installation_type": installation_type,
|
||||
"arch": arch,
|
||||
},
|
||||
):
|
||||
assert await async_setup_component(hass, HOMEASSISTANT_DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(issue_registry.issues) == 1
|
||||
issue = issue_registry.async_get_issue(
|
||||
HOMEASSISTANT_DOMAIN, "deprecated_method_architecture"
|
||||
)
|
||||
assert issue.domain == HOMEASSISTANT_DOMAIN
|
||||
assert issue.severity == ir.IssueSeverity.WARNING
|
||||
assert issue.translation_placeholders == {
|
||||
"installation_type": installation_type[15:],
|
||||
"arch": arch,
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"installation_type",
|
||||
[
|
||||
"Home Assistant Container",
|
||||
"Home Assistant OS",
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize(
|
||||
"arch",
|
||||
[
|
||||
"i386",
|
||||
"armhf",
|
||||
],
|
||||
)
|
||||
async def test_deprecated_installation_issue_32bit(
|
||||
hass: HomeAssistant,
|
||||
issue_registry: ir.IssueRegistry,
|
||||
installation_type: str,
|
||||
arch: str,
|
||||
) -> None:
|
||||
"""Test deprecated installation issue."""
|
||||
with patch(
|
||||
"homeassistant.components.homeassistant.async_get_system_info",
|
||||
return_value={
|
||||
"installation_type": installation_type,
|
||||
"arch": arch,
|
||||
},
|
||||
):
|
||||
assert await async_setup_component(hass, HOMEASSISTANT_DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(issue_registry.issues) == 1
|
||||
issue = issue_registry.async_get_issue(
|
||||
HOMEASSISTANT_DOMAIN, "deprecated_architecture"
|
||||
)
|
||||
assert issue.domain == HOMEASSISTANT_DOMAIN
|
||||
assert issue.severity == ir.IssueSeverity.WARNING
|
||||
assert issue.translation_placeholders == {
|
||||
"installation_type": installation_type[15:],
|
||||
"arch": arch,
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"installation_type",
|
||||
[
|
||||
"Home Assistant Core",
|
||||
"Home Assistant Supervised",
|
||||
],
|
||||
)
|
||||
async def test_deprecated_installation_issue_method(
|
||||
hass: HomeAssistant,
|
||||
issue_registry: ir.IssueRegistry,
|
||||
installation_type: str,
|
||||
) -> None:
|
||||
"""Test deprecated installation issue."""
|
||||
with patch(
|
||||
"homeassistant.components.homeassistant.async_get_system_info",
|
||||
return_value={
|
||||
"installation_type": installation_type,
|
||||
"arch": "generic-x86-64",
|
||||
},
|
||||
):
|
||||
assert await async_setup_component(hass, HOMEASSISTANT_DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(issue_registry.issues) == 1
|
||||
issue = issue_registry.async_get_issue(HOMEASSISTANT_DOMAIN, "deprecated_method")
|
||||
assert issue.domain == HOMEASSISTANT_DOMAIN
|
||||
assert issue.severity == ir.IssueSeverity.WARNING
|
||||
assert issue.translation_placeholders == {
|
||||
"installation_type": installation_type[15:],
|
||||
"arch": "generic-x86-64",
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("board", "issue_id"),
|
||||
[
|
||||
("rpi3", "deprecated_os_aarch64"),
|
||||
("rpi4", "deprecated_os_aarch64"),
|
||||
("tinker", "deprecated_os_armv7"),
|
||||
("odroid-xu4", "deprecated_os_armv7"),
|
||||
("rpi2", "deprecated_os_armv7"),
|
||||
],
|
||||
)
|
||||
async def test_deprecated_installation_issue_aarch64(
|
||||
hass: HomeAssistant,
|
||||
issue_registry: ir.IssueRegistry,
|
||||
board: str,
|
||||
issue_id: str,
|
||||
) -> None:
|
||||
"""Test deprecated installation issue."""
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.homeassistant.async_get_system_info",
|
||||
return_value={
|
||||
"installation_type": "Home Assistant OS",
|
||||
"arch": "armv7",
|
||||
},
|
||||
),
|
||||
patch(
|
||||
"homeassistant.components.hassio.get_os_info", return_value={"board": board}
|
||||
),
|
||||
):
|
||||
assert await async_setup_component(hass, HOMEASSISTANT_DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(issue_registry.issues) == 1
|
||||
issue = issue_registry.async_get_issue(HOMEASSISTANT_DOMAIN, issue_id)
|
||||
assert issue.domain == HOMEASSISTANT_DOMAIN
|
||||
assert issue.severity == ir.IssueSeverity.WARNING
|
||||
assert issue.translation_placeholders == {
|
||||
"installation_guide": "https://www.home-assistant.io/installation/",
|
||||
}
|
||||
|
||||
|
||||
async def test_deprecated_installation_issue_armv7_container(
|
||||
hass: HomeAssistant,
|
||||
issue_registry: ir.IssueRegistry,
|
||||
) -> None:
|
||||
"""Test deprecated installation issue."""
|
||||
with patch(
|
||||
"homeassistant.components.homeassistant.async_get_system_info",
|
||||
return_value={
|
||||
"installation_type": "Home Assistant Container",
|
||||
"arch": "armv7",
|
||||
},
|
||||
):
|
||||
assert await async_setup_component(hass, HOMEASSISTANT_DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(issue_registry.issues) == 1
|
||||
issue = issue_registry.async_get_issue(
|
||||
HOMEASSISTANT_DOMAIN, "deprecated_container_armv7"
|
||||
)
|
||||
assert issue.domain == HOMEASSISTANT_DOMAIN
|
||||
assert issue.severity == ir.IssueSeverity.WARNING
|
||||
|
@ -288,7 +288,6 @@ async def test_create_issue_with_items(
|
||||
assert automations_with_entity(hass, entity_id)[0] == "automation.test"
|
||||
assert scripts_with_entity(hass, entity_id)[0] == "script.test"
|
||||
|
||||
assert len(issue_registry.issues) == 1
|
||||
issue = issue_registry.async_get_issue(DOMAIN, issue_id)
|
||||
assert issue is not None
|
||||
assert issue.translation_key == f"deprecated_switch_{issue_string}_scripts"
|
||||
@ -308,7 +307,6 @@ async def test_create_issue_with_items(
|
||||
|
||||
# Assert the issue is no longer present
|
||||
assert not issue_registry.async_get_issue(DOMAIN, issue_id)
|
||||
assert len(issue_registry.issues) == 0
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@ -413,7 +411,6 @@ async def test_create_issue(
|
||||
|
||||
assert hass.states.get(entity_id).state in [STATE_OFF, STATE_ON]
|
||||
|
||||
assert len(issue_registry.issues) == 1
|
||||
issue = issue_registry.async_get_issue(DOMAIN, issue_id)
|
||||
assert issue is not None
|
||||
assert issue.translation_key == f"deprecated_switch_{issue_string}"
|
||||
@ -433,7 +430,6 @@ async def test_create_issue(
|
||||
|
||||
# Assert the issue is no longer present
|
||||
assert not issue_registry.async_get_issue(DOMAIN, issue_id)
|
||||
assert len(issue_registry.issues) == 0
|
||||
|
||||
|
||||
@pytest.mark.parametrize("device_fixture", ["c2c_arlo_pro_3_switch"])
|
||||
|
Loading…
x
Reference in New Issue
Block a user