In Fedora/RISCV land we build some board/vendor/unified-specific kernels. We build them in Koji in a separate tag (e.g., f43-spacemit, f43-p550). In the past we used to have full repos per each custom need, but these days we incremental repos which basically constains only kernel. We layer them on top of generic Fedora/RISCV repos in Kiwi with repository priorities to make sure the right kernel is picked. Some of these have an older kernel version (LTS) and thus NVR is lower. We have no problems with Kiwi locally as those repo descriptions have priorities. I tried to layer repos and use Koji instead.
So the final Kiwi description contained:
<repository type="rpm-md"> <source path="https://riscv-koji.fedoraproject.org/repos-dist/f43-p550/latest/$arch/"/> </repository> <repository type="rpm-md"> <source path="https://riscv-koji.fedoraproject.org/repos-dist/f43-staging/latest/$arch/"/> </repository> <repository type="rpm-md"> <source path="https://riscv-koji.fedoraproject.org/repos-dist/f43/latest/$arch/"/> </repository>
These repos have no priorities set and thus the highest NVR wins. In this cases it fails to pull a special kernel.
Suggestion would be to teach --repo=REPO about priorities. For example, --repo=[PRIORITY,]REPO
Then set that for Kiwi in:
<repository type="rpm-md" [..] priority="96">
After having a quick look at the code it was clear that didn't require much work. I wanted to play latest Gemini Pro thus I gave it the required code snippets (instead of allowing to read full repo). It didn't better than me in general (and faster).
Tested in Fedora/RISCV Koji.
Builder part:
--- /usr/lib/koji-builder-plugins/kiwi.py.orig 2026-02-19 07:57:40.723541436 +0000 +++ /usr/lib/koji-builder-plugins/kiwi.py 2026-02-19 08:17:50.299351232 +0000 @@ -220,12 +220,29 @@ for old_repo in image.getElementsByTagName('repository'): image.removeChild(old_repo) + ## add koji ones + #for repo in sorted(set(repos)): + # repo_node = newxml.createElement('repository') + # repo_node.setAttribute('type', 'rpm-md') + # source = newxml.createElement('source') + # source.setAttribute('path', repo) + # repo_node.appendChild(source) + # image.appendChild(repo_node) + # add koji ones - for repo in sorted(set(repos)): + # Normalize to (priority, url) tuples so sorting and set() work correctly + norm_repos = [tuple(r) if isinstance(r, list) else (None, r) for r in repos] + + for priority, repo_url in sorted(set(norm_repos), key=lambda x: (str(x[0] or ''), x[1])): repo_node = newxml.createElement('repository') repo_node.setAttribute('type', 'rpm-md') + + # Add the priority attribute if it was provided + if priority is not None: + repo_node.setAttribute('priority', str(priority)) + source = newxml.createElement('source') - source.setAttribute('path', repo) + source.setAttribute('path', repo_url) repo_node.appendChild(source) image.appendChild(repo_node)
CLI part:
--- /usr/lib/python3.14/site-packages/koji_cli_plugins/kiwi.py.orig 2026-02-19 09:47:17.784307049 +0200 +++ /usr/lib/python3.14/site-packages/koji_cli_plugins/kiwi.py 2026-02-19 09:53:24.322316747 +0200 @@ -24,7 +24,8 @@ parser.add_option("--repo", action="append", help="Specify a repo that will override the repo used to install " "RPMs in the image. May be used multiple times. The " - "build tag repo associated with the target is the default.") + "build tag repo associated with the target is the default. " + "Format: [PRIORITY,]REPO") parser.add_option("--repo-releasever", help="Override default releasever of the output image") parser.add_option("--noprogress", action="store_true", help="Do not display progress of the upload") @@ -87,8 +88,25 @@ kwargs['result_bundle_name_format'] = options.result_bundle_name_format if options.arches: kwargs['arches'] = [canonArch(arch) for arch in options.arches] +# if options.repo: +# kwargs['repos'] = options.repo + if options.repo: - kwargs['repos'] = options.repo + kwargs['repos'] = [] + for r in options.repo: + if ',' in r: + # Split once to separate priority from the URL + priority, url = r.split(',', 1) + try: + # Pass as a tuple (priority, url) which Koji APIs typically expect + kwargs['repos'].append((int(priority), url)) + except ValueError: + # Fallback if the first part isn't a valid integer + kwargs['repos'].append(r) + else: + kwargs['repos'].append(r) + print(kwargs['repos']) + if options.repo_releasever: kwargs['repo_releasever'] = options.repo_releasever
Builds: https://riscv-koji.fedoraproject.org/koji/buildinfo?buildID=62791 https://riscv-koji.fedoraproject.org/koji/buildinfo?buildID=62793 https://riscv-koji.fedoraproject.org/koji/buildinfo?buildID=62794
From one of Kiwi files:
[..] <repository type="rpm-md" priority="96"> <source path="https://riscv-koji.fedoraproject.org/repos-dist/f43-p550/latest/$arch/"/> </repository> <repository type="rpm-md" priority="98"> <source path="https://riscv-koji.fedoraproject.org/repos-dist/f43-staging/latest/$arch/"/> </repository> <repository type="rpm-md" priority="99"> <source path="https://riscv-koji.fedoraproject.org/repos-dist/f43/latest/$arch/"/> </repository> [..]
Metadata Update from @tkopecek: - Custom field Size adjusted to None - Issue set to the milestone: 1.37
This issue has been migrated to Fedora Forge: https://forge.fedoraproject.org/koji/koji/issues/4545
Please continue any further discussion there.