From 8aa37bde3407a38f4d177ca561aae37da8d2baaa Mon Sep 17 00:00:00 2001 From: vjrj Date: Wed, 22 Jul 2026 12:17:11 +0200 Subject: [PATCH] ci(release): retry network-fragile steps (fdroidserver download + fdroid build) Even after the dnsmasq DNS cache, the Hetzner vSwitch still blips mid-transfer. Two spots kept killing ~25min builds: the fdroidserver tarball 'curl -sL | tar' (an empty stream -> 'gzip: unexpected end of file') and maven/pub fetches mid-Gradle ('Network is unreachable'). Download fdroidserver to a file with curl --retry (+ -f + validate the gzip before extract), and wrap fdroid build in a 3-attempt loop gated on the APK actually appearing (fdroid build exits 0 even on failure). --- .forgejo/workflows/release.yml | 63 +++++++++++++++++++++++++++++----- 1 file changed, 54 insertions(+), 9 deletions(-) diff --git a/.forgejo/workflows/release.yml b/.forgejo/workflows/release.yml index d0c9bcc..44575f8 100644 --- a/.forgejo/workflows/release.yml +++ b/.forgejo/workflows/release.yml @@ -150,8 +150,16 @@ jobs: # 2) fdroidserver from master, exactly like the fdroiddata CI. fds=/opt/fdroidserver-src mkdir -p "$fds" - curl -sL https://gitlab.com/fdroid/fdroidserver/-/archive/master/fdroidserver-master.tar.gz \ - | tar -xz -C "$fds" --strip-components=1 + # Download to a file with retries: a mid-transfer vSwitch blip used to + # pipe an empty stream straight into tar ("gzip: unexpected end of + # file"). -f fails on HTTP errors; --retry-all-errors covers resets. + for a in 1 2 3 4 5; do + curl -fsSL --retry 5 --retry-delay 3 --retry-all-errors \ + https://gitlab.com/fdroid/fdroidserver/-/archive/master/fdroidserver-master.tar.gz \ + -o /tmp/fds.tgz && tar -tzf /tmp/fds.tgz >/dev/null 2>&1 && break + echo "fdroidserver download attempt $a failed; retrying in 5s" >&2; sleep 5 + done + tar -xz -C "$fds" --strip-components=1 -f /tmp/fds.tgz export PATH="$fds:$PATH" export PYTHONPATH="$fds:$fds/examples" git config --global --add safe.directory '*' @@ -206,7 +214,14 @@ jobs: # per-ABI into its own job/matrix-entry (rather than all 3 sequentially in # one job) is what keeps each build inside the runner's max-job-runtime — # each needs a full cold NDK+tesseract-native+flutter compile. - fdroid build --verbose --no-tarball "org.comunes.tane:${vc}" + # Retry the build: a transient network blip mid-Gradle (maven/pub) used + # to kill it. `fdroid build` exits 0 even on failure, so gate the retry + # on the APK actually appearing. Up to 3 attempts fit the 90m timeout. + for a in 1 2 3; do + fdroid build --verbose --no-tarball "org.comunes.tane:${vc}" || true + if [ -f "unsigned/org.comunes.tane_${vc}.apk" ]; then break; fi + echo "fdroid build attempt $a produced no APK; retrying" >&2 + done # `fdroid build` exits 0 even when builds fail — demand the APK. f="unsigned/org.comunes.tane_${vc}.apk" @@ -281,8 +296,16 @@ jobs: . /etc/profile.d/bsenv.sh fds=/opt/fdroidserver-src mkdir -p "$fds" - curl -sL https://gitlab.com/fdroid/fdroidserver/-/archive/master/fdroidserver-master.tar.gz \ - | tar -xz -C "$fds" --strip-components=1 + # Download to a file with retries: a mid-transfer vSwitch blip used to + # pipe an empty stream straight into tar ("gzip: unexpected end of + # file"). -f fails on HTTP errors; --retry-all-errors covers resets. + for a in 1 2 3 4 5; do + curl -fsSL --retry 5 --retry-delay 3 --retry-all-errors \ + https://gitlab.com/fdroid/fdroidserver/-/archive/master/fdroidserver-master.tar.gz \ + -o /tmp/fds.tgz && tar -tzf /tmp/fds.tgz >/dev/null 2>&1 && break + echo "fdroidserver download attempt $a failed; retrying in 5s" >&2; sleep 5 + done + tar -xz -C "$fds" --strip-components=1 -f /tmp/fds.tgz export PATH="$fds:$PATH" export PYTHONPATH="$fds:$fds/examples" git config --global --add safe.directory '*' @@ -313,7 +336,14 @@ jobs: mkdir -p build git clone -q https://git.comunes.org/comunes/tane.git build/org.comunes.tane git -C build/org.comunes.tane checkout -q "${BUILD_REF}" - fdroid build --verbose --no-tarball "org.comunes.tane:${vc}" + # Retry the build: a transient network blip mid-Gradle (maven/pub) used + # to kill it. `fdroid build` exits 0 even on failure, so gate the retry + # on the APK actually appearing. Up to 3 attempts fit the 90m timeout. + for a in 1 2 3; do + fdroid build --verbose --no-tarball "org.comunes.tane:${vc}" || true + if [ -f "unsigned/org.comunes.tane_${vc}.apk" ]; then break; fi + echo "fdroid build attempt $a produced no APK; retrying" >&2 + done f="unsigned/org.comunes.tane_${vc}.apk" if [ ! -f "$f" ]; then echo "expected $f, not found" >&2 @@ -382,8 +412,16 @@ jobs: . /etc/profile.d/bsenv.sh fds=/opt/fdroidserver-src mkdir -p "$fds" - curl -sL https://gitlab.com/fdroid/fdroidserver/-/archive/master/fdroidserver-master.tar.gz \ - | tar -xz -C "$fds" --strip-components=1 + # Download to a file with retries: a mid-transfer vSwitch blip used to + # pipe an empty stream straight into tar ("gzip: unexpected end of + # file"). -f fails on HTTP errors; --retry-all-errors covers resets. + for a in 1 2 3 4 5; do + curl -fsSL --retry 5 --retry-delay 3 --retry-all-errors \ + https://gitlab.com/fdroid/fdroidserver/-/archive/master/fdroidserver-master.tar.gz \ + -o /tmp/fds.tgz && tar -tzf /tmp/fds.tgz >/dev/null 2>&1 && break + echo "fdroidserver download attempt $a failed; retrying in 5s" >&2; sleep 5 + done + tar -xz -C "$fds" --strip-components=1 -f /tmp/fds.tgz export PATH="$fds:$PATH" export PYTHONPATH="$fds:$fds/examples" git config --global --add safe.directory '*' @@ -414,7 +452,14 @@ jobs: mkdir -p build git clone -q https://git.comunes.org/comunes/tane.git build/org.comunes.tane git -C build/org.comunes.tane checkout -q "${BUILD_REF}" - fdroid build --verbose --no-tarball "org.comunes.tane:${vc}" + # Retry the build: a transient network blip mid-Gradle (maven/pub) used + # to kill it. `fdroid build` exits 0 even on failure, so gate the retry + # on the APK actually appearing. Up to 3 attempts fit the 90m timeout. + for a in 1 2 3; do + fdroid build --verbose --no-tarball "org.comunes.tane:${vc}" || true + if [ -f "unsigned/org.comunes.tane_${vc}.apk" ]; then break; fi + echo "fdroid build attempt $a produced no APK; retrying" >&2 + done f="unsigned/org.comunes.tane_${vc}.apk" if [ ! -f "$f" ]; then echo "expected $f, not found" >&2