From e0351264252972028f61bb58c022df0665c3ce06 Mon Sep 17 00:00:00 2001 From: Stefan Popp Date: Sun, 1 Nov 2026 09:41:35 +0100 Subject: [PATCH] Let CI give up on a dnf mirror that is slow or hangs tools/dnf.sh runs dnf in a CI container: the repository data first (dnf makecache, without -q), then the command, each with 180 seconds per try and up to three tries, 15 seconds apart. It sets minrate=100000 and timeout=20 in /etc/dnf/dnf.conf, so dnf leaves a mirror slower than 100 kB/s. On AlmaLinux the first dnf install of a job once took almost 14 minutes and once ran until the job's 20-minute limit. The repository end-to-end step installs azentrius-repository through it on Fedora, Rocky Linux and AlmaLinux. --- .github/workflows/test.yml | 5 +++-- README.md | 4 +++- tools/dnf.sh | 39 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 3 deletions(-) create mode 100755 tools/dnf.sh diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e70657e..8781f95 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -60,13 +60,14 @@ jobs: test ! -e /etc/apt/sources.list.d/azentrius.sources' for image in fedora:43 rockylinux/rockylinux:9 rockylinux/rockylinux:10 almalinux:9 almalinux:10; do echo "::group::$image" - docker run --rm -v "$AZPKG_ROOT:/repo:ro" -v "$PWD/repository/azentrius.asc:/azentrius.asc:ro" "$image" sh -ec ' + docker run --rm -v "$AZPKG_ROOT:/repo:ro" -v "$PWD/repository/azentrius.asc:/azentrius.asc:ro" \ + -v "$PWD/tools/dnf.sh:/dnf.sh:ro" "$image" sh -ec ' . /etc/os-release echo "$PRETTY_NAME, $(rpm --version)" rpm --import /azentrius.asc rpm --import /repo/test.asc printf "[test]\nname=test\nbaseurl=file:///repo/rpm\ngpgcheck=1\n" > /etc/yum.repos.d/test.repo - dnf install -y -q azentrius-repository + sh /dnf.sh install -y -q azentrius-repository rpm -K /repo/rpm/azentrius-repository-*.rpm | grep -q "digests signatures OK" test -f /usr/share/swcatalog/xml/azentrius.xml grep -q "baseurl=https://packages.azentrius.com/rpm" /etc/yum.repos.d/azentrius.repo diff --git a/README.md b/README.md index c610924..2f737d5 100644 --- a/README.md +++ b/README.md @@ -118,7 +118,9 @@ server tool and installs `azentrius-repository` from it on Debian 13, Fedora 43, 10 and AlmaLinux 9 and 10; the RPM systems import the repository's real key first. `tools/build-packages.sh` is the same file in every Azentrius add-on. `tools/apt-update.sh` runs `apt-get update` on the CI runner with time limits and three tries, so that a mirror that hangs -costs minutes instead of the job; it is the same file as in Cron Jobs. +costs minutes instead of the job; it is the same file as in Cron Jobs. `tools/dnf.sh`, also from +there, runs dnf in the test containers with time limits and three tries, the repository data +first, and lets dnf leave a mirror slower than 100 kB/s. Releases: raise `VERSION`, add a section to `CHANGELOG.md`, merge, then Actions › release › Run workflow on `main`. diff --git a/tools/dnf.sh b/tools/dnf.sh new file mode 100755 index 0000000..ad912ed --- /dev/null +++ b/tools/dnf.sh @@ -0,0 +1,39 @@ +#!/bin/sh +# dnf in a CI container, as root, that leaves a slow mirror and ends a try that hangs, instead of +# waiting until the job times out: on AlmaLinux the first dnf install of a job, which downloads +# the repository data, once took almost 14 minutes without a word under -q (normally well under a +# minute), and once ran into the job's 20-minute limit. +# +# sh /dnf.sh install -y -q PACKAGE... the repository data first, then the command +# sh /dnf.sh makecache only the repository data, for a dnf of its own after it +# +# dnf leaves a mirror that sends less than 100 kB/s for 20 seconds and takes the next one (its own +# defaults: 1 kB/s, 30 seconds); the two settings go into /etc/dnf/dnf.conf and stay for every later +# dnf in the container. The repository data comes first and without -q, so the log shows each +# repository's size and speed. Each try may take 180 seconds; a failed or hung one gets a second +# and a third, 15 seconds apart. +# SPDX-License-Identifier: Apache-2.0 +set -u +[ $# -gt 0 ] || { echo "usage: sh dnf.sh makecache | install -y -q PACKAGE..." >&2; exit 64; } +conf=/etc/dnf/dnf.conf +grep -qx 'minrate=100000' "$conf" 2> /dev/null || + sed -i -e '/^\[main\]/a minrate=100000' -e '/^\[main\]/a timeout=20' "$conf" +grep -qx 'minrate=100000' "$conf" || { echo "::error::no [main] section in $conf"; exit 1; } + +tries() { + for try in 1 2 3; do + rc=0 + timeout --kill-after=10 180 dnf "$@" || rc=$? + [ "$rc" != 0 ] || return 0 + case $rc in + 124 | 137) why="no end within 180 seconds" ;; + *) why="exit code $rc" ;; + esac + echo "::warning::dnf $1 failed ($why, try $try of 3)" + [ "$try" -lt 3 ] || { echo "::error::dnf $1 failed three times"; exit "$rc"; } + sleep 15 + done +} + +tries makecache +[ "$1" = makecache ] || tries "$@"