fix(ci): give the smoke-test container a per-commit name
CI / lint (pull_request) Successful in 55s
docker / lint (pull_request) Successful in 56s
CI / test (pull_request) Successful in 1m6s
docker / test (pull_request) Successful in 1m4s
CI / publish (pull_request) Has been skipped
docker / docker (pull_request) Successful in 41s
CI / lint (pull_request) Successful in 55s
docker / lint (pull_request) Successful in 56s
CI / test (pull_request) Successful in 1m6s
docker / test (pull_request) Successful in 1m4s
CI / publish (pull_request) Has been skipped
docker / docker (pull_request) Successful in 41s
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.
This commit is contained in:
1 parent
6c4cbd13ad
commit
288c696f28
1 file changed
+14
-6
@@ -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 "<httpx call returning a Response>" -> 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
|
||||
Reference in new issue
Block a user