cloud IaC terraform ci claude-curated

Terraform without CI is a single developer with a laptop and admin credentials. CD for Terraform turns the workflow into something a team can use safely: every change is a PR, plans are visible, applies require approval, state is locked, and an audit trail exists. There are several products that solve this; the choice trades cost against control. The pattern is a flavour of GitOps applied to IaC.

The options

ToolHostingCostNotes
Terraform Cloud (TFC)SaaSPer-resource pricingBundles state, runs, policy, drift detection. See Terraform Cloud Workspaces
HCP TerraformSaaSSuccessor branding for TFCSame product
AtlantisSelf-hostedFreePR-driven, single Go binary, simple to run
SpaceliftSaaSPer-run pricingStrong policy, multi-IaC (TF, Pulumi, CloudFormation)
env0SaaSPer-user pricingCost estimation, drift detection
GitHub ActionsSaaS / hostedPer-minuteBring-your-own pipeline, full control
GitLab CISaaS / hostedPer-minuteSimilar to GHA, GitLab-integrated
JenkinsSelf-hostedFree (you operate it)Maximum flexibility, maximum operational burden

Comparison dimensions

The right choice depends which of these you weight most.

  • Cost. TFC and Spacelift charge per managed resource or per run; large estates can hit five-figure monthly bills. Atlantis and DIY GHA/GitLab are essentially free aside from compute.
  • Drift detection. TFC, Spacelift, env0 ship this as a feature. With Atlantis or DIY you build it yourself (a scheduled job that runs plan per workspace).
  • Plan output in PR comments. All of the above can do this. The polish varies — TFC and Spacelift have rich UIs; Atlantis sticks the raw plan in a comment.
  • Policy as code. TFC supports Sentinel and OPA; Spacelift supports OPA; Atlantis can shell out to conftest. DIY pipelines need explicit OPA steps.
  • State locking. TFC and Spacelift handle this themselves. Atlantis and DIY rely on the configured backend (S3 + DynamoDB, GCS, etc.) to provide locking.
  • Audit trail. SaaS products give you a UI of “who did what when”. DIY gives you whatever the underlying CI logs already provide — see CloudTrail Auditing for AWS-side equivalent.

Terraform Cloud

The lowest-effort option for teams that don’t want to operate any infra to manage their infra.

  • Connect a workspace to a Git repo; TFC speculates on PRs and applies on merge.
  • Variables and secrets are stored in TFC, not in the repo.
  • Sentinel or OPA policies gate runs.
  • The catch is cost — pricing scales with managed resources, and at the upper end (thousands of resources, multiple environments) the bill becomes a procurement decision rather than an engineering one. See Terraform Cloud Pitfalls.

Best for small-to-medium estates where the team’s time is more expensive than per-resource pricing.

Atlantis

A PR-driven, self-hosted Terraform runner. Deploy as a single Go binary or container; it listens for webhooks from GitHub/GitLab/Bitbucket and posts plans into PR comments.

Workflow:

  1. Open a PR. Atlantis automatically runs plan and comments the output.
  2. Reviewer reads the plan, comments atlantis apply or atlantis apply -p <project>.
  3. Atlantis applies, posts the result.
  4. Merge.

Pros: free, you own the data, simple operational model. Cons: you operate it (a small VM and a webhook is enough but not zero), no drift detection out of the box, less polished UI.

A common pattern is Atlantis + S3/DynamoDB backend + OPA via conftest. The whole stack is open source, runs on a single small VM, and handles a surprising amount of scale.

GitHub Actions (or GitLab CI)

Maximum flexibility, maximum responsibility. You write your own pipeline.

A typical layout:

on:
  pull_request:
  push:
    branches: [main]
 
jobs:
  plan:
    if: github.event_name == 'pull_request'
    steps:
      - uses: actions/checkout@v4
      - uses: hashicorp/setup-terraform@v3
      - run: terraform init
      - run: terraform plan -out=tfplan
      - uses: actions/upload-artifact@v4
        with: { name: tfplan, path: tfplan }
      # post plan output as a PR comment
 
  apply:
    if: github.event_name == 'push' && github.ref == 'refs/heads/main'
    environment: production   # gates with reviewers
    steps:
      - uses: actions/checkout@v4
      - uses: hashicorp/setup-terraform@v3
      - run: terraform init
      - run: terraform apply -auto-approve

You handle:

  • Posting plan output to the PR (a community action like actions/github-script or a dedicated TF action).
  • Preserving the plan file between plan and apply (artifact upload, or run apply on the merged commit’s plan).
  • Manual approval gates (GitHub environments with required reviewers).
  • Secrets management (GitHub OIDC into AWS, environment secrets) — consider Vault or Secrets Manager.
  • Drift detection (a scheduled workflow that runs plan and alerts on non-empty diff). See Terraform State Drift.

The advantage is you’re not paying per-resource and you can shape the pipeline however you want. The disadvantage is everything that TFC or Spacelift gives you out of the box, you build.

Common patterns regardless of tool

  • PR-driven plans. Every change opens a PR; CI posts the plan; review happens against the diff.
  • Manual approval for prod. Lower environments auto-apply; production requires a second human’s approval click.
  • One workspace per environment. Don’t try to use Terraform CLI workspaces (terraform workspace) to manage prod and dev in one config. Separate root modules with separate state files. Keeps blast radius small and policies easier. See Terraform Module Composition.
  • Pinned Terraform version. required_version in config plus a CI step that asserts the version. Avoids “works on my laptop” plan drift.
  • Provider lockfile in the repo. .terraform.lock.hcl is committed so CI and laptops resolve identical provider versions.
  • No long-lived cloud credentials in CI. OIDC into AWS / GCP / Azure to mint short-lived creds per run. Apply Least Privilages on the assumed IAM role.
  • Plan-then-apply, not plan-and-apply. The PR shows the plan; merge applies the same plan. Don’t re-plan on apply or you risk applying something different to what was reviewed.

Choosing

A reasonable decision tree:

  • Brand-new team, small estate, prefers managed: Terraform Cloud.
  • Existing team, cost-sensitive, willing to run a VM: Atlantis.
  • Already deeply invested in GitHub or GitLab and want to write the pipeline yourself: GitHub Actions / GitLab CI.
  • Multi-IaC estate (Terraform + Pulumi + CFN), policy-heavy: Spacelift.
  • Cost estimation and self-service environments matter most: env0.

The most common path I’ve seen: start with GitHub Actions because it’s already there, outgrow it as the policy and drift-detection load grows, then move to TFC or Atlantis. Migrating later is annoying but not catastrophic. Pair with Terraform CLI with Cloud Hybrid for surgical operations the pipeline can’t do.

See also

References