TerraformPilot

Guides

Terraform CI/CD Pipeline - GitHub Actions, GitLab CI, and Jenkins Guide

How to set up Terraform CI/CD pipelines with GitHub Actions, GitLab CI, and Jenkins with best practices. Step-by-step guide with code examples and best pract...

LLuca Berton1 min read

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

#
#cicd#github-actions#gitlab-ci#automation

Share this article