Table of Contents

Why CI/CD for Terraform?

Automating Terraform with CI/CD ensures consistent deployments, code review for infrastructure changes, and audit trails for compliance.

GitHub Actions Pipeline

name: Terraform
on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  terraform:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: hashicorp/setup-terraform@v3
        with:
          terraform_version: 1.7.0

      - name: Terraform Init
        run: terraform init

      - name: Terraform Format Check
        run: terraform fmt -check

      - name: Terraform Validate
        run: terraform validate

      - name: Terraform Plan
        run: terraform plan -out=tfplan
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

      - name: Terraform Apply
        if: github.ref == 'refs/heads/main'
        run: terraform apply -auto-approve tfplan

GitLab CI Pipeline

stages:
  - validate
  - plan
  - apply

variables:
  TF_ROOT: ${CI_PROJECT_DIR}

validate:
  stage: validate
  script:
    - terraform init -backend=false
    - terraform fmt -check
    - terraform validate

plan:
  stage: plan
  script:
    - terraform init
    - terraform plan -out=tfplan
  artifacts:
    paths: [tfplan]

apply:
  stage: apply
  script:
    - terraform init
    - terraform apply -auto-approve tfplan
  when: manual
  only: [main]

Best Practices

  1. Plan on PR, apply on merge — never auto-apply without review
  2. Use OIDC instead of static credentials when possible
  3. Save plan output as artifact — apply the exact reviewed plan
  4. Add cost estimation with Infracost or Terraform Cloud
  5. Run security scanning with tfsec, checkov, or Snyk
  6. Use branch protection — require approval before merge to main
  7. Lock state — only CI/CD should run apply in production

Learn More