Files
k8s-game-2048/.github/workflows/deploy-prod.yml

186 lines
7.4 KiB
YAML

name: Deploy to Production
on:
workflow_dispatch:
inputs:
image_tag:
description: 'Image tag to deploy (default: latest)'
required: false
default: 'latest'
confirmation:
description: 'Type "DEPLOY" to confirm production deployment'
required: true
source_environment:
description: 'Source environment (staging or manual)'
required: false
default: 'staging'
workflow_run:
workflows: ["Deploy to Staging"]
types:
- completed
branches: [ main, master ]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
deploy-prod:
name: Deploy to Production
runs-on: ubuntu-latest
if: |
(github.event_name == 'workflow_dispatch' && github.event.inputs.confirmation == 'DEPLOY') ||
(github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success')
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set image tag
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
IMAGE_TAG="${{ github.event.inputs.image_tag || 'latest' }}"
else
# For auto-promotion, use the latest successful build
IMAGE_TAG="main-$(echo "${{ github.sha }}" | cut -c1-7)"
fi
echo "IMAGE_TAG=$IMAGE_TAG" >> $GITHUB_ENV
echo "Deploying image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:$IMAGE_TAG"
- name: Deploy to production via webhook (Blue-Green)
run: |
echo "🚀 Triggering blue-green webhook deployment to production..."
# Prepare deployment payload
PAYLOAD=$(cat <<EOF
{
"environment": "production",
"image": "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.IMAGE_TAG }}",
"namespace": "game-2048-prod",
"service_name": "game-2048-prod",
"deployment_id": "${{ github.run_id }}-${{ github.run_attempt }}",
"commit_sha": "${{ github.sha }}",
"triggered_by": "${{ github.actor }}",
"timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
"auto_promotion": "${{ github.event_name == 'workflow_run' }}",
"deployment_strategy": "blue-green",
"traffic_split": {
"initial": 10,
"intermediate": 50,
"final": 100
}
}
EOF
)
# Generate HMAC signature for webhook security
SIGNATURE=$(echo -n "$PAYLOAD" | openssl dgst -sha256 -hmac "${{ secrets.WEBHOOK_SECRET }}" -binary | base64)
# Send webhook
HTTP_CODE=$(curl -s -o /tmp/webhook_response.json -w "%{http_code}" \
-X POST \
-H "Content-Type: application/json" \
-H "X-Signature-SHA256: sha256=$SIGNATURE" \
-H "X-GitHub-Event: deployment" \
-H "X-GitHub-Delivery: ${{ github.run_id }}" \
-d "$PAYLOAD" \
"${{ secrets.PROD_WEBHOOK_URL }}")
echo "Webhook response code: $HTTP_CODE"
cat /tmp/webhook_response.json || echo "No response body"
if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 300 ]; then
echo "✅ Webhook deployment triggered successfully!"
else
echo "❌ Webhook deployment failed with code: $HTTP_CODE"
exit 1
fi
- name: Wait for blue-green deployment phases
run: |
echo "⏳ Waiting for blue-green deployment phases..."
echo "Phase 1: Initial deployment (10% traffic) - 2 minutes"
sleep 120
echo "Phase 2: Intermediate traffic split (50%) - 2 minutes"
sleep 120
echo "Phase 3: Full traffic switch (100%) - 1 minute"
sleep 60
echo "✅ Blue-green deployment phases completed"
- name: Production health check
run: |
echo "🏥 Performing comprehensive production health check..."
MAX_RETRIES=10
RETRY_COUNT=0
# Get the canonical Knative domain for health check
HEALTH_URL="https://game-2048-prod.game-2048-prod.${{ secrets.KNATIVE_DOMAIN }}"
while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do
echo "Attempt $((RETRY_COUNT + 1))/$MAX_RETRIES - Checking: $HEALTH_URL"
# Check if service responds
if curl -f -s --max-time 10 "$HEALTH_URL" > /dev/null; then
echo "✅ Basic health check passed!"
# Additional production validations
echo "🔍 Running extended production validations..."
# Check response time
RESPONSE_TIME=$(curl -o /dev/null -s -w '%{time_total}' "$HEALTH_URL")
echo "Response time: ${RESPONSE_TIME}s"
# Check if response contains expected content
if curl -s --max-time 10 "$HEALTH_URL" | grep -q "2048"; then
echo "✅ Content validation passed!"
echo "🌐 Production application is live at: $HEALTH_URL"
exit 0
else
echo "⚠️ Content validation failed, retrying..."
fi
else
echo "⚠️ Health check failed, retrying in 20 seconds..."
sleep 20
RETRY_COUNT=$((RETRY_COUNT + 1))
fi
done
echo "❌ Production health check failed after $MAX_RETRIES attempts"
echo "The deployment webhook was sent successfully, but the service is not responding correctly"
echo "Please check your cluster logs and consider rolling back"
exit 1
- name: Production deployment summary
if: always()
run: |
echo "## 🚀 Production Deployment Summary" >> $GITHUB_STEP_SUMMARY
echo "- **Environment:** Production" >> $GITHUB_STEP_SUMMARY
echo "- **Image:** \`${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.IMAGE_TAG }}\`" >> $GITHUB_STEP_SUMMARY
echo "- **Deployment Method:** Webhook-based Blue-Green" >> $GITHUB_STEP_SUMMARY
echo "- **Strategy:** 10% → 50% → 100% traffic split" >> $GITHUB_STEP_SUMMARY
echo "- **Triggered by:** ${{ github.actor }}" >> $GITHUB_STEP_SUMMARY
echo "- **Commit:** ${{ github.sha }}" >> $GITHUB_STEP_SUMMARY
if [ "${{ github.event_name }}" = "workflow_run" ]; then
echo "- **Type:** Auto-promotion from Staging" >> $GITHUB_STEP_SUMMARY
else
echo "- **Type:** Manual deployment with confirmation" >> $GITHUB_STEP_SUMMARY
fi
if [ "${{ job.status }}" = "success" ]; then
echo "- **Status:** ✅ **LIVE IN PRODUCTION**" >> $GITHUB_STEP_SUMMARY
echo "- **URL:** https://game-2048-prod.game-2048-prod.${{ secrets.KNATIVE_DOMAIN }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### 🎉 Production is Live!" >> $GITHUB_STEP_SUMMARY
echo "- 🎮 [Play the game](https://game-2048-prod.game-2048-prod.${{ secrets.KNATIVE_DOMAIN }})" >> $GITHUB_STEP_SUMMARY
echo "- 🧪 [Run smoke tests](https://github.com/${{ github.repository }}/actions/workflows/smoke-test.yml)" >> $GITHUB_STEP_SUMMARY
else
echo "- **Status:** ❌ Failed" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### ⚠️ Production Deployment Failed" >> $GITHUB_STEP_SUMMARY
echo "Please check the logs and consider manual intervention or rollback." >> $GITHUB_STEP_SUMMARY
fi