From 288c696f28a47ed5be8bc927981f3e1b3b136a76 Mon Sep 17 00:00:00 2001 From: latte Date: Sun, 5 Jul 2026 13:55:29 +0200 Subject: [PATCH] fix(ci): give the smoke-test container a per-commit name The Docker smoke-test ran the server container under the fixed name familiar-smoke. On the self-hosted runner the job shares the host Docker daemon, so a container left behind by a killed or re-run job (or a concurrent dev push + PR) collides on that name and 'docker run' fails with exit 125. Derive the name from the commit SHA, remove any stale container of that name before starting, and thread the name through the smoke-test and cleanup steps. --- .gitea/workflows/docker.yml | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/.gitea/workflows/docker.yml b/.gitea/workflows/docker.yml index 5fea119..e906357 100644 --- a/.gitea/workflows/docker.yml +++ b/.gitea/workflows/docker.yml @@ -52,6 +52,9 @@ jobs: IMAGE="git.hiddenden.cafe/${GITHUB_REPOSITORY,,}" echo "image=${IMAGE}" >> "$GITHUB_OUTPUT" echo "sha_tag=${IMAGE}:sha-${GITHUB_SHA::12}" >> "$GITHUB_OUTPUT" + # Per-commit container name: the self-hosted runner shares the host + # Docker daemon, so a fixed name collides across concurrent/re-run jobs. + echo "container=familiar-smoke-${GITHUB_SHA::12}" >> "$GITHUB_OUTPUT" if [ "${GITHUB_REF_NAME}" = "main" ]; then echo "branch_tags=${IMAGE}:latest ${IMAGE}:main" >> "$GITHUB_OUTPUT" else @@ -67,8 +70,13 @@ jobs: run: | set -euo pipefail IMG="${{ steps.meta.outputs.sha_tag }}" + CONTAINER="${{ steps.meta.outputs.container }}" TOKEN="smoke-$(date +%s)" + # Remove any container left behind by a killed/re-run job before we + # reuse the name (shared host daemon → stale containers can survive). + docker rm -f "$CONTAINER" >/dev/null 2>&1 || true + # 1. Runs as a non-root user (uid 1000). uid=$(docker run --rm --entrypoint id "$IMG" -u) echo "container uid: $uid" @@ -83,13 +91,13 @@ jobs: # socket and runs the probe in the server's own netns, where # 127.0.0.1:8080 always works regardless of runner topology. The image # ships python + httpx, so no curl or extra pull is needed. - docker run -d --name familiar-smoke -e FAMILIAR_HTTP_TOKEN="$TOKEN" "$IMG" + docker run -d --name "$CONTAINER" -e FAMILIAR_HTTP_TOKEN="$TOKEN" "$IMG" # probe "" -> prints the status code - probe() { docker exec familiar-smoke python -c "import httpx; print(($1).status_code)"; } + probe() { docker exec "$CONTAINER" python -c "import httpx; print(($1).status_code)"; } for i in $(seq 1 30); do - if docker exec familiar-smoke python -c \ + if docker exec "$CONTAINER" python -c \ "import httpx; httpx.get('http://127.0.0.1:8080/healthz', timeout=5)" >/dev/null 2>&1; then break fi @@ -98,7 +106,7 @@ jobs: echo "== /healthz (expect 200) ==" code=$(probe "httpx.get('http://127.0.0.1:8080/healthz', timeout=10)") - [ "$code" = "200" ] || { echo "::error::/healthz returned $code"; docker logs familiar-smoke; exit 1; } + [ "$code" = "200" ] || { echo "::error::/healthz returned $code"; docker logs "$CONTAINER"; exit 1; } echo "== MCP without token (expect 401) ==" code=$(probe "httpx.post('http://127.0.0.1:8080/mcp', timeout=10, headers={'Accept':'application/json, text/event-stream','Content-Type':'application/json'}, json={'jsonrpc':'2.0','id':1,'method':'initialize','params':{}})") @@ -106,7 +114,7 @@ jobs: echo "== MCP with valid token (expect 200) ==" code=$(probe "httpx.post('http://127.0.0.1:8080/mcp', timeout=10, headers={'Authorization':'Bearer $TOKEN','Accept':'application/json, text/event-stream','Content-Type':'application/json'}, json={'jsonrpc':'2.0','id':1,'method':'initialize','params':{'protocolVersion':'2025-06-18','capabilities':{},'clientInfo':{'name':'ci','version':'1'}}})") - [ "$code" = "200" ] || { echo "::error::authenticated MCP returned $code"; docker logs familiar-smoke; exit 1; } + [ "$code" = "200" ] || { echo "::error::authenticated MCP returned $code"; docker logs "$CONTAINER"; exit 1; } echo "Image smoke-test passed." @@ -135,7 +143,7 @@ jobs: if: always() shell: bash run: | - docker rm -f familiar-smoke || true + docker rm -f ${{ steps.meta.outputs.container }} || true docker rmi -f ${{ steps.meta.outputs.sha_tag }} ${{ steps.meta.outputs.branch_tags }} || true docker image prune -f || true docker builder prune -f || true