diff --git a/script/ci_memory_impact_extract.py b/script/ci_memory_impact_extract.py index 96f947e12a..76632ebc33 100755 --- a/script/ci_memory_impact_extract.py +++ b/script/ci_memory_impact_extract.py @@ -132,41 +132,34 @@ def run_detailed_analysis(build_dir: str) -> dict | None: file=sys.stderr, ) - try: - analyzer = MemoryAnalyzer(elf_path, idedata=idedata) - components = analyzer.analyze() + analyzer = MemoryAnalyzer(elf_path, idedata=idedata) + components = analyzer.analyze() - # Convert to JSON-serializable format - result = { - "components": { - name: { - "text": mem.text_size, - "rodata": mem.rodata_size, - "data": mem.data_size, - "bss": mem.bss_size, - "flash_total": mem.flash_total, - "ram_total": mem.ram_total, - "symbol_count": mem.symbol_count, - } - for name, mem in components.items() - }, - "symbols": {}, - } + # Convert to JSON-serializable format + result = { + "components": { + name: { + "text": mem.text_size, + "rodata": mem.rodata_size, + "data": mem.data_size, + "bss": mem.bss_size, + "flash_total": mem.flash_total, + "ram_total": mem.ram_total, + "symbol_count": mem.symbol_count, + } + for name, mem in components.items() + }, + "symbols": {}, + } - # Build symbol map - for section in analyzer.sections.values(): - for symbol_name, size, _ in section.symbols: - if size > 0: - demangled = analyzer._demangle_symbol(symbol_name) - result["symbols"][demangled] = size + # Build symbol map + for section in analyzer.sections.values(): + for symbol_name, size, _ in section.symbols: + if size > 0: + demangled = analyzer._demangle_symbol(symbol_name) + result["symbols"][demangled] = size - return result - except Exception as e: - print(f"Warning: Failed to run detailed analysis: {e}", file=sys.stderr) - import traceback - - traceback.print_exc(file=sys.stderr) - return None + return result def main() -> int: diff --git a/script/determine-jobs.py b/script/determine-jobs.py index bf944886ea..8e2c239fe2 100755 --- a/script/determine-jobs.py +++ b/script/determine-jobs.py @@ -74,6 +74,18 @@ class Platform(StrEnum): MEMORY_IMPACT_FALLBACK_COMPONENT = "api" # Representative component for core changes MEMORY_IMPACT_FALLBACK_PLATFORM = Platform.ESP32_IDF # Most representative platform +# Platform preference order for memory impact analysis +# Prefer newer platforms first as they represent the future of ESPHome +# ESP8266 is most constrained but many new features don't support it +MEMORY_IMPACT_PLATFORM_PREFERENCE = [ + Platform.ESP32_C6_IDF, # ESP32-C6 IDF (newest, supports Thread/Zigbee) + Platform.ESP8266_ARD, # ESP8266 Arduino (most memory constrained - best for impact analysis) + Platform.ESP32_IDF, # ESP32 IDF platform (primary ESP32 platform, most representative) + Platform.ESP32_C3_IDF, # ESP32-C3 IDF + Platform.ESP32_S2_IDF, # ESP32-S2 IDF + Platform.ESP32_S3_IDF, # ESP32-S3 IDF +] + def should_run_integration_tests(branch: str | None = None) -> bool: """Determine if integration tests should run based on changed files. @@ -274,17 +286,6 @@ def detect_memory_impact_config( - platform: platform name for the merged build - use_merged_config: "true" (always use merged config) """ - # Platform preference order for memory impact analysis - # Prefer newer platforms first as they represent the future of ESPHome - # ESP8266 is most constrained but many new features don't support it - PLATFORM_PREFERENCE = [ - Platform.ESP32_C6_IDF, # ESP32-C6 IDF (newest, supports Thread/Zigbee) - Platform.ESP8266_ARD, # ESP8266 Arduino (most memory constrained - best for impact analysis) - Platform.ESP32_IDF, # ESP32 IDF platform (primary ESP32 platform, most representative) - Platform.ESP32_C3_IDF, # ESP32-C3 IDF - Platform.ESP32_S2_IDF, # ESP32-S2 IDF - Platform.ESP32_S3_IDF, # ESP32-S3 IDF - ] # Get actually changed files (not dependencies) files = changed_files(branch) @@ -337,7 +338,7 @@ def detect_memory_impact_config( available_platforms = [] for test_file in test_files: _, platform = parse_test_filename(test_file) - if platform != "all" and platform in PLATFORM_PREFERENCE: + if platform != "all" and platform in MEMORY_IMPACT_PLATFORM_PREFERENCE: available_platforms.append(platform) if not available_platforms: @@ -352,7 +353,7 @@ def detect_memory_impact_config( # Find common platforms supported by ALL components # This ensures we can build all components together in a merged config - common_platforms = set(PLATFORM_PREFERENCE) + common_platforms = set(MEMORY_IMPACT_PLATFORM_PREFERENCE) for component, platforms in component_platforms_map.items(): common_platforms &= platforms @@ -362,7 +363,7 @@ def detect_memory_impact_config( platform = MEMORY_IMPACT_FALLBACK_PLATFORM elif common_platforms: # Pick the most preferred platform that all components support - platform = min(common_platforms, key=PLATFORM_PREFERENCE.index) + platform = min(common_platforms, key=MEMORY_IMPACT_PLATFORM_PREFERENCE.index) else: # No common platform - pick the most commonly supported platform # This allows testing components individually even if they can't be merged @@ -370,10 +371,13 @@ def detect_memory_impact_config( for platforms in component_platforms_map.values(): for p in platforms: platform_counts[p] = platform_counts.get(p, 0) + 1 - # Pick the platform supported by most components, preferring earlier in PLATFORM_PREFERENCE + # Pick the platform supported by most components, preferring earlier in MEMORY_IMPACT_PLATFORM_PREFERENCE platform = max( platform_counts.keys(), - key=lambda p: (platform_counts[p], -PLATFORM_PREFERENCE.index(p)), + key=lambda p: ( + platform_counts[p], + -MEMORY_IMPACT_PLATFORM_PREFERENCE.index(p), + ), ) # Debug output