Terraform Pull Request Automation: A Complete Guide
Comprehensive guide to implementing pull request-based Terraform workflows, from basic automation to enterprise-scale governance.
Why PR-Based Workflows for Infrastructure as Code
Organizations implementing cross-team Terraform PR automation report 40-70% reductions in infrastructure provisioning time. Deutsche Bank's platform team now enables hundreds of development teams to provision compliant infrastructure within minutes, while Spotify successfully migrated 1,200+ microservices using automated Terraform workflows.
The shift from manual infrastructure management to automated workflows has become essential. Teams face a critical decision: choosing between open-source solutions requiring significant maintenance effort or commercial platforms offering managed services with advanced features.
PR-based workflows provide several key advantages:
- Visibility: All infrastructure changes are visible in pull requests before deployment
- Collaboration: Teams discuss changes in a familiar VCS context
- Auditability: Complete history of who changed what and why
- Safety: Automated checks prevent problematic changes from reaching production
- Parallelism: Multiple teams can work simultaneously without conflicts
Understanding PR Workflow Architecture
Terraform pull request automation typically follows one of two patterns: merge-before-apply or apply-before-merge.
Merge-Before-Apply (Apply After Merge)
This is the most recommended and safest approach:
- Developers create feature branches and submit PRs
- Automated checks and
terraform planruns - Peers review the plan
- Only after PR approval and merge into main,
terraform applyexecutes via CI/CD - This keeps main as the source of truth and changes linear
Benefits:
- Low risk of state corruption
- High main branch integrity
- Simple mental model
Trade-offs:
- Slower feedback loop (apply happens post-merge)
- Issues discovered after merge require another fix PR
Apply-Before-Merge (Plan-on-PR Pattern)
Some teams apply before merging to verify changes in a real environment. This approach critically depends on sophisticated tooling like Atlantis or Scalr.
Key requirements:
- PR-level locking to prevent concurrent applies
- Automated plan/apply commands via PR comments
- Robust state management with remote backends
Benefits:
- Faster feedback (detect issues before merge)
- Test changes in real environment
Trade-offs:
- Higher complexity
- Requires powerful tooling to manage safely
Plan-on-PR Patterns: Best Practices
Every pull request should trigger an automatic terraform plan to show reviewers what changes are coming. This visibility is non-negotiable.
GitHub Actions Implementation
Here's a production-ready workflow incorporating best practices:
name: Terraform PR Automation
on:
pull_request:
paths:
- 'terraform/**'
- '.github/workflows/terraform.yml'
permissions:
id-token: write
contents: read
pull-requests: write
jobs:
terraform-check:
runs-on: ubuntu-latest
strategy:
matrix:
environment: [dev, staging, prod]
steps:
- uses: actions/checkout@v4
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/github-actions
aws-region: us-east-1
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: 1.6.0
terraform_wrapper: false
- name: Terraform Format Check
run: terraform fmt -check -recursive
- name: Terraform Init
working-directory: terraform/${{ matrix.environment }}
run: |
terraform init \
-backend-config="bucket=${{ secrets.TF_STATE_BUCKET }}" \
-backend-config="key=${{ matrix.environment }}/terraform.tfstate"
- name: Terraform Validate
working-directory: terraform/${{ matrix.environment }}
run: terraform validate
- name: Run Security Scan
uses: aquasecurity/tfsec-pr-commenter-action@v1
with:
working_directory: terraform/${{ matrix.environment }}
github_token: ${{ github.token }}
- name: Terraform Plan
id: plan
working-directory: terraform/${{ matrix.environment }}
run: |
terraform plan -out=tfplan -no-color 2>&1 | tee plan_output.txt
echo "exitcode=$?" >> $GITHUB_OUTPUT
GitLab CI Implementation
GitLab's native Terraform integration simplifies state management:
stages:
- validate
- plan
variables:
TF_ROOT: ${CI_PROJECT_DIR}/terraform
TF_STATE_NAME: ${CI_ENVIRONMENT_NAME}
.terraform-base:
image: hashicorp/terraform:1.6
before_script:
- cd ${TF_ROOT}/${CI_ENVIRONMENT_NAME}
- terraform init
validate:
extends: .terraform-base
stage: validate
script:
- terraform fmt -check -recursive
- terraform validate
rules:
- if: $CI_MERGE_REQUEST_ID
plan:dev:
extends: .terraform-base
stage: plan
environment:
name: development
script:
- terraform plan -out=tfplan
- terraform show -json tfplan > plan.json
artifacts:
paths:
- ${TF_ROOT}/${CI_ENVIRONMENT_NAME}/tfplan
- ${TF_ROOT}/${CI_ENVIRONMENT_NAME}/plan.json
reports:
terraform: ${TF_ROOT}/${CI_ENVIRONMENT_NAME}/plan.json
rules:
- if: $CI_MERGE_REQUEST_ID
Apply Strategies: Merge-Before-Apply vs Apply-Before-Merge
Merge-Before-Apply (Manual CI/CD)
name: 'Terraform Apply on Merge'
on:
push:
branches: [ main ]
jobs:
apply:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: hashicorp/setup-terraform@v3
- run: terraform init
working-directory: ./terraform
- run: terraform plan -input=false -out=tfplan
working-directory: ./terraform
- run: terraform apply -auto-approve tfplan
working-directory: ./terraform
When to use:
- Small teams (1-10 developers)
- Risk-averse organizations
- Strict change control requirements
Apply-Before-Merge (Specialized Tooling Required)
Platforms like Scalr (or tools like Atlantis) manage apply triggers based on workspace settings and PR interactions:
- On PR creation, a plan is generated and posted
- After approvals, workflows diverge:
- Apply After Merge (Scalr default): Merge triggers platform apply from target branch
- Apply Before Merge (common in Atlantis): PR comment (e.g.,
/atlantis apply,/scalr apply) triggers controlled apply with platform managing locks and state
When to use:
- Medium to large teams (50+ developers)
- Need for fast feedback loops
- Mature infrastructure practices
Atlantis: PR Automation Fundamentals
Atlantis revolutionized Terraform PR automation by bringing automation directly into pull requests.
How Atlantis Works
- Open a PR with your Terraform changes
- Comment
atlantis plan - Atlantis runs the plan, dumps the output back in the PR
- Team reviews; looks good?
- Comment
atlantis apply; Atlantis runs the apply, done
Configuration Example
version: 3
projects:
- name: production
dir: environments/prod
terraform_version: v1.5.0
autoplan:
when_modified: ["*.tf", "*.tfvars"]
enabled: true
apply_requirements: ["approved", "mergeable"]
- name: staging
dir: environments/staging
terraform_version: v1.5.0
autoplan:
when_modified: ["*.tf", "*.tfvars"]
enabled: true
Strengths of Atlantis
- Developer-friendly: Git workflows teams already know
- Quick feedback: See the plan right away
- Collaboration: All discussion happens in one place
- Transparency: Everyone sees what's happening
- Open source: Full control, no licensing costs
Limitations at Scale
- Operational overhead: Self-hosted, requires maintenance and security management
- Governance gaps: OPA policies require custom integrations
- Scaling challenges: Single server becomes a bottleneck with many repos
- State management: Getting locking right across many operations needs careful setup
- Audit complexity: Compliance features may need additional tooling
Scalr: Enterprise PR Automation
Scalr takes the Atlantis-style PR workflow and wraps it in a complete enterprise platform.
VCS-Driven Workflows
Link a workspace to a repo branch, and Scalr gets notified of PRs and merges. It supports two main GitOps flows:
- Merge-Before-Apply: Plan on PR, review, merge, then Scalr applies from main (classic)
- Apply-Before-Merge: Plan and apply right from the PR before it hits main (Atlantis-style)
PR Comment Commands
# See the plan
/scalr plan
# Approve a waiting run
/scalr approve -workspace-id=ws-xxxxxxxxxx
# Apply changes (requires permission)
/scalr apply
# Target specific workspace
/scalr apply -workspace-id=ws-xxxxxxxxxx
Feedback comes right back into the PR with smart summaries for clean plans and detailed reports for errors.
Safety Features
Branch-aware protection:
- Warns if trying to change state from unmerged PR branch
- Prevents auto-applies if branch differs from workspace's main configuration
- Ensures state changes originate from main or verified PR workflows
Controlled applies:
- Requires PR approval and branch protection checks
- Skip post-merge apply with
[skip scalr]or[skip ci]in merge message - RBAC controls: only users with
runs:applypermission can execute
Custom Hooks for Workflows
Scalr lets you inject scripts at different run phases: pre-init, pre-plan, post-plan, pre-apply, post-apply.
Example pre-plan hook to run tflint:
#!/bin/bash
echo "--- Running TFLint ---"
if ! command -v tflint &> /dev/null; then
mkdir -p /tmp/bin
curl -s https://raw.githubusercontent.com/terraform-linters/tflint/master/install_linux.sh | TFLINT_INSTALL_PATH=/tmp/bin bash
export PATH="$PATH:/tmp/bin"
fi
if [ -f ".tflint.hcl" ]; then
tflint --config=.tflint.hcl --recursive .
else
tflint --recursive .
fi
OPA Policy Integration
Write policies in Rego, store in Git, and Scalr checks them pre-plan and post-plan:
package terraform
import input.tfrun as tfrun
# Deny if estimated monthly cost delta exceeds $100
deny[reason] {
cost_delta := tfrun.cost_estimate.delta_monthly_cost
max_allowed_cost_delta := 100.00
cost_delta > max_allowed_cost_delta
reason := sprintf("Cost increase is $%.2f. We allow up to $%.2f.",
[cost_delta, max_allowed_cost_delta])
}
Policies can be advisory (warning only), soft-mandatory (requires approval), or hard-mandatory (blocks run).
Hierarchical Organization Model
Account (top level)
├── Environment (groups of workspaces)
│ └── Workspace (where Terraform runs)
Standards set at Account/Environment level flow down to all workspaces, enabling consistent governance across teams.
Preventing State Updates from Unmerged PRs
A critical challenge in Terraform PR automation is preventing state corruption from changes applied before PR merge.
The Risks of Pre-Merge Applies
State Corruption and Conflicts: Multiple developers applying from unmerged PRs to shared state causes race conditions, overwrites, and inconsistent state.
Infrastructure Drift: The main branch becomes the single source of truth. Applying from unmerged PRs creates divergence where live infrastructure doesn't match main's definition.
Compromised Main Branch Integrity: Hidden issues in pre-applied changes, provider errors, or API limits can cause actual infrastructure to differ from intended state.
Traceability Challenges: Audit trails become obscured, and rollbacks become complex when changes weren't merged into main first.
Mitigation Strategies
"Apply After Merge" Gold Standard: Ensures main is source of truth and changes remain linear.
"Apply Before Merge" with Sophisticated Tooling: Requires PR-level locking, automated plan/apply via comments, and remote state backends with locking.
Essential Supporting Practices:
- Remote state backends with locking (S3 + DynamoDB, GCS, Azure Blob)
- Automated
terraform planin all PRs - Platform-level enforcement of branch awareness
Platform Enforcement
Modern platforms like Scalr provide built-in safeguards:
- Branch awareness: Understands implications of code branches for your state
- Risk warnings: Flags risky operations and unmerged PR changes
- Auto-apply prevention: Stops auto-applies if state branch differs from workspace's main configuration
- Controlled state modifications: Ensures changes originate from main or verified PR workflows
PR Review Best Practices
Plan Review Checklist
- No unexpected resource destruction: Verify
-and~changes are intentional - Cost implications: Check for expensive instance types or resource scaling
- Security: Look for public access, open security groups, unencrypted storage
- Naming conventions: Verify resources follow team standards
- Tagging: Ensure all resources have required tags
- State locking: Confirm remote backend is properly configured
Approval Workflows
# GitHub branch protection rules
Required reviewers: 2
Require status checks to pass before merging:
- Terraform Plan (all environments)
- Security Scan (tfsec, checkov)
- OPA Policy Checks
Common Issues to Watch
- Implicit provider credentials: Use IAM roles instead
- Hard-coded values: Extract to variables
- Overly broad permissions: Apply principle of least privilege
- Missing dependencies: Verify module versions and providers
- State file exposure: Ensure backend is encrypted and access-controlled
Tool Comparison Matrix
| Feature | Atlantis | Spacelift | Terraform Cloud | Scalr |
|---|---|---|---|---|
| Apply-Before-Merge (Native) | Yes (PR Comments) | Yes (Proposed Runs) | Limited | Yes (PR Comments) |
| Merge-Before-Apply | No | Yes (Default) | Yes (Primary) | Yes (Default) |
| Workflow Customization (Hooks) | Limited | Extensive | Limited | Extensive (5 hooks) |
| OPA Policy Depth | Manual Integration | Deep OPA | Sentinel (Proprietary) | Deep OPA |
| State Backend Choice | User's Choice | Managed or User's | TFC Managed Only | Scalr or User's |
| PR Comment Quality | Basic Plan Output | Detailed, Customizable | Basic Status Checks | Rich & Contextual |
| Multi-IaC Support | Terraform | Multiple Tools | Terraform, OpenTofu | Terraform, OpenTofu, Terragrunt |
| Self-Hosted Execution | Yes (Default) | Yes (Worker Pools) | Yes (TFE Agents) | Yes (Custom Images) |
| RBAC Granularity | Auth-dependent | Granular | Limited System Roles | 120+ Permissions |
Best Practices for 2026
Foundation Requirements
- Remote State with Encryption: Use S3 + DynamoDB, GCS, or Azure Blob with encryption enabled
- Automatic Plan on PR: Every PR must trigger
terraform planautomatically - Branch Protection: Require status checks and reviews before merge
- Audit Logging: Track who changed what and when
Scale Considerations
Small Teams (1-10):
- GitHub Actions + S3 backend
- Manual coordination acceptable
- Focus on state locking
Growing Teams (10-50):
- Atlantis for PR automation
- Basic OPA policies
- Shared module library
- ~$500-1000/month operational cost
Enterprise (50-200+):
- Enterprise platform (Scalr, Spacelift, env0)
- Deep OPA governance
- Hierarchical organization
- Self-service platform for teams
- $1500+/month for platform + engineering time saved
Workflow Maturity Progression
Stage 1 - Manual: Local Terraform runs, shared credentials, manual state locking Stage 2 - Basic Automation: CI/CD pipeline, GitHub Actions, remote state Stage 3 - PR-Driven: Atlantis-style automation, plan-on-PR, manual policy checks Stage 4 - Enterprise Governance: OPA policies, RBAC, cost management, compliance Stage 5 - Self-Service Platform: Module marketplace, policy as code, team autonomy
Avoiding Common Pitfalls
- Don't apply from local machines in production: All production applies must go through the pipeline
- Don't bypass branch protection: Every change must follow the same review process
- Don't mix manual and automated state changes: One source of truth only
- Don't ignore state conflicts: Implement robust locking and monitoring
- Don't assume plan correctness: Always verify plan output in PR comments
Summary
Terraform pull request automation has evolved from experimental practice to enterprise necessity. The journey typically starts with basic CI/CD checks, progresses to Atlantis-style PR-based automation, and matures into governed platforms like Scalr for organizations at scale.
Key takeaways:
- Start with merge-before-apply unless you have specific needs for pre-merge validation
- Invest in automated plan visibility - it's the foundation of safe infrastructure changes
- Implement branch protection - make it impossible to bypass reviews and checks
- Choose tooling based on scale - Atlantis suits 10-50 person teams; enterprises need platforms
- Focus on governance from day one - OPA policies, RBAC, and audit trails become non-negotiable as teams grow
The right platform choice depends on your organization's size, toolchain, and governance needs. Starting simple with GitHub Actions and scaling to specialized platforms as requirements grow is the pragmatic approach that has worked for hundreds of organizations.