Skip to content

Major change - break #1

Major change - break

Major change - break #1

Workflow file for this run

name: Infrastructure CI/CD
on:
workflow_dispatch:
inputs:
environment:
description: 'Environment to deploy to'
required: true
type: choice
options:
- dev
- staging
- prod
action:
description: 'Action to perform'
required: true
type: choice
options:
- plan
- apply
- destroy
push:
branches:
- main
paths:
- 'terraform/**'
- 'k8s/**'
- 'helm/**'
- '.github/workflows/infrastructure.yml'
pull_request:
branches:
- main
paths:
- 'terraform/**'
- 'k8s/**'
- 'helm/**'
env:
AWS_REGION: us-west-2
TF_VERSION: 1.6.0
KUBECTL_VERSION: 1.28.0
HELM_VERSION: 3.13.0
jobs:
terraform-plan:
name: Terraform Plan
runs-on: ubuntu-latest
if: github.event_name == 'pull_request' || (github.event_name == 'workflow_dispatch' && github.event.inputs.action == 'plan')
strategy:
matrix:
environment: [dev, staging, prod]
permissions:
contents: read
pull-requests: write
id-token: write
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
aws-region: ${{ env.AWS_REGION }}
role-session-name: terraform-plan-${{ matrix.environment }}
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: ${{ env.TF_VERSION }}
- name: Setup OpenTofu (alternative)
if: env.USE_OPENTOFU == 'true'
run: |
curl -fsSL https://get.opentofu.org/install-opentofu.sh | sudo sh
sudo ln -sf /usr/local/bin/tofu /usr/local/bin/terraform
- name: Terraform Format Check
working-directory: terraform
run: terraform fmt -check -recursive
- name: Terraform Init
working-directory: terraform
run: |
terraform init \
-backend-config="bucket=${{ secrets.TF_STATE_BUCKET }}" \
-backend-config="key=ffmpeg-api/${{ matrix.environment }}/terraform.tfstate" \
-backend-config="region=${{ env.AWS_REGION }}" \
-backend-config="dynamodb_table=${{ secrets.TF_LOCK_TABLE }}"
- name: Terraform Validate
working-directory: terraform
run: terraform validate
- name: Terraform Plan
working-directory: terraform
run: |
terraform plan \
-var-file="environments/${{ matrix.environment }}.tfvars" \
-out="${{ matrix.environment }}.tfplan" \
-detailed-exitcode
continue-on-error: true
- name: Comment PR with Plan
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const plan = fs.readFileSync('terraform/${{ matrix.environment }}.tfplan.txt', 'utf8');
const output = `
## Terraform Plan for ${{ matrix.environment }}
\`\`\`
${plan}
\`\`\`
Plan: \`terraform plan -var-file="environments/${{ matrix.environment }}.tfvars"\`
`;
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: output
});
- name: Upload plan artifact
uses: actions/upload-artifact@v4
with:
name: terraform-plan-${{ matrix.environment }}
path: terraform/${{ matrix.environment }}.tfplan
retention-days: 5
terraform-apply:
name: Terraform Apply
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main' && github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && github.event.inputs.action == 'apply')
needs: [terraform-plan]
strategy:
matrix:
environment: [dev] # Only auto-deploy to dev
include:
- environment: staging
manual: true
- environment: prod
manual: true
environment:
name: ${{ matrix.environment }}
url: https://api-${{ matrix.environment }}.ffmpeg.example.com
permissions:
contents: read
id-token: write
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
aws-region: ${{ env.AWS_REGION }}
role-session-name: terraform-apply-${{ matrix.environment }}
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: ${{ env.TF_VERSION }}
- name: Download plan artifact
uses: actions/download-artifact@v4
with:
name: terraform-plan-${{ matrix.environment }}
path: terraform/
- name: Terraform Init
working-directory: terraform
run: |
terraform init \
-backend-config="bucket=${{ secrets.TF_STATE_BUCKET }}" \
-backend-config="key=ffmpeg-api/${{ matrix.environment }}/terraform.tfstate" \
-backend-config="region=${{ env.AWS_REGION }}" \
-backend-config="dynamodb_table=${{ secrets.TF_LOCK_TABLE }}"
- name: Terraform Apply
working-directory: terraform
run: terraform apply -auto-approve ${{ matrix.environment }}.tfplan
- name: Get cluster credentials
run: |
aws eks update-kubeconfig --region ${{ env.AWS_REGION }} --name ffmpeg-api-${{ matrix.environment }}
- name: Deploy Kubernetes manifests
if: success()
run: |
# Apply namespace first
kubectl apply -f k8s/base/namespace.yaml
# Apply RBAC
envsubst < k8s/base/rbac.yaml | kubectl apply -f -
# Apply ConfigMaps and Secrets
kubectl apply -f k8s/base/configmap.yaml
kubectl apply -f k8s/base/secret.yaml
# Apply services
kubectl apply -f k8s/base/services.yaml
# Apply deployments
kubectl apply -f k8s/base/api-deployment.yaml
kubectl apply -f k8s/base/worker-deployment.yaml
# Apply HPA
kubectl apply -f k8s/base/hpa.yaml
# Apply ingress
envsubst < k8s/base/ingress.yaml | kubectl apply -f -
- name: Wait for deployment
run: |
kubectl rollout status deployment/ffmpeg-api -n ffmpeg-api --timeout=300s
kubectl rollout status deployment/ffmpeg-worker -n ffmpeg-api --timeout=300s
helm-deploy:
name: Helm Deploy
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
needs: [terraform-apply]
strategy:
matrix:
environment: [dev]
permissions:
contents: read
id-token: write
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
aws-region: ${{ env.AWS_REGION }}
- name: Setup Helm
uses: azure/setup-helm@v3
with:
version: ${{ env.HELM_VERSION }}
- name: Setup kubectl
uses: azure/setup-kubectl@v3
with:
version: ${{ env.KUBECTL_VERSION }}
- name: Get cluster credentials
run: |
aws eks update-kubeconfig --region ${{ env.AWS_REGION }} --name ffmpeg-api-${{ matrix.environment }}
- name: Add Helm repositories
run: |
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo add grafana https://grafana.github.io/helm-charts
helm repo update
- name: Deploy with Helm
run: |
helm upgrade --install ffmpeg-api ./helm/ffmpeg-api \
--namespace ffmpeg-api \
--create-namespace \
--values helm/ffmpeg-api/values-${{ matrix.environment }}.yaml \
--set image.tag=${{ github.sha }} \
--timeout 10m \
--wait
- name: Test deployment
run: |
kubectl get pods -n ffmpeg-api
kubectl get services -n ffmpeg-api
kubectl get ingress -n ffmpeg-api
security-scan:
name: Security Scan
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
with:
scan-type: 'fs'
scan-ref: 'terraform/'
format: 'sarif'
output: 'trivy-results.sarif'
- name: Upload Trivy scan results
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: 'trivy-results.sarif'
- name: Run tfsec
uses: aquasecurity/tfsec-action@v1.0.3
with:
working_directory: terraform/
soft_fail: true
cleanup:
name: Cleanup Resources
runs-on: ubuntu-latest
if: github.event_name == 'workflow_dispatch' && github.event.inputs.action == 'destroy'
environment:
name: ${{ github.event.inputs.environment }}-destroy
permissions:
contents: read
id-token: write
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
aws-region: ${{ env.AWS_REGION }}
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: ${{ env.TF_VERSION }}
- name: Terraform Init
working-directory: terraform
run: |
terraform init \
-backend-config="bucket=${{ secrets.TF_STATE_BUCKET }}" \
-backend-config="key=ffmpeg-api/${{ github.event.inputs.environment }}/terraform.tfstate" \
-backend-config="region=${{ env.AWS_REGION }}" \
-backend-config="dynamodb_table=${{ secrets.TF_LOCK_TABLE }}"
- name: Terraform Destroy
working-directory: terraform
run: |
terraform destroy -auto-approve \
-var-file="environments/${{ github.event.inputs.environment }}.tfvars"