Skip to content
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

Mark project as archived and add developer note

Mark project as archived and add developer note #26

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