From 6fd01d45cc844e8c09085ed80e7fde439dfd3f89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pierzcha=C5=82a?= Date: Thu, 20 Aug 2026 08:03:07 +0200 Subject: [PATCH] ci: bound the Linux apt install so a stalled mirror fails fast MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unbounded, the desktop-dependency install could not fail, only stall. On 2026-08-19 a slow package mirror held apt past the job's 30-minute budget on four main-branch runs and several unrelated PRs, cancelling each job before Setup toolchain, Xvfb/D-Bus, or the replay smoke test ran — a red check on branches that never executed a line of project code. timeout-minutes: 6 turns that into a named step failure in six minutes instead of a cancelled job at thirty; a healthy install takes about a minute. The apt options cover the transient cases without a retry loop layered on top of them: socket timeouts bound a mirror that connects and then goes quiet, Acquire::Retries absorbs a blip, and DPkg::Lock::Timeout bounds the runner's own unattended-upgrades timer, which stalls identically and is a plausible alternate cause of the same symptom. Tradeoff: a fast transient failure that apt's own retries miss now fails the job rather than self-healing, traded against carrying a bash retry loop in CI. --- .github/workflows/linux.yml | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 4c37cb62c..47dba01a1 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -45,10 +45,26 @@ jobs: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + # Unbounded, this step could not fail — it could only stall. On 2026-08-19 a slow mirror + # held apt past the job's 30-minute budget on four main-branch runs and several unrelated + # PRs, which reported as a red check on branches that never ran a line of project code. + # Two bounds fix that: apt retries and times out each mirror request itself (a blip + # self-heals without a manual re-run), and `timeout-minutes` is the backstop for a mirror + # that drips bytes slowly enough to defeat the socket timeout. A healthy install takes + # about a minute, so six is generous. - name: Install Linux desktop dependencies + timeout-minutes: 6 run: | - sudo apt-get update -qq - sudo apt-get install -y -qq \ + set -euo pipefail + APT_OPTS=( + -o Acquire::Retries=2 + -o Acquire::http::Timeout=15 + -o Acquire::https::Timeout=15 + # The runner's own unattended-upgrades timer holds the dpkg lock; wait, don't hang. + -o DPkg::Lock::Timeout=60 + ) + sudo apt-get update -qq "${APT_OPTS[@]}" + sudo apt-get install -y -qq "${APT_OPTS[@]}" \ xvfb \ xdotool \ scrot \