diff --git a/script/determine-jobs.py b/script/determine-jobs.py index c46529dfc6..63ffe42d6a 100755 --- a/script/determine-jobs.py +++ b/script/determine-jobs.py @@ -524,13 +524,10 @@ def _path_or_file_trigger( ) -@cache -def _changed_components_closure(branch: str | None) -> frozenset[str]: - """Dependency closure of the changed components (shared by the - per-toolchain narrowing functions and cached per branch).""" - files = changed_files(branch) +def _changed_components_closure(files: list[str]) -> set[str]: + """Dependency closure of the changed components, from the changed files.""" component_files = [f for f in files if filter_component_and_test_files(f)] - return frozenset(get_components_with_dependencies(component_files, True)) + return set(get_components_with_dependencies(component_files, True)) def _esp32_platformio_path_or_file_trigger(files: list[str]) -> bool: @@ -596,9 +593,7 @@ def esp32_platformio_components_to_test(branch: str | None = None) -> list[str]: if core_changed(files) or _esp32_platformio_path_or_file_trigger(files): return sorted(ESP32_PLATFORMIO_TEST_COMPONENTS) - return sorted( - ESP32_PLATFORMIO_TEST_COMPONENTS & _changed_components_closure(branch) - ) + return sorted(ESP32_PLATFORMIO_TEST_COMPONENTS & _changed_components_closure(files)) def should_run_esp32_platformio(branch: str | None = None) -> bool: @@ -671,7 +666,7 @@ def esp8266_native_components_to_test(branch: str | None = None) -> list[str]: if core_changed(files) or _esp8266_native_path_or_file_trigger(files): return sorted(ESP8266_NATIVE_TEST_COMPONENTS) - return sorted(ESP8266_NATIVE_TEST_COMPONENTS & _changed_components_closure(branch)) + return sorted(ESP8266_NATIVE_TEST_COMPONENTS & _changed_components_closure(files)) def determine_cpp_unit_tests( diff --git a/tests/script/test_determine_jobs.py b/tests/script/test_determine_jobs.py index 80f572d9fe..3d42f671e1 100644 --- a/tests/script/test_determine_jobs.py +++ b/tests/script/test_determine_jobs.py @@ -3072,3 +3072,60 @@ def test_memory_impact_elf_layouts_are_found(tmp_path: Path) -> None: elf.write_text("") assert find_elf_path(build_path) == elf, f"{platform} ELF not found" + + +def test_esp8266_native_components_full_list_on_infra_change() -> None: + """Native-ESP8266 infrastructure changes run the full test list.""" + for changed in ( + ["esphome/arduino8266/framework.py"], + ["esphome/build_gen/arduino8266.py"], + ["esphome/components/esp8266/build_surgery.py"], + ): + with ( + patch.object(determine_jobs, "changed_files", return_value=changed), + patch.object( + determine_jobs, + "get_components_with_dependencies", + return_value=["wifi"], + ), + ): + result = determine_jobs.esp8266_native_components_to_test() + assert result == sorted(determine_jobs.ESP8266_NATIVE_TEST_COMPONENTS) + + +@pytest.mark.parametrize( + ("changed_files", "dependency_closure", "expected"), + [ + # Tested component changed -- narrow to the intersection. + ( + ["esphome/components/mqtt/mqtt_client.cpp"], + ["mqtt", "json"], + ["mqtt"], + ), + # Components outside the test set return an empty list (job skipped). + ( + ["esphome/components/wifi/wifi_component.cpp"], + ["wifi", "network"], + [], + ), + # ESP-IDF infra is not an esp8266-native trigger. + (["esphome/build_gen/espidf.py"], [], []), + (["README.md"], [], []), + ], +) +def test_esp8266_native_components_to_test_narrowing( + changed_files: list[str], + dependency_closure: list[str], + expected: list[str], +) -> None: + """Component changes narrow the native-ESP8266 test list.""" + with ( + patch.object(determine_jobs, "changed_files", return_value=changed_files), + patch.object( + determine_jobs, + "get_components_with_dependencies", + return_value=dependency_closure, + ), + ): + result = determine_jobs.esp8266_native_components_to_test() + assert result == expected