diff --git a/.forgejo/workflows/build.yml b/.forgejo/workflows/build.yml index ce3bf76..cbbd559 100644 --- a/.forgejo/workflows/build.yml +++ b/.forgejo/workflows/build.yml @@ -1353,9 +1353,34 @@ jobs: trap 'rc=$?; [ $rc -eq 0 ] || docker logs "$CID" 2>&1 | tail -40; docker rm -f "$CID" >/dev/null 2>&1 || true; exit $rc' EXIT WEB_IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "$CID") test -n "$WEB_IP" + + # The probe runs INSIDE the sandbox, like every check above it. + # + # It has to. Docker gives an `--internal` network isolation rules + # that DROP traffic entering it from any other interface, and this + # job's own container sits on the runner's default bridge — so a + # curl from here to $WEB_IP is discarded before it arrives. Because + # the packets are dropped rather than refused, every attempt burns + # the full --max-time and the job reports a web container that + # "never answered" while the app is running perfectly. That is how + # this read on its first real execution (run 7282): a false failure + # blaming the application for the harness's own blind spot. + # + # Steps 0-2 were already right by accident — each runs a container + # ON $NET. Only this one reached in from outside, and it was the + # only one that could not work. + # + # Same shape as the egress probe above: the image's own python3 over + # `shell -c`, since the runtime stage ships no curl. + probe() { + docker run --rm --network "$NET" "$CANDIDATE" shell -c \ + "python3 -c \"import urllib.request; urllib.request.urlopen('http://$WEB_IP:8080/api/health', timeout=5)\"" \ + >/dev/null 2>&1 + } + healthy="" for i in $(seq 1 60); do - if curl -fsS --max-time 5 "http://$WEB_IP:8080/api/health" >/dev/null 2>&1; then + if probe; then healthy=1 break fi @@ -1381,8 +1406,9 @@ jobs: echo "smoke: python base rather than at startup." >&2 exit 1 fi - curl -fsS --max-time 5 "http://$WEB_IP:8080/api/health" - echo + # Print what it actually answered — from inside, for the same reason. + docker run --rm --network "$NET" "$CANDIDATE" shell -c \ + "python3 -c \"import urllib.request; print(urllib.request.urlopen('http://$WEB_IP:8080/api/health', timeout=5).read().decode())\"" echo "smoke: all checks passed against $CANDIDATE, with egress blocked"