Photo by PJH on Unsplash

On this page

This chapter follows HCL structure in Terraform. Treat formatting and validation as part of every change, locally and in CI, before anyone approves an apply.

terraform fmt

terraform fmt rewrites .tf and .tfvars files to HashiCorp’s canonical style (indentation, alignment, and spacing). The formatter is built into Terraform; it does not shell out to gofmt.

Terminal window
terraform fmt -recursive

Useful flags:

Flag Effect
-check Exit with code 1 if files would change (CI-friendly)
-diff Print a diff when formatting would change files
-recursive Walk subdirectories

Run fmt before every commit. In CI, terraform fmt -check -recursive fails the job when style drifts.

terraform validate

terraform validate checks configuration syntax and internal consistency (unknown arguments, wrong types, invalid references). It does not call cloud APIs and does not prove your credentials work.

Validation requires an initialized working directory:

Terminal window
terraform init -backend=false
terraform validate

-backend=false skips remote backend setup when you only want a fast syntax pass in CI.

Fix reported errors before terraform plan. Validate catches many issues fmt cannot, such as referencing a resource that does not exist in the module.

Variable and resource checks

Variable validation (in variable blocks) rejects invalid input at plan time:

variables.tf
variable "machine_type" {
type = string
validation {
condition = contains(["e2-micro", "e2-small"], var.machine_type)
error_message = "Tutorial VMs must use e2-micro or e2-small."
}
}

Preconditions and postconditions on resources (Terraform 1.5+) assert rules during plan and apply:

main.tf
resource "google_storage_bucket" "example" {
name = var.bucket_name
location = var.region
lifecycle {
precondition {
condition = length(var.bucket_name) >= 3
error_message = "Bucket name must be at least three characters."
}
}
}

Check blocks (Terraform 1.5+) run assertions that can report warnings without failing the run, useful for policy-style feedback. Use them when a violation should surface in plan output but not always block apply—team policy decides.

Plan as the last gate

Even with fmt and validate green, terraform plan remains the authoritative preview of API-level changes. Review creates, updates, replaces, and deletes. For production, store plans with -out=plan.tfplan and apply that file in a later step so CI and humans apply exactly what was reviewed.

terraform plan -refresh-only updates state from the cloud without proposing resource changes—handy for drift inspection, covered further in State data in Terraform.

TFLint and provider rules

TFLint adds lint rules beyond validate: deprecated arguments, naming conventions, and provider-specific checks. For Google Cloud, enable the Google ruleset plugin and run it after init:

Terminal window
tflint --init
tflint

TFLint can fail on issues validate misses, such as invalid machine types for a region. Keep TFLint version and plugins pinned in CI like Terraform itself.

Pre-commit and CI

A minimal pre-commit hook runs fmt and validate on changed directories:

Terminal window
terraform fmt -check -recursive
terraform init -backend=false
terraform validate

In CI, run the same steps on every pull request that touches .tf files. Optionally add TFLint and terraform fmt -check in parallel jobs.

Example GitHub Actions shape (adapt paths and Terraform version):

.github/workflows/terraform.yml
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: hashicorp/setup-terraform@v3
- run: terraform fmt -check -recursive
- run: terraform init -backend=false
working-directory: infra/envs/dev
- run: terraform validate
working-directory: infra/envs/dev

terraform test

For reusable modules, terraform test (.tftest.hcl files) runs apply/destroy or mock-based scenarios against real or mocked providers. It fits module maintainers validating regressions after refactors—see HashiCorp’s documentation when you outgrow fmt, validate, and plan alone.

Next: Terraform modules shows how to package and reuse configuration.

Check your understanding

Question 1 of 7

0 of 7 checked

  1. 1. What does `terraform fmt -check` do in CI?

Search articles

Type a word to search published articles.

Open the search page