100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
HCL

Terraform in CI/CD Pipelines

Learn the standard stages, safety controls, and credential-handling patterns for running Terraform reliably inside a CI/CD pipeline, from plan-on-PR to gated apply-on-merge.

Terraform in ProductionIntermediate9 min readJul 9, 2026
Analogies

Terraform in CI/CD Pipelines

Running Terraform from a laptop works for learning, but production infrastructure needs a pipeline that runs the same commands the same way every time, with credentials scoped tightly, state locked against concurrent runs, and a human approval gate before anything destructive happens. A typical Terraform CI/CD pipeline chains together fast static checks, a plan stage that produces a reviewable artifact, an approval gate, and finally an apply stage that consumes the exact plan that was reviewed — never a fresh, potentially different plan.

🏏

Cricket analogy: Practicing in the backyard works for learning the game, but international cricket needs the same net session run identically every time, with kit checked, the pitch protected from tampering, and an umpire's approval before anything irreversible like a declaration happens.

The standard pipeline stages

A mature pipeline typically runs: (1) terraform fmt -check and terraform validate for cheap, fast correctness checks; (2) terraform plan -out=tfplan on every pull request, posting the human-readable summary as a PR comment for review; (3) policy-as-code evaluation against the plan; (4) a manual approval gate, often built into the CI tool or Terraform Cloud/Enterprise; and (5) terraform apply tfplan on merge to the main branch, applying the exact saved plan file rather than re-planning, which guarantees the applied changes match what was reviewed.

🏏

Cricket analogy: A mature squad selection process runs: fitness checks, then a probable-eleven review posted for selectors to comment on, then a policy check against player workload limits, then a chairman's approval, then fielding the exact eleven that was reviewed — never a fresh, different lineup on the day.

bash
# .github/workflows/terraform.yml (excerpt)
- name: Terraform Init
  run: terraform init -input=false

- name: Terraform Validate
  run: terraform validate

- name: Terraform Plan
  run: terraform plan -input=false -out=tfplan

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

Credentials, state locking, and isolation

CI runners should authenticate using short-lived, workload-scoped credentials — for example, OIDC federation into an AWS IAM role or an Azure/GCP workload identity — rather than long-lived static access keys stored as CI secrets. A remote backend with state locking (S3+DynamoDB, Terraform Cloud, Azure Storage with a lease) is mandatory in CI, since concurrent pipeline runs (two PRs planning at once, or a re-run overlapping a previous apply) would otherwise corrupt the state file. Separate pipelines, workspaces, or even separate cloud accounts per environment (dev/staging/prod) prevent a mistaken apply from crossing environment boundaries.

🏏

Cricket analogy: A touring team should clear customs using short-term match visas scoped to the series, not a permanent residency card kept in a drawer; and a shared, locked team ledger — not two managers' personal notebooks — prevents two people recording conflicting substitutions during a rain-delayed match.

Applying the exact saved plan file (terraform apply tfplan) rather than re-running plan at apply time closes a subtle gap: infrastructure or provider data can change between review and merge, and reusing the saved plan guarantees what gets applied is precisely what a human (or policy engine) already approved.

Never store long-lived cloud access keys as plain CI secrets if avoidable — a leaked static key has no expiration, while OIDC-federated short-lived credentials scoped to a specific pipeline run drastically limit the blast radius of a compromised pipeline.

  • A standard pipeline runs fmt/validate, then plan (on PR), then policy checks, then a gated apply (on merge).
  • Applying a saved plan file (terraform apply tfplan) guarantees what's applied matches exactly what was reviewed.
  • Remote state with locking (S3+DynamoDB, Terraform Cloud, etc.) is mandatory to prevent corruption from concurrent CI runs.
  • Short-lived, OIDC-federated credentials are safer in CI than long-lived static access keys stored as secrets.
  • Separate pipelines or workspaces per environment (dev/staging/prod) prevent accidental cross-environment applies.
  • A manual approval gate between plan and apply keeps a human in the loop before infrastructure changes take effect.

Practice what you learned

Was this page helpful?

Topics covered

#HCL#TerraformInfrastructureAsCodeStudyNotes#DevOps#TerraformInCICDPipelines#Terraform#Pipelines#Standard#Pipeline#StudyNotes#SkillVeris