@@ -227,30 +227,68 @@ jobs:
227227 --environment production
228228
229229 - name : Verify deployment
230+ env :
231+ API_HOST : openhardwaremanager.blackdune-e38fce01.westus3.azurecontainerapps.io
232+ EXPECTED_VERSION : ${{ needs.validate.outputs.version }}
233+ # Lifespan startup (storage + MATCHING_EAGER_INIT up to 120s) can exceed
234+ # the old 20×5s window; use liveness (no storage fingerprint) and tolerate
235+ # empty/non-JSON gateway responses during revision rollout.
230236 run : |
231- for i in $(seq 1 20); do
232- ACTUAL=$(curl -sf https://openhardwaremanager.blackdune-e38fce01.westus3.azurecontainerapps.io/health \
233- | python3 -c "import sys,json; print(json.load(sys.stdin)['version'])" || true)
234- [ "$ACTUAL" = "${{ needs.validate.outputs.version }}" ] && break
235- sleep 5
236- done
237- echo "deployed version=$ACTUAL (expected ${{ needs.validate.outputs.version }})"
238- test "$ACTUAL" = "${{ needs.validate.outputs.version }}"
237+ python3 - <<'PY'
238+ import json
239+ import os
240+ import sys
241+ import time
242+ import urllib.error
243+ import urllib.request
244+
245+ host = os.environ["API_HOST"]
246+ expected = os.environ["EXPECTED_VERSION"]
247+ url = f"https://{host}/health/liveness"
248+ actual = None
249+
250+ for attempt in range(1, 49):
251+ try:
252+ with urllib.request.urlopen(url, timeout=30) as resp:
253+ body = json.load(resp)
254+ actual = body.get("version")
255+ if actual == expected:
256+ print(f"deployed version={actual} (expected {expected})")
257+ sys.exit(0)
258+ print(f"attempt {attempt}/48: version={actual!r} (waiting for {expected!r})")
259+ except (urllib.error.URLError, TimeoutError, json.JSONDecodeError, KeyError) as exc:
260+ print(f"attempt {attempt}/48: not ready ({type(exc).__name__})")
261+ time.sleep(5)
262+
263+ print(f"deployed version={actual!r} (expected {expected!r})")
264+ sys.exit(1)
265+ PY
239266
240267 - name : Verify storage fingerprint (drift + emptiness gate)
241268 # Assert the live app is actually pointed at the container the repo
242269 # declares (config/environments/production.toml) AND that it is non-empty.
243270 # Emptiness is a deploy-gate failure (never promote a release onto an
244271 # empty/mis-pointed prod container) even though it is only a startup warning.
272+ env :
273+ API_HOST : openhardwaremanager.blackdune-e38fce01.westus3.azurecontainerapps.io
245274 run : |
246275 python3 - <<'PY'
247- import json, sys, tomllib, urllib.request
276+ import json, sys, time, tomllib, urllib.error, urllib. request, os
248277
249- host = "openhardwaremanager.blackdune-e38fce01.westus3.azurecontainerapps.io"
278+ host = os.environ["API_HOST"]
250279 with open("config/environments/production.toml", "rb") as f:
251280 expected = tomllib.load(f).get("azure_storage_container", "")
252- with urllib.request.urlopen(f"https://{host}/health", timeout=15) as r:
253- fp = json.load(r).get("storage", {})
281+
282+ fp = {}
283+ for attempt in range(1, 13):
284+ try:
285+ with urllib.request.urlopen(f"https://{host}/health", timeout=30) as r:
286+ fp = json.load(r).get("storage", {})
287+ if fp.get("container") is not None:
288+ break
289+ except (urllib.error.URLError, TimeoutError, json.JSONDecodeError) as exc:
290+ print(f"attempt {attempt}/12: /health not ready ({type(exc).__name__})")
291+ time.sleep(5)
254292
255293 container, okh, okw = fp.get("container"), fp.get("okh_count"), fp.get("okw_count")
256294 print(f"live container={container!r} expected={expected!r} okh={okh} okw={okw}")
@@ -273,7 +311,7 @@ jobs:
273311 publish-frontend :
274312 name : Publish frontend multi-arch to Docker Hub
275313 runs-on : ubuntu-latest
276- needs : [validate]
314+ needs : [validate, test, docker-smoke ]
277315 if : >-
278316 github.event_name == 'push' ||
279317 (github.event_name == 'workflow_dispatch' && inputs.dry_run == false)
@@ -323,7 +361,7 @@ jobs:
323361 deploy-frontend-azure :
324362 name : Deploy frontend to Azure Container Apps
325363 runs-on : ubuntu-latest
326- needs : [validate, publish-frontend]
364+ needs : [validate, publish, publish -frontend]
327365 if : github.event_name == 'push'
328366 environment : production
329367 permissions :
0 commit comments