Skip to content

oferchen/hclalign

Repository files navigation

hclalign

License

hclalign normalizes Terraform and other HCL files with a two‑phase pipeline that mirrors terraform fmt before reordering attributes for consistent alignment.

Pipeline

  1. fmt – detects the Terraform CLI with exec.LookPath; if found it runs terraform fmt, otherwise a pure Go formatter is used. Newline and BOM hints are carried through and applied only when writing the result.
  2. align – reorders attributes to match a configurable schema.

terraform fmt is run again after alignment to ensure canonical layout. This process is idempotent: running the tool multiple times yields the same result.

The Go formatter emits the same spacing, alignment, and comment layout as terraform fmt. Parity tests exercise fixtures covering comments, heredocs, CRLF line endings, and UTF-8 BOM files. When the Terraform CLI is unavailable, hclalign logs a warning and falls back to this Go formatter.

Supported Blocks and Canonical Order

hclalign aligns attributes inside Terraform blocks. By default it processes only variable blocks and targets files matching the glob pattern **/*.tf while excluding .terraform/** and vendor/**.

Attributes are reordered inside these block types using canonical schemas:

  • variable: description, type, default, sensitive, nullable, then any other attributes followed by validation blocks
  • output: description, value, sensitive, ephemeral, depends_on, then other attributes
  • locals: no reordering
  • module: source, version, providers, count, for_each, depends_on, then input variables alphabetically and other attributes
  • provider: alias followed by remaining attributes sorted alphabetically, then nested blocks in their original order
  • terraform: required_version, required_providers (entries sorted alphabetically), backend, cloud, then other attributes and blocks
  • resource/data: provider, count, for_each, depends_on, lifecycle, provisioner, then provider schema attributes grouped as required → optional → computed (each alphabetical), followed by any other attributes

Validation blocks are placed immediately after canonical attributes. Attributes not covered by a canonical list or provider schema keep their original order, except in provider blocks where they are sorted alphabetically after alias. Entries within required_providers are sorted alphabetically by provider name.

required_providers sorting

# before
terraform {
  required_providers {
    azurerm = {
      source = "hashicorp/azurerm"
    }
    aws = {
      source = "hashicorp/aws"
    }
  }
}

# after
terraform {
  required_providers {
    aws = {
      source = "hashicorp/aws"
    }
    azurerm = {
      source = "hashicorp/azurerm"
    }
  }
}

Flag interactions

Use --types to select which block types to align. --order customizes the variable schema and has no effect on other block types:

# align module and output blocks using their default order
hclalign . --types module,output

# override variable attribute order while still aligning modules with defaults
hclalign . --types variable,module --order value,description,type

# --order is ignored when variable blocks are not selected
hclalign . --types module --order value,description,type

Provider Schema Integration

Resource and data blocks can be ordered according to provider schemas. Supply a schema file via --providers-schema or let hclalign invoke terraform providers schema -json by passing --use-terraform-schema. When Terraform is invoked, schemas are cached under --schema-cache (default .terraform/schema-cache) using a key derived from the Terraform version, provider versions, and module path. Disable caching with --no-schema-cache. Unknown attributes keep their original order.

CLI Flags

By default hclalign rewrites files in place. The following flags adjust this behavior:

  • --write: write result to files (default true)
  • --check: exit with non‑zero status if changes are required
  • --diff: print unified diff instead of writing files
  • --follow-symlinks: follow symbolic links when searching for files
  • --stdin, --stdout: read from stdin and/or write to stdout
  • --include, --exclude: glob patterns controlling which files are processed (defaults: include **/*.tf; exclude .terraform/**, vendor/**)
  • --order: control variable attribute order
  • --concurrency: maximum parallel file processing
  • --providers-schema: path to a provider schema JSON file
  • --use-terraform-schema: derive schema via terraform providers schema -json
  • --schema-cache: directory for Terraform schema cache
  • --no-schema-cache: disable Terraform schema caching
  • --types: comma-separated list of block types to align (defaults to variable)
  • --all: align all supported block types (mutually exclusive with --types)

Exit Codes

  • 0: success
  • 1: files need formatting when run with --check or --diff
  • 2: invalid CLI usage or configuration
  • 3: processing error during formatting or alignment

Atomic Writes and BOM Preservation

Files are written atomically via a temporary file rename and the original newline style and optional UTF‑8 byte‑order mark (BOM) are preserved.

Installation

git clone https://github.com/oferchen/hclalign.git
cd hclalign
make init tidy build

The binary is created at .build/hclalign.

Usage

hclalign [path] [flags]

Examples

Format all .tf files under the current directory and write the result back:

hclalign . --include "**/*.tf"

Check whether files are already formatted:

hclalign . --check

Preview the diff of required changes:

hclalign . --diff

Process a single file from STDIN and write to STDOUT:

cat variables.tf | hclalign --stdin --stdout

Make Targets

Target Description
make init download and verify Go modules
make tidy tidy module dependencies
make fmt run gofumpt (v0.6.0); regenerate golden files; run terraform fmt on test cases if available
make strip remove comments and enforce the single-line comment policy
make lint execute golangci-lint
make test run tests with coverage
make cover verify coverage ≥95%
make build build the hclalign binary into .build/
make clean remove build artifacts

Terraform CLI is optional. If installed, make fmt runs terraform fmt on tests/cases and regenerates golden test files.

make fmt uses go run mvdan.cc/[email protected] so contributors do not need to install gofumpt manually.

Continuous Integration

Use hclalign . --check in CI to fail builds when formatting is needed. The provided GitHub Actions workflow runs make tidy, make fmt, make lint, make test, and make cover on Linux and macOS with multiple Go versions.

License

hclalign is released under the Apache-2.0 License.

About

hclalign

Resources

License

Contributing

Stars

Watchers

Forks

Packages

No packages published