diff --git a/.github/workflows/db-backup.yml b/.github/workflows/db-backup.yml index 8424072..6668f26 100644 --- a/.github/workflows/db-backup.yml +++ b/.github/workflows/db-backup.yml @@ -91,8 +91,41 @@ jobs: version: 2.75.0 - name: Install age + # The dump, encrypt, and upload step is the recovery point and needs the + # job budget. Without a step bound, one hung apt call consumes all 30 + # minutes and no backup is taken. `age` is a single small package, so 5 + # minutes is a wide margin over its normal install and it leaves 25 of + # the 30 job minutes for the backup itself. + timeout-minutes: 5 run: | - sudo apt-get update -qq + set -uo pipefail + # The hosted runner resolves its Ubuntu mirror through + # /etc/apt/apt-mirrors.txt, which points at azure.archive.ubuntu.com. + # That mirror fails intermittently, and each failure costs minutes of + # apt retries. Prefer the canonical archive. Best-effort: an absent or + # already-canonical file changes nothing. + # + # The canonical archive is the source azure.archive.ubuntu.com mirrors, + # so the same suite resolves the same `age` package. The package name + # and its flags below are unchanged, so the encryption tool this backup + # depends on is the same build it has always been. + sudo sed -i \ + 's|http://azure.archive.ubuntu.com/ubuntu|http://archive.ubuntu.com/ubuntu|g' \ + /etc/apt/apt-mirrors.txt 2>/dev/null || true + update_ok="" + for attempt in 1 2 3; do + if sudo apt-get update -qq; then + update_ok=1 + break + fi + echo "::warning::apt-get update failed (attempt ${attempt}/3); retrying" + sleep $((attempt * 10)) + done + if [ -z "$update_ok" ]; then + echo "::error::apt-get update failed three times; the Ubuntu mirror is unreachable" + exit 1 + fi + set -e sudo apt-get install -y -qq age - name: Validate the exact source, private target, and recipient