From eafb8296e38352422044b5ca5dc62df0be3f07b1 Mon Sep 17 00:00:00 2001 From: TaprootFreak <142087526+TaprootFreak@users.noreply.github.com> Date: Tue, 2 Jun 2026 09:40:37 +0200 Subject: [PATCH] fix(ci/deploy-dev): smoke-test gates on /health/ready, not /api/info MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Post-deploy smoke test was checking `/api/info` for HTTP 200, but after #154 the node binds the HTTP listener BEFORE the Plonky2 prover warmup completes — `/api/info` returns 200 within seconds while `/health/ready` stays at `{"ready":false,"prover":"warming"}` for the 10-30 s warmup window. Downstream jobs (API E2E preflight against `/health/ready` + `/health/publisher`) raced the warmup: the E2E job picked the runner up ~4 s after the deploy job reported success, hit `/health/ready` once, got back the warming snapshot, and failed with `::error::/health/ready not ready` — observed empirically on Release PR #166's run https://github.com/zk-coins/node/actions/runs/26793933906/job/78986599030. Switch the smoke loop to `/health/ready` + a `jq '.ready == true'` assertion, keeping the 30-attempt × 10-s budget (~5 min) so a genuine bootstrap stall still surfaces with the same timeout behaviour. The deploy job now only reports success once the node is actually ready for traffic, which removes the race the E2E preflight was tripping over. `/api/info` is no longer a deploy-success signal. The E2E preflight retains its explicit `/health/ready` + publisher-wallet gate as a sanity check (still a single shot — it relies on the smoke test having already enforced readiness). The deploy job runs on `ubuntu-24.04-arm` where `jq` is part of the default GitHub-hosted image; no install step needed here. --- .github/workflows/deploy-dev.yaml | 43 +++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/.github/workflows/deploy-dev.yaml b/.github/workflows/deploy-dev.yaml index fa140756..32ce85b8 100644 --- a/.github/workflows/deploy-dev.yaml +++ b/.github/workflows/deploy-dev.yaml @@ -102,28 +102,45 @@ jobs: ${{ secrets.DEPLOY_DEV_USER }}@${{ secrets.DEPLOY_DEV_HOST }} \ "$DEPLOY_CMD" - # Post-deploy smoke test: hit the public endpoint until /api/info - # answers 200 or we give up. A green "Build and deploy to DEV" - # without this step was historically misleading — a runtime-bootstrap - # panic left the container Up-but-unresponsive while the workflow - # reported success. Failing this step blocks the auto-release PR - # from collecting a green check and surfaces the regression in CI. + # Post-deploy smoke test: hit the public endpoint until + # /health/ready reports `ready: true` (or we give up). A green + # "Build and deploy to DEV" without this step was historically + # misleading — a runtime-bootstrap panic left the container + # Up-but-unresponsive while the workflow reported success. + # Failing this step blocks the auto-release PR from collecting + # a green check and surfaces the regression in CI. + # + # `/health/ready` (not `/api/info`) is the load-bearing gate. + # Post-#154 the node binds the HTTP listener immediately and + # warms the Plonky2 prover in a background task; `/api/info` + # returns 200 within seconds, but `/health/ready` stays at + # `{"ready":false,"prover":"warming"}` for the 10-30 s warmup. + # Downstream jobs (E2E preflight, smoke tests against the + # publisher wallet) gated on `/health/ready` and were racing + # the warmup — observed empirically in + # https://github.com/zk-coins/node/actions/runs/26793933906/job/78986599030 + # (Release PR #166, prover still warming at +4 s after the + # E2E job picked the runner up). Polling `/health/ready` here + # means the deploy job only reports success once the node is + # actually ready for traffic. - name: Smoke test public endpoint run: | set -euo pipefail - URL="https://dev-api.zkcoins.app/api/info" + URL="https://dev-api.zkcoins.app/health/ready" for i in $(seq 1 30); do - code=$(curl -sS -o /tmp/info.json -w '%{http_code}' --max-time 10 "$URL" || echo "000") - if [ "$code" = "200" ]; then - echo "DEV /api/info responded 200 after ${i} attempt(s):" - cat /tmp/info.json + body=$(curl -sS -o /tmp/ready.json -w '%{http_code}' --max-time 10 "$URL" || echo "000") + code="$body" + if [ "$code" = "200" ] && jq -e '.ready == true' /tmp/ready.json > /dev/null 2>&1; then + echo "DEV /health/ready reports ready=true after ${i} attempt(s):" + cat /tmp/ready.json echo exit 0 fi - echo "[$i/30] $URL -> ${code} (waiting 10 s)" + ready_snap=$(jq -c '. // "(no body)"' /tmp/ready.json 2>/dev/null || echo "(non-json)") + echo "[$i/30] $URL -> ${code} ${ready_snap} (waiting 10 s)" sleep 10 done - echo "::error::DEV /api/info never returned 200 within ~5 min after deploy" + echo "::error::DEV /health/ready never reported ready=true within ~5 min after deploy" exit 1 # Functional verification of the deployed DEV node.