feat: support .tofu file extension and update hooks/tools

Add support for the `.tofu` file extension in OpenTofu config
matching and documentation. Update pre-commit hooks, regex, and
README to reflect support for `.tofu` files alongside `.tf` and
`.tfvars`. Fix minor shell quoting and array assignment issues.
Upgrade pre-commit-hooks to v6.0.0.

Signed-off-by: Michael Rosenfeld <michael@rosesecurity.com>
This commit is contained in:
Michael Rosenfeld 2026-05-24 22:01:30 -04:00
commit 9624cc8f24
No known key found for this signature in database
GPG key ID: C17037A434741480
6 changed files with 14 additions and 14 deletions

View file

@ -98,4 +98,3 @@ jobs:
tags: | tags: |
registry.hub.docker.com/tofuutils/pre-commit-opentofu:nightly registry.hub.docker.com/tofuutils/pre-commit-opentofu:nightly
provenance: false provenance: false

View file

@ -1,6 +1,6 @@
repos: repos:
- repo: https://github.com/pre-commit/pre-commit-hooks - repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0 rev: v6.0.0
hooks: hooks:
# Git style # Git style
- id: check-added-large-files - id: check-added-large-files

View file

@ -22,7 +22,7 @@ RUN [ ${PRE_COMMIT_VERSION} = "latest" ] && pip3 install --no-cache-dir pre-comm
RUN curl -LO https://github.com/opentofu/opentofu/releases/download/v${TOFU_VERSION}/tofu_${TOFU_VERSION}_${TARGETOS}_${TARGETARCH}.zip \ RUN curl -LO https://github.com/opentofu/opentofu/releases/download/v${TOFU_VERSION}/tofu_${TOFU_VERSION}_${TARGETOS}_${TARGETARCH}.zip \
&& curl -LO https://github.com/opentofu/opentofu/releases/download/v${TOFU_VERSION}/tofu_${TOFU_VERSION}_SHA256SUMS \ && curl -LO https://github.com/opentofu/opentofu/releases/download/v${TOFU_VERSION}/tofu_${TOFU_VERSION}_SHA256SUMS \
&& [ $(sha256sum "tofu_${TOFU_VERSION}_${TARGETOS}_${TARGETARCH}.zip" | cut -f 1 -d ' ') = "$(grep "tofu_${TOFU_VERSION}_${TARGETOS}_${TARGETARCH}.zip" tofu_*_SHA256SUMS | cut -f 1 -d ' ')" ] \ && [ "$(sha256sum "tofu_${TOFU_VERSION}_${TARGETOS}_${TARGETARCH}.zip" | cut -f 1 -d ' ')" = "$(grep "tofu_${TOFU_VERSION}_${TARGETOS}_${TARGETARCH}.zip" tofu_*_SHA256SUMS | cut -f 1 -d ' ')" ] \
&& unzip tofu_${TOFU_VERSION}_${TARGETOS}_${TARGETARCH}.zip -d /usr/bin/ \ && unzip tofu_${TOFU_VERSION}_${TARGETOS}_${TARGETARCH}.zip -d /usr/bin/ \
&& rm "tofu_${TOFU_VERSION}_${TARGETOS}_${TARGETARCH}.zip" \ && rm "tofu_${TOFU_VERSION}_${TARGETOS}_${TARGETARCH}.zip" \
&& rm "tofu_${TOFU_VERSION}_SHA256SUMS" && rm "tofu_${TOFU_VERSION}_SHA256SUMS"
@ -235,4 +235,3 @@ ENV INFRACOST_API_KEY=${INFRACOST_API_KEY:-}
ENV INFRACOST_SKIP_UPDATE_CHECK=${INFRACOST_SKIP_UPDATE_CHECK:-false} ENV INFRACOST_SKIP_UPDATE_CHECK=${INFRACOST_SKIP_UPDATE_CHECK:-false}
ENTRYPOINT [ "/entrypoint.sh" ] ENTRYPOINT [ "/entrypoint.sh" ]

View file

