Deploy #3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Deploy | |
| # Runs after CI succeeds on main — never deploys a commit that hasn't | |
| # passed lint/tests/eval/security/docker-smoke-test. Single-environment | |
| # (production) with the smoke test as the gate: if it fails, we redeploy | |
| # the last known-good commit automatically rather than leaving a broken | |
| # deploy live. | |
| # | |
| # NOTE: this workflow's exact Render API response shapes are written | |
| # against Render's documented v1 API but have not yet been exercised | |
| # against a real Render service (none existed at authoring time) — treat | |
| # the first real run as a dry-run and check the Actions log carefully. | |
| on: | |
| workflow_run: | |
| workflows: ["CI"] | |
| types: [completed] | |
| branches: [main] | |
| jobs: | |
| deploy: | |
| if: github.event.workflow_run.conclusion == 'success' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ github.event.workflow_run.head_sha }} | |
| - name: Trigger Render deploy for this commit | |
| id: trigger | |
| env: | |
| RENDER_API_KEY: ${{ secrets.RENDER_API_KEY }} | |
| RENDER_SERVICE_ID: ${{ secrets.RENDER_SERVICE_ID }} | |
| COMMIT_SHA: ${{ github.event.workflow_run.head_sha }} | |
| run: | | |
| RESPONSE=$(curl -sf -X POST \ | |
| "https://api.render.com/v1/services/$RENDER_SERVICE_ID/deploys" \ | |
| -H "Authorization: Bearer $RENDER_API_KEY" \ | |
| -H "Content-Type: application/json" \ | |
| -d "{\"commitId\": \"$COMMIT_SHA\"}") | |
| echo "$RESPONSE" | |
| DEPLOY_ID=$(echo "$RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])") | |
| echo "deploy_id=$DEPLOY_ID" >> "$GITHUB_OUTPUT" | |
| - name: Wait for deploy to go live | |
| env: | |
| RENDER_API_KEY: ${{ secrets.RENDER_API_KEY }} | |
| RENDER_SERVICE_ID: ${{ secrets.RENDER_SERVICE_ID }} | |
| DEPLOY_ID: ${{ steps.trigger.outputs.deploy_id }} | |
| run: | | |
| for i in $(seq 1 60); do | |
| STATUS=$(curl -sf "https://api.render.com/v1/services/$RENDER_SERVICE_ID/deploys/$DEPLOY_ID" \ | |
| -H "Authorization: Bearer $RENDER_API_KEY" | python3 -c "import sys,json; print(json.load(sys.stdin)['status'])") | |
| echo "deploy status: $STATUS" | |
| if [ "$STATUS" = "live" ]; then exit 0; fi | |
| case "$STATUS" in | |
| build_failed|update_failed|canceled|deactivated) | |
| echo "deploy ended with status $STATUS"; exit 1 ;; | |
| esac | |
| sleep 10 | |
| done | |
| echo "timed out waiting for the deploy to go live"; exit 1 | |
| - name: Smoke test the live deployment | |
| id: smoke | |
| run: bash scripts/smoke_test.sh "${{ vars.RENDER_SERVICE_URL }}" | |
| - name: Roll back to the previous live deploy on smoke test failure | |
| if: failure() && steps.smoke.outcome == 'failure' | |
| env: | |
| RENDER_API_KEY: ${{ secrets.RENDER_API_KEY }} | |
| RENDER_SERVICE_ID: ${{ secrets.RENDER_SERVICE_ID }} | |
| run: | | |
| echo "::warning::Smoke test failed against the new deploy — rolling back" | |
| PREV_COMMIT=$(curl -sf "https://api.render.com/v1/services/$RENDER_SERVICE_ID/deploys?status=live&limit=1" \ | |
| -H "Authorization: Bearer $RENDER_API_KEY" \ | |
| | python3 -c "import sys,json; d=json.load(sys.stdin); print(d[0]['commit']['id'])") | |
| echo "rolling back to $PREV_COMMIT" | |
| curl -sf -X POST "https://api.render.com/v1/services/$RENDER_SERVICE_ID/deploys" \ | |
| -H "Authorization: Bearer $RENDER_API_KEY" \ | |
| -H "Content-Type: application/json" \ | |
| -d "{\"commitId\": \"$PREV_COMMIT\"}" | |
| exit 1 |