Skip to content

Commit 70ede2e

Browse files
author
Matthew
committed
Merge branch 'feat/terragrunt-support' into 'main'
docs(standards): add terragrunt support across all repos See merge request orgdocs/development-standards!21
2 parents f1b70dc + 71c2ca2 commit 70ede2e

File tree

11 files changed

+91
-11
lines changed

11 files changed

+91
-11
lines changed

DEVELOPMENT.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,7 @@ Every repo includes an `.editorconfig` file that defines formatting rules (inden
516516
|---|---|---|
517517
| Linter | **tflint** | Terraform-specific linting rules |
518518
| Formatter | **terraform fmt** | Canonical formatting |
519+
| Formatter | **terragrunt hclfmt** | Terragrunt HCL formatting (when `terragrunt.hcl` files present) |
519520
| Security | **tfsec**, **checkov** | Infrastructure security scanning |
520521
| Tests | **terratest** | Go-based infrastructure testing |
521522
| Docs | **terraform-docs** | Auto-generate module documentation |

dev-toolchain/Makefile

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,10 @@ _format: _check-config
303303
if [ -n "$(HAS_TERRAFORM)" ]; then \
304304
ran_languages="$${ran_languages}\"terraform\","; \
305305
terraform fmt -check -recursive || { overall_exit=1; failed_languages="$${failed_languages}\"terraform\","; }; \
306+
tg_files=$$(find . -name 'terragrunt.hcl' -not -path './.git/*' -not -path './.terraform/*' 2>/dev/null); \
307+
if [ -n "$$tg_files" ]; then \
308+
terragrunt hclfmt --terragrunt-check || { overall_exit=1; failed_languages="$${failed_languages}\"terraform:terragrunt\","; }; \
309+
fi; \
306310
if [ "$(DEVRAIL_FAIL_FAST)" = "1" ] && [ $$overall_exit -ne 0 ]; then \
307311
end_time=$$(date +%s%3N); \
308312
duration=$$((end_time - start_time)); \
@@ -402,6 +406,10 @@ _fix: _check-config
402406
if [ -n "$(HAS_TERRAFORM)" ]; then \
403407
ran_languages="$${ran_languages}\"terraform\","; \
404408
terraform fmt -recursive || { overall_exit=1; failed_languages="$${failed_languages}\"terraform\","; }; \
409+
tg_files=$$(find . -name 'terragrunt.hcl' -not -path './.git/*' -not -path './.terraform/*' 2>/dev/null); \
410+
if [ -n "$$tg_files" ]; then \
411+
terragrunt hclfmt || { overall_exit=1; failed_languages="$${failed_languages}\"terraform:terragrunt\","; }; \
412+
fi; \
405413
if [ "$(DEVRAIL_FAIL_FAST)" = "1" ] && [ $$overall_exit -ne 0 ]; then \
406414
end_time=$$(date +%s%3N); \
407415
duration=$$((end_time - start_time)); \
@@ -786,6 +794,7 @@ _docs: _check-config
786794
_tv tfsec "tfsec --version"; \
787795
_tv checkov "checkov --version"; \
788796
_tv terraform-docs "terraform-docs --version"; \
797+
_tv terragrunt "terragrunt --version"; \
789798
fi; \
790799
if [ -n "$(HAS_ANSIBLE)" ]; then \
791800
_tv ansible-lint "ansible-lint --version"; \

dev-toolchain/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ test Run validation tests
5050
|----------------|---------------------------------------------------|
5151
| Python | ruff, bandit, semgrep, pytest, mypy |
5252
| Bash | shellcheck, shfmt, bats |
53-
| Terraform | tflint, tfsec, checkov, terraform-docs, terraform |
53+
| Terraform | tflint, tfsec, checkov, terraform-docs, terraform, terragrunt |
5454
| Ansible | ansible-lint, molecule |
5555
| Ruby | rubocop, reek, brakeman, bundler-audit, rspec, sorbet |
5656
| Go | golangci-lint, gofumpt, govulncheck, go test |

dev-toolchain/scripts/install-terraform.sh

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
# - checkov (IaC security scanner — installed via pip)
1313
# - terraform-docs (Terraform documentation gen — built in Go builder stage)
1414
# - terraform (Terraform CLI — downloaded from HashiCorp)
15+
# - terragrunt (Terraform wrapper for DRY configs — downloaded from GitHub)
1516
#
1617
# Notes:
1718
# - terratest is a Go module dependency, not a standalone binary.
@@ -32,7 +33,7 @@ source "${DEVRAIL_LIB}/platform.sh"
3233
if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
3334
log_info "install-terraform.sh — Install Terraform tooling for DevRail"
3435
log_info "Usage: bash scripts/install-terraform.sh [--help]"
35-
log_info "Tools: tflint, tfsec, checkov, terraform-docs, terraform"
36+
log_info "Tools: tflint, tfsec, checkov, terraform-docs, terraform, terragrunt"
3637
log_info "Note: terratest is a Go module dependency — not installed as a binary"
3738
exit 0
3839
fi
@@ -111,6 +112,31 @@ else
111112
log_info "terraform ${TERRAFORM_VERSION} installed successfully"
112113
fi
113114

115+
# Install terragrunt (idempotent)
116+
if command -v terragrunt &>/dev/null; then
117+
log_info "terragrunt is already installed, skipping"
118+
else
119+
log_info "Installing terragrunt"
120+
require_cmd "curl" "curl is required to download terragrunt"
121+
122+
ARCH="$(get_arch)"
123+
OS="$(get_os)"
124+
125+
# Fetch the latest terragrunt version from GitHub API
126+
TERRAGRUNT_VERSION=$(curl -s https://api.github.com/repos/gruntwork-io/terragrunt/releases/latest | jq -r '.tag_name' | sed 's/^v//')
127+
if is_empty "${TERRAGRUNT_VERSION}"; then
128+
log_warn "Could not determine latest terragrunt version, using fallback"
129+
TERRAGRUNT_VERSION="0.99.4"
130+
fi
131+
132+
log_info "Downloading terragrunt ${TERRAGRUNT_VERSION} for ${OS}/${ARCH}"
133+
TERRAGRUNT_URL="https://github.com/gruntwork-io/terragrunt/releases/download/v${TERRAGRUNT_VERSION}/terragrunt_${OS}_${ARCH}"
134+
curl -fsSL "${TERRAGRUNT_URL}" -o "${TMPDIR_CLEANUP}/terragrunt"
135+
install -m 0755 "${TMPDIR_CLEANUP}/terragrunt" /usr/local/bin/terragrunt
136+
137+
log_info "terragrunt ${TERRAGRUNT_VERSION} installed successfully"
138+
fi
139+
114140
# Note about terratest
115141
log_info "terratest is a Go module dependency — not installed as a binary"
116142
log_info "Consumer projects use 'go get github.com/gruntwork-io/terratest' as needed"

dev-toolchain/tests/test-terraform.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ source "${DEVRAIL_LIB}/log.sh"
1818
if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
1919
log_info "test-terraform.sh — Validate Terraform tooling installation"
2020
log_info "Usage: bash tests/test-terraform.sh [--help]"
21-
log_info "Checks: tflint, tfsec, checkov, terraform-docs, terraform"
21+
log_info "Checks: tflint, tfsec, checkov, terraform-docs, terraform, terragrunt"
2222
exit 0
2323
fi
2424

@@ -52,6 +52,7 @@ check_tool "tfsec" "--version"
5252
check_tool "checkov" "--version"
5353
check_tool "terraform-docs" "--version"
5454
check_tool "terraform" "version"
55+
check_tool "terragrunt" "--version"
5556

5657
# terratest is a Go module, not a binary — log a note
5758
log_info "terratest is a Go module dependency — no binary to validate"

devrail.dev/content/docs/standards/_index.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ The following table shows the default tool for each concern per language. These
1414
| Concern | Python | Bash | Terraform | Ansible | Ruby | Go | JavaScript |
1515
|---|---|---|---|---|---|---|---|
1616
| Linter | ruff | shellcheck | tflint | ansible-lint | rubocop, reek | golangci-lint | eslint |
17-
| Formatter | ruff format | shfmt | terraform fmt | -- | rubocop | gofumpt | prettier |
17+
| Formatter | ruff format | shfmt | terraform fmt, terragrunt hclfmt | -- | rubocop | gofumpt | prettier |
1818
| Security | bandit, semgrep | -- | tfsec, checkov | -- | brakeman, bundler-audit | govulncheck | npm audit |
1919
| Tests | pytest | bats | terratest | molecule | rspec | go test | vitest |
2020
| Type Check | mypy | -- | -- | -- | sorbet | -- | tsc |
@@ -30,8 +30,8 @@ Each Makefile target runs the relevant tools for all languages declared in `.dev
3030
| Target | What It Runs |
3131
|---|---|
3232
| `make lint` | ruff check, shellcheck, tflint, ansible-lint, mypy, rubocop, reek, golangci-lint, eslint, tsc |
33-
| `make format` | ruff format --check, shfmt -d, terraform fmt -check, rubocop --check, gofumpt -d, prettier --check |
34-
| `make fix` | ruff format, shfmt -w, terraform fmt, rubocop -a, gofumpt -w, prettier --write |
33+
| `make format` | ruff format --check, shfmt -d, terraform fmt -check, terragrunt hclfmt --terragrunt-check, rubocop --check, gofumpt -d, prettier --check |
34+
| `make fix` | ruff format, shfmt -w, terraform fmt, terragrunt hclfmt, rubocop -a, gofumpt -w, prettier --write |
3535
| `make test` | pytest, bats, terratest, molecule, rspec, go test, vitest |
3636
| `make security` | bandit, semgrep, tfsec, checkov, brakeman, bundler-audit, govulncheck, npm audit |
3737
| `make scan` | trivy, gitleaks (universal -- all projects) |
@@ -44,7 +44,7 @@ Each Makefile target runs the relevant tools for all languages declared in `.dev
4444
- [Coding Practices](/docs/standards/practices/) -- principles, error handling, testing, git workflow
4545
- [Python Standards](/docs/standards/python/) -- ruff, bandit, semgrep, pytest, mypy
4646
- [Bash Standards](/docs/standards/bash/) -- shellcheck, shfmt, bats
47-
- [Terraform Standards](/docs/standards/terraform/) -- tflint, terraform fmt, tfsec, checkov, terratest, terraform-docs
47+
- [Terraform Standards](/docs/standards/terraform/) -- tflint, terraform fmt, terragrunt hclfmt, tfsec, checkov, terratest, terraform-docs
4848
- [Ansible Standards](/docs/standards/ansible/) -- ansible-lint, molecule
4949
- [Ruby Standards](/docs/standards/ruby/) -- rubocop, brakeman, bundler-audit, rspec, reek, sorbet
5050
- [Go Standards](/docs/standards/go/) -- golangci-lint, gofumpt, govulncheck, go test

devrail.dev/content/docs/standards/terraform.md

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
title: "Terraform Standards"
33
linkTitle: "Terraform"
44
weight: 30
5-
description: "Terraform tooling standards: tflint, terraform fmt, tfsec, checkov, terratest, and terraform-docs."
5+
description: "Terraform tooling standards: tflint, terraform fmt, terragrunt hclfmt, tfsec, checkov, terratest, and terraform-docs."
66
---
77

88
## Tools
@@ -11,6 +11,7 @@ description: "Terraform tooling standards: tflint, terraform fmt, tfsec, checkov
1111
|---|---|---|
1212
| Linting | tflint | Terraform-specific linting rules |
1313
| Formatting | terraform fmt | Canonical HCL formatting |
14+
| Formatting | terragrunt hclfmt | Terragrunt HCL formatting (when `terragrunt.hcl` present) |
1415
| Security | tfsec | Terraform-focused security scanning |
1516
| Security | checkov | Policy-as-code scanning |
1617
| Testing | terratest | Go-based infrastructure testing |
@@ -110,6 +111,20 @@ func TestTerraformModule(t *testing.T) {
110111

111112
The `tests/` directory must contain a `go.mod` file for the test module.
112113

114+
### terragrunt hclfmt
115+
116+
No config file required. Terragrunt is a companion tool that runs automatically when `terragrunt.hcl` files are detected in the project. It formats Terragrunt HCL files to a canonical style.
117+
118+
```bash
119+
# Check formatting (exits non-zero if files need formatting)
120+
terragrunt hclfmt --terragrunt-check
121+
122+
# Apply formatting
123+
terragrunt hclfmt
124+
```
125+
126+
Projects that do not use Terragrunt are unaffected — the formatter is silently skipped when no `terragrunt.hcl` files exist.
127+
113128
### terraform-docs
114129

115130
No config file required for default operation. Generates markdown documentation from Terraform module inputs, outputs, and descriptions.
@@ -134,6 +149,8 @@ terraform-docs markdown table . > README.md
134149
|---|---|---|
135150
| `make lint` | `tflint --recursive` | Lint all Terraform configurations |
136151
| `make format` | `terraform fmt -check -recursive` | Check formatting (no changes) |
152+
| `make format` | `terragrunt hclfmt --terragrunt-check` | Check Terragrunt formatting (when `terragrunt.hcl` present) |
153+
| `make fix` | `terragrunt hclfmt` | Apply Terragrunt formatting fixes (when `terragrunt.hcl` present) |
137154
| `make security` | `tfsec .` | Security scanning for Terraform |
138155
| `make security` | `checkov -d .` | Policy-as-code scanning |
139156
| `make test` | `cd tests && go test -v -timeout 30m` | Run terratest suite |
@@ -153,6 +170,8 @@ repos:
153170
hooks:
154171
- id: terraform_fmt
155172
- id: terraform_tflint
173+
# Uncomment if using Terragrunt:
174+
# - id: terragrunt_fmt
156175
```
157176

158177
### CI-Only (too slow for local hooks)
@@ -164,7 +183,7 @@ repos:
164183

165184
## Notes
166185

167-
- **`terraform fmt` is the only accepted formatter.** Do not use third-party HCL formatters.
186+
- **`terraform fmt` is the only accepted formatter** for `.tf` files. Do not use third-party HCL formatters. Terragrunt HCL files (`terragrunt.hcl`) are formatted by `terragrunt hclfmt`.
168187
- **Both `tfsec` and `checkov` run as part of `make security`.** They are complementary: tfsec focuses on Terraform-specific misconfigurations, checkov applies broader policy-as-code rules.
169188
- **`terraform-docs` runs as part of `make docs`.** Place `<!-- BEGIN_TF_DOCS -->` / `<!-- END_TF_DOCS -->` markers in your `README.md`.
170189
- **`terratest` tests are written in Go.** The `tests/` directory must contain a `go.mod` file.

github-repo-template/.pre-commit-config.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ repos:
3939
# hooks:
4040
# - id: terraform_fmt
4141
# - id: terraform_tflint
42+
# # Uncomment if using Terragrunt:
43+
# # - id: terragrunt_fmt
4244

4345
# --- Ruby (uncomment if languages includes ruby) ---
4446
# Linting and formatting with rubocop

gitlab-repo-template/.pre-commit-config.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ repos:
3939
# hooks:
4040
# - id: terraform_fmt
4141
# - id: terraform_tflint
42+
# # Uncomment if using Terragrunt:
43+
# # - id: terragrunt_fmt
4244

4345
# --- Ruby (uncomment if languages includes ruby) ---
4446
# Linting and formatting with rubocop

standards/devrail-yml-schema.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ The following table shows the default tool for each concern per language. These
352352
| Concern | Python | Bash | Terraform | Ansible | Ruby | Go | JavaScript | Rust |
353353
|---|---|---|---|---|---|---|---|---|
354354
| Linter | ruff | shellcheck | tflint | ansible-lint | rubocop, reek | golangci-lint | eslint | clippy |
355-
| Formatter | ruff format | shfmt | terraform fmt | -- | rubocop | gofumpt | prettier | rustfmt |
355+
| Formatter | ruff format | shfmt | terraform fmt, terragrunt hclfmt | -- | rubocop | gofumpt | prettier | rustfmt |
356356
| Security | bandit, semgrep | -- | tfsec, checkov | -- | brakeman, bundler-audit | govulncheck | npm audit | cargo-audit, cargo-deny |
357357
| Tests | pytest | bats | terratest | molecule | rspec | go test | vitest | cargo test |
358358
| Type Check | mypy | -- | -- | -- | sorbet | -- | tsc | -- |
@@ -364,6 +364,7 @@ The following table shows the default tool for each concern per language. These
364364
- "Universal" tools run for all languages and are not language-specific overrides
365365
- A `--` entry means the concern does not apply to that language
366366
- Default tools are used when no per-language override is specified
367+
- `terraform` includes Terragrunt formatting (`terragrunt hclfmt`) — no separate language entry needed. Terragrunt formatting runs automatically when `terragrunt.hcl` files are detected
367368

368369
## Exit Codes
369370

0 commit comments

Comments
 (0)