Skip to content

Commit c53f0a7

Browse files
committed
Generate full availability report for the components
1 parent bf1661f commit c53f0a7

File tree

1 file changed

+84
-22
lines changed

1 file changed

+84
-22
lines changed

jobs.py

Lines changed: 84 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ class RebuildContext:
6666
missing_packages: dict = field(default_factory=lambda: collections.defaultdict(set))
6767
unresolvable_components: set = field(default_factory=set)
6868
prerel_abi_blocked_components: set = field(default_factory=set)
69+
component_availability: dict = field(default_factory=dict)
6970

7071

7172
def _query_packages_by_deps(sack_getter, deps, excluded_components):
@@ -208,7 +209,15 @@ def _update_blocker_statistics(blocking_components, blocker_counter, loop_detect
208209
blocker_counter['single'][next(iter(blocking_components))] += 1
209210
elif 1 < len(blocking_components) < 10: # this is an arbitrarily chosen number to avoid cruft
210211
blocker_counter['combinations'][tuple(sorted(blocking_components))] += 1
211-
loop_detector[component] = sorted(blocking_components)
212+
known_blocking_components = set(loop_detector.get(component, []))
213+
if not known_blocking_components:
214+
loop_detector[component] = sorted(blocking_components)
215+
else:
216+
if blocking_components <= known_blocking_components:
217+
pass
218+
else:
219+
# can this ever happen?
220+
loop_detector[component] = sorted(known_blocking_components | blocking_components)
212221

213222

214223
def are_all_done(component, packages_to_check, ctx):
@@ -486,31 +495,45 @@ def check_bcond_build(component, bcond_config, number_of_resolved, ctx):
486495
return ready_to_rebuild
487496

488497

498+
def extract_bcond_identifier(s):
499+
non_empty_parts = [p for p in s.split(':') if p]
500+
return non_empty_parts[1] if len(non_empty_parts) >= 2 else None
501+
502+
489503
def check_bcond_builds(component, number_of_resolved, ctx):
490504
"""
491505
Check all bcond builds for a component that isn't ready for regular build.
492-
506+
493507
Args:
494508
component: Name of the component to check
495509
number_of_resolved: Number of packages in regular build (for comparison)
496510
ctx: RebuildContext with shared data and state
497-
511+
498512
Prints any bcond build identifiers that are ready to rebuild.
513+
514+
Returns:
515+
tuple: (buildable_bconds, non_buildable_bconds)
499516
"""
500517
from bconds import bcond_cache_identifier
501-
502-
if component not in CONFIG['bconds']:
503-
return
504-
505-
for bcond_config in CONFIG['bconds'][component]:
506-
bcond_config['id'] = bcond_cache_identifier(component, bcond_config)
507-
log(f'• {component} not ready and {bcond_config["id"]} bcond found, will check that one')
508-
509-
ready_to_rebuild = check_bcond_build(component, bcond_config, number_of_resolved, ctx)
510-
511-
if ready_to_rebuild:
512-
if should_print_component(component, ctx.components_done):
513-
print(bcond_config['id'])
518+
519+
buildable_bconds = []
520+
non_buildable_bconds = []
521+
522+
if component in CONFIG['bconds']:
523+
for bcond_config in CONFIG['bconds'][component]:
524+
bcond_config['id'] = bcond_cache_identifier(component, bcond_config)
525+
log(f'• {component} not ready and {bcond_config["id"]} bcond found, will check that one')
526+
527+
ready_to_rebuild = check_bcond_build(component, bcond_config, number_of_resolved, ctx)
528+
529+
if ready_to_rebuild:
530+
if should_print_component(component, ctx.components_done):
531+
print(bcond_config['id'])
532+
buildable_bconds.append(extract_bcond_identifier(bcond_config['id']))
533+
else:
534+
non_buildable_bconds.append(extract_bcond_identifier(bcond_config['id']))
535+
536+
return sorted(buildable_bconds), sorted(non_buildable_bconds)
514537

515538

516539
def should_print_component(component, components_done):
@@ -526,20 +549,30 @@ def should_print_component(component, components_done):
526549
def process_component(component, ctx):
527550
"""
528551
Process a single component: check regular build and bcond builds if needed.
529-
552+
Stores availability data in ctx.component_availability.
553+
530554
Args:
531555
component: Name of the component to process
532556
ctx: RebuildContext with shared data and state
533-
557+
534558
Prints the component or bcond identifier if ready to rebuild.
535559
"""
536560
ready_to_rebuild, number_of_resolved = check_regular_build(component, ctx)
537-
561+
availability = {
562+
'can_build_regular': ready_to_rebuild,
563+
'buildable_bconds': [],
564+
'non_buildable_bconds': [],
565+
}
566+
538567
if ready_to_rebuild:
539568
if should_print_component(component, ctx.components_done):
540569
print(component)
541570
else:
542-
check_bcond_builds(component, number_of_resolved, ctx)
571+
buildable_bconds, non_buildable_bconds = check_bcond_builds(component, number_of_resolved, ctx)
572+
availability['buildable_bconds'] = buildable_bconds
573+
availability['non_buildable_bconds'] = non_buildable_bconds
574+
575+
ctx.component_availability[component] = availability
543576

544577

545578
def assemble_component_info(component, count, ctx):
@@ -596,7 +629,6 @@ def generate_reports(ctx):
596629
log('\nThe 20 most commonly last-blocking small combinations of components are:')
597630
for components_tuple, count in ctx.blocker_counter['combinations'].most_common(20):
598631
log(f'{count:>5} {", ".join(components_tuple)}')
599-
600632
report_data['most_commonly_last_blocking_combinations'].append({
601633
'components': list(components_tuple),
602634
'count': count
@@ -610,6 +642,35 @@ def generate_reports(ctx):
610642
log('\nReport saved to commonly-needed-report.json')
611643

612644

645+
def generate_component_availability_report(ctx):
646+
"""
647+
Generate and save full component availability report.
648+
Creates component-availability-report.json with per-component data.
649+
650+
Args:
651+
ctx: RebuildContext with component availability data
652+
"""
653+
654+
report_data = {}
655+
for component in ctx.components:
656+
availability = ctx.component_availability.get(component, {})
657+
658+
report_data[component] = {
659+
'was_already_built': component in ctx.components_done,
660+
'is_resolvable': component not in ctx.unresolvable_components,
661+
'prerel_abi_compatible': component not in ctx.prerel_abi_blocked_components,
662+
'can_build_regular': availability.get('can_build_regular', False),
663+
'buildable_bconds': availability.get('buildable_bconds'),
664+
'non_buildable_bconds': availability.get('non_buildable_bconds'),
665+
'blocked_by': sorted(ctx.loop_detector.get(component, [])),
666+
'blocks_count': ctx.blocker_counter['general'].get(component, 0)
667+
}
668+
669+
with open('component-availability-report.json', 'w') as f:
670+
json.dump(report_data, f, indent=2, sort_keys=True)
671+
log('Full component availability report saved to component-availability-report.json')
672+
673+
613674
def main():
614675
"""
615676
Main entry point for rebuild analysis.
@@ -638,8 +699,9 @@ def main():
638699

639700
for component in components_to_process:
640701
process_component(component, ctx)
641-
702+
642703
generate_reports(ctx)
704+
generate_component_availability_report(ctx)
643705

644706

645707
if __name__ == '__main__':

0 commit comments

Comments
 (0)