From 9b9b4195f2814430bd0e4f1ba4972531c1a669e0 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 9 Oct 2025 17:03:51 -1000 Subject: [PATCH] improve grouping of no bus components, they can go into any group, saves another 20m --- script/analyze_component_buses.py | 4 ++++ script/merge_component_configs.py | 12 +++++++++++- script/split_components_for_ci.py | 3 ++- script/test_build_components.py | 32 +++++++++++++++++++++++++++++-- 4 files changed, 47 insertions(+), 4 deletions(-) mode change 100644 => 100755 script/analyze_component_buses.py diff --git a/script/analyze_component_buses.py b/script/analyze_component_buses.py old mode 100644 new mode 100755 index 5f0b406703..e421204c7a --- a/script/analyze_component_buses.py +++ b/script/analyze_component_buses.py @@ -52,6 +52,10 @@ PACKAGE_DEPENDENCIES = { # Components defining these directly cannot be grouped (they create unique bus IDs) DIRECT_BUS_TYPES = ("i2c", "spi", "uart", "modbus") +# Signature for components with no bus requirements +# These components can be merged with any other group +NO_BUSES_SIGNATURE = "no_buses" + # Base bus components - these ARE the bus implementations and should not # be flagged as needing migration since they are the platform/base components BASE_BUS_COMPONENTS = { diff --git a/script/merge_component_configs.py b/script/merge_component_configs.py index df09e980a6..15045a64f2 100755 --- a/script/merge_component_configs.py +++ b/script/merge_component_configs.py @@ -206,11 +206,21 @@ def merge_component_configs( # Load the component's test file comp_data = load_yaml_file(test_file) - # Validate packages are identical + # Validate packages are compatible + # Components with no packages (no_buses) can merge with any group comp_packages = extract_packages_from_yaml(comp_data) + if all_packages is None: + # First component - set the baseline + all_packages = comp_packages + elif not comp_packages: + # This component has no packages (no_buses) - it can merge with any group + pass + elif not all_packages: + # Previous components had no packages, but this one does - adopt these packages all_packages = comp_packages elif comp_packages != all_packages: + # Both have packages but they differ - this is an error raise ValueError( f"Component {comp_name} has different packages than previous components. " f"Expected: {all_packages}, Got: {comp_packages}. " diff --git a/script/split_components_for_ci.py b/script/split_components_for_ci.py index ce43e75875..184c05eae0 100755 --- a/script/split_components_for_ci.py +++ b/script/split_components_for_ci.py @@ -22,6 +22,7 @@ sys.path.insert(0, str(Path(__file__).parent.parent)) from script.analyze_component_buses import ( ISOLATED_COMPONENTS, + NO_BUSES_SIGNATURE, analyze_all_components, create_grouping_signature, ) @@ -105,7 +106,7 @@ def create_intelligent_batches( break # Only use first platform for grouping else: # No buses found for any platform - can be grouped together - signature_groups["no_buses"].append(component) + signature_groups[NO_BUSES_SIGNATURE].append(component) # Create batches by keeping signature groups together # Components with the same signature stay in the same batches diff --git a/script/test_build_components.py b/script/test_build_components.py index b042452d9d..916af93b0d 100755 --- a/script/test_build_components.py +++ b/script/test_build_components.py @@ -28,6 +28,7 @@ sys.path.insert(0, str(Path(__file__).parent.parent)) # pylint: disable=wrong-import-position from script.analyze_component_buses import ( ISOLATED_COMPONENTS, + NO_BUSES_SIGNATURE, analyze_all_components, create_grouping_signature, is_platform_component, @@ -403,11 +404,11 @@ def run_grouped_component_tests( continue # Create signature for this component's bus configuration - # Components with no buses get a signature of "no_buses" so they can be grouped together + # Components with no buses get NO_BUSES_SIGNATURE so they can be grouped together if buses: signature = create_grouping_signature({platform: buses}, platform) else: - signature = "no_buses" + signature = NO_BUSES_SIGNATURE # Add to grouped components (including those with no buses) if signature: @@ -462,6 +463,33 @@ def run_grouped_component_tests( f"\n Other non-groupable components: {len(other_reasons)} components" ) + # Distribute no_buses components into other groups to maximize efficiency + # Components with no buses can merge with any bus group since they have no conflicting requirements + no_buses_by_platform: dict[str, list[str]] = {} + for (platform, signature), components in list(grouped_components.items()): + if signature == NO_BUSES_SIGNATURE: + no_buses_by_platform[platform] = components + # Remove from grouped_components - we'll distribute them + del grouped_components[(platform, signature)] + + # Distribute no_buses components into existing groups for each platform + for platform, no_buses_comps in no_buses_by_platform.items(): + # Find all non-empty groups for this platform (excluding no_buses) + platform_groups = [ + (sig, comps) + for (plat, sig), comps in grouped_components.items() + if plat == platform and sig != NO_BUSES_SIGNATURE + ] + + if platform_groups: + # Distribute no_buses components round-robin across existing groups + for i, comp in enumerate(no_buses_comps): + sig, _ = platform_groups[i % len(platform_groups)] + grouped_components[(platform, sig)].append(comp) + else: + # No other groups for this platform - keep no_buses components together + grouped_components[(platform, NO_BUSES_SIGNATURE)] = no_buses_comps + groups_to_test = [] individual_tests = set() # Use set to avoid duplicates