Skip to content

Commit 67fbc04

Browse files
committed
src/konflux-rpm-lockfile: update baseurl dynamically
Until now, we tackled the DNF5 issue [1] by prioritizing the URL location of the repo 'coreos-pool' when multiple repo were found for the say locked NEVRA. But, if that locked NEVRA has only one URL location coming from the fedora repos i.e: fedora, fedora-updates, then the repoquery command returns a broken URL location for ppc64le and s390x arches because of the DNF5 issue. It returns the URL from the first item defined in baseurl, whereas the resolution worked with the second item i.e fedora-secondary repo where the RPMs for ppc64le and s390x are available. This patch fixes this until the issue [1] is fixed upstream. It's designed to work only with the main fedora baseurl FQDN i.e dl.fedoraproject.org and for ppc64le/s390x arches. It basically updates the repos to use the fedora-secondary URL as the main one as we know the RPMs for those arches lives there. [1] rpm-software-management/dnf5#1673
1 parent eef1c19 commit 67fbc04

File tree

1 file changed

+54
-8
lines changed

1 file changed

+54
-8
lines changed

src/konflux-rpm-lockfile

Lines changed: 54 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,59 @@ import os
66
import sys
77
import subprocess
88
import yaml
9+
import shutil
10+
import tempfile
11+
import re
12+
from pathlib import Path
913

1014
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
1115
from cosalib.cmdlib import get_basearch
1216

1317

18+
# TODO: remove the use of this function once the DNF5 issue is fixed
19+
# c.f https://github.com/rpm-software-management/dnf5/issues/2466
20+
def copy_repo_files_to_temp_repo(context_dir, arch):
21+
"""
22+
If the architecture is 'ppc64le' or 's390x', then we copy all '.repo' files
23+
from contextdir to a new temporary directory. We then edit the baseurls.
24+
If not, then we return context_dir without processing anything.
25+
"""
26+
if arch not in ['ppc64le', 's390x']:
27+
return context_dir
28+
temp_repo_dir = Path(tempfile.mkdtemp())
29+
context_path = Path(context_dir)
30+
for source_path in context_path.rglob('*.repo'):
31+
destination_path = temp_repo_dir / source_path.name
32+
shutil.copy2(source_path, destination_path)
33+
update_repo_baseurls(str(destination_path))
34+
return str(temp_repo_dir)
35+
36+
37+
# TODO: remove the use of this function once the DNF5 issue is fixed
38+
# c.f https://github.com/rpm-software-management/dnf5/issues/2466
39+
# This is fragile as it relies on the repo definitions we are defining in the config dir
40+
# but also on the Fedora URL structure that might evolve in the future.
41+
def update_repo_baseurls(repo_path):
42+
"""
43+
Updates the baseurl in the repo file to use the fedora-secondary repo which
44+
provides the RPMs for ppc64le and s390x arches.
45+
"""
46+
old_baseurl_pattern = r"(baseurl=https?://dl\.fedoraproject\.org/)(.*)fedora/linux(.*)"
47+
new_baseurl_replacement = r"\1\2fedora-secondary\3"
48+
with open(repo_path, 'r', encoding='utf-8') as f:
49+
content = f.read()
50+
updated_count = 0
51+
new_content, count = re.subn(
52+
old_baseurl_pattern,
53+
new_baseurl_replacement,
54+
content,
55+
flags=re.IGNORECASE | re.MULTILINE
56+
)
57+
if count > 0:
58+
with open(repo_path, 'w', encoding='utf-8') as f:
59+
f.write(new_content)
60+
61+
1462
def format_packages_with_repoid(pkgs, repos):
1563
"""
1664
Takes a list of package URLs and repos and returns a list
@@ -117,13 +165,8 @@ def query_packages_location(locks, repoquery_args):
117165
if not line:
118166
continue
119167
name, url = line.split(' ')
120-
# Prioritize the url from fedora-coreos-pool
121-
# there is a bug in dnf here where the url returned is incorrect when the
122-
# repofile have more than one baseurl, which causes ppc64le and s390x
123-
# urls comming from fedora and fedora-updates to be invalid
124-
# See https://github.com/rpm-software-management/dnf5/issues/2466
125168
existing_url = processed_urls.get(name, None)
126-
if 'coreos-pool' in url or not existing_url:
169+
if not existing_url:
127170
processed_urls[name] = url
128171

129172
pkg_urls = list(processed_urls.values())
@@ -179,7 +222,7 @@ def generate_main(args):
179222
repos += manifest_data.get('lockfile-repos', [])
180223

181224
# Tell dnf to load repos files from $contextdir
182-
repoquery_args = ["--refresh", "--quiet", f"--setopt=reposdir={contextdir}"]
225+
repoquery_args = ["--refresh", "--quiet"]
183226
repoquery_args.extend([f"--repo={','.join(repos)}"])
184227

185228
if releasever is None:
@@ -195,13 +238,16 @@ def generate_main(args):
195238
sys.exit(1)
196239
print(f"Resolving packages for {arch}...")
197240
arch_args = []
241+
repos_dir = copy_repo_files_to_temp_repo(contextdir, arch)
198242
if arch is not get_basearch():
199243
# append noarch as well because otherwise those packages get excluded from results
200244
# We use --forcearch here because otherwise dnf still respect the system basearch
201245
# we have to specify both --arch and --forcearch to get both result for $arch and $noarch
202-
arch_args = ['--forcearch', arch, '--arch', arch, '--arch', 'noarch']
246+
arch_args = [f"--setopt=reposdir={repos_dir}", '--forcearch', arch, '--arch', arch, '--arch', 'noarch']
203247
pkg_urls = query_packages_location(locks, repoquery_args + arch_args)
204248
packages.append({'arch': arch, 'packages': pkg_urls})
249+
if repos_dir != contextdir:
250+
shutil.rmtree(repos_dir)
205251

206252
lockfile = write_hermeto_lockfile(packages, repos)
207253

0 commit comments

Comments
 (0)