#!/usr/bin/env bash # Run a check that can red on box state or the network twice before calling it red (standing rule, 7 October 2026, 17:2x UK: # a check that talks to a build box or a live host gets one retry and, on a runner without the resource, a clear skip line # from the check itself). The first failure is printed as a line, the command runs again after a pause, and only the second # failure is the check's verdict. A check that passes first time runs once. # # tools/ci/retry-once.sh # exit = the last run's exit code; RETRY_ONCE_PAUSE seconds between (default 5) # tools/ci/retry-once.sh --self-test # a command that fails once then passes is ok; one that fails twice is red; # # a command that passes runs exactly once set -uo pipefail PAUSE="${RETRY_ONCE_PAUSE:-5}" if [ "${1:-}" = --self-test ]; then fails=0; d=$(mktemp -d) # fails once then passes: the marker file is the memory flaky="$d/flaky.sh"; printf '#!/usr/bin/env bash\nif [ -f "%s/seen" ]; then exit 0; fi; touch "%s/seen"; echo first-try-failed; exit 7\n' "$d" "$d" > "$flaky"; chmod +x "$flaky" out=$(RETRY_ONCE_PAUSE=0 bash "$0" flaky "$flaky" 2>&1); rc=$? [ "$rc" = 0 ] || { echo "self-test failed: a command that fails once then passes was red (exit $rc): $out"; fails=1; } case "$out" in *"retry-once: flaky failed once (exit 7)"*) ;; *) echo "self-test failed: the first failure was not printed: $out"; fails=1 ;; esac # fails twice: red with the second exit code out=$(RETRY_ONCE_PAUSE=0 bash "$0" dead bash -c 'echo nope; exit 3' 2>&1); rc=$? [ "$rc" = 3 ] || { echo "self-test failed: a command that fails twice was not red with its exit code (got $rc): $out"; fails=1; } [ "$(printf '%s\n' "$out" | grep -c '^nope$')" = 2 ] || { echo "self-test failed: the command did not run exactly twice: $out"; fails=1; } # passes: runs once c="$d/count"; : > "$c" RETRY_ONCE_PAUSE=0 bash "$0" fine bash -c "echo x >> '$c'" >/dev/null 2>&1 || { echo "self-test failed: a passing command was red"; fails=1; } [ "$(wc -l < "$c" | tr -d ' ')" = 1 ] || { echo "self-test failed: a passing command ran $(wc -l < "$c") times"; fails=1; } rm -rf "$d" [ "$fails" = 0 ] && echo "self-test passed: one retry after a first failure, red only on the second, a passing command runs once" exit $fails fi [ $# -ge 2 ] || { echo "usage: tools/ci/retry-once.sh | --self-test" >&2; exit 2; } NAME="$1"; shift "$@"; rc=$? [ "$rc" = 0 ] && exit 0 echo "retry-once: $NAME failed once (exit $rc); second try in ${PAUSE}s (a box or network check gets one retry before it is red)" sleep "$PAUSE" "$@"