From 87241ea0515e40282c0d0af9de43935e6447c3a6 Mon Sep 17 00:00:00 2001 From: Jan Bouwhuis Date: Tue, 2 Dec 2025 08:02:06 +0100 Subject: [PATCH] Add read support for MQTT config entry version to 2.1 (#157623) --- homeassistant/components/mqtt/__init__.py | 18 ++++++++++-------- homeassistant/components/mqtt/config_flow.py | 5 ++--- homeassistant/components/mqtt/const.py | 8 ++++---- tests/components/mqtt/test_config_flow.py | 15 +++++---------- 4 files changed, 21 insertions(+), 25 deletions(-) diff --git a/homeassistant/components/mqtt/__init__.py b/homeassistant/components/mqtt/__init__.py index 9611ff0a9701..9989e07c49b7 100644 --- a/homeassistant/components/mqtt/__init__.py +++ b/homeassistant/components/mqtt/__init__.py @@ -378,31 +378,33 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: async def async_migrate_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Migrate the options from config entry data.""" - _LOGGER.debug("Migrating from version %s:%s", entry.version, entry.minor_version) + _LOGGER.debug("Migrating from version %s.%s", entry.version, entry.minor_version) data: dict[str, Any] = dict(entry.data) options: dict[str, Any] = dict(entry.options) - if entry.version > 1: + if entry.version > 2 or (entry.version == 2 and entry.minor_version > 1): # This means the user has downgraded from a future version + # We allow read support for version 2.1 return False if entry.version == 1 and entry.minor_version < 2: - # Can be removed when config entry is bumped to version 2.1 - # with HA Core 2026.1.0. Read support for version 2.1 is expected before 2026.1 - # From 2026.1 we will write version 2.1 + # Can be removed when the config entry is bumped to version 2.1 + # with HA Core 2026.7.0. Read support for version 2.1 is expected with 2026.1 + # From 2026.7 we will write version 2.1 for key in ENTRY_OPTION_FIELDS: if key not in data: continue options[key] = data.pop(key) + # Write version 1.2 for backwards compatibility hass.config_entries.async_update_entry( entry, data=data, options=options, - version=CONFIG_ENTRY_VERSION, - minor_version=CONFIG_ENTRY_MINOR_VERSION, + version=1, + minor_version=2, ) _LOGGER.debug( - "Migration to version %s:%s successful", entry.version, entry.minor_version + "Migration to version %s.%s successful", entry.version, entry.minor_version ) return True diff --git a/homeassistant/components/mqtt/config_flow.py b/homeassistant/components/mqtt/config_flow.py index d1cc05f2e804..230fae72bd46 100644 --- a/homeassistant/components/mqtt/config_flow.py +++ b/homeassistant/components/mqtt/config_flow.py @@ -3952,9 +3952,8 @@ REAUTH_SCHEMA = vol.Schema( class FlowHandler(ConfigFlow, domain=DOMAIN): """Handle a config flow.""" - # Can be bumped to version 2.1 with HA Core 2026.1.0 - VERSION = CONFIG_ENTRY_VERSION # 1 - MINOR_VERSION = CONFIG_ENTRY_MINOR_VERSION # 2 + VERSION = CONFIG_ENTRY_VERSION # 2 + MINOR_VERSION = CONFIG_ENTRY_MINOR_VERSION # 1 _hassio_discovery: dict[str, Any] | None = None _addon_manager: AddonManager diff --git a/homeassistant/components/mqtt/const.py b/homeassistant/components/mqtt/const.py index ae7b341d9d45..96300977722c 100644 --- a/homeassistant/components/mqtt/const.py +++ b/homeassistant/components/mqtt/const.py @@ -381,13 +381,13 @@ MQTT_PROCESSED_SUBSCRIPTIONS = "mqtt_processed_subscriptions" PAYLOAD_EMPTY_JSON = "{}" PAYLOAD_NONE = "None" -CONFIG_ENTRY_VERSION = 1 -CONFIG_ENTRY_MINOR_VERSION = 2 +CONFIG_ENTRY_VERSION = 2 +CONFIG_ENTRY_MINOR_VERSION = 1 # Split mqtt entry data and options # Can be removed when config entry is bumped to version 2.1 -# with HA Core 2026.1.0. Read support for version 2.1 is expected before 2026.1 -# From 2026.1 we will write version 2.1 +# with HA Core 2026.7.0. Read support for version 2.1 is expected from 2026.1 +# From 2026.7 we will write version 2.1 ENTRY_OPTION_FIELDS = ( CONF_DISCOVERY, CONF_DISCOVERY_PREFIX, diff --git a/tests/components/mqtt/test_config_flow.py b/tests/components/mqtt/test_config_flow.py index f73dfe573746..50aef011f59b 100644 --- a/tests/components/mqtt/test_config_flow.py +++ b/tests/components/mqtt/test_config_flow.py @@ -386,8 +386,8 @@ async def test_user_connection_works( "port": 1883, } # Check we have the latest Config Entry version - assert result["result"].version == 1 - assert result["result"].minor_version == 2 + assert result["result"].version == 2 + assert result["result"].minor_version == 1 # Check we tried the connection assert len(mock_try_connection.mock_calls) == 1 # Check config entry got setup @@ -2590,7 +2590,7 @@ async def test_reconfigure_no_changed_password( [ (1, 1, MOCK_ENTRY_DATA | MOCK_ENTRY_OPTIONS, {}, 1, 2), (1, 2, MOCK_ENTRY_DATA, MOCK_ENTRY_OPTIONS, 1, 2), - (1, 3, MOCK_ENTRY_DATA, MOCK_ENTRY_OPTIONS, 1, 3), + (2, 1, MOCK_ENTRY_DATA, MOCK_ENTRY_OPTIONS, 2, 1), ], ) @pytest.mark.usefixtures("mock_reload_after_entry_update") @@ -2631,11 +2631,10 @@ async def test_migrate_config_entry( "minor_version", "data", "options", - "expected_version", - "expected_minor_version", ), [ - (2, 1, MOCK_ENTRY_DATA, MOCK_ENTRY_OPTIONS, 2, 1), + (2, 2, MOCK_ENTRY_DATA, MOCK_ENTRY_OPTIONS), + (3, 1, MOCK_ENTRY_DATA, MOCK_ENTRY_OPTIONS), ], ) @pytest.mark.usefixtures("mock_reload_after_entry_update") @@ -2646,8 +2645,6 @@ async def test_migrate_of_incompatible_config_entry( minor_version: int, data: dict[str, Any], options: dict[str, Any], - expected_version: int, - expected_minor_version: int, ) -> None: """Test migrating a config entry.""" config_entry = hass.config_entries.async_entries(mqtt.DOMAIN)[0] @@ -2660,8 +2657,6 @@ async def test_migrate_of_incompatible_config_entry( minor_version=minor_version, ) await hass.async_block_till_done() - assert config_entry.version == expected_version - assert config_entry.minor_version == expected_minor_version # Try to start MQTT with incompatible config entry with pytest.raises(AssertionError):