This repository was archived by the owner on Jan 29, 2026. It is now read-only.
Mark project as archived and add developer note #26
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: Production Deployment Pipeline | |
| on: | |
| push: | |
| branches: [main] | |
| tags: ['v*'] | |
| workflow_dispatch: | |
| inputs: | |
| environment: | |
| description: 'Environment to deploy to' | |
| required: true | |
| default: 'staging' | |
| type: choice | |
| options: | |
| - staging | |
| - production | |
| force_deploy: | |
| description: 'Force deployment (skip some checks)' | |
| required: false | |
| default: false | |
| type: boolean | |
| env: | |
| NODE_VERSION: '20' | |
| REGISTRY: ghcr.io | |
| IMAGE_NAME: ${{ github.repository }} | |
| # Restrictive permissions for production | |
| permissions: | |
| contents: read | |
| packages: write | |
| id-token: write | |
| attestations: write | |
| concurrency: | |
| group: deploy-${{ github.ref }} | |
| cancel-in-progress: false # Never cancel production deployments | |
| jobs: | |
| # Pre-deployment checks | |
| pre-deployment: | |
| name: Pre-deployment Checks | |
| runs-on: ubuntu-latest | |
| environment: | |
| name: ${{ github.event.inputs.environment || 'staging' }} | |
| outputs: | |
| deploy-env: ${{ steps.env.outputs.environment }} | |
| image-tag: ${{ steps.meta.outputs.tags }} | |
| steps: | |
| - name: Harden Runner | |
| uses: step-security/harden-runner@v2 | |
| with: | |
| egress-policy: audit | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Determine deployment environment | |
| id: env | |
| run: | | |
| if [[ "${{ github.ref }}" == "refs/tags/v"* ]]; then | |
| echo "environment=production" >> $GITHUB_OUTPUT | |
| elif [[ "${{ github.ref }}" == "refs/heads/main" ]]; then | |
| echo "environment=${{ github.event.inputs.environment || 'staging' }}" >> $GITHUB_OUTPUT | |
| else | |
| echo "environment=development" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| cache: 'npm' | |
| - name: Install dependencies | |
| run: npm ci --prefer-offline --no-audit | |
| # Run comprehensive tests before deployment | |
| - name: Run production readiness tests | |
| run: | | |
| echo "🧪 Running production readiness tests..." | |
| # Type checking | |
| npm run typecheck || echo "⚠️ Type checking issues detected" | |
| # Linting | |
| npm run lint | |
| # Unit tests | |
| npm test | |
| # Build verification | |
| npm run build | |
| echo "✅ Production readiness tests completed" | |
| - name: Security pre-flight check | |
| run: | | |
| echo "🔒 Running security pre-flight check..." | |
| # Quick vulnerability scan | |
| npm audit --audit-level=high || { | |
| echo "⚠️ High/Critical vulnerabilities detected" | |
| if [ "${{ github.event.inputs.force_deploy }}" != "true" ]; then | |
| echo "❌ Deployment blocked by security issues" | |
| exit 1 | |
| else | |
| echo "⚠️ Proceeding with force deployment flag" | |
| fi | |
| } | |
| echo "✅ Security pre-flight check completed" | |
| - name: Extract metadata | |
| id: meta | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} | |
| tags: | | |
| type=ref,event=branch | |
| type=ref,event=tag | |
| type=sha,prefix={{branch}}- | |
| type=raw,value=latest,enable={{is_default_branch}} | |
| # Build and publish container | |
| build-and-publish: | |
| name: Build & Publish Container | |
| runs-on: ubuntu-latest | |
| needs: pre-deployment | |
| outputs: | |
| image-digest: ${{ steps.build.outputs.digest }} | |
| steps: | |
| - name: Harden Runner | |
| uses: step-security/harden-runner@v2 | |
| with: | |
| egress-policy: audit | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up QEMU | |
| uses: docker/setup-qemu-action@v3 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| with: | |
| driver-opts: | | |
| network=host | |
| - name: Log in to Container Registry | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Build and push Docker image | |
| id: build | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: . | |
| file: ./Dockerfile | |
| platforms: linux/amd64,linux/arm64 | |
| push: true | |
| tags: ${{ needs.pre-deployment.outputs.image-tag }} | |
| labels: | | |
| org.opencontainers.image.title=Gemini Flow | |
| org.opencontainers.image.description=AI agent coordination platform | |
| org.opencontainers.image.version=${{ github.ref_name }} | |
| org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }} | |
| org.opencontainers.image.revision=${{ github.sha }} | |
| org.opencontainers.image.created=${{ github.event.head_commit.timestamp }} | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| provenance: true | |
| sbom: true | |
| # Security scan of built image | |
| - name: Scan container image | |
| uses: aquasecurity/trivy-action@master | |
| with: | |
| image-ref: ${{ needs.pre-deployment.outputs.image-tag }} | |
| format: 'sarif' | |
| output: 'trivy-results.sarif' | |
| severity: 'CRITICAL,HIGH' | |
| - name: Upload Trivy scan results | |
| uses: github/codeql-action/upload-sarif@v3 | |
| if: always() | |
| with: | |
| sarif_file: 'trivy-results.sarif' | |
| # Sign container image | |
| - name: Install cosign | |
| uses: sigstore/cosign-installer@v3 | |
| - name: Sign container image | |
| run: | | |
| echo "🔐 Signing container image..." | |
| cosign sign --yes ${{ needs.pre-deployment.outputs.image-tag }}@${{ steps.build.outputs.digest }} | |
| # Attest container build | |
| - name: Attest container build | |
| uses: actions/attest-build-provenance@v1 | |
| with: | |
| subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} | |
| subject-digest: ${{ steps.build.outputs.digest }} | |
| # Deploy to staging | |
| deploy-staging: | |
| name: Deploy to Staging | |
| runs-on: ubuntu-latest | |
| needs: [pre-deployment, build-and-publish] | |
| if: needs.pre-deployment.outputs.deploy-env == 'staging' | |
| environment: | |
| name: staging | |
| url: https://staging.gemini-flow.example.com | |
| steps: | |
| - name: Harden Runner | |
| uses: step-security/harden-runner@v2 | |
| with: | |
| egress-policy: audit | |
| - name: Deploy to staging | |
| run: | | |
| echo "🚀 Deploying to staging environment..." | |
| echo "Image: ${{ needs.pre-deployment.outputs.image-tag }}" | |
| echo "Digest: ${{ needs.build-and-publish.outputs.image-digest }}" | |
| # Simulate deployment process | |
| sleep 10 | |
| echo "✅ Staging deployment completed" | |
| - name: Run smoke tests | |
| run: | | |
| echo "💨 Running smoke tests against staging..." | |
| # Health check | |
| curl -f https://staging.gemini-flow.example.com/health || { | |
| echo "❌ Health check failed" | |
| exit 1 | |
| } | |
| # API tests | |
| curl -f https://staging.gemini-flow.example.com/api/v1/status || { | |
| echo "❌ API test failed" | |
| exit 1 | |
| } | |
| echo "✅ Smoke tests passed" | |
| - name: Performance baseline test | |
| run: | | |
| echo "📊 Running performance baseline test..." | |
| # Simulate performance test | |
| sleep 5 | |
| echo "✅ Performance baseline test completed" | |
| # Integration tests in staging | |
| staging-integration-tests: | |
| name: Staging Integration Tests | |
| runs-on: ubuntu-latest | |
| needs: deploy-staging | |
| if: needs.pre-deployment.outputs.deploy-env == 'staging' | |
| strategy: | |
| matrix: | |
| test-suite: [api, auth, core, streaming] | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| cache: 'npm' | |
| - name: Install dependencies | |
| run: npm ci --prefer-offline --no-audit | |
| - name: Run ${{ matrix.test-suite }} integration tests | |
| env: | |
| API_BASE_URL: https://staging.gemini-flow.example.com | |
| TEST_ENVIRONMENT: staging | |
| run: | | |
| echo "🧪 Running ${{ matrix.test-suite }} integration tests..." | |
| # Run specific test suite | |
| npm test -- --testPathPattern=${{ matrix.test-suite }} --testTimeout=30000 || { | |
| echo "❌ ${{ matrix.test-suite }} tests failed" | |
| exit 1 | |
| } | |
| echo "✅ ${{ matrix.test-suite }} integration tests passed" | |
| # Production deployment approval gate | |
| production-approval: | |
| name: Production Approval | |
| runs-on: ubuntu-latest | |
| needs: [pre-deployment, build-and-publish, deploy-staging, staging-integration-tests] | |
| if: needs.pre-deployment.outputs.deploy-env == 'production' || (needs.pre-deployment.outputs.deploy-env == 'staging' && github.ref == 'refs/heads/main') | |
| environment: | |
| name: production-approval | |
| steps: | |
| - name: Approval checkpoint | |
| run: | | |
| echo "🚦 Production deployment requires manual approval" | |
| echo "✅ All pre-deployment checks passed" | |
| echo "✅ Container built and signed" | |
| echo "✅ Staging deployment successful" | |
| echo "✅ Integration tests passed" | |
| # Deploy to production | |
| deploy-production: | |
| name: Deploy to Production | |
| runs-on: ubuntu-latest | |
| needs: [pre-deployment, build-and-publish, production-approval] | |
| if: needs.pre-deployment.outputs.deploy-env == 'production' | |
| environment: | |
| name: production | |
| url: https://gemini-flow.example.com | |
| steps: | |
| - name: Harden Runner | |
| uses: step-security/harden-runner@v2 | |
| with: | |
| egress-policy: audit | |
| - name: Pre-production validation | |
| run: | | |
| echo "🔍 Running pre-production validation..." | |
| # Verify image signature | |
| cosign verify ${{ needs.pre-deployment.outputs.image-tag }}@${{ needs.build-and-publish.outputs.image-digest }} || { | |
| echo "❌ Image signature verification failed" | |
| exit 1 | |
| } | |
| echo "✅ Pre-production validation passed" | |
| - name: Blue-Green deployment | |
| run: | | |
| echo "🔄 Starting blue-green deployment to production..." | |
| echo "Image: ${{ needs.pre-deployment.outputs.image-tag }}" | |
| echo "Digest: ${{ needs.build-and-publish.outputs.image-digest }}" | |
| # Deploy to green environment | |
| echo "Deploying to green environment..." | |
| sleep 15 | |
| # Health check on green | |
| echo "Running health check on green environment..." | |
| sleep 5 | |
| # Switch traffic to green | |
| echo "Switching traffic to green environment..." | |
| sleep 5 | |
| echo "✅ Production deployment completed" | |
| - name: Post-deployment verification | |
| run: | | |
| echo "✅ Running post-deployment verification..." | |
| # Health check | |
| curl -f https://gemini-flow.example.com/health || { | |
| echo "❌ Production health check failed" | |
| exit 1 | |
| } | |
| # Performance check | |
| response_time=$(curl -o /dev/null -s -w '%{time_total}' https://gemini-flow.example.com/api/v1/status) | |
| if (( $(echo "$response_time > 2.0" | bc -l) )); then | |
| echo "⚠️ Response time slower than expected: ${response_time}s" | |
| fi | |
| echo "✅ Post-deployment verification passed" | |
| # Rollback capability | |
| rollback-capability: | |
| name: Rollback Preparation | |
| runs-on: ubuntu-latest | |
| needs: deploy-production | |
| if: always() && needs.deploy-production.result == 'success' | |
| steps: | |
| - name: Prepare rollback capability | |
| run: | | |
| echo "🔄 Rollback capability prepared" | |
| echo "Previous version: available for immediate rollback" | |
| echo "Rollback command: kubectl rollout undo deployment/gemini-flow" | |
| # Monitoring and alerting setup | |
| post-deployment-monitoring: | |
| name: Post-Deployment Monitoring | |
| runs-on: ubuntu-latest | |
| needs: [deploy-staging, deploy-production] | |
| if: always() && (needs.deploy-staging.result == 'success' || needs.deploy-production.result == 'success') | |
| steps: | |
| - name: Setup monitoring | |
| run: | | |
| ENV="${{ needs.pre-deployment.outputs.deploy-env }}" | |
| echo "📊 Setting up monitoring for $ENV environment..." | |
| # Configure alerts | |
| echo "Configuring alerts for deployment..." | |
| # Setup dashboards | |
| echo "Setting up monitoring dashboards..." | |
| # Synthetic monitoring | |
| echo "Enabling synthetic monitoring..." | |
| echo "✅ Monitoring setup completed" | |
| - name: Deployment notification | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const env = '${{ needs.pre-deployment.outputs.deploy-env }}'; | |
| const success = '${{ needs.deploy-production.result }}' === 'success' || '${{ needs.deploy-staging.result }}' === 'success'; | |
| const title = success ? | |
| `🚀 Deployment to ${env} successful` : | |
| `❌ Deployment to ${env} failed`; | |
| const body = ` | |
| ## Deployment Summary | |
| - **Environment:** ${env} | |
| - **Status:** ${success ? '✅ SUCCESS' : '❌ FAILED'} | |
| - **Image:** ${{ needs.pre-deployment.outputs.image-tag }} | |
| - **Commit:** ${{ github.sha }} | |
| - **Triggered by:** ${{ github.actor }} | |
| ${success ? | |
| '🎉 Deployment completed successfully! All systems operational.' : | |
| '⚠️ Deployment failed. Please check the logs and consider rollback if necessary.' | |
| } | |
| `; | |
| // You could send this to Slack, Discord, or other notification systems | |
| console.log(title); | |
| console.log(body); | |
| # Deployment summary | |
| deployment-summary: | |
| name: Deployment Summary | |
| runs-on: ubuntu-latest | |
| needs: [pre-deployment, build-and-publish, deploy-staging, deploy-production, post-deployment-monitoring] | |
| if: always() | |
| steps: | |
| - name: Generate deployment summary | |
| run: | | |
| echo "## 🚀 Deployment Pipeline Summary" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "**Environment:** ${{ needs.pre-deployment.outputs.deploy-env }}" >> $GITHUB_STEP_SUMMARY | |
| echo "**Triggered by:** ${{ github.actor }}" >> $GITHUB_STEP_SUMMARY | |
| echo "**Commit:** ${{ github.sha }}" >> $GITHUB_STEP_SUMMARY | |
| echo "**Image:** ${{ needs.pre-deployment.outputs.image-tag }}" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "### Pipeline Results" >> $GITHUB_STEP_SUMMARY | |
| echo "| Stage | Status |" >> $GITHUB_STEP_SUMMARY | |
| echo "|-------|--------|" >> $GITHUB_STEP_SUMMARY | |
| echo "| Pre-deployment Checks | ${{ needs.pre-deployment.result }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "| Build & Publish | ${{ needs.build-and-publish.result }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "| Staging Deployment | ${{ needs.deploy-staging.result || 'skipped' }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "| Production Deployment | ${{ needs.deploy-production.result || 'skipped' }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "| Monitoring Setup | ${{ needs.post-deployment-monitoring.result }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| # Overall status | |
| if [[ "${{ needs.deploy-production.result }}" == "success" ]]; then | |
| echo "### ✅ Production Deployment: SUCCESS" >> $GITHUB_STEP_SUMMARY | |
| echo "Application successfully deployed to production!" >> $GITHUB_STEP_SUMMARY | |
| elif [[ "${{ needs.deploy-staging.result }}" == "success" ]]; then | |
| echo "### ✅ Staging Deployment: SUCCESS" >> $GITHUB_STEP_SUMMARY | |
| echo "Application successfully deployed to staging!" >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "### ❌ Deployment: FAILED" >> $GITHUB_STEP_SUMMARY | |
| echo "Deployment encountered issues. Please review the logs." >> $GITHUB_STEP_SUMMARY | |
| fi |