From 405a6d5477725b2f50a6eb9245c09d8eccaf2efe Mon Sep 17 00:00:00 2001 From: "George L. Yermulnik" Date: Fri, 17 Oct 2025 00:07:35 +0300 Subject: [PATCH 1/4] feat: Convert `__GIT_WORKING_DIR__` to a global scope Move `__GIT_WORKING_DIR__` permutation feature over right into `common::parse_cmdline` function so that it is available to all hooks that utilize `common::parse_cmdline` function. Resolves #944 --- README.md | 115 +++++++++++++------------------------ hooks/_common.sh | 4 +- hooks/terraform_checkov.sh | 4 -- hooks/terraform_tflint.sh | 5 +- hooks/terraform_tfsec.sh | 4 -- hooks/terraform_trivy.sh | 4 -- 6 files changed, 45 insertions(+), 91 deletions(-) diff --git a/README.md b/README.md index ce09ffe44..b2515be80 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,7 @@ If you want to support the development of `pre-commit-terraform` and [many other * [Hooks usage notes and examples](#hooks-usage-notes-and-examples) * [Known limitations](#known-limitations) * [All hooks: Usage of environment variables in `--args`](#all-hooks-usage-of-environment-variables-in---args) + * [All hooks: Usage of `__GIT_WORKING_DIR__` placeholder in `--args`](#all-hooks-usage-of---git-working-dir---placeholder-in---args) * [All hooks: Set env vars inside hook at runtime](#all-hooks-set-env-vars-inside-hook-at-runtime) * [All hooks: Disable color output](#all-hooks-disable-color-output) * [All hooks: Log levels](#all-hooks-log-levels) @@ -366,6 +367,21 @@ Config example: If for config above set up `export CONFIG_NAME=.tflint; export CONFIG_EXT=hcl` before `pre-commit run`, args will be expanded to `--config=.tflint.hcl --call-module-type="all"`. +### All hooks: Usage of `__GIT_WORKING_DIR__` placeholder in `--args` + +You can use `__GIT_WORKING_DIR__` placeholder in `--args`. It will be replaced +by the Git working directory (repo root) at run time. + +For instance, if you have multiple directories and want to run +`terraform_tflint` in all of them while sharing a single config file — use the +`__GIT_WORKING_DIR__` placeholder in the file path. For example: + +```yaml +- id: terraform_tflint + args: + - --args=--config=__GIT_WORKING_DIR__/.tflint.hcl +``` + ### All hooks: Set env vars inside hook at runtime > All, except deprecated hooks: `checkov`, `terraform_docs_replace` @@ -478,34 +494,26 @@ If you don't see code above in your `pre-commit-config.yaml` or logs - you don't Note that `terraform_checkov` runs recursively during `-d .` usage. That means, for example, if you change `.tf` file in repo root, all existing `.tf` files in the repo will be checked. -1. You can specify custom arguments. E.g.: +You can specify custom arguments. E.g.: - ```yaml - - id: terraform_checkov - args: - - --args=--quiet - - --args=--skip-check CKV2_AWS_8 - ``` - - Check all available arguments [here](https://www.checkov.io/2.Basics/CLI%20Command%20Reference.html). - - For deprecated hook you need to specify each argument separately: +```yaml +- id: terraform_checkov + args: + - --args=--quiet + - --args=--skip-check CKV2_AWS_8 +``` - ```yaml - - id: checkov - args: [ - "-d", ".", - "--skip-check", "CKV2_AWS_8", - ] - ``` +Check all available arguments [here](https://www.checkov.io/2.Basics/CLI%20Command%20Reference.html). -2. When you have multiple directories and want to run `terraform_checkov` in all of them and share a single config file - use the `__GIT_WORKING_DIR__` placeholder. It will be replaced by `terraform_checkov` hooks with the Git working directory (repo root) at run time. For example: +For deprecated hook you need to specify each argument separately: - ```yaml - - id: terraform_checkov - args: - - --args=--config-file __GIT_WORKING_DIR__/.checkov.yml - ``` +```yaml +- id: checkov + args: [ + "-d", ".", + "--skip-check", "CKV2_AWS_8", + ] +``` ### infracost_breakdown @@ -702,15 +710,15 @@ To replicate functionality in `terraform_docs` hook: ### terraform_fmt -1. `terraform_fmt` supports custom arguments so you can pass [supported flags](https://www.terraform.io/docs/cli/commands/fmt.html#usage). Eg: +`terraform_fmt` supports custom arguments so you can pass [supported flags](https://www.terraform.io/docs/cli/commands/fmt.html#usage). Eg: - ```yaml - - id: terraform_fmt - args: - - --args=-no-color - - --args=-diff - - --args=-write=false - ``` +```yaml + - id: terraform_fmt + args: + - --args=-no-color + - --args=-diff + - --args=-write=false +``` ### terraform_providers_lock @@ -834,15 +842,7 @@ To replicate functionality in `terraform_docs` hook: - --args=--enable-rule=terraform_documented_variables ``` -2. When you have multiple directories and want to run `tflint` in all of them and share a single config file, it is impractical to hard-code the path to the `.tflint.hcl` file. The solution is to use the `__GIT_WORKING_DIR__` placeholder which will be replaced by `terraform_tflint` hooks with the Git working directory (repo root) at run time. For example: - - ```yaml - - id: terraform_tflint - args: - - --args=--config=__GIT_WORKING_DIR__/.tflint.hcl - ``` - -3. By default, pre-commit-terraform performs directory switching into the terraform 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: +2. By default, pre-commit-terraform performs directory switching into the terraform 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: terraform_tflint @@ -850,7 +850,6 @@ To replicate functionality in `terraform_docs` hook: - --hook-config=--delegate-chdir ``` - ### terraform_tfsec (deprecated) **DEPRECATED**. [tfsec was replaced by trivy](https://github.com/aquasecurity/tfsec/discussions/1994), so please use [`terraform_trivy`](#terraform_trivy). @@ -894,22 +893,6 @@ To replicate functionality in `terraform_docs` hook: -e aws-s3-enable-bucket-logging,aws-s3-specify-public-access-block ``` -4. When you have multiple directories and want to run `tfsec` in all of them and share a single config file - use the `__GIT_WORKING_DIR__` placeholder. It will be replaced by `terraform_tfsec` hooks with Git working directory (repo root) at run time. For example: - - ```yaml - - id: terraform_tfsec - args: - - --args=--config-file=__GIT_WORKING_DIR__/.tfsec.json - ``` - - Otherwise, will be used files that located in sub-folders: - - ```yaml - - id: terraform_tfsec - args: - - --args=--config-file=.tfsec.json - ``` - ### terraform_trivy 1. `terraform_trivy` will consume modified files that pre-commit @@ -951,14 +934,6 @@ To replicate functionality in `terraform_docs` hook: - --args=--skip-dirs="**/.terraform" ``` -4. When you have multiple directories and want to run `trivy` in all of them and share a single config file - use the `__GIT_WORKING_DIR__` placeholder. It will be replaced by `terraform_trivy` hooks with Git working directory (repo root) at run time. For example: - - ```yaml - - id: terraform_trivy - args: - - --args=--ignorefile=__GIT_WORKING_DIR__/.trivyignore - ``` - ### terraform_validate > [!IMPORTANT] @@ -1123,14 +1098,6 @@ If the generated name is incorrect, set them by providing the `module-repo-short See the `terrascan run -h` command line help for available options. - To pass the config file path, use the `__GIT_WORKING_DIR__` placeholder. It will be replaced with the Git working directory (repo root) at run time. For example: - - ```yaml - - id: terrascan - args: - - --args=--config-path=__GIT_WORKING_DIR__/.terrascan.toml - ``` - 2. Use the `--args=--verbose` parameter to see the rule ID in the scanning output. Useful to skip validations. 3. Use `--skip-rules="ruleID1,ruleID2"` parameter to skip one or more rules globally while scanning (e.g.: `--args=--skip-rules="ruleID1,ruleID2"`). 4. Use the syntax `#ts:skip=RuleID optional_comment` inside a resource to skip the rule for that resource. diff --git a/hooks/_common.sh b/hooks/_common.sh index c63918033..fd26dfce1 100644 --- a/hooks/_common.sh +++ b/hooks/_common.sh @@ -83,7 +83,9 @@ function common::parse_cmdline { # into a proper array, where each element is a standalone array slice # with quoted elements being treated as a standalone slice of array as well. while read -r -d '' ARG; do - ARGS+=("$ARG") + # Also replace any occurrence of `__GIT_WORKING_DIR__` with + # actual path to Git working dir (repo root) + ARGS+=("${ARG//__GIT_WORKING_DIR__/$PWD}") done < <(echo "$1" | xargs printf '%s\0') shift ;; diff --git a/hooks/terraform_checkov.sh b/hooks/terraform_checkov.sh index 01e2f2454..43143df56 100755 --- a/hooks/terraform_checkov.sh +++ b/hooks/terraform_checkov.sh @@ -12,10 +12,6 @@ function main { common::parse_cmdline "$@" common::export_provided_env_vars "${ENV_VARS[@]}" common::parse_and_export_env_vars - # Support for setting PATH to repo root. - for i in "${!ARGS[@]}"; do - ARGS[i]=${ARGS[i]/__GIT_WORKING_DIR__/$(pwd)\/} - done # Suppress checkov color if [ "$PRE_COMMIT_COLOR" = "never" ]; then diff --git a/hooks/terraform_tflint.sh b/hooks/terraform_tflint.sh index 54bcebe38..77183ecf7 100755 --- a/hooks/terraform_tflint.sh +++ b/hooks/terraform_tflint.sh @@ -13,10 +13,7 @@ function main { common::parse_cmdline "$@" common::export_provided_env_vars "${ENV_VARS[@]}" common::parse_and_export_env_vars - # Support for setting PATH to repo root. - for i in "${!ARGS[@]}"; do - ARGS[i]=${ARGS[i]/__GIT_WORKING_DIR__/$(pwd)\/} - done + # JFYI: tflint color already suppressed via PRE_COMMIT_COLOR=never # Run `tflint --init` for check that plugins installed. diff --git a/hooks/terraform_tfsec.sh b/hooks/terraform_tfsec.sh index dddad49a6..aa1f3fc8b 100755 --- a/hooks/terraform_tfsec.sh +++ b/hooks/terraform_tfsec.sh @@ -12,10 +12,6 @@ function main { common::parse_cmdline "$@" common::export_provided_env_vars "${ENV_VARS[@]}" common::parse_and_export_env_vars - # Support for setting PATH to repo root. - for i in "${!ARGS[@]}"; do - ARGS[i]=${ARGS[i]/__GIT_WORKING_DIR__/$(pwd)\/} - done # Suppress tfsec color if [ "$PRE_COMMIT_COLOR" = "never" ]; then diff --git a/hooks/terraform_trivy.sh b/hooks/terraform_trivy.sh index d607d67a5..fb90c0a88 100755 --- a/hooks/terraform_trivy.sh +++ b/hooks/terraform_trivy.sh @@ -12,10 +12,6 @@ function main { common::parse_cmdline "$@" common::export_provided_env_vars "${ENV_VARS[@]}" common::parse_and_export_env_vars - # Support for setting PATH to repo root. - for i in "${!ARGS[@]}"; do - ARGS[i]=${ARGS[i]/__GIT_WORKING_DIR__/$(pwd)\/} - done common::per_dir_hook "$HOOK_ID" "${#ARGS[@]}" "${ARGS[@]}" "${FILES[@]}" } From 9faa85778c3633aa430e75679bc85a54c6710ba6 Mon Sep 17 00:00:00 2001 From: "George L. Yermulnik" Date: Fri, 17 Oct 2025 00:23:31 +0300 Subject: [PATCH 2/4] Fix TOC link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b2515be80..6824515c3 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ If you want to support the development of `pre-commit-terraform` and [many other * [Hooks usage notes and examples](#hooks-usage-notes-and-examples) * [Known limitations](#known-limitations) * [All hooks: Usage of environment variables in `--args`](#all-hooks-usage-of-environment-variables-in---args) - * [All hooks: Usage of `__GIT_WORKING_DIR__` placeholder in `--args`](#all-hooks-usage-of---git-working-dir---placeholder-in---args) + * [All hooks: Usage of `__GIT_WORKING_DIR__` placeholder in `--args`](#all-hooks-usage-of-__git_working_dir__-placeholder-in---args) * [All hooks: Set env vars inside hook at runtime](#all-hooks-set-env-vars-inside-hook-at-runtime) * [All hooks: Disable color output](#all-hooks-disable-color-output) * [All hooks: Log levels](#all-hooks-log-levels) From 84a07ea5976383b17d0bc00446f7725d0b4497c2 Mon Sep 17 00:00:00 2001 From: "George L. Yermulnik" Date: Fri, 17 Oct 2025 00:34:55 +0300 Subject: [PATCH 3/4] Address `shellcheck` errors --- hooks/terraform_checkov.sh | 1 + hooks/terraform_tflint.sh | 1 + hooks/terraform_trivy.sh | 1 + 3 files changed, 3 insertions(+) diff --git a/hooks/terraform_checkov.sh b/hooks/terraform_checkov.sh index 43143df56..39a93ef5f 100755 --- a/hooks/terraform_checkov.sh +++ b/hooks/terraform_checkov.sh @@ -18,6 +18,7 @@ function main { export ANSI_COLORS_DISABLED=true fi + # shellcheck disable=SC2153 # ARGS is set in common::parse_cmdline common::per_dir_hook "$HOOK_ID" "${#ARGS[@]}" "${ARGS[@]}" "${FILES[@]}" } diff --git a/hooks/terraform_tflint.sh b/hooks/terraform_tflint.sh index 77183ecf7..1c2439f0f 100755 --- a/hooks/terraform_tflint.sh +++ b/hooks/terraform_tflint.sh @@ -19,6 +19,7 @@ function main { # Run `tflint --init` for check that plugins installed. # It should run once on whole repo. { + # shellcheck disable=SC2153 # ARGS is set in common::parse_cmdline TFLINT_INIT=$(tflint --init "${ARGS[@]}" 2>&1) 2> /dev/null && common::colorify "green" "Command 'tflint --init' successfully done:" && echo -e "${TFLINT_INIT}\n\n\n" diff --git a/hooks/terraform_trivy.sh b/hooks/terraform_trivy.sh index fb90c0a88..86f56f013 100755 --- a/hooks/terraform_trivy.sh +++ b/hooks/terraform_trivy.sh @@ -13,6 +13,7 @@ function main { common::export_provided_env_vars "${ENV_VARS[@]}" common::parse_and_export_env_vars + # shellcheck disable=SC2153 # ARGS is set in common::parse_cmdline common::per_dir_hook "$HOOK_ID" "${#ARGS[@]}" "${ARGS[@]}" "${FILES[@]}" } From 145d6f898762bb630d705c4c418e1565957ac233 Mon Sep 17 00:00:00 2001 From: Maksym Vlasov Date: Fri, 17 Oct 2025 16:18:52 +0300 Subject: [PATCH 4/4] Apply suggestions from code review --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 6824515c3..4fc4f41d2 100644 --- a/README.md +++ b/README.md @@ -369,6 +369,9 @@ If for config above set up `export CONFIG_NAME=.tflint; export CONFIG_EXT=hcl` b ### All hooks: Usage of `__GIT_WORKING_DIR__` placeholder in `--args` + +> All, except deprecated hooks: `checkov`, `terraform_docs_replace` + You can use `__GIT_WORKING_DIR__` placeholder in `--args`. It will be replaced by the Git working directory (repo root) at run time.