fix: make package existence check distro-aware
check_package_exists was only checking name+version+release, so an almalinux package already in Gitea would cause fedora builds to be skipped incorrectly. Now passes the target distro from PackageInfo through to check_package_exists, which maps it to an RPM dist suffix (.el9, .fc43, etc.) and queries the Gitea package files endpoint to confirm a distro-specific file exists before skipping the build. Also adds fedora/42, fedora/43, fedora/44 to the allowed repository values in the metadata schema.
This commit is contained in:
+62
-8
@@ -94,7 +94,7 @@ METADATA_SCHEMA = {
|
|||||||
'minlength': 1,
|
'minlength': 1,
|
||||||
'schema': {
|
'schema': {
|
||||||
'type': 'string',
|
'type': 'string',
|
||||||
'allowed': ['almalinux/el8', 'almalinux/el9'],
|
'allowed': ['almalinux/el8', 'almalinux/el9', 'fedora/42', 'fedora/43', 'fedora/44'],
|
||||||
'empty': False
|
'empty': False
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -504,17 +504,39 @@ def normalize_version(version: str) -> str:
|
|||||||
return ''.join(normalized_parts)
|
return ''.join(normalized_parts)
|
||||||
|
|
||||||
|
|
||||||
def check_package_exists(package_name: str, version: str, release: str) -> bool:
|
def get_rpm_dist_suffix(distro: str) -> str:
|
||||||
|
"""
|
||||||
|
Map a distro path to the RPM dist tag suffix used in package filenames.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
'almalinux/el9' -> '.el9'
|
||||||
|
'fedora/43' -> '.fc43'
|
||||||
|
"""
|
||||||
|
if distro.startswith('almalinux/'):
|
||||||
|
return '.' + distro.split('/', 1)[1]
|
||||||
|
if distro.startswith('fedora/'):
|
||||||
|
return '.fc' + distro.split('/', 1)[1]
|
||||||
|
return ''
|
||||||
|
|
||||||
|
|
||||||
|
def check_package_exists(package_name: str, version: str, release: str, distro: str = '') -> bool:
|
||||||
"""
|
"""
|
||||||
Check if a package version exists in the Gitea package registry.
|
Check if a package version exists in the Gitea package registry.
|
||||||
|
|
||||||
|
When distro is provided the check is distro-aware: it lists the files
|
||||||
|
attached to the package version and returns True only when a file whose
|
||||||
|
name contains the expected RPM dist suffix (e.g. '.el9', '.fc43') is
|
||||||
|
found. This prevents a package built for almalinux/el9 from being
|
||||||
|
mistaken for a fedora/43 build (and vice-versa).
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
package_name: Name of the package
|
package_name: Name of the package
|
||||||
version: Version string
|
version: Version string
|
||||||
release: Release number
|
release: Release number
|
||||||
|
distro: Target distro path (e.g. 'almalinux/el9', 'fedora/43')
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
True if package exists, False otherwise
|
True if package exists for the given distro, False otherwise
|
||||||
"""
|
"""
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -543,10 +565,41 @@ def check_package_exists(package_name: str, version: str, release: str) -> bool:
|
|||||||
|
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
package_info = response.json()
|
package_info = response.json()
|
||||||
# Package exists if we get package info back
|
if not package_info.get('id'):
|
||||||
exists = bool(package_info.get('id'))
|
logger.debug(f"Package {package_name}:{full_version} not found")
|
||||||
logger.debug(f"Package {package_name}:{full_version} {'exists' if exists else 'not found'}")
|
return False
|
||||||
return exists
|
|
||||||
|
# No distro filter – treat any file as a match
|
||||||
|
if not distro:
|
||||||
|
logger.debug(f"Package {package_name}:{full_version} exists")
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Distro-aware check: inspect individual file names for the dist suffix
|
||||||
|
dist_suffix = get_rpm_dist_suffix(distro)
|
||||||
|
if not dist_suffix:
|
||||||
|
logger.debug(f"Package {package_name}:{full_version} exists (no dist suffix for {distro})")
|
||||||
|
return True
|
||||||
|
|
||||||
|
files_url = f"{base_url}/api/v1/packages/{owner}/{package_type}/{package_name}/{full_version}/files"
|
||||||
|
logger.debug(f"Checking distro-specific files: {files_url}")
|
||||||
|
files_response = requests.get(files_url, headers=headers, timeout=30)
|
||||||
|
|
||||||
|
if files_response.status_code == 200:
|
||||||
|
files = files_response.json()
|
||||||
|
for file_info in files:
|
||||||
|
if dist_suffix in file_info.get('name', ''):
|
||||||
|
logger.debug(f"Package {package_name}:{full_version} exists for {distro}")
|
||||||
|
return True
|
||||||
|
logger.debug(f"Package {package_name}:{full_version} not found for {distro} (no {dist_suffix} file)")
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
# If files endpoint fails fall back to treating version existence as a match
|
||||||
|
logger.warning(
|
||||||
|
f"Could not list files for {package_name}:{full_version}: "
|
||||||
|
f"{files_response.status_code} – assuming package exists"
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
|
||||||
elif response.status_code == 404:
|
elif response.status_code == 404:
|
||||||
logger.debug(f"Package {package_name}:{full_version} not found (404)")
|
logger.debug(f"Package {package_name}:{full_version} not found (404)")
|
||||||
return False
|
return False
|
||||||
@@ -1449,7 +1502,8 @@ class Builder:
|
|||||||
if check_package_exists(
|
if check_package_exists(
|
||||||
package_info.name,
|
package_info.name,
|
||||||
package_info.version,
|
package_info.version,
|
||||||
package_info.release
|
package_info.release,
|
||||||
|
package_info.distro
|
||||||
):
|
):
|
||||||
self.logger.info(
|
self.logger.info(
|
||||||
f"Skipping {package_info} (already exists in repository)"
|
f"Skipping {package_info} (already exists in repository)"
|
||||||
|
|||||||
Reference in New Issue
Block a user