diff --git a/Makefile b/Makefile index c0bcd18..ac948e7 100644 --- a/Makefile +++ b/Makefile @@ -319,6 +319,10 @@ _format: _check-config if [ -n "$(HAS_TERRAFORM)" ]; then \ ran_languages="$${ran_languages}\"terraform\","; \ terraform fmt -check -recursive || { overall_exit=1; failed_languages="$${failed_languages}\"terraform\","; }; \ + tg_files=$$(find . -name 'terragrunt.hcl' -not -path './.git/*' -not -path './.terraform/*' 2>/dev/null); \ + if [ -n "$$tg_files" ]; then \ + terragrunt hclfmt --terragrunt-check || { overall_exit=1; failed_languages="$${failed_languages}\"terraform:terragrunt\","; }; \ + fi; \ if [ "$(DEVRAIL_FAIL_FAST)" = "1" ] && [ $$overall_exit -ne 0 ]; then \ end_time=$$(date +%s%3N); \ duration=$$((end_time - start_time)); \ @@ -433,6 +437,10 @@ _fix: _check-config if [ -n "$(HAS_TERRAFORM)" ]; then \ ran_languages="$${ran_languages}\"terraform\","; \ terraform fmt -recursive || { overall_exit=1; failed_languages="$${failed_languages}\"terraform\","; }; \ + tg_files=$$(find . -name 'terragrunt.hcl' -not -path './.git/*' -not -path './.terraform/*' 2>/dev/null); \ + if [ -n "$$tg_files" ]; then \ + terragrunt hclfmt || { overall_exit=1; failed_languages="$${failed_languages}\"terraform:terragrunt\","; }; \ + fi; \ if [ "$(DEVRAIL_FAIL_FAST)" = "1" ] && [ $$overall_exit -ne 0 ]; then \ end_time=$$(date +%s%3N); \ duration=$$((end_time - start_time)); \ @@ -874,6 +882,7 @@ _docs: _check-config _tv tfsec "tfsec --version"; \ _tv checkov "checkov --version"; \ _tv terraform-docs "terraform-docs --version"; \ + _tv terragrunt "terragrunt --version"; \ fi; \ if [ -n "$(HAS_ANSIBLE)" ]; then \ _tv ansible-lint "ansible-lint --version"; \ diff --git a/README.md b/README.md index d29a644..1827f74 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ test Run validation tests |----------------|---------------------------------------------------| | Python | ruff, bandit, semgrep, pytest, mypy | | Bash | shellcheck, shfmt, bats | -| Terraform | tflint, tfsec, checkov, terraform-docs, terraform | +| Terraform | tflint, tfsec, checkov, terraform-docs, terraform, terragrunt | | Ansible | ansible-lint, molecule | | Ruby | rubocop, reek, brakeman, bundler-audit, rspec, sorbet | | Go | golangci-lint, gofumpt, govulncheck, go test | diff --git a/scripts/install-terraform.sh b/scripts/install-terraform.sh index d8066bc..9f1b1e1 100644 --- a/scripts/install-terraform.sh +++ b/scripts/install-terraform.sh @@ -12,6 +12,7 @@ # - checkov (IaC security scanner — installed via pip) # - terraform-docs (Terraform documentation gen — built in Go builder stage) # - terraform (Terraform CLI — downloaded from HashiCorp) +# - terragrunt (Terraform wrapper for DRY configs — downloaded from GitHub) # # Notes: # - terratest is a Go module dependency, not a standalone binary. @@ -32,7 +33,7 @@ source "${DEVRAIL_LIB}/platform.sh" if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then log_info "install-terraform.sh — Install Terraform tooling for DevRail" log_info "Usage: bash scripts/install-terraform.sh [--help]" - log_info "Tools: tflint, tfsec, checkov, terraform-docs, terraform" + log_info "Tools: tflint, tfsec, checkov, terraform-docs, terraform, terragrunt" log_info "Note: terratest is a Go module dependency — not installed as a binary" exit 0 fi @@ -111,6 +112,31 @@ else log_info "terraform ${TERRAFORM_VERSION} installed successfully" fi +# Install terragrunt (idempotent) +if command -v terragrunt &>/dev/null; then + log_info "terragrunt is already installed, skipping" +else + log_info "Installing terragrunt" + require_cmd "curl" "curl is required to download terragrunt" + + ARCH="$(get_arch)" + OS="$(get_os)" + + # Fetch the latest terragrunt version from GitHub API + TERRAGRUNT_VERSION=$(curl -s https://api.github.com/repos/gruntwork-io/terragrunt/releases/latest | jq -r '.tag_name' | sed 's/^v//') + if is_empty "${TERRAGRUNT_VERSION}"; then + log_warn "Could not determine latest terragrunt version, using fallback" + TERRAGRUNT_VERSION="0.99.4" + fi + + log_info "Downloading terragrunt ${TERRAGRUNT_VERSION} for ${OS}/${ARCH}" + TERRAGRUNT_URL="https://github.com/gruntwork-io/terragrunt/releases/download/v${TERRAGRUNT_VERSION}/terragrunt_${OS}_${ARCH}" + curl -fsSL "${TERRAGRUNT_URL}" -o "${TMPDIR_CLEANUP}/terragrunt" + install -m 0755 "${TMPDIR_CLEANUP}/terragrunt" /usr/local/bin/terragrunt + + log_info "terragrunt ${TERRAGRUNT_VERSION} installed successfully" +fi + # Note about terratest log_info "terratest is a Go module dependency — not installed as a binary" log_info "Consumer projects use 'go get github.com/gruntwork-io/terratest' as needed" diff --git a/tests/test-terraform.sh b/tests/test-terraform.sh index 5d3ced1..99d5914 100644 --- a/tests/test-terraform.sh +++ b/tests/test-terraform.sh @@ -18,7 +18,7 @@ source "${DEVRAIL_LIB}/log.sh" if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then log_info "test-terraform.sh — Validate Terraform tooling installation" log_info "Usage: bash tests/test-terraform.sh [--help]" - log_info "Checks: tflint, tfsec, checkov, terraform-docs, terraform" + log_info "Checks: tflint, tfsec, checkov, terraform-docs, terraform, terragrunt" exit 0 fi @@ -52,6 +52,7 @@ check_tool "tfsec" "--version" check_tool "checkov" "--version" check_tool "terraform-docs" "--version" check_tool "terraform" "version" +check_tool "terragrunt" "--version" # terratest is a Go module, not a binary — log a note log_info "terratest is a Go module dependency — no binary to validate"