From 4acf6836628157f829f864b6074341c5763a2830 Mon Sep 17 00:00:00 2001 From: latte Date: Sun, 5 Jul 2026 13:31:49 +0200 Subject: [PATCH] fix(ci): smoke-test the image over its bridge IP, not a published host port MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Self-hosted runners can execute job steps as a sibling container sharing the host's Docker socket, so -p 18080:8080 publishes on the runner host rather than inside the step's own container — 127.0.0.1 never reaches it (curl exit 7). Container-to-container traffic over the bridge network always works, so resolve the smoke container's own IP and probe that. --- .gitea/workflows/docker.yml | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/.gitea/workflows/docker.yml b/.gitea/workflows/docker.yml index 38079d8..17048ed 100644 --- a/.gitea/workflows/docker.yml +++ b/.gitea/workflows/docker.yml @@ -74,25 +74,33 @@ jobs: echo "container uid: $uid" [ "$uid" = "1000" ] || { echo "::error::image runs as uid $uid, expected 1000"; exit 1; } - # 2. Boot the server and probe it over HTTP. + # 2. Boot the server and probe it over HTTP. Talk to the container's own + # bridge IP rather than a host-published port (-p): self-hosted runners + # commonly execute steps as a sibling container sharing the host's + # Docker socket, in which case -p publishes on the *runner host*, not + # inside this step's container, and 127.0.0.1 never reaches it. + # Container-to-container traffic over the bridge network always works. docker run -d --name familiar-smoke -e FAMILIAR_HTTP_TOKEN="$TOKEN" -p 18080:8080 "$IMG" + ip=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' familiar-smoke) + BASE="http://${ip}:8080" + for i in $(seq 1 30); do - if curl -fsS "http://127.0.0.1:18080/healthz" >/dev/null 2>&1; then break; fi + if curl -fsS "$BASE/healthz" >/dev/null 2>&1; then break; fi sleep 1 done echo "== /healthz (expect 200) ==" - code=$(curl -s -o /dev/null -w '%{http_code}' "http://127.0.0.1:18080/healthz") + code=$(curl -s -o /dev/null -w '%{http_code}' "$BASE/healthz") [ "$code" = "200" ] || { echo "::error::/healthz returned $code"; docker logs familiar-smoke; exit 1; } echo "== MCP without token (expect 401) ==" - code=$(curl -s -o /dev/null -w '%{http_code}' -X POST "http://127.0.0.1:18080/mcp" \ + code=$(curl -s -o /dev/null -w '%{http_code}' -X POST "$BASE/mcp" \ -H 'Accept: application/json, text/event-stream' -H 'Content-Type: application/json' \ -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}') [ "$code" = "401" ] || { echo "::error::unauthenticated MCP returned $code"; exit 1; } echo "== MCP with valid token (expect 200) ==" - code=$(curl -s -o /dev/null -w '%{http_code}' -X POST "http://127.0.0.1:18080/mcp" \ + code=$(curl -s -o /dev/null -w '%{http_code}' -X POST "$BASE/mcp" \ -H "Authorization: Bearer $TOKEN" \ -H 'Accept: application/json, text/event-stream' -H 'Content-Type: application/json' \ -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"ci","version":"1"}}}')