Throwaway: upload a build's dnf cache to the forge's RPM registry, and time it
All checks were successful
RPM mirror test / upload (push) Successful in 1m33s

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Philip Peterson 2026-10-30 23:45:13 -08:00
parent 36b34ba66c
commit 0f07b8cff5
2 changed files with 83 additions and 0 deletions

47
.forgejo/upload-rpms.sh Executable file
View file

@ -0,0 +1,47 @@
#!/usr/bin/env bash
# Uploads the RPMs a build downloaded (its dnf cache, kept by
# Containerfile.in's cache mounts) to this forge's RPM registry, one group
# per upstream repository: fedora, updates, terra, copr-ublue-os-packages...
# Each group is a dnf repository at
# https://forge.quinefoundation.com/api/packages/quine-global-labs/rpm/<group>.
#
# Usage: upload-rpms.sh CACHE_DIR (a libdnf5 cache: one directory per
# repository, <repo id>-<hash>/packages/*.rpm)
#
# Needs REGISTRY_USER and REGISTRY_TOKEN (package write access). Packages
# the registry already has are skipped (409). Best effort: a failed upload
# is a warning, not a failure.
set -euo pipefail
cache=$1
api=${RPM_API:-https://forge.quinefoundation.com/api/packages/quine-global-labs/rpm}
# The token goes to curl in a file, not on its command line.
netrc=$(mktemp)
trap 'rm -f "$netrc"' EXIT
chmod 600 "$netrc"
printf 'machine %s login %s password %s\n' \
"$(sed -E 's|^https?://([^/]+).*|\1|' <<<"$api")" "$REGISTRY_USER" "$REGISTRY_TOKEN" >"$netrc"
upload() { # group rpm
local code
code=$(curl -sS -o /dev/null -w '%{http_code}' --retry 3 --netrc-file "$netrc" \
--upload-file "$2" "$api/$1/upload") || code=000
case $code in
201) echo "new $1 ${2##*/}" ;;
409) echo "had $1 ${2##*/}" ;;
*) echo "::warning::$code uploading ${2##*/} to $1" ;;
esac
}
export -f upload
export api netrc
for dir in "$cache"/*/; do
id=$(basename "$dir")
id=${id%-*} # the hash libdnf5 appends
[[ $id == @* ]] && continue # @commandline: local files, not a repository
# copr:copr.fedorainfracloud.org:ublue-os:packages -> copr-ublue-os-packages
group=$(sed -E 's/^copr:[^:]+:/copr-/; s/:/-/g' <<<"$id")
find "$dir" -name '*.rpm' -printf "$group\0%p\0"
done | xargs -0 -n 2 -P 4 bash -c 'upload "$@"' _ |
tee /dev/stderr | awk '{n[$1]++} END {for (k in n) printf "%s: %d\n", k, n[k]}'

View file

@ -0,0 +1,36 @@
name: RPM mirror test
# Throwaway (branch rpm-mirror-test): uploads the last build's dnf cache to
# the forge's RPM registry and times it, then checks dnf can read a group.
on:
push:
branches: [rpm-mirror-test]
jobs:
upload:
runs-on: runner-x86-linux
steps:
- uses: https://forge.quinefoundation.com/quine-global-labs/mirror-actions-checkout@v4
- name: Upload the dnf cache
env:
REGISTRY_USER: ${{ vars.REGISTRY_USER || github.actor }}
REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
run: |
cache=$(dirname "$(ls -d /var/tmp/buildah-cache-0/*/fedora-* | head -1)")
echo "cache: $cache ($(du -sh "$cache" | cut -f1))"
start=$(date +%s)
.forgejo/upload-rpms.sh "$cache"
echo "took $(( $(date +%s) - start ))s"
- name: dnf reads the groups
run: |
api=https://forge.quinefoundation.com/api/packages/quine-global-labs/rpm
sleep 30 # the registry rebuilds repodata after uploads
for g in fedora updates terra; do
curl -fsS -o /dev/null -w "$g repomd: %{http_code}\n" "$api/$g/repodata/repomd.xml"
done
podman run --rm registry.fedoraproject.org/fedora:latest \
dnf -q repoquery --disablerepo='*' --repofrompath="f,$api/fedora" \
--repofrompath="u,$api/updates" --setopt=f.gpgcheck=0 --setopt=u.gpgcheck=0 \
--available | wc -l