Agent: "Create GitHub Actions workflow with:
- Matrix builds for multiple versions
- Deployment to staging/production
# .github/workflows/main.yml
branches: [main, develop]
IMAGE_NAME: ${{ github.repository }}
# Code Quality and Security
name: Code Quality Checks
uses: actions/checkout@v4
fetch-depth: 0 # Full history for better analysis
uses: actions/setup-node@v4
node-version: ${{ env.NODE_VERSION }}
- name: Install dependencies
- name: Run type checking
- name: Check code formatting
run: npm run format:check
- name: Run security audit
run: npm audit --audit-level=moderate
uses: SonarSource/sonarcloud-github-action@master
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
node-version: [18.x, 20.x, 22.x]
test-suite: [unit, integration, e2e]
POSTGRES_PASSWORD: postgres
--health-cmd "redis-cli ping"
uses: actions/checkout@v4
uses: actions/setup-node@v4
node-version: ${{ matrix.node-version }}
- name: Install dependencies
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test_db
- name: Run ${{ matrix.test-suite }} tests
run: npm run test:${{ matrix.test-suite }}
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test_db
REDIS_URL: redis://localhost:6379
if: matrix.test-suite == 'unit' && matrix.node-version == '20.x'
uses: codecov/codecov-action@v4
file: ./coverage/lcov.info
# Build and Push Docker Image
image: ${{ steps.image.outputs.image }}
digest: ${{ steps.build.outputs.digest }}
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to registry
uses: docker/login-action@v3
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
uses: docker/metadata-action@v5
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
- name: Build and push Docker image
uses: docker/build-push-action@v5
platforms: linux/amd64,linux/arm64
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-to: type=gha,mode=max
VERSION=${{ github.sha }}
BUILD_DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
uses: anchore/sbom-action@v0
image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }}
output-file: sbom.spdx.json
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }}
output: 'trivy-results.sarif'
severity: 'CRITICAL,HIGH'
- name: Upload Trivy scan results
uses: github/codeql-action/upload-sarif@v3
sarif_file: 'trivy-results.sarif'
run: echo "image=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }}" >> $GITHUB_OUTPUT
if: github.ref == 'refs/heads/develop'
uses: actions/checkout@v4
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
- name: Update kubeconfig
aws eks update-kubeconfig --name staging-cluster --region us-east-1
- name: Deploy to Kubernetes
kubectl set image deployment/app app=${{ needs.build.outputs.image }} -n staging
kubectl rollout status deployment/app -n staging
./scripts/smoke-test.sh https://staging.example.com
uses: 8398a7/action-slack@v3
status: ${{ job.status }}
webhook_url: ${{ secrets.SLACK_WEBHOOK }}
text: 'Staging deployment ${{ job.status }}'
name: Deploy to Production
needs: [build, deploy-staging]
if: github.event_name == 'release'
uses: actions/checkout@v4
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
role-to-assume: ${{ secrets.AWS_PROD_ROLE_ARN }}
- name: Update kubeconfig
aws eks update-kubeconfig --name production-cluster --region us-east-1
- name: Create deployment record
uses: actions/github-script@v7
const deployment = await github.rest.repos.createDeployment({
owner: context.repo.owner,
environment: 'production',
production_environment: true,
return deployment.data.id;
- name: Blue-Green Deployment
# Deploy to green environment
kubectl set image deployment/app-green app=${{ needs.build.outputs.image }} -n production
kubectl rollout status deployment/app-green -n production
./scripts/health-check.sh https://green.example.com
kubectl patch service app-service -n production -p '{"spec":{"selector":{"version":"green"}}}'
./scripts/verify-deployment.sh https://example.com
- name: Update deployment status
uses: actions/github-script@v7
await github.rest.repos.createDeploymentStatus({
owner: context.repo.owner,
deployment_id: ${{ steps.deployment.outputs.result }},
state: '${{ job.status }}',
environment_url: 'https://example.com'
- name: Create release notes
uses: actions/github-script@v7
const release = await github.rest.repos.getReleaseByTag({
owner: context.repo.owner,
tag: context.ref.replace('refs/tags/', '')
const newBody = release.data.body + '\n\n## Deployment\n' +
`- Image: \`${{ needs.build.outputs.image }}\`\n` +
`- Deployed at: ${new Date().toISOString()}\n` +
`- Deployed by: @${context.actor}`;
await github.rest.repos.updateRelease({
owner: context.repo.owner,
release_id: release.data.id,