From 5b15827009a1269df71754b850295580ad90e0eb Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 21 Oct 2025 17:58:40 -1000 Subject: [PATCH] [CI] Fix component detection when core files change in determine-jobs (#11461) --- script/determine-jobs.py | 24 ++++++------ tests/script/test_determine_jobs.py | 57 +++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 11 deletions(-) diff --git a/script/determine-jobs.py b/script/determine-jobs.py index 6651553ce7..7cdec959c7 100755 --- a/script/determine-jobs.py +++ b/script/determine-jobs.py @@ -606,21 +606,23 @@ def main() -> None: # [list]: Changed components (already includes dependencies) changed_components_result = get_changed_components() + # Always analyze component files, even if core files changed + # This is needed for component testing and memory impact analysis + changed = changed_files(args.branch) + component_files = [f for f in changed if filter_component_and_test_files(f)] + + directly_changed_components = get_components_with_dependencies( + component_files, False + ) + if changed_components_result is None: # Core files changed - will trigger full clang-tidy scan - # No specific components to test - changed_components = [] - directly_changed_components = [] + # But we still need to track changed components for testing and memory analysis + changed_components = get_components_with_dependencies(component_files, True) is_core_change = True else: - # Get both directly changed and all changed (with dependencies) - changed = changed_files(args.branch) - component_files = [f for f in changed if filter_component_and_test_files(f)] - - directly_changed_components = get_components_with_dependencies( - component_files, False - ) - changed_components = get_components_with_dependencies(component_files, True) + # Use the result from get_changed_components() which includes dependencies + changed_components = changed_components_result is_core_change = False # Filter to only components that have test files diff --git a/tests/script/test_determine_jobs.py b/tests/script/test_determine_jobs.py index a859b3c24d..6095e86ea7 100644 --- a/tests/script/test_determine_jobs.py +++ b/tests/script/test_determine_jobs.py @@ -910,3 +910,60 @@ def test_clang_tidy_mode_targeted_scan( output = json.loads(captured.out) assert output["clang_tidy_mode"] == expected_mode + + +def test_main_core_files_changed_still_detects_components( + mock_should_run_integration_tests: Mock, + mock_should_run_clang_tidy: Mock, + mock_should_run_clang_format: Mock, + mock_should_run_python_linters: Mock, + mock_changed_files: Mock, + mock_determine_cpp_unit_tests: Mock, + capsys: pytest.CaptureFixture[str], + monkeypatch: pytest.MonkeyPatch, +) -> None: + """Test that component changes are detected even when core files change.""" + monkeypatch.delenv("GITHUB_ACTIONS", raising=False) + + mock_should_run_integration_tests.return_value = True + mock_should_run_clang_tidy.return_value = True + mock_should_run_clang_format.return_value = True + mock_should_run_python_linters.return_value = True + mock_determine_cpp_unit_tests.return_value = (True, []) + + mock_changed_files.return_value = [ + "esphome/core/helpers.h", + "esphome/components/select/select_traits.h", + "esphome/components/select/select_traits.cpp", + "esphome/components/api/api.proto", + ] + + with ( + patch("sys.argv", ["determine-jobs.py"]), + patch.object(determine_jobs, "_is_clang_tidy_full_scan", return_value=False), + patch.object(determine_jobs, "get_changed_components", return_value=None), + patch.object( + determine_jobs, + "filter_component_and_test_files", + side_effect=lambda f: f.startswith("esphome/components/"), + ), + patch.object( + determine_jobs, + "get_components_with_dependencies", + side_effect=lambda files, deps: ( + ["select", "api"] + if not deps + else ["select", "api", "bluetooth_proxy", "logger"] + ), + ), + ): + determine_jobs.main() + + captured = capsys.readouterr() + output = json.loads(captured.out) + + assert output["clang_tidy"] is True + assert output["clang_tidy_mode"] == "split" + assert "select" in output["changed_components"] + assert "api" in output["changed_components"] + assert len(output["changed_components"]) > 0