Skip to content

Deploy & Verify HYDRA #232

Deploy & Verify HYDRA

Deploy & Verify HYDRA #232

Workflow file for this run

name: Deploy & Verify HYDRA
on:
push:
branches: [master]
schedule:
- cron: '0 */6 * * *'
workflow_dispatch:
jobs:
deploy-verify:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- name: Check if service is already live
id: health_check
continue-on-error: true
run: |
echo "Checking https://hydra-api-nlnj.onrender.com/health ..."
HTTP_CODE=$(curl -s -o /tmp/health_response.json -w "%{http_code}" \
--max-time 15 \
https://hydra-api-nlnj.onrender.com/health 2>/dev/null || echo "000")
echo "HTTP status: $HTTP_CODE"
if [ "$HTTP_CODE" = "200" ]; then
echo "status=live" >> $GITHUB_OUTPUT
echo "✅ Service is LIVE"
cat /tmp/health_response.json | python3 -m json.tool 2>/dev/null || cat /tmp/health_response.json
else
echo "status=down" >> $GITHUB_OUTPUT
echo "⚠️ Service returned HTTP $HTTP_CODE — may be sleeping or not deployed"
fi
- name: Trigger Render deploy hook (if secret exists)
if: steps.health_check.outputs.status != 'live'
continue-on-error: true
env:
RENDER_DEPLOY_HOOK: ${{ secrets.RENDER_DEPLOY_HOOK }}
run: |
if [ -n "$RENDER_DEPLOY_HOOK" ]; then
echo "🚀 Triggering Render deploy hook..."
curl -s -X POST "$RENDER_DEPLOY_HOOK" --max-time 30
echo ""
echo "Deploy hook triggered. Waiting for service to start..."
else
echo "ℹ️ No RENDER_DEPLOY_HOOK secret configured."
echo ""
echo "To enable auto-deploy, either:"
echo " 1. Connect this repo to Render at https://render.com (uses render.yaml blueprint)"
echo " 2. Or add a RENDER_DEPLOY_HOOK secret with your Render deploy hook URL"
echo ""
echo "The render.yaml blueprint is ready — Render will auto-configure everything."
fi
- name: Wait for service to come up
if: steps.health_check.outputs.status != 'live'
id: wait_check
run: |
echo "Waiting for service to respond (checking every 30s for up to 5 min)..."
for i in 1 2 3 4 5 6 7 8 9 10; do
sleep 30
HTTP_CODE=$(curl -s -o /tmp/health_retry.json -w "%{http_code}" \
--max-time 15 \
https://hydra-api-nlnj.onrender.com/health 2>/dev/null || echo "000")
echo "Attempt $i: HTTP $HTTP_CODE"
if [ "$HTTP_CODE" = "200" ]; then
echo "status=live" >> $GITHUB_OUTPUT
echo "✅ Service is now LIVE!"
cat /tmp/health_retry.json | python3 -m json.tool 2>/dev/null || true
exit 0
fi
done
echo "status=down" >> $GITHUB_OUTPUT
echo "❌ Service did not come up within 5 minutes"
- name: Verify all endpoints respond
if: steps.health_check.outputs.status == 'live' || steps.wait_check.outputs.status == 'live'
run: |
BASE="https://hydra-api-nlnj.onrender.com"
echo "=== Endpoint Verification ==="
echo -n "GET /health ... "
curl -s -o /dev/null -w "%{http_code}" "$BASE/health" --max-time 10
echo ""
echo -n "GET /pricing ... "
curl -s -o /dev/null -w "%{http_code}" "$BASE/pricing" --max-time 10
echo ""
echo -n "GET /docs ... "
curl -s -o /dev/null -w "%{http_code}" "$BASE/docs" --max-time 10
echo ""
echo -n "GET /openapi.json ... "
curl -s -o /dev/null -w "%{http_code}" "$BASE/openapi.json" --max-time 10
echo ""
echo -n "GET /.well-known/x402.json ... "
curl -s -o /dev/null -w "%{http_code}" "$BASE/.well-known/x402.json" --max-time 10
echo ""
echo -n "GET /.well-known/ai-plugin.json ... "
curl -s -o /dev/null -w "%{http_code}" "$BASE/.well-known/ai-plugin.json" --max-time 10
echo ""
echo -n "GET /.well-known/mcp.json ... "
curl -s -o /dev/null -w "%{http_code}" "$BASE/.well-known/mcp.json" --max-time 10
echo ""
echo -n "GET /.well-known/agent.json ... "
curl -s -o /dev/null -w "%{http_code}" "$BASE/.well-known/agent.json" --max-time 10
echo ""
echo -n "GET /.well-known/agent-card.json ... "
curl -s -o /dev/null -w "%{http_code}" "$BASE/.well-known/agent-card.json" --max-time 10
echo ""
echo -n "GET /.well-known/llms.txt ... "
curl -s -o /dev/null -w "%{http_code}" "$BASE/.well-known/llms.txt" --max-time 10
echo ""
echo -n "GET /mcp (MCP server) ... "
curl -s -o /dev/null -w "%{http_code}" "$BASE/mcp" --max-time 10
echo ""
echo -n "GET /v1/markets (free discovery) ... "
curl -s -o /dev/null -w "%{http_code}" "$BASE/v1/markets" --max-time 10
echo ""
echo -n "GET /v1/markets/discovery (free) ... "
curl -s -o /dev/null -w "%{http_code}" "$BASE/v1/markets/discovery" --max-time 10
echo ""
echo -n "POST /v1/regulatory/scan (expect 402) ... "
curl -s -o /dev/null -w "%{http_code}" -X POST "$BASE/v1/regulatory/scan" \
-H "Content-Type: application/json" \
-d '{"business_description":"test crypto exchange in Wyoming","jurisdiction":"US"}' \
--max-time 10
echo ""
echo -n "POST /v1/fed/signal (expect 402) ... "
curl -s -o /dev/null -w "%{http_code}" -X POST "$BASE/v1/fed/signal" \
-H "Content-Type: application/json" \
-d '{}' \
--max-time 10
echo ""
echo ""
echo "Free endpoints should return 200. Paid endpoints should return 402."
echo "402 = x402 payment required (correct behavior — payment gateway working)."
- name: Report deployment status (fails on stale deploy)
if: always()
run: |
echo "============================================"
echo " HYDRA DEPLOYMENT STATUS REPORT"
echo "============================================"
BASE="https://hydra-api-nlnj.onrender.com"
# Reachability ≠ current code. Compare the LIVE version to the repo's
# APP_VERSION and confirm a discovery manifest serves. This catches the
# "frozen on an old build" failure that plain 200-checks miss.
EXPECTED=$(grep -E 'APP_VERSION' config/settings.py | head -1 | sed -E 's/.*"([0-9.]+)".*/\1/')
LIVE=$(curl -s --max-time 20 "$BASE/health" | python3 -c "import sys,json;print(json.load(sys.stdin).get('version',''))" 2>/dev/null || echo "")
X402=$(curl -s -o /dev/null -w "%{http_code}" --max-time 20 "$BASE/.well-known/x402.json" || echo "000")
echo "Repo APP_VERSION : ${EXPECTED:-unknown}"
echo "Live /health ver : ${LIVE:-unreachable}"
echo "x402 manifest : $X402 (expect 200)"
echo ""
FAIL=0
if [ -z "$LIVE" ]; then echo "❌ Service unreachable."; FAIL=1; fi
if [ -n "$EXPECTED" ] && [ -n "$LIVE" ] && [ "$LIVE" != "$EXPECTED" ]; then
echo "❌ STALE DEPLOY: live=$LIVE but repo=$EXPECTED — Render is NOT serving current master."
echo " Fix in Render dashboard: confirm service is connected to master with"
echo " autoDeploy on, check the Deploys tab for build failures, then Manual Deploy"
echo " (Clear build cache & deploy). render.yaml blueprint is ready."
FAIL=1
fi
if [ "$X402" != "200" ]; then
echo "❌ Discovery manifest /.well-known/x402.json → $X402 (should be 200)."
FAIL=1
fi
if [ "$FAIL" = "1" ]; then
echo "::error::HYDRA deployment is stale or broken — see details above."
exit 1
fi
echo "✅ HYDRA is LIVE and CURRENT (v$LIVE), discovery manifests serving."
echo "============================================"