From 1e5739fb93b28af3b2cfaa79c82d4952065bafa2 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 29 Dec 2025 16:22:04 -1000 Subject: [PATCH 1/4] [core] Fix incremental build failures when adding components on ESP32-Arduino --- esphome/writer.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/esphome/writer.py b/esphome/writer.py index 9ae40e417a..cb9c921693 100644 --- a/esphome/writer.py +++ b/esphome/writer.py @@ -103,14 +103,11 @@ def storage_should_clean(old: StorageJSON | None, new: StorageJSON) -> bool: def storage_should_update_cmake_cache(old: StorageJSON, new: StorageJSON) -> bool: - if ( + # ESP32 uses CMake for both Arduino and ESP-IDF frameworks + return ( old.loaded_integrations != new.loaded_integrations or old.loaded_platforms != new.loaded_platforms - ) and new.core_platform == PLATFORM_ESP32: - from esphome.components.esp32 import FRAMEWORK_ESP_IDF - - return new.framework == FRAMEWORK_ESP_IDF - return False + ) and new.core_platform == PLATFORM_ESP32 def update_storage_json() -> None: From 1472914527e9e076081ea6375d9e3fa4f0ae1b75 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 29 Dec 2025 16:24:10 -1000 Subject: [PATCH 2/4] cover --- tests/unit_tests/test_writer.py | 108 ++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/tests/unit_tests/test_writer.py b/tests/unit_tests/test_writer.py index f354d71bb7..c792f09f79 100644 --- a/tests/unit_tests/test_writer.py +++ b/tests/unit_tests/test_writer.py @@ -28,6 +28,7 @@ from esphome.writer import ( generate_build_info_data_h, get_build_info, storage_should_clean, + storage_should_update_cmake_cache, update_storage_json, write_cpp, write_gitignore, @@ -171,6 +172,113 @@ def test_storage_edge_case_from_empty_integrations( assert storage_should_clean(old, new) is False +# Tests for storage_should_update_cmake_cache + + +def test_storage_should_update_cmake_cache_when_integration_added_esp32( + create_storage: Callable[..., StorageJSON], +) -> None: + """Test cmake cache update triggered when integration added on ESP32.""" + old = create_storage( + loaded_integrations=["api", "wifi"], + core_platform="esp32", + framework="arduino", + ) + new = create_storage( + loaded_integrations=["api", "wifi", "restart"], + core_platform="esp32", + framework="arduino", + ) + assert storage_should_update_cmake_cache(old, new) is True + + +def test_storage_should_update_cmake_cache_when_integration_added_esp32_idf( + create_storage: Callable[..., StorageJSON], +) -> None: + """Test cmake cache update triggered when integration added on ESP32-IDF.""" + old = create_storage( + loaded_integrations=["api", "wifi"], + core_platform="esp32", + framework="esp-idf", + ) + new = create_storage( + loaded_integrations=["api", "wifi", "restart"], + core_platform="esp32", + framework="esp-idf", + ) + assert storage_should_update_cmake_cache(old, new) is True + + +def test_storage_should_update_cmake_cache_when_platform_changed_esp32( + create_storage: Callable[..., StorageJSON], +) -> None: + """Test cmake cache update triggered when platforms change on ESP32.""" + old = create_storage( + loaded_integrations=["api", "wifi"], + loaded_platforms={"sensor"}, + core_platform="esp32", + framework="arduino", + ) + new = create_storage( + loaded_integrations=["api", "wifi"], + loaded_platforms={"sensor", "binary_sensor"}, + core_platform="esp32", + framework="arduino", + ) + assert storage_should_update_cmake_cache(old, new) is True + + +def test_storage_should_not_update_cmake_cache_when_nothing_changes( + create_storage: Callable[..., StorageJSON], +) -> None: + """Test cmake cache not updated when nothing changes.""" + old = create_storage( + loaded_integrations=["api", "wifi"], + core_platform="esp32", + framework="arduino", + ) + new = create_storage( + loaded_integrations=["api", "wifi"], + core_platform="esp32", + framework="arduino", + ) + assert storage_should_update_cmake_cache(old, new) is False + + +def test_storage_should_not_update_cmake_cache_for_esp8266( + create_storage: Callable[..., StorageJSON], +) -> None: + """Test cmake cache not updated for ESP8266 (uses different build system).""" + old = create_storage( + loaded_integrations=["api", "wifi"], + core_platform="esp8266", + framework="arduino", + ) + new = create_storage( + loaded_integrations=["api", "wifi", "restart"], + core_platform="esp8266", + framework="arduino", + ) + assert storage_should_update_cmake_cache(old, new) is False + + +def test_storage_should_not_update_cmake_cache_for_rp2040( + create_storage: Callable[..., StorageJSON], +) -> None: + """Test cmake cache not updated for RP2040.""" + old = create_storage( + loaded_integrations=["api", "wifi"], + core_platform="rp2040", + framework="arduino", + ) + new = create_storage( + loaded_integrations=["api", "wifi", "restart"], + core_platform="rp2040", + framework="arduino", + ) + assert storage_should_update_cmake_cache(old, new) is False + + @patch("esphome.writer.clean_build") @patch("esphome.writer.StorageJSON") @patch("esphome.writer.storage_path") From 1d1f2a98770e635307a5df15aca451ebbc272bca Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 29 Dec 2025 16:25:17 -1000 Subject: [PATCH 3/4] cover --- tests/unit_tests/test_writer.py | 50 +++++++-------------------------- 1 file changed, 10 insertions(+), 40 deletions(-) diff --git a/tests/unit_tests/test_writer.py b/tests/unit_tests/test_writer.py index c792f09f79..b103776c36 100644 --- a/tests/unit_tests/test_writer.py +++ b/tests/unit_tests/test_writer.py @@ -175,36 +175,21 @@ def test_storage_edge_case_from_empty_integrations( # Tests for storage_should_update_cmake_cache +@pytest.mark.parametrize("framework", ["arduino", "esp-idf"]) def test_storage_should_update_cmake_cache_when_integration_added_esp32( create_storage: Callable[..., StorageJSON], + framework: str, ) -> None: """Test cmake cache update triggered when integration added on ESP32.""" old = create_storage( loaded_integrations=["api", "wifi"], core_platform="esp32", - framework="arduino", + framework=framework, ) new = create_storage( loaded_integrations=["api", "wifi", "restart"], core_platform="esp32", - framework="arduino", - ) - assert storage_should_update_cmake_cache(old, new) is True - - -def test_storage_should_update_cmake_cache_when_integration_added_esp32_idf( - create_storage: Callable[..., StorageJSON], -) -> None: - """Test cmake cache update triggered when integration added on ESP32-IDF.""" - old = create_storage( - loaded_integrations=["api", "wifi"], - core_platform="esp32", - framework="esp-idf", - ) - new = create_storage( - loaded_integrations=["api", "wifi", "restart"], - core_platform="esp32", - framework="esp-idf", + framework=framework, ) assert storage_should_update_cmake_cache(old, new) is True @@ -245,35 +230,20 @@ def test_storage_should_not_update_cmake_cache_when_nothing_changes( assert storage_should_update_cmake_cache(old, new) is False -def test_storage_should_not_update_cmake_cache_for_esp8266( +@pytest.mark.parametrize("core_platform", ["esp8266", "rp2040", "bk72xx", "rtl87xx"]) +def test_storage_should_not_update_cmake_cache_for_non_esp32( create_storage: Callable[..., StorageJSON], + core_platform: str, ) -> None: - """Test cmake cache not updated for ESP8266 (uses different build system).""" + """Test cmake cache not updated for non-ESP32 platforms.""" old = create_storage( loaded_integrations=["api", "wifi"], - core_platform="esp8266", + core_platform=core_platform, framework="arduino", ) new = create_storage( loaded_integrations=["api", "wifi", "restart"], - core_platform="esp8266", - framework="arduino", - ) - assert storage_should_update_cmake_cache(old, new) is False - - -def test_storage_should_not_update_cmake_cache_for_rp2040( - create_storage: Callable[..., StorageJSON], -) -> None: - """Test cmake cache not updated for RP2040.""" - old = create_storage( - loaded_integrations=["api", "wifi"], - core_platform="rp2040", - framework="arduino", - ) - new = create_storage( - loaded_integrations=["api", "wifi", "restart"], - core_platform="rp2040", + core_platform=core_platform, framework="arduino", ) assert storage_should_update_cmake_cache(old, new) is False From 2297d240be482371b2a4c5bdf4bed8f274c45128 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 29 Dec 2025 16:28:14 -1000 Subject: [PATCH 4/4] cleanup --- tests/unit_tests/test_writer.py | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/tests/unit_tests/test_writer.py b/tests/unit_tests/test_writer.py index b103776c36..ac05e0d31b 100644 --- a/tests/unit_tests/test_writer.py +++ b/tests/unit_tests/test_writer.py @@ -13,6 +13,13 @@ from unittest.mock import MagicMock, patch import pytest +from esphome.const import ( + PLATFORM_BK72XX, + PLATFORM_ESP32, + PLATFORM_ESP8266, + PLATFORM_RP2040, + PLATFORM_RTL87XX, +) from esphome.core import EsphomeError from esphome.storage_json import StorageJSON from esphome.writer import ( @@ -183,12 +190,12 @@ def test_storage_should_update_cmake_cache_when_integration_added_esp32( """Test cmake cache update triggered when integration added on ESP32.""" old = create_storage( loaded_integrations=["api", "wifi"], - core_platform="esp32", + core_platform=PLATFORM_ESP32, framework=framework, ) new = create_storage( loaded_integrations=["api", "wifi", "restart"], - core_platform="esp32", + core_platform=PLATFORM_ESP32, framework=framework, ) assert storage_should_update_cmake_cache(old, new) is True @@ -201,13 +208,13 @@ def test_storage_should_update_cmake_cache_when_platform_changed_esp32( old = create_storage( loaded_integrations=["api", "wifi"], loaded_platforms={"sensor"}, - core_platform="esp32", + core_platform=PLATFORM_ESP32, framework="arduino", ) new = create_storage( loaded_integrations=["api", "wifi"], loaded_platforms={"sensor", "binary_sensor"}, - core_platform="esp32", + core_platform=PLATFORM_ESP32, framework="arduino", ) assert storage_should_update_cmake_cache(old, new) is True @@ -219,18 +226,21 @@ def test_storage_should_not_update_cmake_cache_when_nothing_changes( """Test cmake cache not updated when nothing changes.""" old = create_storage( loaded_integrations=["api", "wifi"], - core_platform="esp32", + core_platform=PLATFORM_ESP32, framework="arduino", ) new = create_storage( loaded_integrations=["api", "wifi"], - core_platform="esp32", + core_platform=PLATFORM_ESP32, framework="arduino", ) assert storage_should_update_cmake_cache(old, new) is False -@pytest.mark.parametrize("core_platform", ["esp8266", "rp2040", "bk72xx", "rtl87xx"]) +@pytest.mark.parametrize( + "core_platform", + [PLATFORM_ESP8266, PLATFORM_RP2040, PLATFORM_BK72XX, PLATFORM_RTL87XX], +) def test_storage_should_not_update_cmake_cache_for_non_esp32( create_storage: Callable[..., StorageJSON], core_platform: str,