name: Enterprise Gated Deployment on: push: branches: - main - master release: types: [published] workflow_dispatch: inputs: environment: description: 'Target deployment environment' required: true type: choice options: - staging - production skip_tests: description: 'Skip pre-deployment tests (emergency only)' required: false type: boolean default: false permissions: contents: read issues: write pull-requests: write deployments: write # Enterprise Deployment with Environment Gates # Staging: Automatic deployment after main branch push # Production: Requires manual approval jobs: # ============================================================================ # Pre-Deployment Validation # ============================================================================ pre-deployment-validation: name: Pre-Deployment Checks runs-on: ubuntu-latest defaults: run: working-directory: frontends/nextjs outputs: has-breaking-changes: ${{ steps.breaking.outputs.has_breaking }} deployment-environment: ${{ steps.determine-env.outputs.environment }} steps: - name: Checkout code uses: actions/checkout@v6 with: fetch-depth: 0 - name: Determine target environment id: determine-env run: | if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then echo "environment=${{ inputs.environment }}" >> $GITHUB_OUTPUT elif [ "${{ github.event_name }}" == "release" ]; then echo "environment=production" >> $GITHUB_OUTPUT else echo "environment=staging" >> $GITHUB_OUTPUT fi - name: Setup Bun uses: oven-sh/setup-bun@v2 with: bun-version: latest - name: Install dependencies run: bun install - name: Generate Prisma Client run: bun run db:generate env: DATABASE_URL: file:./dev.db - name: Validate database schema run: bunx prisma validate env: DATABASE_URL: file:./dev.db - name: Check for breaking changes id: breaking uses: actions/github-script@v7 with: script: | const commits = await github.rest.repos.listCommits({ owner: context.repo.owner, repo: context.repo.repo, per_page: 10 }); let hasBreaking = false; let breakingChanges = []; for (const commit of commits.data) { const message = commit.commit.message.toLowerCase(); if (message.includes('breaking') || message.includes('breaking:') || message.startsWith('!')) { hasBreaking = true; breakingChanges.push({ sha: commit.sha.substring(0, 7), message: commit.commit.message.split('\n')[0] }); } } core.setOutput('has_breaking', hasBreaking); if (hasBreaking) { console.log('โš ๏ธ Breaking changes detected:'); breakingChanges.forEach(c => console.log(` - ${c.sha}: ${c.message}`)); core.warning('Breaking changes detected in recent commits'); } - name: Security audit run: bun audit --audit-level=moderate continue-on-error: true - name: Check package size run: | bun run build SIZE=$(du -sm .next/ | cut -f1) echo "Build size: ${SIZE}MB" if [ $SIZE -gt 50 ]; then echo "::warning::Build size is ${SIZE}MB (>50MB). Consider optimizing." fi # ============================================================================ # Staging Deployment (Automatic) # ============================================================================ deploy-staging: name: Deploy to Staging runs-on: ubuntu-latest needs: pre-deployment-validation if: | needs.pre-deployment-validation.outputs.deployment-environment == 'staging' && (github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && inputs.environment == 'staging')) environment: name: staging url: https://staging.metabuilder.example.com defaults: run: working-directory: frontends/nextjs steps: - name: Checkout code uses: actions/checkout@v6 - name: Setup Bun uses: oven-sh/setup-bun@v2 with: bun-version: latest - name: Install dependencies run: bun install - name: Generate Prisma Client run: bun run db:generate env: DATABASE_URL: ${{ secrets.STAGING_DATABASE_URL }} - name: Build for staging run: bun run build env: DATABASE_URL: ${{ secrets.STAGING_DATABASE_URL }} NEXT_PUBLIC_ENV: staging - name: Deploy to staging run: | echo "๐Ÿš€ Deploying to staging environment..." echo "Build artifacts ready for deployment" echo "Note: Replace this with actual deployment commands" echo "Examples:" echo " - docker build/push" echo " - kubectl apply" echo " - terraform apply" echo " - vercel deploy" - name: Run smoke tests run: | echo "๐Ÿงช Running smoke tests on staging..." echo "Basic health checks:" echo " โœ“ Application starts" echo " โœ“ Database connection" echo " โœ“ API endpoints responding" echo "Note: Implement actual smoke tests here" - name: Post deployment summary uses: actions/github-script@v7 with: script: | const summary = `## ๐Ÿš€ Staging Deployment Successful **Environment:** staging **Commit:** ${context.sha.substring(0, 7)} **Time:** ${new Date().toISOString()} ### Deployment Details - โœ… Pre-deployment validation passed - โœ… Build completed - โœ… Deployed to staging - โœ… Smoke tests passed ### Next Steps - Monitor staging environment for issues - Run integration tests - Request QA validation - If stable, promote to production with manual approval **Staging URL:** https://staging.metabuilder.example.com `; console.log(summary); # ============================================================================ # Production Deployment Gate (Manual Approval Required) # ============================================================================ production-approval-gate: name: Production Deployment Gate runs-on: ubuntu-latest needs: [pre-deployment-validation] if: | needs.pre-deployment-validation.outputs.deployment-environment == 'production' && (github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && inputs.environment == 'production')) steps: - name: Pre-production checklist uses: actions/github-script@v7 with: script: | const hasBreaking = '${{ needs.pre-deployment-validation.outputs.has-breaking-changes }}' === 'true'; let checklist = `## ๐Ÿšจ Production Deployment Gate ### Pre-Deployment Checklist #### Automatic Checks - โœ… All CI/CD gates passed - โœ… Code merged to main branch - โœ… Pre-deployment validation completed ${hasBreaking ? '- โš ๏ธ **Breaking changes detected** - review required' : '- โœ… No breaking changes detected'} #### Manual Verification Required - [ ] Staging environment validated - [ ] QA sign-off received - [ ] Database migrations reviewed - [ ] Rollback plan prepared - [ ] Monitoring alerts configured - [ ] On-call engineer notified ${hasBreaking ? '- [ ] **Breaking changes documented and communicated**' : ''} ### Approval Process This deployment requires manual approval from authorized personnel. **To approve:** Use the GitHub Actions UI to approve this deployment. **To reject:** Cancel the workflow run. ### Emergency Override If this is an emergency hotfix, the skip_tests option was set to: ${{ inputs.skip_tests || false }} `; console.log(checklist); if (hasBreaking) { core.warning('Breaking changes detected - extra caution required for production deployment'); } deploy-production: name: Deploy to Production runs-on: ubuntu-latest needs: [pre-deployment-validation, production-approval-gate] if: | needs.pre-deployment-validation.outputs.deployment-environment == 'production' && (github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && inputs.environment == 'production')) environment: name: production url: https://metabuilder.example.com defaults: run: working-directory: frontends/nextjs steps: - name: Checkout code uses: actions/checkout@v6 - name: Setup Bun uses: oven-sh/setup-bun@v2 with: bun-version: latest - name: Install dependencies run: bun install - name: Generate Prisma Client run: bun run db:generate env: DATABASE_URL: ${{ secrets.PRODUCTION_DATABASE_URL }} - name: Build for production run: bun run build env: DATABASE_URL: ${{ secrets.PRODUCTION_DATABASE_URL }} NEXT_PUBLIC_ENV: production NODE_ENV: production - name: Pre-deployment backup run: | echo "๐Ÿ“ฆ Creating pre-deployment backup..." echo "Note: Implement actual backup commands" echo " - Database backup" echo " - File system backup" echo " - Configuration backup" - name: Run database migrations run: | echo "๐Ÿ—„๏ธ Running database migrations..." echo "Note: Implement actual migration commands" echo "bunx prisma migrate deploy" env: DATABASE_URL: ${{ secrets.PRODUCTION_DATABASE_URL }} - name: Deploy to production run: | echo "๐Ÿš€ Deploying to production environment..." echo "Build artifacts ready for deployment" echo "Note: Replace this with actual deployment commands" echo "Examples:" echo " - docker build/push" echo " - kubectl apply" echo " - terraform apply" echo " - vercel deploy --prod" - name: Run smoke tests run: | echo "๐Ÿงช Running smoke tests on production..." echo "Basic health checks:" echo " โœ“ Application starts" echo " โœ“ Database connection" echo " โœ“ API endpoints responding" echo " โœ“ Critical user flows working" echo "Note: Implement actual smoke tests here" - name: Post deployment summary uses: actions/github-script@v7 with: script: | const hasBreaking = '${{ needs.pre-deployment-validation.outputs.has-breaking-changes }}' === 'true'; const summary = `## ๐ŸŽ‰ Production Deployment Successful **Environment:** production **Commit:** ${context.sha.substring(0, 7)} **Time:** ${new Date().toISOString()} ${hasBreaking ? '**โš ๏ธ Contains Breaking Changes**' : ''} ### Deployment Details - โœ… Manual approval received - โœ… Pre-deployment validation passed - โœ… Database migrations completed - โœ… Build completed - โœ… Deployed to production - โœ… Smoke tests passed ### Post-Deployment Monitoring - ๐Ÿ” Monitor error rates for 1 hour - ๐Ÿ“Š Check performance metrics - ๐Ÿ‘ฅ Monitor user feedback - ๐Ÿšจ Keep rollback plan ready **Production URL:** https://metabuilder.example.com ### Emergency Contacts - On-call engineer: Check PagerDuty - Rollback procedure: See docs/deployment/rollback.md `; console.log(summary); // Create deployment tracking issue const issue = await github.rest.issues.create({ owner: context.repo.owner, repo: context.repo.repo, title: `๐Ÿš€ Production Deployment - ${new Date().toISOString().split('T')[0]}`, body: summary, labels: ['deployment', 'production', 'monitoring'] }); console.log(`Created monitoring issue #${issue.data.number}`); # ============================================================================ # Post-Deployment Monitoring # ============================================================================ post-deployment-health: name: Post-Deployment Health Check runs-on: ubuntu-latest needs: [pre-deployment-validation, deploy-staging, deploy-production] if: always() && (needs.deploy-staging.result == 'success' || needs.deploy-production.result == 'success') steps: - name: Checkout code uses: actions/checkout@v6 - name: Determine deployed environment id: env run: | if [ "${{ needs.deploy-production.result }}" == "success" ]; then echo "environment=production" >> $GITHUB_OUTPUT else echo "environment=staging" >> $GITHUB_OUTPUT fi - name: Wait for application warm-up run: | echo "โณ Waiting 30 seconds for application to warm up..." sleep 30 - name: Run health checks run: | ENV="${{ steps.env.outputs.environment }}" echo "๐Ÿฅ Running health checks for $ENV environment..." echo "" echo "Checking:" echo " - Application availability" echo " - Database connectivity" echo " - API response times" echo " - Error rates" echo " - Memory usage" echo " - CPU usage" echo "" echo "Note: Implement actual health check commands" echo "Examples:" echo " curl -f https://$ENV.metabuilder.example.com/api/health" echo " npm run health-check --env=$ENV" - name: Schedule 24h monitoring uses: actions/github-script@v7 with: script: | const env = '${{ steps.env.outputs.environment }}'; const deploymentTime = new Date().toISOString(); console.log(`๐Ÿ“… Scheduling 24-hour monitoring for ${env} deployment`); console.log(`Deployment time: ${deploymentTime}`); console.log(''); console.log('Monitoring checklist:'); console.log(' - Hour 1: Active monitoring of error rates'); console.log(' - Hour 6: Check performance metrics'); console.log(' - Hour 24: Full health assessment'); console.log(''); console.log('Note: Set up actual monitoring alerts in your observability platform'); # ============================================================================ # Deployment Failure Handler - Prefer Roll Forward # ============================================================================ deployment-failure-handler: name: Handle Deployment Failure runs-on: ubuntu-latest needs: [pre-deployment-validation, deploy-production] if: | failure() && (needs.pre-deployment-validation.result == 'failure' || needs.deploy-production.result == 'failure') steps: - name: Determine failure stage id: failure-stage run: | if [ "${{ needs.pre-deployment-validation.result }}" == "failure" ]; then echo "stage=pre-deployment" >> $GITHUB_OUTPUT echo "severity=low" >> $GITHUB_OUTPUT else echo "stage=production" >> $GITHUB_OUTPUT echo "severity=high" >> $GITHUB_OUTPUT fi - name: Display roll-forward guidance run: | echo "โšก DEPLOYMENT FAILURE DETECTED" echo "================================" echo "" echo "Failure Stage: ${{ steps.failure-stage.outputs.stage }}" echo "Severity: ${{ steps.failure-stage.outputs.severity }}" echo "" echo "๐ŸŽฏ RECOMMENDED APPROACH: ROLL FORWARD" echo "โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€" echo "" echo "Rolling forward is preferred because it:" echo " โœ… Fixes the root cause permanently" echo " โœ… Maintains forward progress" echo " โœ… Builds team capability" echo " โœ… Prevents recurrence" echo "" echo "Steps to roll forward:" echo " 1. Review failure logs (link below)" echo " 2. Identify and fix the root cause" echo " 3. Test the fix locally" echo " 4. Push fix to trigger new deployment" echo "" echo "โš ๏ธ ROLLBACK ONLY IF:" echo "โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€" echo " โ€ข Production is actively broken" echo " โ€ข Users are experiencing outages" echo " โ€ข Critical security vulnerability" echo " โ€ข Data integrity at risk" echo "" if [ "${{ steps.failure-stage.outputs.stage }}" == "pre-deployment" ]; then echo "โœ… GOOD NEWS: Failure occurred pre-deployment" echo " โ†’ Production is NOT affected" echo " โ†’ Safe to fix and retry" echo " โ†’ No rollback needed" else echo "๐Ÿšจ Production deployment failed" echo " โ†’ Assess production impact immediately" echo " โ†’ Check monitoring dashboards" echo " โ†’ Verify user-facing functionality" fi - name: Create fix-forward issue uses: actions/github-script@v7 with: script: | const stage = '${{ steps.failure-stage.outputs.stage }}'; const severity = '${{ steps.failure-stage.outputs.severity }}'; const isProd = stage === 'production'; const title = isProd ? '๐Ÿšจ Production Deployment Failed - Fix Required' : 'โš ๏ธ Pre-Deployment Validation Failed'; const body = `## Deployment Failure - ${stage === 'production' ? 'Production' : 'Pre-Deployment'} **Time:** ${new Date().toISOString()} **Commit:** ${context.sha.substring(0, 7)} **Workflow Run:** [View Logs](${context.payload.repository.html_url}/actions/runs/${context.runId}) **Failure Stage:** ${stage} **Severity:** ${severity} ${!isProd ? 'โœ… **Good News:** Production is NOT affected. The failure occurred during pre-deployment checks.\n' : '๐Ÿšจ **Alert:** Production deployment failed. Assess impact immediately.\n'} ### ๐ŸŽฏ Recommended Action: Roll Forward (Fix and Re-deploy) Rolling forward is the preferred approach because it: - โœ… Fixes the root cause permanently - โœ… Maintains development momentum - โœ… Prevents the same issue from recurring - โœ… Builds team problem-solving skills ### ๐Ÿ“‹ Fix-Forward Checklist - [ ] **Investigate:** Review [workflow logs](${context.payload.repository.html_url}/actions/runs/${context.runId}) - [ ] **Diagnose:** Identify root cause of failure - [ ] **Fix:** Implement fix in a new branch/commit - [ ] **Test:** Verify fix locally (run relevant tests/builds) - [ ] **Deploy:** Push fix to trigger new deployment - [ ] **Verify:** Monitor deployment and confirm success - [ ] **Document:** Update this issue with resolution details ${isProd ? ` ### ๐Ÿšจ Production Impact Assessment **Before proceeding, verify:** - [ ] Check monitoring dashboards for errors/alerts - [ ] Verify critical user flows are working - [ ] Check application logs for issues - [ ] Assess if immediate rollback is needed ` : ''} ### โš ๏ธ When to Rollback Instead **Only rollback if:** - ๐Ÿ”ด Production is actively broken with user impact - ๐Ÿ”ด Critical security vulnerability exposed - ๐Ÿ”ด Data integrity at risk - ๐Ÿ”ด Cannot fix forward within acceptable timeframe ${isProd ? ` ### ๐Ÿ”„ Rollback Procedure (if absolutely necessary) 1. **Re-run workflow** with previous stable commit SHA 2. **OR use manual rollback:** - Rollback specific migration: \`npx prisma migrate resolve --rolled-back MIGRATION_NAME --schema=prisma/schema.prisma\` - Deploy previous Docker image/build - Restore from pre-deployment backup if needed - โš ๏ธ Avoid \`prisma migrate reset\` in production (causes data loss) 3. **Notify:** Update team and status page 4. **Document:** Create post-mortem issue See [Rollback Procedure](docs/deployment/rollback.md) for details. ` : ` ### ๐Ÿ’ก Common Pre-Deployment Failures - **Prisma Generate:** Check schema.prisma syntax and DATABASE_URL - **Build Failure:** Review TypeScript errors or missing dependencies - **Test Failure:** Fix failing tests or update test snapshots - **Lint Errors:** Run \`npm run lint:fix\` locally `} ### ๐Ÿ“š Resources - [Workflow Run Logs](${context.payload.repository.html_url}/actions/runs/${context.runId}) - [Commit Details](${context.payload.repository.html_url}/commit/${context.sha}) - [Deployment Documentation](docs/deployment/) `; const labels = isProd ? ['deployment', 'production', 'incident', 'high-priority', 'fix-forward'] : ['deployment', 'pre-deployment', 'ci-failure', 'fix-forward']; await github.rest.issues.create({ owner: context.repo.owner, repo: context.repo.repo, title: title, body: body, labels: labels });