Simpl-Resultat/.forgejo/workflows/diag-cache-probe.yml
le king fu 68aef2a74a
Some checks failed
PR Check — Frontend / frontend (pull_request) Successful in 1m41s
Diag — cache server reachability (#234) / probe (pull_request) Failing after 1m52s
ci: keep the cache probe running past an expected failure (#234)
The runner starts `shell: bash` steps as `bash -e -o pipefail`, so run 453
stopped at the first TIMEOUT instead of probing the other addresses. Each
probe now swallows its own exit code, and the env listing and the forge
lookup no longer abort the step when they come back empty.

Refs #234

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 13:53:44 -04:00

146 lines
6 KiB
YAML

name: Diag — cache server reachability (#234)
# THROWAWAY DIAGNOSTIC — never merge. Lives on its own branch for #234.
#
# Since #232 no workflow calls the Actions cache: in July both the restore
# (getCacheEntry) and the save (reserveCache) ended in "Request timeout". The
# suspected cause is that the job container cannot reach the cache address the
# runner hands it. This job checks that from inside a job container, without
# host access:
# 1. which cache address the runner advertises (path redacted: it may carry a
# per-run token, and this repository's job logs are public);
# 2. raw TCP reachability of that address, next to other ports and other host
# addresses, to tell "dropped" from "refused" from "open";
# 3. an end-to-end round trip through actions/cache with a tiny payload.
# The job is green only if the payload comes back from the cache server.
#
# Steps that use bash features set `shell: bash`: inside a container the runner
# defaults to `sh`, and a job-level `defaults` block is refused by the runner.
# The runner starts those steps as `bash -e -o pipefail`, so every probe that
# is expected to fail must swallow its own exit code (run 453 stopped at the
# first TIMEOUT for that reason).
on:
pull_request:
paths:
- '.forgejo/workflows/diag-cache-probe.yml'
permissions:
contents: read
jobs:
probe:
runs-on: ubuntu
container: ubuntu:22.04
timeout-minutes: 20
steps:
- name: Cache address and TCP reachability
shell: bash
run: |
echo "Runner-provided variables (names only):"
compgen -e | grep -E 'ACTIONS|RUNNER|FORGEJO|GITEA' | sort | sed 's/^/ /' || true
compgen -e | grep -E '_RUNNER_VERSION$' | while read -r v; do echo " $v=${!v}"; done || true
url="${ACTIONS_CACHE_URL:-}"
if [ -z "$url" ]; then
echo "ACTIONS_CACHE_URL is empty: the runner gives this job no cache server."
exit 0
fi
base=$(printf '%s' "$url" | sed -E 's#^(https?://[^/]+).*#\1#')
scheme=${base%%://*}
hostport=${base#*://}
case "$hostport" in
\[*\]:*) host=${hostport%]:*}; host=${host#[}; port=${hostport##*]:} ;;
*:*) host=${hostport%:*}; port=${hostport##*:} ;;
*) host=$hostport; port="" ;;
esac
if [ -z "$port" ]; then
if [ "$scheme" = https ]; then port=443; else port=80; fi
fi
shown=$host
case "$host" in *:*) shown="[$host]" ;; esac
echo
echo "Cache address advertised by the runner: $scheme://$shown:$port/<path redacted>"
forge=$(getent ahostsv4 git.lacompagniemaximus.com | awk '{ print $1; exit }') || true
echo "git.lacompagniemaximus.com resolves to (IPv4): ${forge:-unresolved}"
echo "Container addresses: $(hostname -I 2>/dev/null || echo unknown)"
gw_hex=$(awk '$2 == "00000000" { print $3; exit }' /proc/net/route)
gw=""
if [ -n "$gw_hex" ]; then
gw=$(printf '%d.%d.%d.%d' "0x${gw_hex:6:2}" "0x${gw_hex:4:2}" "0x${gw_hex:2:2}" "0x${gw_hex:0:2}")
fi
echo "Default gateway (the host, seen from this job network): ${gw:-unknown}"
probe() {
local label=$1 h=$2 p=$3 start ms rc err verdict
start=$(date +%s%N)
err=$(timeout 10 bash -c "exec 3<>/dev/tcp/$h/$p" 2>&1) && rc=0 || rc=$?
ms=$(( ($(date +%s%N) - start) / 1000000 ))
case $rc in
0) verdict="OPEN" ;;
124) verdict="TIMEOUT" ;;
*) case "$err" in
*refused*) verdict="REFUSED" ;;
*) verdict="ERROR (${err##*: })" ;;
esac ;;
esac
printf ' %-36s %-26s %-8s %6d ms\n' "$label" "$h:$p" "$verdict" "$ms"
}
echo
echo "TCP probes, 10 s each. OPEN = handshake done; REFUSED = the host answered"
echo "but nothing listens there; TIMEOUT = no answer (packets dropped, or the"
echo "address is unreachable from this network)."
probe "advertised cache address" "$host" "$port"
probe "same host, port 22 (sshd)" "$host" 22
probe "same host, port 443 (Traefik)" "$host" 443
if [ -n "$gw" ]; then
probe "job network gateway, cache port" "$gw" "$port"
probe "job network gateway, port 22" "$gw" 22
fi
probe "docker0 172.17.0.1, cache port" 172.17.0.1 "$port"
- name: Install Node.js 20
run: |
apt-get update
apt-get install -y --no-install-recommends curl ca-certificates
# actions/cache is a JavaScript action: it needs `node` in the container PATH.
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
apt-get install -y nodejs
node --version
- name: Write a tiny payload
id: payload
shell: bash
run: |
key="diag-234-$(date -u +%Y%m%dT%H%M%SZ)-$RANDOM"
mkdir -p probe-payload
printf '%s' "$key" > probe-payload/stamp
echo "key=$key" >> "${GITHUB_OUTPUT:-$FORGEJO_OUTPUT}"
echo "payload key: $key"
- name: Save it (actions/cache/save)
uses: https://github.com/actions/cache/save@v4
with:
path: probe-payload
key: ${{ steps.payload.outputs.key }}
- name: Delete the local copy
run: rm -rf probe-payload
- name: Restore it (actions/cache/restore, fails on a miss)
uses: https://github.com/actions/cache/restore@v4
with:
path: probe-payload
key: ${{ steps.payload.outputs.key }}
fail-on-cache-miss: true
- name: Check the payload made the round trip
shell: bash
run: |
if [ "$(cat probe-payload/stamp 2>/dev/null)" = "${{ steps.payload.outputs.key }}" ]; then
echo "ROUND TRIP OK: the payload came back from the cache server."
else
echo "ROUND TRIP FAILED: the payload is missing or different."
exit 1
fi