mirror of
https://github.com/esphome/esphome.git
synced 2025-11-17 23:35:47 +00:00
[ci] Fix memory impact analysis to filter incompatible platform components (#11706)
This commit is contained in:
@@ -94,6 +94,22 @@ class Platform(StrEnum):
|
|||||||
MEMORY_IMPACT_FALLBACK_COMPONENT = "api" # Representative component for core changes
|
MEMORY_IMPACT_FALLBACK_COMPONENT = "api" # Representative component for core changes
|
||||||
MEMORY_IMPACT_FALLBACK_PLATFORM = Platform.ESP32_IDF # Most representative platform
|
MEMORY_IMPACT_FALLBACK_PLATFORM = Platform.ESP32_IDF # Most representative platform
|
||||||
|
|
||||||
|
# Platform-specific components that can only be built on their respective platforms
|
||||||
|
# These components contain platform-specific code and cannot be cross-compiled
|
||||||
|
# Regular components (wifi, logger, api, etc.) are cross-platform and not listed here
|
||||||
|
PLATFORM_SPECIFIC_COMPONENTS = frozenset(
|
||||||
|
{
|
||||||
|
"esp32", # ESP32 platform implementation
|
||||||
|
"esp8266", # ESP8266 platform implementation
|
||||||
|
"rp2040", # Raspberry Pi Pico / RP2040 platform implementation
|
||||||
|
"bk72xx", # Beken BK72xx platform implementation (uses LibreTiny)
|
||||||
|
"rtl87xx", # Realtek RTL87xx platform implementation (uses LibreTiny)
|
||||||
|
"ln882x", # Winner Micro LN882x platform implementation (uses LibreTiny)
|
||||||
|
"host", # Host platform (for testing on development machine)
|
||||||
|
"nrf52", # Nordic nRF52 platform implementation
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
# Platform preference order for memory impact analysis
|
# Platform preference order for memory impact analysis
|
||||||
# This order is used when no platform-specific hints are detected from filenames
|
# This order is used when no platform-specific hints are detected from filenames
|
||||||
# Priority rationale:
|
# Priority rationale:
|
||||||
@@ -568,6 +584,20 @@ def detect_memory_impact_config(
|
|||||||
)
|
)
|
||||||
platform = _select_platform_by_count(platform_counts)
|
platform = _select_platform_by_count(platform_counts)
|
||||||
|
|
||||||
|
# Filter out platform-specific components that are incompatible with selected platform
|
||||||
|
# Platform components (esp32, esp8266, rp2040, etc.) can only build on their own platform
|
||||||
|
# Other components (wifi, logger, etc.) are cross-platform and can build anywhere
|
||||||
|
compatible_components = [
|
||||||
|
component
|
||||||
|
for component in components_with_tests
|
||||||
|
if component not in PLATFORM_SPECIFIC_COMPONENTS
|
||||||
|
or platform in component_platforms_map.get(component, set())
|
||||||
|
]
|
||||||
|
|
||||||
|
# If no components are compatible with the selected platform, don't run
|
||||||
|
if not compatible_components:
|
||||||
|
return {"should_run": "false"}
|
||||||
|
|
||||||
# Debug output
|
# Debug output
|
||||||
print("Memory impact analysis:", file=sys.stderr)
|
print("Memory impact analysis:", file=sys.stderr)
|
||||||
print(f" Changed components: {sorted(changed_component_set)}", file=sys.stderr)
|
print(f" Changed components: {sorted(changed_component_set)}", file=sys.stderr)
|
||||||
@@ -579,10 +609,11 @@ def detect_memory_impact_config(
|
|||||||
print(f" Platform hints from filenames: {platform_hints}", file=sys.stderr)
|
print(f" Platform hints from filenames: {platform_hints}", file=sys.stderr)
|
||||||
print(f" Common platforms: {sorted(common_platforms)}", file=sys.stderr)
|
print(f" Common platforms: {sorted(common_platforms)}", file=sys.stderr)
|
||||||
print(f" Selected platform: {platform}", file=sys.stderr)
|
print(f" Selected platform: {platform}", file=sys.stderr)
|
||||||
|
print(f" Compatible components: {compatible_components}", file=sys.stderr)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"should_run": "true",
|
"should_run": "true",
|
||||||
"components": components_with_tests,
|
"components": compatible_components,
|
||||||
"platform": platform,
|
"platform": platform,
|
||||||
"use_merged_config": "true",
|
"use_merged_config": "true",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1130,3 +1130,111 @@ def test_main_core_files_changed_still_detects_components(
|
|||||||
assert "select" in output["changed_components"]
|
assert "select" in output["changed_components"]
|
||||||
assert "api" in output["changed_components"]
|
assert "api" in output["changed_components"]
|
||||||
assert len(output["changed_components"]) > 0
|
assert len(output["changed_components"]) > 0
|
||||||
|
|
||||||
|
|
||||||
|
def test_detect_memory_impact_config_filters_incompatible_esp32_on_esp8266(
|
||||||
|
tmp_path: Path,
|
||||||
|
) -> None:
|
||||||
|
"""Test that ESP32 components are filtered out when ESP8266 platform is selected.
|
||||||
|
|
||||||
|
This test verifies the fix for the issue where ESP32 components were being included
|
||||||
|
when ESP8266 was selected as the platform, causing build failures in PR 10387.
|
||||||
|
"""
|
||||||
|
# Create test directory structure
|
||||||
|
tests_dir = tmp_path / "tests" / "components"
|
||||||
|
|
||||||
|
# esp32 component only has esp32-idf tests (NOT compatible with esp8266)
|
||||||
|
esp32_dir = tests_dir / "esp32"
|
||||||
|
esp32_dir.mkdir(parents=True)
|
||||||
|
(esp32_dir / "test.esp32-idf.yaml").write_text("test: esp32")
|
||||||
|
(esp32_dir / "test.esp32-s3-idf.yaml").write_text("test: esp32")
|
||||||
|
|
||||||
|
# esp8266 component only has esp8266-ard test (NOT compatible with esp32)
|
||||||
|
esp8266_dir = tests_dir / "esp8266"
|
||||||
|
esp8266_dir.mkdir(parents=True)
|
||||||
|
(esp8266_dir / "test.esp8266-ard.yaml").write_text("test: esp8266")
|
||||||
|
|
||||||
|
# Mock changed_files to return both esp32 and esp8266 component changes
|
||||||
|
# Include esp8266-specific filename to trigger esp8266 platform hint
|
||||||
|
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,
|
||||||
|
):
|
||||||
|
mock_changed_files.return_value = [
|
||||||
|
"tests/components/esp32/common.yaml",
|
||||||
|
"tests/components/esp8266/test.esp8266-ard.yaml",
|
||||||
|
"esphome/core/helpers_esp8266.h", # ESP8266-specific file to hint platform
|
||||||
|
]
|
||||||
|
determine_jobs._component_has_tests.cache_clear()
|
||||||
|
|
||||||
|
result = determine_jobs.detect_memory_impact_config()
|
||||||
|
|
||||||
|
# Memory impact should run
|
||||||
|
assert result["should_run"] == "true"
|
||||||
|
|
||||||
|
# Platform should be esp8266-ard (due to ESP8266 filename hint)
|
||||||
|
assert result["platform"] == "esp8266-ard"
|
||||||
|
|
||||||
|
# CRITICAL: Only esp8266 component should be included, not esp32
|
||||||
|
# This prevents trying to build ESP32 components on ESP8266 platform
|
||||||
|
assert result["components"] == ["esp8266"], (
|
||||||
|
"When esp8266-ard platform is selected, only esp8266 component should be included, "
|
||||||
|
"not esp32. This prevents trying to build ESP32 components on ESP8266 platform."
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result["use_merged_config"] == "true"
|
||||||
|
|
||||||
|
|
||||||
|
def test_detect_memory_impact_config_filters_incompatible_esp8266_on_esp32(
|
||||||
|
tmp_path: Path,
|
||||||
|
) -> None:
|
||||||
|
"""Test that ESP8266 components are filtered out when ESP32 platform is selected.
|
||||||
|
|
||||||
|
This is the inverse of the ESP8266 test - ensures filtering works both ways.
|
||||||
|
"""
|
||||||
|
# Create test directory structure
|
||||||
|
tests_dir = tmp_path / "tests" / "components"
|
||||||
|
|
||||||
|
# esp32 component only has esp32-idf tests (NOT compatible with esp8266)
|
||||||
|
esp32_dir = tests_dir / "esp32"
|
||||||
|
esp32_dir.mkdir(parents=True)
|
||||||
|
(esp32_dir / "test.esp32-idf.yaml").write_text("test: esp32")
|
||||||
|
(esp32_dir / "test.esp32-s3-idf.yaml").write_text("test: esp32")
|
||||||
|
|
||||||
|
# esp8266 component only has esp8266-ard test (NOT compatible with esp32)
|
||||||
|
esp8266_dir = tests_dir / "esp8266"
|
||||||
|
esp8266_dir.mkdir(parents=True)
|
||||||
|
(esp8266_dir / "test.esp8266-ard.yaml").write_text("test: esp8266")
|
||||||
|
|
||||||
|
# Mock changed_files to return both esp32 and esp8266 component changes
|
||||||
|
# Include MORE esp32-specific filenames to ensure esp32-idf wins the hint count
|
||||||
|
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,
|
||||||
|
):
|
||||||
|
mock_changed_files.return_value = [
|
||||||
|
"tests/components/esp32/common.yaml",
|
||||||
|
"tests/components/esp8266/test.esp8266-ard.yaml",
|
||||||
|
"esphome/components/wifi/wifi_component_esp_idf.cpp", # ESP-IDF hint
|
||||||
|
"esphome/components/ethernet/ethernet_esp32.cpp", # ESP32 hint
|
||||||
|
]
|
||||||
|
determine_jobs._component_has_tests.cache_clear()
|
||||||
|
|
||||||
|
result = determine_jobs.detect_memory_impact_config()
|
||||||
|
|
||||||
|
# Memory impact should run
|
||||||
|
assert result["should_run"] == "true"
|
||||||
|
|
||||||
|
# Platform should be esp32-idf (due to more ESP32-IDF hints)
|
||||||
|
assert result["platform"] == "esp32-idf"
|
||||||
|
|
||||||
|
# CRITICAL: Only esp32 component should be included, not esp8266
|
||||||
|
# This prevents trying to build ESP8266 components on ESP32 platform
|
||||||
|
assert result["components"] == ["esp32"], (
|
||||||
|
"When esp32-idf platform is selected, only esp32 component should be included, "
|
||||||
|
"not esp8266. This prevents trying to build ESP8266 components on ESP32 platform."
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result["use_merged_config"] == "true"
|
||||||
|
|||||||
Reference in New Issue
Block a user