[ci] Fix memory impact build selecting unbuildable platform (#16788)

This commit is contained in:
J. Nick Koston
2026-06-03 22:30:36 -05:00
committed by GitHub
parent d47f6b896e
commit 3e562b9267
4 changed files with 171 additions and 74 deletions
+83 -17
View File
@@ -1426,7 +1426,15 @@ def test_detect_memory_impact_config_core_python_only_changes(tmp_path: Path) ->
@pytest.mark.usefixtures("mock_target_branch_dev")
def test_detect_memory_impact_config_no_common_platform(tmp_path: Path) -> None:
"""Test memory impact detection when components have no common platform."""
"""Test memory impact detection when components have no common platform.
The merged build runs with --base-only on a single platform, so components
without a base test on the selected platform cannot be built and must be
dropped. We build the largest subset that shares the selected platform
rather than handing the runner components it has nothing to compile for
(which previously produced "0 passed, 0 failed" and a failed memory
extraction).
"""
# Create test directory structure
tests_dir = tmp_path / "tests" / "components"
@@ -1453,12 +1461,70 @@ def test_detect_memory_impact_config_no_common_platform(tmp_path: Path) -> None:
result = determine_jobs.detect_memory_impact_config()
# Should pick the most frequently supported platform
# No common platform: pick the most preferred platform among those supported
# (esp8266-ard outranks esp32-idf in the preference list) and build only the
# components that have a base test on it. wifi (esp32-idf only) is dropped.
assert result["should_run"] == "true"
assert set(result["components"]) == {"wifi", "logger"}
# When no common platform, picks most commonly supported
# esp8266-ard is preferred over esp32-idf in the preference list
assert result["platform"] in ["esp32-idf", "esp8266-ard"]
assert result["platform"] == "esp8266-ard"
assert result["components"] == ["logger"]
assert result["use_merged_config"] == "true"
def test_detect_memory_impact_config_variant_only_platform_excluded(
tmp_path: Path,
) -> None:
"""Regression test for the const + shelly_dimmer memory-impact failure.
Reproduces https://github.com/esphome/esphome/actions/runs/26746938473
where a platform hint selected esp32-idf even though neither changed
component had a base test.esp32-idf.yaml. The merged --base-only build then
found nothing to compile ("0 passed, 0 failed") and memory extraction
failed. Also covers a component whose only esp32-idf test is a *variant*
(test-*.esp32-idf.yaml): --base-only never compiles variants, so it must
not count toward platform availability.
"""
tests_dir = tmp_path / "tests" / "components"
# const: base test only on esp32-s3-idf
const_dir = tests_dir / "const"
const_dir.mkdir(parents=True)
(const_dir / "test.esp32-s3-idf.yaml").write_text("test: const")
# shelly_dimmer: base test only on esp8266-ard
shelly_dir = tests_dir / "shelly_dimmer"
shelly_dir.mkdir(parents=True)
(shelly_dir / "test.esp8266-ard.yaml").write_text("test: shelly_dimmer")
# mdns: only a VARIANT test on esp32-idf (no base test.esp32-idf.yaml).
# --base-only would never build it, so it must be excluded entirely.
mdns_dir = tests_dir / "mdns"
mdns_dir.mkdir(parents=True)
(mdns_dir / "test-min.esp32-idf.yaml").write_text("test: mdns")
with (
patch.object(determine_jobs, "root_path", str(tmp_path)),
patch.object(helpers, "root_path", str(tmp_path)),
patch.object(determine_jobs, "changed_files") as mock_changed_files,
):
# The "_esp32" filename yields an esp32-idf platform hint, reproducing
# the original bug where the hint picked a platform no component could
# build as a base test.
mock_changed_files.return_value = [
"esphome/components/const/const.cpp",
"esphome/components/shelly_dimmer/shelly_dimmer_esp32.cpp",
"esphome/components/mdns/mdns.cpp",
]
result = determine_jobs.detect_memory_impact_config()
# The esp32-idf hint is unbuildable (no base test), so we fall back to the
# platform supported by the most components, broken by preference order:
# esp8266-ard (shelly_dimmer) outranks esp32-s3-idf (const). Only the
# component with a base test on the selected platform is returned; the
# variant-only mdns is excluded entirely.
assert result["should_run"] == "true"
assert result["platform"] == "esp8266-ard"
assert result["components"] == ["shelly_dimmer"]
assert result["use_merged_config"] == "true"
@@ -1545,12 +1611,16 @@ def test_detect_memory_impact_config_includes_base_bus_components(
@pytest.mark.usefixtures("mock_target_branch_dev")
def test_detect_memory_impact_config_with_variant_tests(tmp_path: Path) -> None:
"""Test memory impact detection for components with only variant test files.
def test_detect_memory_impact_config_variant_only_components_skipped(
tmp_path: Path,
) -> None:
"""Components with only variant tests are skipped for memory impact.
This verifies that memory impact analysis works correctly for components like
improv_serial, ethernet, mdns, etc. which only have variant test files
(test-*.yaml) instead of base test files (test.*.yaml).
Components like improv_serial and ethernet only have variant test files
(test-*.yaml), no base test.<platform>.yaml. The memory-impact build runs
test_build_components.py with --base-only, which never compiles variants, so
these components have nothing buildable and must not be selected. Selecting
them previously produced "0 passed, 0 failed" and a failed memory extraction.
"""
# Create test directory structure
tests_dir = tmp_path / "tests" / "components"
@@ -1581,12 +1651,8 @@ def test_detect_memory_impact_config_with_variant_tests(tmp_path: Path) -> None:
result = determine_jobs.detect_memory_impact_config()
# Should detect both components even though they only have variant tests
assert result["should_run"] == "true"
assert set(result["components"]) == {"improv_serial", "ethernet"}
# Both components support esp32-idf
assert result["platform"] == "esp32-idf"
assert result["use_merged_config"] == "true"
# Neither component has a base test, so nothing is buildable under --base-only
assert result["should_run"] == "false"
# Tests for clang-tidy split mode logic