name: Build + boot check # Proves the split Dockerfile actually builds and boots standalone (repo-split # Stage 7b) -- not yet a full pytest-suite migration (that's separate, real # follow-up work, same category as thermograph-copy's deferred vendoring). # THERMOGRAPH_FRONTEND_BASE_INTERNAL is required (fails loud if unset) but # never actually exercised here -- /healthz doesn't go through the # catch-all proxy, so an unreachable placeholder is fine for this check. on: push: branches: [main] pull_request: branches: [main] jobs: build: runs-on: docker steps: - uses: actions/checkout@v4 - name: Install Docker CLI run: | apt-get update -qq apt-get install -y -qq docker.io - name: Build run: docker build -t thermograph-backend:ci . - name: Boot + health check # Curling the sibling container's own bridge IP does NOT work on # this runner (docker-outside-of-docker: the job container's network # namespace can't reach another container's bridge IP directly -- # every attempt hangs for the full TCP SYN timeout, ~130s, instead of # failing fast) -- confirmed by a stuck run. 127.0.0.1 DOES work # (proven by the monorepo's own build.yml, which has used a # published host port successfully all along), so publish one, but # to a per-run unique port rather than a fixed one -- this runner's # snap-Docker install has a known AppArmor bug denying docker # stop/kill, so a leftover container from any prior failed run # permanently squats whatever host port it was given, and a fixed # port would block every subsequent run too. GITHUB_RUN_ID (NOT # $$ -- every job container's shell gets the same low PID, so that # collided with an already-stuck leftover from a prior run) is # genuinely unique per run. run: | name="backend-ci-${GITHUB_RUN_ID}" port=$((18000 + (GITHUB_RUN_ID % 1000))) docker run -d --name "$name" \ -e THERMOGRAPH_FRONTEND_BASE_INTERNAL=http://127.0.0.1:1 \ -p "127.0.0.1:${port}:8137" thermograph-backend:ci # 60s, not 30 -- confirmed by a real run's own docker logs: alembic # migrations + starting 4 uvicorn workers took just over 30s under # this runner's resource contention (capacity 2, so another job's # build often runs concurrently), even though the same boot takes # ~3s locally with nothing else competing for CPU. ok=0 for i in $(seq 1 60); do if curl -fsS -o /dev/null "http://127.0.0.1:${port}/healthz"; then ok=1; break; fi sleep 1 done docker logs "$name" docker rm -f "$name" >/dev/null 2>&1 || true if [ "$ok" != 1 ]; then echo "backend never became healthy"; exit 1; fi echo "OK: backend booted standalone"