Files
gh-ahmedasmar-devops-claude…/skills/assets/workflows/github-actions-terraform.yml
2025-11-29 17:51:17 +08:00

225 lines
6.4 KiB
YAML

name: Terraform CI/CD
on:
pull_request:
branches: [main, master]
paths:
- '**.tf'
- '**.tfvars'
- '.github/workflows/terraform.yml'
push:
branches: [main, master]
paths:
- '**.tf'
- '**.tfvars'
workflow_dispatch:
env:
TF_VERSION: '1.5.0'
TF_WORKING_DIR: '.' # Change to your terraform directory
permissions:
contents: read
pull-requests: write
id-token: write # Required for OIDC
jobs:
validate:
name: Validate
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: ${{ env.TF_VERSION }}
- name: Terraform Format Check
id: fmt
run: terraform fmt -check -recursive
working-directory: ${{ env.TF_WORKING_DIR }}
continue-on-error: true
- name: Terraform Init
id: init
run: terraform init -backend=false
working-directory: ${{ env.TF_WORKING_DIR }}
- name: Terraform Validate
id: validate
run: terraform validate -no-color
working-directory: ${{ env.TF_WORKING_DIR }}
- name: Comment PR - Validation Results
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
script: |
const output = `#### Terraform Format and Style 🖌\`${{ steps.fmt.outcome }}\`
#### Terraform Initialization ⚙️\`${{ steps.init.outcome }}\`
#### Terraform Validation 🤖\`${{ steps.validate.outcome }}\`
*Pusher: @${{ github.actor }}, Action: \`${{ github.event_name }}\`, Working Directory: \`${{ env.TF_WORKING_DIR }}\`, Workflow: \`${{ github.workflow }}\`*`;
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: output
})
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup TFLint
uses: terraform-linters/setup-tflint@v4
- name: Init TFLint
run: tflint --init
- name: Run TFLint
run: tflint -f compact
working-directory: ${{ env.TF_WORKING_DIR }}
security:
name: Security Scan
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Run Checkov
uses: bridgecrewio/checkov-action@master
with:
directory: ${{ env.TF_WORKING_DIR }}
framework: terraform
output_format: sarif
output_file_path: reports/checkov.sarif
soft_fail: true # Don't fail the build, just report
- name: Upload Checkov Results
if: always()
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: reports/checkov.sarif
plan:
name: Plan
runs-on: ubuntu-latest
needs: [validate, lint]
if: github.event_name == 'pull_request'
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Configure AWS Credentials (OIDC)
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
aws-region: us-east-1
# Alternative: Use access keys (not recommended)
# - name: Configure AWS Credentials
# uses: aws-actions/configure-aws-credentials@v4
# with:
# aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
# aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
# aws-region: us-east-1
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: ${{ env.TF_VERSION }}
- name: Terraform Init
run: terraform init
working-directory: ${{ env.TF_WORKING_DIR }}
- name: Terraform Plan
id: plan
run: |
terraform plan -no-color -out=tfplan
terraform show -no-color tfplan > plan_output.txt
working-directory: ${{ env.TF_WORKING_DIR }}
- name: Comment PR - Plan
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const plan = fs.readFileSync('${{ env.TF_WORKING_DIR }}/plan_output.txt', 'utf8');
const maxLength = 65000;
const truncatedPlan = plan.length > maxLength ? plan.substring(0, maxLength) + '\n... (truncated)' : plan;
const output = `#### Terraform Plan 📖
<details><summary>Show Plan</summary>
\`\`\`terraform
${truncatedPlan}
\`\`\`
</details>
*Pusher: @${{ github.actor }}, Action: \`${{ github.event_name }}\`, Working Directory: \`${{ env.TF_WORKING_DIR }}\`*`;
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: output
})
- name: Upload Plan
uses: actions/upload-artifact@v4
with:
name: tfplan
path: ${{ env.TF_WORKING_DIR }}/tfplan
retention-days: 5
apply:
name: Apply
runs-on: ubuntu-latest
needs: [validate, lint, security]
if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master')
environment: production # Requires approval in GitHub settings
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Configure AWS Credentials (OIDC)
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
aws-region: us-east-1
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: ${{ env.TF_VERSION }}
- name: Terraform Init
run: terraform init
working-directory: ${{ env.TF_WORKING_DIR }}
- name: Terraform Apply
run: terraform apply -auto-approve
working-directory: ${{ env.TF_WORKING_DIR }}
- name: Notify Success
if: success()
run: |
echo "✅ Terraform apply completed successfully"
# Add notification logic here (Slack, email, etc.)
- name: Notify Failure
if: failure()
run: |
echo "❌ Terraform apply failed"
# Add notification logic here (Slack, email, etc.)