From c9cd4a805d378516a24dac33278fa51deb98bf2e Mon Sep 17 00:00:00 2001 From: Nikolai Mishin Date: Tue, 26 May 2026 23:40:30 +0200 Subject: [PATCH 01/10] fix: Update hadolint installation Signed-off-by: Nikolai Mishin --- .github/workflows/pre-commit.yaml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pre-commit.yaml b/.github/workflows/pre-commit.yaml index 1e873b6..b0566cf 100644 --- a/.github/workflows/pre-commit.yaml +++ b/.github/workflows/pre-commit.yaml @@ -27,9 +27,13 @@ jobs: sudo apt update && sudo apt install shellcheck - name: Install hadolint + env: + GH_TOKEN: ${{ github.token }} run: | - curl -L "$(curl -s https://api.github.com/repos/hadolint/hadolint/releases/latest | grep -o -E -m 1 "https://.+?/hadolint-Linux-x86_64")" > hadolint \ - && chmod +x hadolint && sudo mv hadolint /usr/bin/ + gh release download v2.14.0 --repo hadolint/hadolint --pattern "hadolint-linux-x86_64" + mv hadolint-linux-x86_64 hadolint + chmod +x hadolint + sudo mv hadolint /usr/bin/ # Need to success pre-commit fix push - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: From 3f263a968cd776924c3d1f4981e0fbf1cd79ff4d Mon Sep 17 00:00:00 2001 From: Michael Rosenfeld Date: Tue, 26 May 2026 12:06:07 -0400 Subject: [PATCH 02/10] fix: typo fixes Signed-off-by: Michael Rosenfeld --- CHANGELOG.md | 2 +- README.md | 2 +- lib_getopt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 847c7e6..2112ef2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,7 +48,7 @@ All notable changes to this project will be documented in this file. ### Features -* spport .tofu files ([#6](https://github.com/tofuutils/pre-commit-opentofu/issues/6)) ([e059c58](https://github.com/tofuutils/pre-commit-opentofu/commit/e059c5859bceddf1ca018f55851f6940ad51f1c2)) +* support .tofu files ([#6](https://github.com/tofuutils/pre-commit-opentofu/issues/6)) ([e059c58](https://github.com/tofuutils/pre-commit-opentofu/commit/e059c5859bceddf1ca018f55851f6940ad51f1c2)) # [2.0.0](https://github.com/tofuutils/pre-commit-opentofu/compare/v1.0.4...v2.0.0) (2024-09-25) diff --git a/README.md b/README.md index c5f25a9..c8434c9 100644 --- a/README.md +++ b/README.md @@ -718,7 +718,7 @@ To replicate functionality in `tofu_docs` hook: - --args=--config=__GIT_WORKING_DIR__/.tflint.hcl ``` -3. By default, pre-commit-opentofu performs directory switching into the OpenTofu modules for you. If you want to delgate the directory changing to the binary - this will allow tflint to determine the full paths for error/warning messages, rather than just module relative paths. *Note: this requires `tflint>=0.44.0`.* For example: +3. By default, pre-commit-opentofu performs directory switching into the OpenTofu modules for you. If you want to delegate the directory changing to the binary - this will allow tflint to determine the full paths for error/warning messages, rather than just module relative paths. *Note: this requires `tflint>=0.44.0`.* For example: ```yaml - id: tofu_tflint diff --git a/lib_getopt b/lib_getopt index c4b21fa..74e72f1 100644 --- a/lib_getopt +++ b/lib_getopt @@ -360,7 +360,7 @@ getopt() { } _getopt_resolve_abbrev() { - # Resolves an abbrevation from a list of possibilities. + # Resolves an abbreviation from a list of possibilities. # If the abbreviation is unambiguous, echoes the expansion on stdout # and returns 0. If the abbreviation is ambiguous, prints a message on # stderr and returns 1. (For first parse this should convert to exit From b766f82b087793f75b3ffa61eb22da80031455ce Mon Sep 17 00:00:00 2001 From: Michael Rosenfeld Date: Fri, 29 May 2026 14:44:22 -0400 Subject: [PATCH 03/10] fix: initialize config_file_no_color variable Initialize the config_file_no_color variable to prevent potential unbound variable errors during script execution. This change improves script robustness and reliability. Signed-off-by: Michael Rosenfeld --- hooks/tofu_docs.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/hooks/tofu_docs.sh b/hooks/tofu_docs.sh index 8b8d136..975ca79 100755 --- a/hooks/tofu_docs.sh +++ b/hooks/tofu_docs.sh @@ -69,6 +69,7 @@ function tofu_docs { local -a -r files=("$@") local -a paths + local config_file_no_color="" local index=0 local file_with_path From 9316d2989cd3bf4b1ba3f2d6af95d06b6360bb57 Mon Sep 17 00:00:00 2001 From: Michael Rosenfeld Date: Fri, 29 May 2026 14:48:02 -0400 Subject: [PATCH 04/10] refactor: improve directory handling and tofu validate logic Deduplicate directories in tofu_docs_replace.py by using a set of real paths, ensuring each directory is processed only once. Refactor tofu_validate.sh to use command substitution with proper exit code handling, improving reliability and clarity. Signed-off-by: Michael Rosenfeld --- hooks/tofu_docs_replace.py | 13 +++++++------ hooks/tofu_validate.sh | 21 +++++++++++++++------ 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/hooks/tofu_docs_replace.py b/hooks/tofu_docs_replace.py index 26f1d06..2e0f4ba 100644 --- a/hooks/tofu_docs_replace.py +++ b/hooks/tofu_docs_replace.py @@ -36,13 +36,14 @@ def main(argv=None): args = parser.parse_args(argv) dirs = [] + seen_dirs = set() for filename in args.filenames: - if os.path.realpath(filename) not in dirs and ( - filename.endswith(".tf") - or filename.endswith(".tofu") - or filename.endswith(".tfvars") - ): - dirs.append(os.path.dirname(filename)) + if filename.endswith((".tf", ".tofu", ".tfvars")): + dir_path = os.path.dirname(filename) + dir_key = os.path.realpath(dir_path) + if dir_key not in seen_dirs: + seen_dirs.add(dir_key) + dirs.append(dir_path) retval = 0 diff --git a/hooks/tofu_validate.sh b/hooks/tofu_validate.sh index 3999b9f..c332a18 100755 --- a/hooks/tofu_validate.sh +++ b/hooks/tofu_validate.sh @@ -128,12 +128,18 @@ function per_dir_hook_unique_part { if [ "$retry_once_with_cleanup" != "true" ]; then # tofu validate only - validate_output=$(tofu validate "${args[@]}" 2>&1) - exit_code=$? + if validate_output=$(tofu validate "${args[@]}" 2>&1); then + exit_code=0 + else + exit_code=$? + fi else # tofu validate, plus capture possible errors - validate_output=$(tofu validate -json "${args[@]}" 2>&1) - exit_code=$? + if validate_output=$(tofu validate -json "${args[@]}" 2>&1); then + exit_code=0 + else + exit_code=$? + fi # Match specific validation errors local -i validate_errors_matched @@ -155,8 +161,11 @@ function per_dir_hook_unique_part { return $exit_code } - validate_output=$(tofu validate "${args[@]}" 2>&1) - exit_code=$? + if validate_output=$(tofu validate "${args[@]}" 2>&1); then + exit_code=0 + else + exit_code=$? + fi fi fi From 7067827cf3815a5658345bbaba4dbaed5ab09122 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 1 Jun 2026 21:40:06 +0000 Subject: [PATCH 05/10] chore(release): version 2.4.1 [skip ci] ## [2.4.1](https://github.com/tofuutils/pre-commit-opentofu/compare/v2.4.0...v2.4.1) (2026-06-01) ### Bug Fixes * initialize config_file_no_color variable ([b766f82](https://github.com/tofuutils/pre-commit-opentofu/commit/b766f82b087793f75b3ffa61eb22da80031455ce)) * typo fixes ([3f263a9](https://github.com/tofuutils/pre-commit-opentofu/commit/3f263a968cd776924c3d1f4981e0fbf1cd79ff4d)) * Update hadolint installation ([c9cd4a8](https://github.com/tofuutils/pre-commit-opentofu/commit/c9cd4a805d378516a24dac33278fa51deb98bf2e)) --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2112ef2..d702c9e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,15 @@ All notable changes to this project will be documented in this file. +## [2.4.1](https://github.com/tofuutils/pre-commit-opentofu/compare/v2.4.0...v2.4.1) (2026-06-01) + + +### Bug Fixes + +* initialize config_file_no_color variable ([b766f82](https://github.com/tofuutils/pre-commit-opentofu/commit/b766f82b087793f75b3ffa61eb22da80031455ce)) +* typo fixes ([3f263a9](https://github.com/tofuutils/pre-commit-opentofu/commit/3f263a968cd776924c3d1f4981e0fbf1cd79ff4d)) +* Update hadolint installation ([c9cd4a8](https://github.com/tofuutils/pre-commit-opentofu/commit/c9cd4a805d378516a24dac33278fa51deb98bf2e)) + # [2.4.0](https://github.com/tofuutils/pre-commit-opentofu/compare/v2.3.0...v2.4.0) (2026-05-25) From caab3b8701405a446489a7864f91a2c9f281eee0 Mon Sep 17 00:00:00 2001 From: Michael Rosenfeld Date: Fri, 12 Jun 2026 15:24:20 -0400 Subject: [PATCH 06/10] fix(hooks): make env var regex portable Adjust the regex used to detect ${ENV_VAR} patterns in hooks/_common.sh to avoid Bash-incompatible constructs and to be compatible with macOS/BSD regex behavior. - Remove unnecessary leading/trailing '.*' since =~ matches substrings. - Allow lowercase letters in subsequent identifier characters ([A-Za-z0-9_]) so variable names with lowercase chars are detected. - Keep first-char restriction to uppercase or underscore to match existing extraction logic. Signed-off-by: Michael Rosenfeld --- hooks/_common.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hooks/_common.sh b/hooks/_common.sh index 5808c19..59236fd 100644 --- a/hooks/_common.sh +++ b/hooks/_common.sh @@ -112,7 +112,7 @@ function common::parse_and_export_env_vars { while true; do # Check if at least 1 env var exists in `$arg` # shellcheck disable=SC2016 # '${' should not be expanded - if [[ "$arg" =~ .*'${'[A-Z_][A-Z0-9_]*'}'.* ]]; then + if [[ "$arg" =~ '${'[A-Z_][A-Za-z0-9_]*'}' ]]; then # Get `ENV_VAR` from `.*${ENV_VAR}.*` local env_var_name=${arg#*$\{} env_var_name=${env_var_name%%\}*} From c43835bd4b4962a2121e6dcdceaaf1440d68885d Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 12 Jun 2026 22:00:23 +0000 Subject: [PATCH 07/10] chore(release): version 2.4.2 [skip ci] ## [2.4.2](https://github.com/tofuutils/pre-commit-opentofu/compare/v2.4.1...v2.4.2) (2026-06-12) ### Bug Fixes * **hooks:** make env var regex portable ([caab3b8](https://github.com/tofuutils/pre-commit-opentofu/commit/caab3b8701405a446489a7864f91a2c9f281eee0)) --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d702c9e..6f4cca5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. +## [2.4.2](https://github.com/tofuutils/pre-commit-opentofu/compare/v2.4.1...v2.4.2) (2026-06-12) + + +### Bug Fixes + +* **hooks:** make env var regex portable ([caab3b8](https://github.com/tofuutils/pre-commit-opentofu/commit/caab3b8701405a446489a7864f91a2c9f281eee0)) + ## [2.4.1](https://github.com/tofuutils/pre-commit-opentofu/compare/v2.4.0...v2.4.1) (2026-06-01) From 5fed19ce027bc4e65e4489cb294f7eb2f94e3a8d Mon Sep 17 00:00:00 2001 From: Nikolai Mishin Date: Sat, 20 Jun 2026 00:11:15 +0200 Subject: [PATCH 08/10] feat: Remove build and push nightly schedule Signed-off-by: Nikolai Mishin --- .github/workflows/build-image.yaml | 33 ------------------------------ 1 file changed, 33 deletions(-) diff --git a/.github/workflows/build-image.yaml b/.github/workflows/build-image.yaml index a79e218..3096d89 100644 --- a/.github/workflows/build-image.yaml +++ b/.github/workflows/build-image.yaml @@ -5,8 +5,6 @@ on: release: types: - created - schedule: - - cron: '00 00 * * *' jobs: docker: @@ -33,7 +31,6 @@ jobs: echo IMAGE_TAG=$([ ${{ github.ref_type }} == 'tag' ] && echo ${{ github.ref_name }} || echo 'latest') >> $GITHUB_ENV - name: Build and Push release to ghcr.io - if: github.event_name != 'schedule' uses: docker/build-push-action@v5 with: context: . @@ -49,22 +46,6 @@ jobs: secrets: | "github_token=${{ secrets.GITHUB_TOKEN }}" - - name: Build and Push nightly to ghcr.io - if: github.event_name == 'schedule' - uses: docker/build-push-action@v5 - with: - context: . - build-args: | - INSTALL_ALL=true - platforms: linux/amd64,linux/arm64 - push: true - tags: | - ghcr.io/${{ github.repository }}:nightly - # Fix multi-platform: https://github.com/docker/buildx/issues/1533 - provenance: false - secrets: | - "github_token=${{ secrets.GITHUB_TOKEN }}" - - name: Login to DockerHub Container Registry uses: docker/login-action@v4 with: @@ -73,7 +54,6 @@ jobs: password: ${{ secrets.DOCKERHUB_PASSWORD }} - name: Build and Push release to DockerHub - if: github.event_name != 'schedule' uses: docker/build-push-action@v5 with: context: . @@ -85,16 +65,3 @@ jobs: registry.hub.docker.com/tofuutils/pre-commit-opentofu:${{ env.IMAGE_TAG }} registry.hub.docker.com/tofuutils/pre-commit-opentofu:latest provenance: false - - - name: Build and Push nightly to DockerHub - if: github.event_name == 'schedule' - uses: docker/build-push-action@v5 - with: - context: . - build-args: | - INSTALL_ALL=true - platforms: linux/amd64,linux/arm64 - push: true - tags: | - registry.hub.docker.com/tofuutils/pre-commit-opentofu:nightly - provenance: false From 577e9ca85d9a7e58044c50da619bcbd278ebe6b7 Mon Sep 17 00:00:00 2001 From: Nikolai Mishin Date: Sat, 20 Jun 2026 00:18:23 +0200 Subject: [PATCH 09/10] feat: Update maintained status Signed-off-by: Nikolai Mishin --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c8434c9..73fc9bf 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Collection of git hooks for OpenTofu to be used with [pre-commit framework](http://pre-commit.com/) -[![Github tag](https://img.shields.io/github/tag/tofuutils/pre-commit-opentofu.svg)](https://github.com/tofuutils/pre-commit-opentofu/releases) ![maintenance status](https://img.shields.io/maintenance/yes/2024.svg) [![Help Contribute to Open Source](https://www.codetriage.com/tofuutils/pre-commit-opentofu/badges/users.svg)](https://www.codetriage.com/tofuutils/pre-commit-opentofu) +[![Github tag](https://img.shields.io/github/tag/tofuutils/pre-commit-opentofu.svg)](https://github.com/tofuutils/pre-commit-opentofu/releases) ![maintenance status](https://img.shields.io/maintenance/yes/2026.svg) [![Help Contribute to Open Source](https://www.codetriage.com/tofuutils/pre-commit-opentofu/badges/users.svg)](https://www.codetriage.com/tofuutils/pre-commit-opentofu) Want to contribute? Check [open issues](https://github.com/tofuutils/pre-commit-opentofu/issues?q=label%3A%22good+first+issue%22+is%3Aopen+sort%3Aupdated-desc) and [contributing notes](/.github/CONTRIBUTING.md). From c2f6c57a254910ebe768481e324bfb0253c13bc9 Mon Sep 17 00:00:00 2001 From: you Date: Tue, 7 Jul 2026 16:18:41 +0000 Subject: [PATCH 10/10] docs: fix broken anchor links in README Signed-off-by: Montana --- README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 73fc9bf..748b3b5 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ If you are using `pre-commit-opentofu` already or want to support its developmen * [tfupdate](#tfupdate) * [Docker Usage](#docker-usage) * [File Permissions](#file-permissions) - * [Download OpenTofu modules from private GitHub repositories](#download-tofu-modules-from-private-github-repositories) + * [Download OpenTofu modules from private GitHub repositories](#download-opentofu-modules-from-private-github-repositories) * [Authors](#authors) * [License](#license) @@ -301,19 +301,19 @@ There are several [pre-commit](https://pre-commit.com/) hooks to keep OpenTofu c | ------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ | | `checkov` and `tofu_checkov` | [checkov](https://github.com/bridgecrewio/checkov) static analysis of OpenTofu templates to spot potential security issues. [Hook notes](#checkov-deprecated-and-tofu_checkov) | `checkov`
Ubuntu deps: `python3`, `python3-pip` | | `infracost_breakdown` | Check how much your infra costs with [infracost](https://github.com/infracost/infracost). [Hook notes](#infracost_breakdown) | `infracost`, `jq`, [Infracost API key](https://www.infracost.io/docs/#2-get-api-key) | -| `tofu_docs` | Inserts input and output documentation into `README.md`. Recommended. [Hook notes](#terraform_docs) | `terraform-docs` | -| `tofu_docs_replace` | Runs `terraform-docs` and pipes the output directly to README.md. **DEPRECATED**. [Hook notes](#terraform_docs_replace-deprecated) | `python3`, `terraform-docs` | -| `tofu_docs_without_`
`aggregate_type_defaults` | Inserts input and output documentation into `README.md` without aggregate type defaults. Hook notes same as for [tofu_docs](#terraform_docs) | `tofu-docs` | -| `tofu_fmt` | Reformat all OpenTofu configuration files to a canonical format. [Hook notes](#terraform_fmt) | - | -| `tofu_providers_lock` | Updates provider signatures in [dependency lock files](https://www.terraform.io/docs/cli/commands/providers/lock.html). [Hook notes](#terraform_providers_lock) | - | -| `tofu_tflint` | Validates all OpenTofu configuration files with [TFLint](https://github.com/terraform-linters/tflint). [Available TFLint rules](https://github.com/terraform-linters/tflint/tree/master/docs/rules#rules). [Hook notes](#terraform_tflint). | `tflint` | -| `tofu_tfsec` | [TFSec](https://github.com/aquasecurity/tfsec) static analysis of terraform templates to spot potential security issues. **DEPRECATED**, use `tofu_trivy`. [Hook notes](#terraform_tfsec-deprecated) | `tfsec` | -| `tofu_trivy` | [Trivy](https://github.com/aquasecurity/trivy) static analysis of terraform templates to spot potential security issues. [Hook notes](#terraform_trivy) | `trivy` | +| `tofu_docs` | Inserts input and output documentation into `README.md`. Recommended. [Hook notes](#tofu_docs) | `terraform-docs` | +| `tofu_docs_replace` | Runs `terraform-docs` and pipes the output directly to README.md. **DEPRECATED**. [Hook notes](#tofu_docs_replace-deprecated) | `python3`, `terraform-docs` | +| `tofu_docs_without_`
`aggregate_type_defaults` | Inserts input and output documentation into `README.md` without aggregate type defaults. Hook notes same as for [tofu_docs](#tofu_docs) | `tofu-docs` | +| `tofu_fmt` | Reformat all OpenTofu configuration files to a canonical format. [Hook notes](#tofu_fmt) | - | +| `tofu_providers_lock` | Updates provider signatures in [dependency lock files](https://www.terraform.io/docs/cli/commands/providers/lock.html). [Hook notes](#tofu_providers_lock) | - | +| `tofu_tflint` | Validates all OpenTofu configuration files with [TFLint](https://github.com/terraform-linters/tflint). [Available TFLint rules](https://github.com/terraform-linters/tflint/tree/master/docs/rules#rules). [Hook notes](#tofu_tflint). | `tflint` | +| `tofu_tfsec` | [TFSec](https://github.com/aquasecurity/tfsec) static analysis of terraform templates to spot potential security issues. **DEPRECATED**, use `tofu_trivy`. [Hook notes](#tofu_tfsec-deprecated) | `tfsec` | +| `tofu_trivy` | [Trivy](https://github.com/aquasecurity/trivy) static analysis of terraform templates to spot potential security issues. [Hook notes](#tofu_trivy) | `trivy` | | `tofu_validate` | Validates all Terraform configuration files. [Hook notes](#tofu_validate) | `jq`, only for `--retry-once-with-cleanup` flag | | `terragrunt_fmt` | Reformat all [Terragrunt](https://github.com/gruntwork-io/terragrunt) configuration files (`*.hcl`) to a canonical format. | `terragrunt` | | `terragrunt_validate` | Validates all [Terragrunt](https://github.com/gruntwork-io/terragrunt) configuration files (`*.hcl`) | `terragrunt` | | `terragrunt_validate_inputs` | Validates Terragrunt unused and undefined inputs. | `terragrunt` | -| `tofu_wrapper_module_for_each` | Generates OpenTofu wrappers with `for_each` in module. [Hook notes](#terraform_wrapper_module_for_each) | `hcledit` | +| `tofu_wrapper_module_for_each` | Generates OpenTofu wrappers with `for_each` in module. [Hook notes](#tofu_wrapper_module_for_each) | `hcledit` | | `terrascan` | [terrascan](https://github.com/tenable/terrascan) Detect compliance and security violations. [Hook notes](#terrascan) | `terrascan` | | `tfupdate` | [tfupdate](https://github.com/minamijoyo/tfupdate) Update version constraints of OpenTofu core, providers, and modules. [Hook notes](#tfupdate) | `tfupdate` |