Commitbba9415unknown_key
fix(deploy): smoke-test localhost on the box, not public DNS
fix(deploy): smoke-test localhost on the box, not public DNS The old smoke test hit https://gluecron.com/healthz from the GH runner. That made deploys fail during DNS migrations (the domain may still point at an old box) or before Caddy has issued the TLS cert (new domain on fresh box). Now the smoke test SSHes BACK into the box and curls http://localhost:3010/healthz directly. We're testing the actual instance we just deployed, not whatever the public DNS happens to resolve to. Independent of DNS state + TLS state + external reachability. Bonus: on success it prints /api/version output so the run log shows which sha is now serving. On failure it dumps systemctl status + last 30 journal lines for instant diagnosis without a second SSH round-trip.
1 file changed+33−17bba941502e736f5188767fe5ef91a2d441cc70af
1 changed file+33−17
Modified.github/workflows/hetzner-deploy.yml+33−17View fileUnifiedSplit
@@ -70,24 +70,40 @@ jobs:
7070 echo "Deploying SHA: $new_sha"
7171 bash scripts/deploy-crontech.sh
7272
73 # ─── 3. Smoke-test the live URL ─────────────────────────────────────
74 - name: Smoke test (https://gluecron.com/healthz)
73 # ─── 3. Smoke-test the deployed app on the box ──────────────────────
74 # We SSH back in and curl localhost:3010/healthz directly. This tests
75 # the EXACT instance we just deployed, independent of:
76 # - DNS state (gluecron.com may still point at an old box during a
77 # migration)
78 # - Caddy TLS state (cert may not be issued yet for a new domain)
79 # - external network reachability from GH runners
80 # If you ALSO want a public-DNS smoke check, add a second step that
81 # hits https://gluecron.com after this one succeeds.
82 - name: Smoke test (localhost on the box)
7583 id: smoke
76 run: |
77 set +e
78 for i in 1 2 3 4 5 6 7 8; do
79 code=$(curl -s -o /dev/null -w "%{http_code}" https://gluecron.com/healthz)
80 echo "Attempt $i: /healthz → $code"
81 if [ "$code" = "200" ]; then
82 echo "smoke_status=ok" >> $GITHUB_OUTPUT
83 echo "✓ gluecron.com is live and healthy."
84 exit 0
85 fi
86 sleep 8
87 done
88 echo "smoke_status=fail" >> $GITHUB_OUTPUT
89 echo "✗ /healthz did not return 200 after 64s. Triggering rollback."
90 exit 1
84 uses: appleboy/ssh-action@v1.2.0
85 with:
86 host: ${{ secrets.HETZNER_HOST }}
87 username: ${{ secrets.HETZNER_USER }}
88 key: ${{ secrets.HETZNER_SSH_KEY }}
89 script_stop: true
90 script: |
91 set +e
92 for i in 1 2 3 4 5 6 7 8; do
93 code=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:3010/healthz)
94 echo "Attempt $i: /healthz -> $code"
95 if [ "$code" = "200" ]; then
96 echo "OK: gluecron is healthy on localhost:3010"
97 # Also print the sha so the deploy log shows what's running
98 curl -s http://localhost:3010/api/version || true
99 exit 0
100 fi
101 sleep 6
102 done
103 echo "FAIL: /healthz did not return 200 after 48s"
104 systemctl status gluecron --no-pager | head -10 || true
105 journalctl -u gluecron -n 30 --no-pager || true
106 exit 1
91107
92108 # ─── 4. Auto-rollback on smoke failure ──────────────────────────────
93109 # Only rolls back if the workflow was triggered by a normal push.
94110