From 593a10b57e2e489ffde13028d65aeb72b1b904d1 Mon Sep 17 00:00:00 2001 From: Pieter Viljoen Date: Tue, 4 Aug 2026 15:34:21 -0700 Subject: [PATCH 1/2] Separate a transport failure from a missing header while waiting The reload wait read an unreachable host as a reply carrying no release, so a connection lost mid-wait reported as a config that never reloaded. Co-Authored-By: Claude Opus 5 (1M context) --- checks/check-live-urls.sh | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/checks/check-live-urls.sh b/checks/check-live-urls.sh index eba83c5..8ef3f4d 100755 --- a/checks/check-live-urls.sh +++ b/checks/check-live-urls.sh @@ -140,9 +140,12 @@ fi # Nothing else proves the rules answering are the ones just shipped, as no deploy restarts Caddy. # A stale config serves the previous release's rules while the new content is already live. +# Returns non-zero on a transport failure, and empty on a reply carrying no release header. +# Collapsing the two would report an unreachable host as a config that never reloaded. read_release() { - curl -s -o /dev/null -D- --max-time 30 "${AUTH[@]}" "$BASE/" | - grep -i '^x-blog-release:' | tr -d '\r' | sed 's/^[^:]*: *//' + local headers + headers=$(curl -sS -o /dev/null -D- --max-time 30 "${AUTH[@]}" "$BASE/" 2>"$CURLERR") || return 1 + printf '%s' "$headers" | grep -i '^x-blog-release:' | tr -d '\r' | sed 's/^[^:]*: *//' } got_release=$(printf '%s' "$preflight_headers" | grep -i '^x-blog-release:' | tr -d '\r' | sed 's/^[^:]*: *//') @@ -154,7 +157,11 @@ if [ -n "${EXPECT_RELEASE:-}" ]; then while [ "$got_release" != "$EXPECT_RELEASE" ] && [ "$waited" -lt "${RELOAD_TIMEOUT:-30}" ]; do sleep 1 waited=$((waited + 1)) - got_release=$(read_release) + if ! got_release=$(read_release); then + echo "FAIL: $BASE/ became unreachable after ${waited}s of waiting for the reload" >&2 + sed 's/^/ /' "$CURLERR" >&2 + exit 1 + fi done if [ "$got_release" != "$EXPECT_RELEASE" ]; then echo "FAIL preflight: after ${waited}s the rules are from release '${got_release:-}', expected '$EXPECT_RELEASE'" >&2 From fdd9158cc3082f71082e846f9b85ed282a3190eb Mon Sep 17 00:00:00 2001 From: Pieter Viljoen Date: Tue, 4 Aug 2026 15:39:36 -0700 Subject: [PATCH 2/2] Keep a missing header from reporting as an unreachable host Pipefail carries grep's no-match status out of the read, so a reachable host serving no release header reported as a lost connection. Co-Authored-By: Claude Opus 5 (1M context) --- checks/check-live-urls.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/checks/check-live-urls.sh b/checks/check-live-urls.sh index 8ef3f4d..a5de29a 100755 --- a/checks/check-live-urls.sh +++ b/checks/check-live-urls.sh @@ -146,6 +146,9 @@ read_release() { local headers headers=$(curl -sS -o /dev/null -D- --max-time 30 "${AUTH[@]}" "$BASE/" 2>"$CURLERR") || return 1 printf '%s' "$headers" | grep -i '^x-blog-release:' | tr -d '\r' | sed 's/^[^:]*: *//' + # Explicit, because pipefail carries grep's no-match status out of the function, which would + # report a reachable host serving no release header as unreachable. + return 0 } got_release=$(printf '%s' "$preflight_headers" | grep -i '^x-blog-release:' | tr -d '\r' | sed 's/^[^:]*: *//')