@ -294,7 +294,7 @@ repos:
## Available Hooks ## Available Hooks
There are several [pre-commit](https://pre-commit.com/) hooks to keep OpenTofu configurations (both `*.tf` and `*.tfvars`) and Terragrunt configurations (`*.hcl`) in a good shape: There are several [pre-commit](https://pre-commit.com/) hooks to keep OpenTofu configurations (`*.tf`, `*.tofu`, and `*.tfvars`) and Terragrunt configurations (`*.hcl`) in a good shape:
<!-- markdownlint-disable no-inline-html --> <!-- markdownlint-disable no-inline-html -->
| Hook name | Description | Dependencies<br><sup>[Install instructions here](#1-install-dependencies)</sup> | | Hook name | Description | Dependencies<br><sup>[Install instructions here](#1-install-dependencies)</sup> |
@ -326,6 +326,8 @@ Check the [source file](https://github.com/tofuutils/pre-commit-opentofu/blob/ma
OpenTofu operates on a per-dir basis, while `pre-commit` framework only supports files and files that exist. This means if you only remove the TF-related file without any other changes in the same dir, checks will be skipped. Example and details [here](https://github.com/pre-commit/pre-commit/issues/3048). OpenTofu operates on a per-dir basis, while `pre-commit` framework only supports files and files that exist. This means if you only remove the TF-related file without any other changes in the same dir, checks will be skipped. Example and details [here](https://github.com/pre-commit/pre-commit/issues/3048).
Hooks match `*.tofu` files where OpenTofu configuration files are supported, but some wrapped third-party tools may lag behind OpenTofu's native `*.tofu` parsing. If a hook runs `terraform-docs`, `tflint`, `tfsec`, `trivy`, `checkov`, `infracost`, or `tfupdate`, make sure the installed tool version supports the file extensions used in your repository.
### All hooks: Usage of environment variables in `--args` ### All hooks: Usage of environment variables in `--args`
> All, except deprecated hooks: `checkov`, `tofu_docs_replace` > All, except deprecated hooks: `checkov`, `tofu_docs_replace`
@ -930,7 +932,7 @@ To replicate functionality in `tofu_docs` hook:
require_serial: true require_serial: true
entry: .generate-providers.sh entry: .generate-providers.sh
language: script language: script
files: \.tf(vars)?$ files: \.(tf|tofu|tfvars)$
pass_filenames: false pass_filenames: false
- repo: https://github.com/pre-commit/pre-commit-hooks - repo: https://github.com/pre-commit/pre-commit-hooks

View file

@ -123,7 +123,7 @@ function common::parse_and_export_env_vars {
# `$arg` will be checked in `if` conditional, `$ARGS` will be used in the next functions. # `$arg` will be checked in `if` conditional, `$ARGS` will be used in the next functions.
# shellcheck disable=SC2016 # '${' should not be expanded # shellcheck disable=SC2016 # '${' should not be expanded
arg=${arg/'${'$env_var_name'}'/$env_var_value} arg=${arg/'${'$env_var_name'}'/$env_var_value}
ARGS[$arg_idx]=$arg ARGS[arg_idx]=$arg
# shellcheck disable=SC2016 # '${' should not be expanded # shellcheck disable=SC2016 # '${' should not be expanded
common::colorify "green" 'After ${'"$env_var_name"'} expansion: '"'$arg'\n" common::colorify "green" 'After ${'"$env_var_name"'} expansion: '"'$arg'\n"
continue continue

View file

@ -32,8 +32,8 @@ function normalize_validate_args_for_modern_terragrunt {
for arg_idx in "${!ARGS[@]}"; do for arg_idx in "${!ARGS[@]}"; do
case "${ARGS[$arg_idx]}" in case "${ARGS[$arg_idx]}" in
--terragrunt-strict-validate|--strict-validate) --terragrunt-strict-validate | --strict-validate)
ARGS[$arg_idx]="--strict" ARGS[arg_idx]="--strict"
;; ;;
esac esac
done done
@ -45,7 +45,7 @@ function terragrunt_version_ge_0_78 {
local major local major
local minor local minor
version_raw=$(terragrunt --version 2>/dev/null || true) version_raw=$(terragrunt --version 2> /dev/null || true)
version=$(echo "$version_raw" | sed -E 's/.*v?([0-9]+)\.([0-9]+)\.([0-9]+).*/\1.\2.\3/') version=$(echo "$version_raw" | sed -E 's/.*v?([0-9]+)\.([0-9]+)\.([0-9]+).*/\1.\2.\3/')
if [[ ! $version =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then if [[ ! $version =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
@ -109,8 +109,8 @@ function legacy_unit_dirs_from_files {
if common::is_hook_run_on_whole_repo "$HOOK_ID" "${FILES[@]}"; then if common::is_hook_run_on_whole_repo "$HOOK_ID" "${FILES[@]}"; then
find . -type f -name terragrunt.hcl \ find . -type f -name terragrunt.hcl \
-not -path '*/.terragrunt-cache/*' \ -not -path '*/.terragrunt-cache/*' \
-not -path '*/.terraform/*' \ -not -path '*/.terraform/*' |
| sort -u | while read -r unit_file; do sort -u | while read -r unit_file; do
dirname "$unit_file" dirname "$unit_file"
done done
return return
@ -137,8 +137,8 @@ function legacy_unit_dirs_from_files {
if [[ ${#unit_files[@]} -eq 0 ]]; then if [[ ${#unit_files[@]} -eq 0 ]]; then
find . -type f -name terragrunt.hcl \ find . -type f -name terragrunt.hcl \
-not -path '*/.terragrunt-cache/*' \ -not -path '*/.terragrunt-cache/*' \
-not -path '*/.terraform/*' \ -not -path '*/.terraform/*' |
| sort -u | while read -r unit_file; do sort -u | while read -r unit_file; do
dirname "$unit_file" dirname "$unit_file"
done done
return return