Skip to content

Commit 99c4d69

Browse files
befelemehroncok
authored andcommitted
Filter components with unsatisfied prerel-abi dependencies
Some packages require python(prerel-abi) = X.Y.Z~alphaN which may not match the prerel-abi version currently available in the target repo. These packages need to be treated as "not yet successfully rebuilt" even though they depend on the new Python ABI and exist in the target. This change adds filtering logic that: - Checks all packages in components_done for unsatisfied prerel-abi deps - Removes components with mismatched prerel-abi from components_done - Allows them to be reported as ready to rebuild - Tracks blocked components for proper status reporting Assisted-By: Claude 4.5 Sonnet
1 parent 278aa39 commit 99c4d69

2 files changed

Lines changed: 83 additions & 5 deletions

File tree

config.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ baseurl = ["https://copr-be.cloud.fedoraproject.org/results/@python/python3.15/f
7474
# baseurl = ["http://kojipkgs.fedoraproject.org/repos/f44-build/latest/$basearch/"]
7575
metadata_expire = 60
7676

77+
[prerel]
78+
current_version = "3.15.0~alpha7"
79+
7780
[bconds]
7881
[[bconds.python-setuptools]]
7982
withs = ["bootstrap"]

jobs.py

Lines changed: 80 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ class RebuildContext:
5151
loop_detector: Map of components to their blocking components
5252
missing_packages: Map of components to their missing package names
5353
unresolvable_components: Set of components whose dependencies cannot be resolved
54+
prerel_abi_blocked_components: Set of components blocked by unsatisfied prerel-abi dependencies
5455
"""
5556
components: ReverseLookupDict
5657
components_done: ReverseLookupDict
@@ -63,6 +64,7 @@ class RebuildContext:
6364
loop_detector: dict = field(default_factory=dict)
6465
missing_packages: dict = field(default_factory=lambda: collections.defaultdict(set))
6566
unresolvable_components: set = field(default_factory=set)
67+
prerel_abi_blocked_components: set = field(default_factory=set)
6668

6769

6870
def _query_packages_by_deps(sack_getter, deps, excluded_components):
@@ -291,9 +293,11 @@ def report_blocking_components(loop_detector):
291293
log(' • ' + ' → '.join(loop))
292294

293295

294-
def get_component_status_info(component, missing_packages, components, unresolvable_components):
296+
def get_component_status_info(component, missing_packages, components, unresolvable_components, prerel_abi_blocked_components=None):
295297
"""Generate status information for a component explaining why it's blocked."""
296-
if component in unresolvable_components:
298+
if prerel_abi_blocked_components and component in prerel_abi_blocked_components:
299+
return " (unsatisfied prerel-abi dependency)"
300+
elif component in unresolvable_components:
297301
return " (can't resolve dependencies)"
298302
elif component in components:
299303
if component in missing_packages:
@@ -311,6 +315,67 @@ def get_component_status_info(component, missing_packages, components, unresolva
311315
return f" (build failed)"
312316

313317

318+
def _filter_components_with_unsatisfied_prerel_abi(components_done):
319+
"""
320+
Filter out components that have unsatisfied python(prerel-abi) dependencies.
321+
322+
Some packages require python(prerel-abi) = X.Y.Z~alphaN which should match
323+
the current_version defined in config.toml [prerel] section.
324+
325+
Args:
326+
components_done: ReverseLookupDict of components that have been built
327+
328+
Returns:
329+
Tuple of (filtered_components, blocked_components) where:
330+
- filtered_components: ReverseLookupDict with components that have matching prerel-abi removed
331+
- blocked_components: set of component names that were filtered (should not be rebuilt)
332+
"""
333+
import re
334+
335+
# Get the expected prerel-abi version from config
336+
expected_version = CONFIG.get('prerel', {}).get('current_version')
337+
if not expected_version:
338+
log(' • Warning: No prerel.current_version found in config.toml, skipping prerel-abi filtering')
339+
return components_done, set()
340+
341+
filtered = ReverseLookupDict()
342+
blocked_components = set()
343+
344+
for component, packages in components_done.items():
345+
component_has_unsatisfied_prerel = False
346+
347+
for pkg in packages:
348+
for req in pkg.requires:
349+
req_str = str(req)
350+
if 'python(prerel-abi)' in req_str:
351+
# Extract version from requirement string
352+
# Format: python(prerel-abi) = X.Y.Z~alphaN
353+
match = re.search(r'python\(prerel-abi\)\s*=\s*([^\s]+)', req_str)
354+
if match:
355+
required_version = match.group(1)
356+
if required_version != expected_version:
357+
log(f' • Filtering {component}: required {req_str}, expected python(prerel-abi) = {expected_version}')
358+
component_has_unsatisfied_prerel = True
359+
blocked_components.add(component)
360+
break
361+
else:
362+
log(f' • Warning: Could not parse prerel-abi requirement: {req_str}')
363+
364+
if component_has_unsatisfied_prerel:
365+
break
366+
367+
# Only include this component if it doesn't have unsatisfied prerel-abi deps
368+
if not component_has_unsatisfied_prerel:
369+
filtered[component] = packages
370+
371+
filtered.default_factory = None
372+
373+
if blocked_components:
374+
log(f'• Filtered out {len(blocked_components)} components with unsatisfied prerel-abi dependencies.')
375+
376+
return filtered, blocked_components
377+
378+
314379
def initialize_component_data():
315380
"""
316381
Load and prepare all component data needed for rebuild analysis.
@@ -330,12 +395,16 @@ def initialize_component_data():
330395
excluded_components=tuple(CONFIG['components']['excluded'])
331396
)
332397

398+
# Filter out components with unsatisfied prerel-abi dependencies
399+
components_done, prerel_abi_blocked = _filter_components_with_unsatisfied_prerel_abi(components_done)
400+
333401
binary_rpms = components.all_values()
334402

335403
return RebuildContext(
336404
components=components,
337405
components_done=components_done,
338-
binary_rpms=binary_rpms
406+
binary_rpms=binary_rpms,
407+
prerel_abi_blocked_components=prerel_abi_blocked
339408
)
340409

341410

@@ -480,12 +549,18 @@ def generate_reports(ctx):
480549
"""
481550
log('\nThe 50 most commonly needed components are:')
482551
for component, count in ctx.blocker_counter['general'].most_common(50):
483-
status_info = get_component_status_info(component, ctx.missing_packages, ctx.components, ctx.unresolvable_components)
552+
status_info = get_component_status_info(
553+
component, ctx.missing_packages, ctx.components,
554+
ctx.unresolvable_components, ctx.prerel_abi_blocked_components
555+
)
484556
log(f'{count:>5} {component:<35} {status_info}')
485557

486558
log('\nThe 20 most commonly last-blocking components are:')
487559
for component, count in ctx.blocker_counter['single'].most_common(20):
488-
status_info = get_component_status_info(component, ctx.missing_packages, ctx.components, ctx.unresolvable_components)
560+
status_info = get_component_status_info(
561+
component, ctx.missing_packages, ctx.components,
562+
ctx.unresolvable_components, ctx.prerel_abi_blocked_components
563+
)
489564
log(f'{count:>5} {component:<35} {status_info}')
490565

491566
log('\nThe 20 most commonly last-blocking small combinations of components are:')

0 commit comments

Comments
 (0)