Compare commits

...

1 Commits

Author SHA1 Message Date
Erik b9688b7fb2 Open repair issue when deprecated trigger behavior is used 2026-06-08 10:13:36 +02:00
3 changed files with 82 additions and 1 deletions
@@ -135,6 +135,10 @@
"description": "The {integration_title} integration is being removed as it depends on system packages that can only be installed on systems running a deprecated architecture. To resolve this, remove the {domain} entry from your configuration.yaml file and restart Home Assistant.",
"title": "The {integration_title} integration is being removed"
},
"deprecated_trigger_behavior": {
"description": "An automation, script or template entity uses the trigger behavior option `{deprecated_behavior}`, which has been renamed to `{new_behavior}`. The old value still works for now, but support for it will be removed in a future release.\n\nTo fix this issue, edit the affected automations and scripts and change the behavior option from `{deprecated_behavior}` to `{new_behavior}`, then restart Home Assistant.",
"title": "Deprecated trigger behavior option in use"
},
"deprecated_yaml": {
"description": "Configuring {integration_title} using YAML is being removed.\n\nYour existing YAML configuration has been imported into the UI automatically.\n\nRemove the `{domain}` configuration from your configuration.yaml file and restart Home Assistant to fix this issue.",
"title": "The {integration_title} YAML configuration is being removed"
+28
View File
@@ -44,11 +44,13 @@ from homeassistant.const import (
)
from homeassistant.core import (
CALLBACK_TYPE,
DOMAIN as HOMEASSISTANT_DOMAIN,
Context,
HassJob,
HassJobType,
HomeAssistant,
State,
async_get_hass_or_none,
callback,
get_hassjob_callable_job_type,
is_callback,
@@ -331,11 +333,37 @@ BEHAVIOR_ALL: Final = "all"
BEHAVIOR_EACH: Final = "each"
def _create_deprecated_behavior_issue(deprecated: str, replacement: str) -> None:
"""Inform the user a renamed trigger behavior value is still in use."""
# Returns None when called from the wrong thread or before hass is set up
# (e.g. a `check_config` run), in which case there's nothing to report to.
if (hass := async_get_hass_or_none()) is None:
return
from .issue_registry import IssueSeverity, async_create_issue # noqa: PLC0415
async_create_issue(
hass,
HOMEASSISTANT_DOMAIN,
f"deprecated_trigger_behavior_{deprecated}",
breaks_in_ha_version="2027.1",
is_fixable=False,
severity=IssueSeverity.WARNING,
translation_key="deprecated_trigger_behavior",
translation_placeholders={
"deprecated_behavior": deprecated,
"new_behavior": replacement,
},
)
def _backwards_compatible_behavior(value: Any) -> Any:
"""Convert legacy behavior values to new ones."""
if value == "any":
_create_deprecated_behavior_issue("any", BEHAVIOR_EACH)
return BEHAVIOR_EACH
if value == "last":
_create_deprecated_behavior_issue("last", BEHAVIOR_ALL)
return BEHAVIOR_ALL
return value
+50 -1
View File
@@ -34,6 +34,7 @@ from homeassistant.const import (
)
from homeassistant.core import (
CALLBACK_TYPE,
DOMAIN as HOMEASSISTANT_DOMAIN,
Context,
HomeAssistant,
ServiceCall,
@@ -41,7 +42,7 @@ from homeassistant.core import (
callback,
)
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import config_validation as cv, trigger
from homeassistant.helpers import config_validation as cv, issue_registry as ir, trigger
from homeassistant.helpers.automation import (
DomainSpec,
move_top_level_schema_fields_to_options,
@@ -4814,6 +4815,54 @@ def test_entity_state_trigger_schema_behavior_backwards_compatible(
assert validated[CONF_OPTIONS][ATTR_BEHAVIOR] == expected
@pytest.mark.parametrize(
("behavior", "expected"),
[
("any", BEHAVIOR_EACH),
("last", BEHAVIOR_ALL),
],
)
async def test_entity_state_trigger_legacy_behavior_creates_repair_issue(
hass: HomeAssistant,
issue_registry: ir.IssueRegistry,
behavior: str,
expected: str,
) -> None:
"""Test a repair issue is raised when a legacy behavior value is used."""
config = {
CONF_TARGET: {CONF_ENTITY_ID: "test.entity"},
CONF_OPTIONS: {ATTR_BEHAVIOR: behavior},
}
validated = ENTITY_STATE_TRIGGER_SCHEMA_WITH_BEHAVIOR(config)
assert validated[CONF_OPTIONS][ATTR_BEHAVIOR] == expected
issue = issue_registry.async_get_issue(
HOMEASSISTANT_DOMAIN, f"deprecated_trigger_behavior_{behavior}"
)
assert issue is not None
assert issue.translation_key == "deprecated_trigger_behavior"
assert issue.translation_placeholders == {
"deprecated_behavior": behavior,
"new_behavior": expected,
}
@pytest.mark.parametrize("behavior", [BEHAVIOR_EACH, BEHAVIOR_FIRST, BEHAVIOR_ALL])
async def test_entity_state_trigger_new_behavior_no_repair_issue(
hass: HomeAssistant,
issue_registry: ir.IssueRegistry,
behavior: str,
) -> None:
"""Test no repair issue is raised when a current behavior value is used."""
config = {
CONF_TARGET: {CONF_ENTITY_ID: "test.entity"},
CONF_OPTIONS: {ATTR_BEHAVIOR: behavior},
}
ENTITY_STATE_TRIGGER_SCHEMA_WITH_BEHAVIOR(config)
assert not issue_registry.issues
def test_entity_state_trigger_schema_behavior_default() -> None:
"""Test the behavior defaults to 'each' when omitted."""
config = {