run() { # log status: prints what the script says; $root/env is its GITHUB_ENV
: > "$root/env"
GITHUB_ENV="$root/env" bash "$EU" "$1" "$2" 2>&1
}
# The upgrade job's v0.2.0 install on 2026-10-02: GitHub refused cloudflared's download.
{
step "release channel: v0.2.0"
step "installing cloudflared 2026.9.1 (amd64)"
echo "curl: (22) The requested URL returned error: 403"
trapped 1727 22
} > "$root/403.log"
out="$(run "$root/403.log" 22)"
status "a 403 on a download skips" 0 $?
expect " with a warning that quotes curl" "::warning::the installer stopped on an upstream download (curl: (22) The requested URL returned error: 403)" "$out"
same " and gates the later steps" "E2E_UPSTREAM_SKIP=1" "$(cat "$root/env")"
for e in "(6) Could not resolve host: github.com" \
"(7) Failed to connect to github.com port 443 after 130 ms: Couldn't connect to server" \
"(28) Operation timed out after 300000 milliseconds with 0 out of 0 bytes received" \
"(35) OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to objects.githubusercontent.com:443" \
"(56) Recv failure: Connection reset by peer" \
"(22) The requested URL returned error: 429" \
"(22) The requested URL returned error: 503" \
"(22) The requested URL returned error: 502 Bad Gateway"; do
# What the installer prints after the trap, as it exits, changes nothing.
{
cat "$root/403.log"
printf '\033[1;33m[warn]\033[0m %s\n' "restored the previous felis binary at /usr/local/bin/felis; the database was not migrated, so rerunning the installer picks up where this run stopped"
} > "$root/cleanup.log"
out="$(run "$root/cleanup.log" 22)"
status "warnings after the trap still skip" 0 $?
# set -E: the trap again for a function the failure unwound through.