Terraform CI/CD with GitHub Actions - Complete Pipeline
Automate Terraform with GitHub Actions. Plan on PR, apply on merge, OIDC authentication, environment protection, and drift detection workflows.
Terraform
Automate Terraform with Azure DevOps Pipelines. YAML pipelines, service connections, environment approvals, and Azure backend state configuration.
trigger:
branches:
include: [main]
pool:
vmImage: 'ubuntu-latest'
steps:
- task: TerraformInstaller@1
inputs:
terraformVersion: '1.8.5'
- script: terraform init
- script: terraform plan -out=tfplan
- script: terraform apply -auto-approve tfplan
condition: eq(variables['Build.SourceBranch'], 'refs/heads/main')# azure-pipelines.yml
trigger:
branches:
include: [main]
paths:
include: [terraform/**]
pr:
branches:
include: [main]
variables:
- group: terraform-vars
- name: TF_IN_AUTOMATION
value: 'true'
stages:
- stage: Validate
jobs:
- job: Validate
pool:
vmImage: 'ubuntu-latest'
steps:
- task: TerraformInstaller@1
inputs:
terraformVersion: '1.8.5'
- script: |
cd terraform
terraform init -backend=false
terraform validate
terraform fmt -check
displayName: 'Validate & Format'
- stage: Plan
dependsOn: Validate
jobs:
- job: Plan
pool:
vmImage: 'ubuntu-latest'
steps:
- task: TerraformInstaller@1
inputs:
terraformVersion: '1.8.5'
- task: AzureCLI@2
inputs:
azureSubscription: 'terraform-service-connection'
scriptType: 'bash'
scriptLocation: 'inlineScript'
inlineScript: |
cd terraform
export ARM_CLIENT_ID=$servicePrincipalId
export ARM_CLIENT_SECRET=$servicePrincipalKey
export ARM_SUBSCRIPTION_ID=$(az account show --query id -o tsv)
export ARM_TENANT_ID=$tenantId
terraform init
terraform plan -out=tfplan -no-color
addSpnToEnvironment: true
- publish: terraform/tfplan
artifact: tfplan
- stage: Apply
dependsOn: Plan
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
jobs:
- deployment: Apply
pool:
vmImage: 'ubuntu-latest'
environment: 'production' # Requires approval
strategy:
runOnce:
deploy:
steps:
- download: current
artifact: tfplan
- task: TerraformInstaller@1
inputs:
terraformVersion: '1.8.5'
- task: AzureCLI@2
inputs:
azureSubscription: 'terraform-service-connection'
scriptType: 'bash'
scriptLocation: 'inlineScript'
inlineScript: |
cd terraform
export ARM_CLIENT_ID=$servicePrincipalId
export ARM_CLIENT_SECRET=$servicePrincipalKey
export ARM_SUBSCRIPTION_ID=$(az account show --query id -o tsv)
export ARM_TENANT_ID=$tenantId
terraform init
terraform apply -auto-approve $(Pipeline.Workspace)/tfplan/tfplan
addSpnToEnvironment: trueterraform {
backend "azurerm" {
resource_group_name = "terraform-state-rg"
storage_account_name = "tfstate12345"
container_name = "tfstate"
key = "production.tfstate"
}
}terraform-service-connection# Create variable group in Azure DevOps
# Project Settings → Pipelines → Library → Variable groups
# Add: ARM_CLIENT_ID, ARM_CLIENT_SECRET (secret), ARM_SUBSCRIPTION_ID, ARM_TENANT_IDUse Azure DevOps service connections for authentication, the azurerm backend for state, Environment approvals for production gates, and the AzureCLI task to inject service principal credentials. Publish plan artifacts between stages and use deployment jobs for apply.
Automate Terraform with GitHub Actions. Plan on PR, apply on merge, OIDC authentication, environment protection, and drift detection workflows.
Automate Terraform with GitLab CI/CD. Plan on merge requests, apply on main, remote state with HTTP backend, and environment-specific pipelines.
Automate Terraform with Jenkins pipelines. Declarative and scripted pipelines, credentials management, approval gates, and multi-environment deployments.
Run Terraform in Docker containers for consistent CI/CD environments. Official HashiCorp image, custom Dockerfiles, and Docker Compose workflows.