Files
miracles_in_motion/.github/workflows/production-deployment.yml

249 lines
9.1 KiB
YAML

name: Production Deployment
on:
push:
branches: [ main ]
workflow_dispatch:
inputs:
custom_domain:
description: 'Custom domain name'
required: false
default: 'miraclesinmotion.org'
force_deploy:
description: 'Force deployment even if tests fail'
required: false
default: 'false'
env:
NODE_VERSION: '22'
AZURE_STATIC_WEB_APPS_API_TOKEN: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN }}
AZURE_CREDENTIALS: ${{ secrets.AZURE_CREDENTIALS }}
jobs:
build-and-test:
runs-on: ubuntu-latest
name: Build and Test
steps:
- uses: actions/checkout@v4
with:
submodules: true
lfs: false
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: Install main dependencies
run: npm install --legacy-peer-deps
- name: Install API dependencies
run: |
cd api
npm install
cd ..
- name: Run linting
run: npm run lint
continue-on-error: true
- name: Run tests
run: npx vitest run --reporter=verbose
continue-on-error: ${{ github.event.inputs.force_deploy == 'true' }}
- name: Build application
run: npm run build
- name: Build API
run: |
cd api
npm run build || npm run tsc
cd ..
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: build-files
path: |
dist/
api/
staticwebapp.config.json
deploy-infrastructure:
runs-on: ubuntu-latest
needs: build-and-test
name: Deploy Infrastructure
outputs:
static-web-app-name: ${{ steps.deploy.outputs.staticWebAppName }}
function-app-name: ${{ steps.deploy.outputs.functionAppName }}
static-web-app-url: ${{ steps.deploy.outputs.staticWebAppUrl }}
steps:
- uses: actions/checkout@v4
- name: Azure Login
uses: azure/login@v2
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Create Resource Group
run: |
az group create \
--name rg-miraclesinmotion-prod \
--location "East US"
- name: Deploy Infrastructure
id: deploy
run: |
DEPLOYMENT_NAME="mim-prod-$(date +%Y%m%d-%H%M%S)"
# Deploy infrastructure
DEPLOYMENT_OUTPUT=$(az deployment group create \
--resource-group rg-miraclesinmotion-prod \
--template-file infrastructure/main-production.bicep \
--parameters infrastructure/main-production.parameters.json \
--parameters stripePublicKey="${{ secrets.STRIPE_PUBLIC_KEY }}" \
--parameters customDomainName="${{ github.event.inputs.custom_domain || 'miraclesinmotion.org' }}" \
--parameters enableCustomDomain=true \
--name $DEPLOYMENT_NAME \
--output json)
# Extract outputs
STATIC_WEB_APP_NAME=$(echo $DEPLOYMENT_OUTPUT | jq -r '.properties.outputs.staticWebAppName.value')
FUNCTION_APP_NAME=$(echo $DEPLOYMENT_OUTPUT | jq -r '.properties.outputs.functionAppName.value')
STATIC_WEB_APP_URL=$(echo $DEPLOYMENT_OUTPUT | jq -r '.properties.outputs.staticWebAppUrl.value')
# Set outputs
echo "staticWebAppName=$STATIC_WEB_APP_NAME" >> $GITHUB_OUTPUT
echo "functionAppName=$FUNCTION_APP_NAME" >> $GITHUB_OUTPUT
echo "staticWebAppUrl=$STATIC_WEB_APP_URL" >> $GITHUB_OUTPUT
echo "✅ Infrastructure deployed successfully"
echo "📱 Static Web App: $STATIC_WEB_APP_NAME"
echo "⚡ Function App: $FUNCTION_APP_NAME"
echo "🌐 URL: $STATIC_WEB_APP_URL"
deploy-application:
runs-on: ubuntu-latest
needs: deploy-infrastructure
name: Deploy Application
environment:
name: production
url: ${{ needs.deploy-infrastructure.outputs.static-web-app-url }}
steps:
- uses: actions/checkout@v4
- name: Download build artifacts
uses: actions/download-artifact@v4
with:
name: build-files
- name: Azure Login
uses: azure/login@v2
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Get Static Web App Deployment Token
id: swa-token
run: |
DEPLOYMENT_TOKEN=$(az staticwebapp secrets list \
--name ${{ needs.deploy-infrastructure.outputs.static-web-app-name }} \
--resource-group rg-miraclesinmotion-prod \
--query "properties.apiKey" \
--output tsv)
echo "::add-mask::$DEPLOYMENT_TOKEN"
echo "token=$DEPLOYMENT_TOKEN" >> $GITHUB_OUTPUT
- name: Setup Node.js for SWA CLI
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: Install SWA CLI
run: npm install -g @azure/static-web-apps-cli
- name: Deploy to Static Web App
run: |
swa deploy ./dist \
--api-location ./api \
--env production \
--deployment-token ${{ steps.swa-token.outputs.token }}
- name: Deploy Azure Functions
run: |
# Create deployment package
cd api
zip -r ../api-deployment.zip . -x "node_modules/*" "*.test.*" "*.md"
cd ..
# Deploy functions
az functionapp deployment source config-zip \
--resource-group rg-miraclesinmotion-prod \
--name ${{ needs.deploy-infrastructure.outputs.function-app-name }} \
--src api-deployment.zip
- name: Warm up application
run: |
echo "🔥 Warming up the deployed application..."
curl -s ${{ needs.deploy-infrastructure.outputs.static-web-app-url }} > /dev/null
curl -s ${{ needs.deploy-infrastructure.outputs.static-web-app-url }}/#/portals > /dev/null
echo "✅ Application warmed up successfully"
post-deployment:
runs-on: ubuntu-latest
needs: [deploy-infrastructure, deploy-application]
name: Post-Deployment Tasks
steps:
- name: Run smoke tests
run: |
echo "🧪 Running smoke tests..."
# Test main page
STATUS=$(curl -s -o /dev/null -w "%{http_code}" ${{ needs.deploy-infrastructure.outputs.static-web-app-url }})
if [ $STATUS -eq 200 ]; then
echo "✅ Main page is accessible"
else
echo "❌ Main page returned status: $STATUS"
exit 1
fi
# Test portals page
STATUS=$(curl -s -o /dev/null -w "%{http_code}" ${{ needs.deploy-infrastructure.outputs.static-web-app-url }}/#/portals)
if [ $STATUS -eq 200 ]; then
echo "✅ Portals page is accessible"
else
echo "❌ Portals page returned status: $STATUS"
exit 1
fi
echo "🎉 All smoke tests passed!"
- name: Create deployment summary
run: |
echo "## 🚀 Production Deployment Complete" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### 📊 Deployment Details" >> $GITHUB_STEP_SUMMARY
echo "- **Static Web App**: ${{ needs.deploy-infrastructure.outputs.static-web-app-name }}" >> $GITHUB_STEP_SUMMARY
echo "- **Primary URL**: ${{ needs.deploy-infrastructure.outputs.static-web-app-url }}" >> $GITHUB_STEP_SUMMARY
echo "- **Portal Access**: ${{ needs.deploy-infrastructure.outputs.static-web-app-url }}/#/portals" >> $GITHUB_STEP_SUMMARY
echo "- **Custom Domain**: https://${{ github.event.inputs.custom_domain || 'miraclesinmotion.org' }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### 🔗 Quick Links" >> $GITHUB_STEP_SUMMARY
echo "- [🏠 Main Site](${{ needs.deploy-infrastructure.outputs.static-web-app-url }})" >> $GITHUB_STEP_SUMMARY
echo "- [🚪 Portals](${{ needs.deploy-infrastructure.outputs.static-web-app-url }}/#/portals)" >> $GITHUB_STEP_SUMMARY
echo "- [💰 Donate](${{ needs.deploy-infrastructure.outputs.static-web-app-url }}/#/donate)" >> $GITHUB_STEP_SUMMARY
echo "- [🤝 Volunteer](${{ needs.deploy-infrastructure.outputs.static-web-app-url }}/#/volunteers)" >> $GITHUB_STEP_SUMMARY
echo "- [📊 Analytics](${{ needs.deploy-infrastructure.outputs.static-web-app-url }}/#/analytics)" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### 📋 Next Steps" >> $GITHUB_STEP_SUMMARY
echo "1. Configure DNS records for custom domain" >> $GITHUB_STEP_SUMMARY
echo "2. Update Stripe webhook endpoints" >> $GITHUB_STEP_SUMMARY
echo "3. Test all portal functionality" >> $GITHUB_STEP_SUMMARY
echo "4. Monitor application performance" >> $GITHUB_STEP_SUMMARY
- name: Notify team
if: success()
run: |
echo "🎉 Production deployment completed successfully!"
echo "🌐 Application is live at: ${{ needs.deploy-infrastructure.outputs.static-web-app-url }}"
echo "🚪 Portals are accessible at: ${{ needs.deploy-infrastructure.outputs.static-web-app-url }}/#/portals"