Compare commits

..

No commits in common. "main" and "v1.0.4" have entirely different histories.

20 changed files with 124 additions and 456 deletions

View file

@ -1,10 +0,0 @@
---
version: 2
updates:
- package-ecosystem: "github-actions"
directory: /
schedule:
interval: daily
time: "11:00"
commit-message:
prefix: "gh-actions:"

View file

@ -9,13 +9,13 @@ jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Get changed Dockerfile - name: Get changed Dockerfile
id: changed-files-specific id: changed-files-specific
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5 uses: tj-actions/changed-files@2c85495a7bb72f2734cb5181e29b2ee5e08e61f7 # v13.1
with: with:
files: | files: |
Dockerfile Dockerfile
@ -52,7 +52,7 @@ jobs:
- name: Dive - check image for waste files - name: Dive - check image for waste files
if: steps.changed-files-specific.outputs.any_changed == 'true' if: steps.changed-files-specific.outputs.any_changed == 'true'
uses: MaxymVlasov/dive-action@fafb796951b322cc4926b8a5eafda89ab9de8edf # v1.5.1 uses: MaxymVlasov/dive-action@0035999cae50d4ef657ac94be84f01812aa192a5 # v0.1.0
with: with:
image: ghcr.io/${{ github.repository }}:${{ env.IMAGE_TAG }} image: ghcr.io/${{ github.repository }}:${{ env.IMAGE_TAG }}
config-file: ${{ github.workspace }}/.github/.dive-ci.yaml config-file: ${{ github.workspace }}/.github/.dive-ci.yaml

View file

@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v5.0.1 uses: actions/checkout@v4
- name: Set up QEMU - name: Set up QEMU
uses: docker/setup-qemu-action@v3 uses: docker/setup-qemu-action@v3
@ -22,7 +22,7 @@ jobs:
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v3
- name: Login to ghcr.io - name: Login to ghcr.io
uses: docker/login-action@v4 uses: docker/login-action@v3
with: with:
registry: ghcr.io registry: ghcr.io
username: ${{ github.repository_owner }} username: ${{ github.repository_owner }}
@ -66,7 +66,7 @@ jobs:
"github_token=${{ secrets.GITHUB_TOKEN }}" "github_token=${{ secrets.GITHUB_TOKEN }}"
- name: Login to DockerHub Container Registry - name: Login to DockerHub Container Registry
uses: docker/login-action@v4 uses: docker/login-action@v3
with: with:
registry: registry.hub.docker.com registry: registry.hub.docker.com
username: ${{ secrets.DOCKERHUB_USER }} username: ${{ secrets.DOCKERHUB_USER }}
@ -98,3 +98,4 @@ 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

@ -14,7 +14,7 @@ jobs:
steps: steps:
# Please look up the latest version from # Please look up the latest version from
# https://github.com/amannn/action-semantic-pull-request/releases # https://github.com/amannn/action-semantic-pull-request/releases
- uses: amannn/action-semantic-pull-request@48f256284bd46cdaab1048c3721360e808335d50 # v6.1.1 - uses: amannn/action-semantic-pull-request@e9fabac35e210fea40ca5b14c0da95a099eff26f # v5.4.0
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with: with:

View file

@ -6,7 +6,7 @@ jobs:
pre-commit: pre-commit:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- run: | - run: |
git fetch --no-tags --prune --depth=1 origin +refs/heads/*:refs/remotes/origin/* git fetch --no-tags --prune --depth=1 origin +refs/heads/*:refs/remotes/origin/*
@ -27,24 +27,20 @@ jobs:
sudo apt update && sudo apt install shellcheck sudo apt update && sudo apt install shellcheck
- name: Install hadolint - name: Install hadolint
env:
GH_TOKEN: ${{ github.token }}
run: | run: |
gh release download v2.14.0 --repo hadolint/hadolint --pattern "hadolint-linux-x86_64" curl -L "$(curl -s https://api.github.com/repos/hadolint/hadolint/releases/latest | grep -o -E -m 1 "https://.+?/hadolint-Linux-x86_64")" > hadolint \
mv hadolint-linux-x86_64 hadolint && chmod +x hadolint && sudo mv hadolint /usr/bin/
chmod +x hadolint
sudo mv hadolint /usr/bin/
# Need to success pre-commit fix push # Need to success pre-commit fix push
- uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with: with:
fetch-depth: 0 fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha }} ref: ${{ github.event.pull_request.head.sha }}
# Skip tofu_tflint which interferes to commit pre-commit auto-fixes # Skip tofu_tflint which interferes to commit pre-commit auto-fixes
- uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0 - uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5.0.0
with: with:
python-version: '3.9' python-version: '3.9'
- name: Execute pre-commit - name: Execute pre-commit
uses: pre-commit/action@576ff52938d158a24ac7e009dfa94b1455e7df99 uses: pre-commit/action@9b88afc9cd57fd75b655d5c71bd38146d07135fe # v2.0.3
env: env:
SKIP: no-commit-to-branch,hadolint SKIP: no-commit-to-branch,hadolint
with: with:
@ -53,7 +49,7 @@ jobs:
# Run only skipped checks # Run only skipped checks
- name: Execute pre-commit check that have no auto-fixes - name: Execute pre-commit check that have no auto-fixes
if: always() if: always()
uses: pre-commit/action@576ff52938d158a24ac7e009dfa94b1455e7df99 uses: pre-commit/action@9b88afc9cd57fd75b655d5c71bd38146d07135fe # v2.0.3
env: env:
SKIP: check-added-large-files,check-merge-conflict,check-vcs-permalinks,forbid-new-submodules,no-commit-to-branch,end-of-file-fixer,trailing-whitespace,check-yaml,check-merge-conflict,check-executables-have-shebangs,check-case-conflict,mixed-line-ending,detect-aws-credentials,detect-private-key,shfmt,shellcheck SKIP: check-added-large-files,check-merge-conflict,check-vcs-permalinks,forbid-new-submodules,no-commit-to-branch,end-of-file-fixer,trailing-whitespace,check-yaml,check-merge-conflict,check-executables-have-shebangs,check-case-conflict,mixed-line-ending,detect-aws-credentials,detect-private-key,shfmt,shellcheck
with: with:

View file

@ -18,13 +18,13 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with: with:
persist-credentials: false persist-credentials: false
fetch-depth: 0 fetch-depth: 0
- name: Release - name: Release
uses: cycjimmy/semantic-release-action@b12c8f6015dc215fe37bc154d4ad456dd3833c90 # v6.0.0 uses: cycjimmy/semantic-release-action@61680d0e9b02ff86f5648ade99e01be17f0260a4 # v4.0.0
with: with:
semantic_version: 18.0.0 semantic_version: 18.0.0
extra_plugins: | extra_plugins: |

View file

@ -7,7 +7,7 @@ jobs:
stale: stale:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/stale@3a9db7e6a41a89f618792c92c0e97cc736e1b13f # v10.0.0 - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # v9.0.0
with: with:
repo-token: ${{ secrets.GITHUB_TOKEN }} repo-token: ${{ secrets.GITHUB_TOKEN }}
# Staling issues and PR's # Staling issues and PR's

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: v6.0.0 rev: v4.5.0
hooks: hooks:
# Git style # Git style
- id: check-added-large-files - id: check-added-large-files

View file

@ -4,7 +4,7 @@
entry: hooks/infracost_breakdown.sh entry: hooks/infracost_breakdown.sh
language: script language: script
require_serial: true require_serial: true
files: \.(tf|tofu|tfvars|hcl)$ files: \.(tf(vars)?|hcl)$
exclude: \.terraform\/.*$ exclude: \.terraform\/.*$
- id: tofu_fmt - id: tofu_fmt
@ -12,29 +12,25 @@
description: Rewrites all OpenTofu configuration files to a canonical format. description: Rewrites all OpenTofu configuration files to a canonical format.
entry: hooks/tofu_fmt.sh entry: hooks/tofu_fmt.sh
language: script language: script
files: \.(tf|tofu|tfvars|(tftest|tofutest|tfmock|tfquery)\.hcl)$ files: (\.tf|\.tfvars)$
exclude: \.terraform\/.*$ exclude: \.terraform\/.*$
- id: tofu_docs - id: tofu_docs
name: OpenTofu docs name: OpenTofu docs
description: description: Inserts input and output documentation into README.md (using terraform-docs).
Inserts input and output documentation into README.md (using
terraform-docs).
require_serial: true require_serial: true
entry: hooks/tofu_docs.sh entry: hooks/tofu_docs.sh
language: script language: script
files: \.(tf|tofu|terraform\.lock\.hcl)$ files: (\.tf|\.terraform\.lock\.hcl)$
exclude: \.terraform\/.*$ exclude: \.terraform\/.*$
- id: tofu_docs_without_aggregate_type_defaults - id: tofu_docs_without_aggregate_type_defaults
name: OpenTofu docs (without aggregate type defaults) name: OpenTofu docs (without aggregate type defaults)
description: description: Inserts input and output documentation into README.md (using terraform-docs). Identical to terraform_docs.
Inserts input and output documentation into README.md (using
terraform-docs). Identical to terraform_docs.
require_serial: true require_serial: true
entry: hooks/tofu_docs.sh entry: hooks/tofu_docs.sh
language: script language: script
files: \.(tf|tofu)$ files: (\.tf)$
exclude: \.terraform\/.*$ exclude: \.terraform\/.*$
- id: tofu_docs_replace - id: tofu_docs_replace
@ -43,7 +39,7 @@
require_serial: true require_serial: true
entry: hooks/tofu_docs_replace.py entry: hooks/tofu_docs_replace.py
language: python language: python
files: \.(tf|tofu)$ files: (\.tf)$
exclude: \.terraform\/.*$ exclude: \.terraform\/.*$
- id: tofu_validate - id: tofu_validate
@ -52,7 +48,7 @@
require_serial: true require_serial: true
entry: hooks/tofu_validate.sh entry: hooks/tofu_validate.sh
language: script language: script
files: \.(tf|tofu|tfvars|terraform\.lock\.hcl)$ files: (\.tf|\.tfvars)$
exclude: \.terraform\/.*$ exclude: \.terraform\/.*$
- id: tofu_providers_lock - id: tofu_providers_lock
@ -70,13 +66,12 @@
require_serial: true require_serial: true
entry: hooks/tofu_tflint.sh entry: hooks/tofu_tflint.sh
language: script language: script
files: \.(tf|tofu|tfvars)$ files: (\.tf|\.tfvars)$
exclude: \.terraform\/.*$ exclude: \.terraform\/.*$
- id: terragrunt_fmt - id: terragrunt_fmt
name: Terragrunt fmt name: Terragrunt fmt
description: description: Rewrites all Terragrunt configuration files to a canonical format.
Rewrites all Terragrunt configuration files to a canonical format.
entry: hooks/terragrunt_fmt.sh entry: hooks/terragrunt_fmt.sh
language: script language: script
files: (\.hcl)$ files: (\.hcl)$
@ -90,30 +85,20 @@
files: (\.hcl)$ files: (\.hcl)$
exclude: \.terraform\/.*$ exclude: \.terraform\/.*$
- id: terragrunt_validate_inputs
name: Terragrunt validate inputs
description: Validates Terragrunt unused and undefined inputs.
entry: hooks/terragrunt_validate_inputs.sh
language: script
files: (\.hcl)$
exclude: \.terraform\/.*$
- id: tofu_tfsec - id: tofu_tfsec
name: OpenTofu validate with tfsec (deprecated, use "tofu_trivy") name: OpenTofu validate with tfsec (deprecated, use "tofu_trivy")
description: description: Static analysis of OpenTofu templates to spot potential security issues.
Static analysis of OpenTofu templates to spot potential security issues.
require_serial: true require_serial: true
entry: hooks/tofu_tfsec.sh entry: hooks/tofu_tfsec.sh
files: \.(tf|tofu|tfvars)$ files: \.tf(vars)?$
language: script language: script
- id: tofu_trivy - id: tofu_trivy
name: OpenTofu validate with trivy name: OpenTofu validate with trivy
description: description: Static analysis of OpenTofu templates to spot potential security issues.
Static analysis of OpenTofu templates to spot potential security issues.
require_serial: true require_serial: true
entry: hooks/tofu_trivy.sh entry: hooks/tofu_trivy.sh
files: \.(tf|tofu|tfvars)$ files: \.tf(vars)?$
language: script language: script
- id: checkov - id: checkov
@ -123,7 +108,7 @@
language: python language: python
pass_filenames: false pass_filenames: false
always_run: false always_run: false
files: \.(tf|tofu)$ files: \.tf$
exclude: \.terraform\/.*$ exclude: \.terraform\/.*$
require_serial: true require_serial: true
@ -133,7 +118,7 @@
entry: hooks/tofu_checkov.sh entry: hooks/tofu_checkov.sh
language: script language: script
always_run: false always_run: false
files: \.(tf|tofu)$ files: \.tf$
exclude: \.terraform\/.*$ exclude: \.terraform\/.*$
require_serial: true require_serial: true
@ -145,7 +130,7 @@
pass_filenames: false pass_filenames: false
always_run: false always_run: false
require_serial: true require_serial: true
files: \.(tf|tofu)$ files: \.tf$
exclude: \.terraform\/.*$ exclude: \.terraform\/.*$
- id: terrascan - id: terrascan
@ -153,7 +138,7 @@
description: Runs terrascan on OpenTofu templates. description: Runs terrascan on OpenTofu templates.
language: script language: script
entry: hooks/terrascan.sh entry: hooks/terrascan.sh
files: \.(tf|tofu)$ files: \.tf$
exclude: \.terraform\/.*$ exclude: \.terraform\/.*$
require_serial: true require_serial: true
@ -164,5 +149,5 @@
entry: hooks/tfupdate.sh entry: hooks/tfupdate.sh
args: args:
- --args=terraform - --args=terraform
files: \.(tf|tofu)$ files: \.tf$
require_serial: true require_serial: true

View file

@ -2,66 +2,6 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
# [2.4.0](https://github.com/tofuutils/pre-commit-opentofu/compare/v2.3.0...v2.4.0) (2026-05-25)
### Bug Fixes
* expand file extension patterns for tofu hooks ([451aaa5](https://github.com/tofuutils/pre-commit-opentofu/commit/451aaa59b552eb3913629c835af8b6b568aab120))
### Features
* support .tofu file extension and update hooks/tools ([9624cc8](https://github.com/tofuutils/pre-commit-opentofu/commit/9624cc8f24177378449203194b4f0ee71bc6c1a0))
# [2.3.0](https://github.com/tofuutils/pre-commit-opentofu/compare/v2.2.2...v2.3.0) (2026-04-21)
### Features
* add terragrunt_validate_inputs hook ([0ca9eca](https://github.com/tofuutils/pre-commit-opentofu/commit/0ca9eca3823420f31d09c62bf1672bea03ca3e07))
## [2.2.2](https://github.com/tofuutils/pre-commit-opentofu/compare/v2.2.1...v2.2.2) (2025-10-22)
### Bug Fixes
* replace deprecated hclfmt with hcl format command ([f1a589b](https://github.com/tofuutils/pre-commit-opentofu/commit/f1a589bd124b277cc02fcbf04ee05017fb8822c0))
## [2.2.1](https://github.com/tofuutils/pre-commit-opentofu/compare/v2.2.0...v2.2.1) (2025-06-04)
### Bug Fixes
* make infracost_breakdown.sh compatible with bash 3.2 (macOS) ([df886fa](https://github.com/tofuutils/pre-commit-opentofu/commit/df886fa772e7d1eedf5603327c0cf02968e7d779))
* Update pre-commit/action version ([#30](https://github.com/tofuutils/pre-commit-opentofu/issues/30)) ([44c7b5d](https://github.com/tofuutils/pre-commit-opentofu/commit/44c7b5dec9362d2fe7ed5e8786f4d95956791d3d))
# [2.2.0](https://github.com/tofuutils/pre-commit-opentofu/compare/v2.1.0...v2.2.0) (2025-03-29)
### Features
* make release ([e625db1](https://github.com/tofuutils/pre-commit-opentofu/commit/e625db13ec285e132f43cdf6e5aa3f3272e45451))
# [2.1.0](https://github.com/tofuutils/pre-commit-opentofu/compare/v2.0.0...v2.1.0) (2024-10-16)
### Features
* 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)
### Features
* **tofu:** add handling for missing tofu binary in Docker image This commit introduces logic to gracefully handle the case when the tofu binary is not found in the Docker image, improving the overall user experience. BREAKING CHANGE: The previous behavior of the application when the tofu binary was missing may have caused unexpected crashes. ([14fc63e](https://github.com/tofuutils/pre-commit-opentofu/commit/14fc63eb5b04e3ad1525d06e437b15935841775f))
### BREAKING CHANGES
* **tofu:** The previous behavior of the application when the tofu binary was missing may have caused unexpected crashes."
## [1.0.4](https://github.com/tofuutils/pre-commit-opentofu/compare/v1.0.3...v1.0.4) (2024-09-21) ## [1.0.4](https://github.com/tofuutils/pre-commit-opentofu/compare/v1.0.3...v1.0.4) (2024-09-21)

View file

@ -10,22 +10,22 @@ RUN apk add --no-cache \
curl=~8 && \ curl=~8 && \
# Upgrade packages for be able get latest Checkov # Upgrade packages for be able get latest Checkov
python3 -m pip install --no-cache-dir --upgrade \ python3 -m pip install --no-cache-dir --upgrade \
pip \ pip \
setuptools setuptools
ARG PRE_COMMIT_VERSION=${PRE_COMMIT_VERSION:-latest} ARG PRE_COMMIT_VERSION=${PRE_COMMIT_VERSION:-latest}
ARG TOFU_VERSION=${TOFU_VERSION:-1.9.0} ARG TOFU_VERSION=${TOFU_VERSION:-1.6.1}
# Install pre-commit # Install pre-commit
RUN [ ${PRE_COMMIT_VERSION} = "latest" ] && pip3 install --no-cache-dir pre-commit \ RUN [ ${PRE_COMMIT_VERSION} = "latest" ] && pip3 install --no-cache-dir pre-commit \
|| pip3 install --no-cache-dir pre-commit==${PRE_COMMIT_VERSION} || pip3 install --no-cache-dir pre-commit==${PRE_COMMIT_VERSION}
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 \
&& rm "tofu_${TOFU_VERSION}_${TARGETOS}_${TARGETARCH}.zip" \ && mv tofu /usr/bin/tofu
&& rm "tofu_${TOFU_VERSION}_SHA256SUMS"
# #
# Install tools # Install tools
@ -47,18 +47,18 @@ ARG HCLEDIT_VERSION=${HCLEDIT_VERSION:-false}
# specified in step below # specified in step below
ARG INSTALL_ALL=${INSTALL_ALL:-false} ARG INSTALL_ALL=${INSTALL_ALL:-false}
RUN if [ "$INSTALL_ALL" != "false" ]; then \ RUN if [ "$INSTALL_ALL" != "false" ]; then \
echo "export CHECKOV_VERSION=latest" >> /.env && \ echo "export CHECKOV_VERSION=latest" >> /.env && \
echo "export INFRACOST_VERSION=latest" >> /.env && \ echo "export INFRACOST_VERSION=latest" >> /.env && \
echo "export TERRAFORM_DOCS_VERSION=latest" >> /.env && \ echo "export TERRAFORM_DOCS_VERSION=latest" >> /.env && \
echo "export TERRAGRUNT_VERSION=latest" >> /.env && \ echo "export TERRAGRUNT_VERSION=latest" >> /.env && \
echo "export TERRASCAN_VERSION=latest" >> /.env && \ echo "export TERRASCAN_VERSION=latest" >> /.env && \
echo "export TFLINT_VERSION=latest" >> /.env && \ echo "export TFLINT_VERSION=latest" >> /.env && \
echo "export TFSEC_VERSION=latest" >> /.env && \ echo "export TFSEC_VERSION=latest" >> /.env && \
echo "export TRIVY_VERSION=latest" >> /.env && \ echo "export TRIVY_VERSION=latest" >> /.env && \
echo "export TFUPDATE_VERSION=latest" >> /.env && \ echo "export TFUPDATE_VERSION=latest" >> /.env && \
echo "export HCLEDIT_VERSION=latest" >> /.env \ echo "export HCLEDIT_VERSION=latest" >> /.env \
; else \ ; else \
touch /.env \ touch /.env \
; fi ; fi
@ -66,10 +66,10 @@ RUN if [ "$INSTALL_ALL" != "false" ]; then \
RUN . /.env && \ RUN . /.env && \
if [ "$CHECKOV_VERSION" != "false" ]; then \ if [ "$CHECKOV_VERSION" != "false" ]; then \
( \ ( \
apk add --no-cache gcc=~12 libffi-dev=~3 musl-dev=~1; \ apk add --no-cache gcc=~12 libffi-dev=~3 musl-dev=~1; \
[ "$CHECKOV_VERSION" = "latest" ] && pip3 install --no-cache-dir checkov \ [ "$CHECKOV_VERSION" = "latest" ] && pip3 install --no-cache-dir checkov \
|| pip3 install --no-cache-dir checkov==${CHECKOV_VERSION}; \ || pip3 install --no-cache-dir checkov==${CHECKOV_VERSION}; \
apk del gcc libffi-dev musl-dev \ apk del gcc libffi-dev musl-dev \
) \ ) \
; fi ; fi
@ -77,9 +77,9 @@ RUN . /.env && \
RUN . /.env && \ RUN . /.env && \
if [ "$INFRACOST_VERSION" != "false" ]; then \ if [ "$INFRACOST_VERSION" != "false" ]; then \
( \ ( \
INFRACOST_RELEASES="https://api.github.com/repos/infracost/infracost/releases" && \ INFRACOST_RELEASES="https://api.github.com/repos/infracost/infracost/releases" && \
[ "$INFRACOST_VERSION" = "latest" ] && curl -L "$(curl -s ${INFRACOST_RELEASES}/latest | grep -o -E -m 1 "https://.+?-${TARGETOS}-${TARGETARCH}.tar.gz")" > infracost.tgz \ [ "$INFRACOST_VERSION" = "latest" ] && curl -L "$(curl -s ${INFRACOST_RELEASES}/latest | grep -o -E -m 1 "https://.+?-${TARGETOS}-${TARGETARCH}.tar.gz")" > infracost.tgz \
|| curl -L "$(curl -s ${INFRACOST_RELEASES} | grep -o -E "https://.+?v${INFRACOST_VERSION}/infracost-${TARGETOS}-${TARGETARCH}.tar.gz")" > infracost.tgz \ || curl -L "$(curl -s ${INFRACOST_RELEASES} | grep -o -E "https://.+?v${INFRACOST_VERSION}/infracost-${TARGETOS}-${TARGETARCH}.tar.gz")" > infracost.tgz \
) && tar -xzf infracost.tgz && rm infracost.tgz && mv infracost-${TARGETOS}-${TARGETARCH} infracost \ ) && tar -xzf infracost.tgz && rm infracost.tgz && mv infracost-${TARGETOS}-${TARGETARCH} infracost \
; fi ; fi
@ -87,9 +87,9 @@ RUN . /.env && \
RUN . /.env && \ RUN . /.env && \
if [ "$TERRAFORM_DOCS_VERSION" != "false" ]; then \ if [ "$TERRAFORM_DOCS_VERSION" != "false" ]; then \
( \ ( \
TERRAFORM_DOCS_RELEASES="https://api.github.com/repos/terraform-docs/terraform-docs/releases" && \ TERRAFORM_DOCS_RELEASES="https://api.github.com/repos/terraform-docs/terraform-docs/releases" && \
[ "$TERRAFORM_DOCS_VERSION" = "latest" ] && curl -L "$(curl -s ${TERRAFORM_DOCS_RELEASES}/latest | grep -o -E -m 1 "https://.+?-${TARGETOS}-${TARGETARCH}.tar.gz")" > terraform-docs.tgz \ [ "$TERRAFORM_DOCS_VERSION" = "latest" ] && curl -L "$(curl -s ${TERRAFORM_DOCS_RELEASES}/latest | grep -o -E -m 1 "https://.+?-${TARGETOS}-${TARGETARCH}.tar.gz")" > terraform-docs.tgz \
|| curl -L "$(curl -s ${TERRAFORM_DOCS_RELEASES} | grep -o -E "https://.+?v${TERRAFORM_DOCS_VERSION}-${TARGETOS}-${TARGETARCH}.tar.gz")" > terraform-docs.tgz \ || curl -L "$(curl -s ${TERRAFORM_DOCS_RELEASES} | grep -o -E "https://.+?v${TERRAFORM_DOCS_VERSION}-${TARGETOS}-${TARGETARCH}.tar.gz")" > terraform-docs.tgz \
) && tar -xzf terraform-docs.tgz terraform-docs && rm terraform-docs.tgz && chmod +x terraform-docs \ ) && tar -xzf terraform-docs.tgz terraform-docs && rm terraform-docs.tgz && chmod +x terraform-docs \
; fi ; fi
@ -97,9 +97,9 @@ RUN . /.env && \
RUN . /.env \ RUN . /.env \
&& if [ "$TERRAGRUNT_VERSION" != "false" ]; then \ && if [ "$TERRAGRUNT_VERSION" != "false" ]; then \
( \ ( \
TERRAGRUNT_RELEASES="https://api.github.com/repos/gruntwork-io/terragrunt/releases" && \ TERRAGRUNT_RELEASES="https://api.github.com/repos/gruntwork-io/terragrunt/releases" && \
[ "$TERRAGRUNT_VERSION" = "latest" ] && curl -L "$(curl -s ${TERRAGRUNT_RELEASES}/latest | grep -o -E -m 1 "https://.+?/terragrunt_${TARGETOS}_${TARGETARCH}")" > terragrunt \ [ "$TERRAGRUNT_VERSION" = "latest" ] && curl -L "$(curl -s ${TERRAGRUNT_RELEASES}/latest | grep -o -E -m 1 "https://.+?/terragrunt_${TARGETOS}_${TARGETARCH}")" > terragrunt \
|| curl -L "$(curl -s ${TERRAGRUNT_RELEASES} | grep -o -E -m 1 "https://.+?v${TERRAGRUNT_VERSION}/terragrunt_${TARGETOS}_${TARGETARCH}")" > terragrunt \ || curl -L "$(curl -s ${TERRAGRUNT_RELEASES} | grep -o -E -m 1 "https://.+?v${TERRAGRUNT_VERSION}/terragrunt_${TARGETOS}_${TARGETARCH}")" > terragrunt \
) && chmod +x terragrunt \ ) && chmod +x terragrunt \
; fi ; fi
@ -111,9 +111,9 @@ RUN . /.env && \
# Convert the first letter to Uppercase # Convert the first letter to Uppercase
OS="$(echo ${TARGETOS} | cut -c1 | tr '[:lower:]' '[:upper:]' | xargs echo -n; echo ${TARGETOS} | cut -c2-)"; \ OS="$(echo ${TARGETOS} | cut -c1 | tr '[:lower:]' '[:upper:]' | xargs echo -n; echo ${TARGETOS} | cut -c2-)"; \
( \ ( \
TERRASCAN_RELEASES="https://api.github.com/repos/tenable/terrascan/releases" && \ TERRASCAN_RELEASES="https://api.github.com/repos/tenable/terrascan/releases" && \
[ "$TERRASCAN_VERSION" = "latest" ] && curl -L "$(curl -s ${TERRASCAN_RELEASES}/latest | grep -o -E -m 1 "https://.+?_${OS}_${ARCH}.tar.gz")" > terrascan.tar.gz \ [ "$TERRASCAN_VERSION" = "latest" ] && curl -L "$(curl -s ${TERRASCAN_RELEASES}/latest | grep -o -E -m 1 "https://.+?_${OS}_${ARCH}.tar.gz")" > terrascan.tar.gz \
|| curl -L "$(curl -s ${TERRASCAN_RELEASES} | grep -o -E "https://.+?${TERRASCAN_VERSION}_${OS}_${ARCH}.tar.gz")" > terrascan.tar.gz \ || curl -L "$(curl -s ${TERRASCAN_RELEASES} | grep -o -E "https://.+?${TERRASCAN_VERSION}_${OS}_${ARCH}.tar.gz")" > terrascan.tar.gz \
) && tar -xzf terrascan.tar.gz terrascan && rm terrascan.tar.gz && \ ) && tar -xzf terrascan.tar.gz terrascan && rm terrascan.tar.gz && \
./terrascan init \ ./terrascan init \
; fi ; fi
@ -122,9 +122,9 @@ RUN . /.env && \
RUN . /.env && \ RUN . /.env && \
if [ "$TFLINT_VERSION" != "false" ]; then \ if [ "$TFLINT_VERSION" != "false" ]; then \
( \ ( \
TFLINT_RELEASES="https://api.github.com/repos/terraform-linters/tflint/releases" && \ TFLINT_RELEASES="https://api.github.com/repos/terraform-linters/tflint/releases" && \
[ "$TFLINT_VERSION" = "latest" ] && curl -L "$(curl -s ${TFLINT_RELEASES}/latest | grep -o -E -m 1 "https://.+?_${TARGETOS}_${TARGETARCH}.zip")" > tflint.zip \ [ "$TFLINT_VERSION" = "latest" ] && curl -L "$(curl -s ${TFLINT_RELEASES}/latest | grep -o -E -m 1 "https://.+?_${TARGETOS}_${TARGETARCH}.zip")" > tflint.zip \
|| curl -L "$(curl -s ${TFLINT_RELEASES} | grep -o -E "https://.+?/v${TFLINT_VERSION}/tflint_${TARGETOS}_${TARGETARCH}.zip")" > tflint.zip \ || curl -L "$(curl -s ${TFLINT_RELEASES} | grep -o -E "https://.+?/v${TFLINT_VERSION}/tflint_${TARGETOS}_${TARGETARCH}.zip")" > tflint.zip \
) && unzip tflint.zip && rm tflint.zip \ ) && unzip tflint.zip && rm tflint.zip \
; fi ; fi
@ -132,9 +132,9 @@ RUN . /.env && \
RUN . /.env && \ RUN . /.env && \
if [ "$TFSEC_VERSION" != "false" ]; then \ if [ "$TFSEC_VERSION" != "false" ]; then \
( \ ( \
TFSEC_RELEASES="https://api.github.com/repos/aquasecurity/tfsec/releases" && \ TFSEC_RELEASES="https://api.github.com/repos/aquasecurity/tfsec/releases" && \
[ "$TFSEC_VERSION" = "latest" ] && curl -L "$(curl -s ${TFSEC_RELEASES}/latest | grep -o -E -m 1 "https://.+?/tfsec-${TARGETOS}-${TARGETARCH}")" > tfsec \ [ "$TFSEC_VERSION" = "latest" ] && curl -L "$(curl -s ${TFSEC_RELEASES}/latest | grep -o -E -m 1 "https://.+?/tfsec-${TARGETOS}-${TARGETARCH}")" > tfsec \
|| curl -L "$(curl -s ${TFSEC_RELEASES} | grep -o -E -m 1 "https://.+?v${TFSEC_VERSION}/tfsec-${TARGETOS}-${TARGETARCH}")" > tfsec \ || curl -L "$(curl -s ${TFSEC_RELEASES} | grep -o -E -m 1 "https://.+?v${TFSEC_VERSION}/tfsec-${TARGETOS}-${TARGETARCH}")" > tfsec \
) && chmod +x tfsec \ ) && chmod +x tfsec \
; fi ; fi
@ -143,9 +143,9 @@ RUN . /.env && \
if [ "$TRIVY_VERSION" != "false" ]; then \ if [ "$TRIVY_VERSION" != "false" ]; then \
if [ "$TARGETARCH" != "amd64" ]; then ARCH="$TARGETARCH"; else ARCH="64bit"; fi; \ if [ "$TARGETARCH" != "amd64" ]; then ARCH="$TARGETARCH"; else ARCH="64bit"; fi; \
( \ ( \
TRIVY_RELEASES="https://api.github.com/repos/aquasecurity/trivy/releases" && \ TRIVY_RELEASES="https://api.github.com/repos/aquasecurity/trivy/releases" && \
[ "$TRIVY_VERSION" = "latest" ] && curl -L "$(curl -s ${TRIVY_RELEASES}/latest | grep -o -E -i -m 1 "https://.+?/trivy_.+?_${TARGETOS}-${ARCH}.tar.gz")" > trivy.tar.gz \ [ "$TRIVY_VERSION" = "latest" ] && curl -L "$(curl -s ${TRIVY_RELEASES}/latest | grep -o -E -i -m 1 "https://.+?/trivy_.+?_${TARGETOS}-${ARCH}.tar.gz")" > trivy.tar.gz \
|| curl -L "$(curl -s ${TRIVY_RELEASES} | grep -o -E -i -m 1 "https://.+?/v${TRIVY_VERSION}/trivy_.+?_${TARGETOS}-${ARCH}.tar.gz")" > trivy.tar.gz \ || curl -L "$(curl -s ${TRIVY_RELEASES} | grep -o -E -i -m 1 "https://.+?/v${TRIVY_VERSION}/trivy_.+?_${TARGETOS}-${ARCH}.tar.gz")" > trivy.tar.gz \
) && tar -xzf trivy.tar.gz trivy && rm trivy.tar.gz \ ) && tar -xzf trivy.tar.gz trivy && rm trivy.tar.gz \
; fi ; fi
@ -153,9 +153,9 @@ RUN . /.env && \
RUN . /.env && \ RUN . /.env && \
if [ "$TFUPDATE_VERSION" != "false" ]; then \ if [ "$TFUPDATE_VERSION" != "false" ]; then \
( \ ( \
TFUPDATE_RELEASES="https://api.github.com/repos/minamijoyo/tfupdate/releases" && \ TFUPDATE_RELEASES="https://api.github.com/repos/minamijoyo/tfupdate/releases" && \
[ "$TFUPDATE_VERSION" = "latest" ] && curl -L "$(curl -s ${TFUPDATE_RELEASES}/latest | grep -o -E -m 1 "https://.+?_${TARGETOS}_${TARGETARCH}.tar.gz")" > tfupdate.tgz \ [ "$TFUPDATE_VERSION" = "latest" ] && curl -L "$(curl -s ${TFUPDATE_RELEASES}/latest | grep -o -E -m 1 "https://.+?_${TARGETOS}_${TARGETARCH}.tar.gz")" > tfupdate.tgz \
|| curl -L "$(curl -s ${TFUPDATE_RELEASES} | grep -o -E -m 1 "https://.+?${TFUPDATE_VERSION}_${TARGETOS}_${TARGETARCH}.tar.gz")" > tfupdate.tgz \ || curl -L "$(curl -s ${TFUPDATE_RELEASES} | grep -o -E -m 1 "https://.+?${TFUPDATE_VERSION}_${TARGETOS}_${TARGETARCH}.tar.gz")" > tfupdate.tgz \
) && tar -xzf tfupdate.tgz tfupdate && rm tfupdate.tgz \ ) && tar -xzf tfupdate.tgz tfupdate && rm tfupdate.tgz \
; fi ; fi
@ -163,9 +163,9 @@ RUN . /.env && \
RUN . /.env && \ RUN . /.env && \
if [ "$HCLEDIT_VERSION" != "false" ]; then \ if [ "$HCLEDIT_VERSION" != "false" ]; then \
( \ ( \
HCLEDIT_RELEASES="https://api.github.com/repos/minamijoyo/hcledit/releases" && \ HCLEDIT_RELEASES="https://api.github.com/repos/minamijoyo/hcledit/releases" && \
[ "$HCLEDIT_VERSION" = "latest" ] && curl -L "$(curl -s ${HCLEDIT_RELEASES}/latest | grep -o -E -m 1 "https://.+?_${TARGETOS}_${TARGETARCH}.tar.gz")" > hcledit.tgz \ [ "$HCLEDIT_VERSION" = "latest" ] && curl -L "$(curl -s ${HCLEDIT_RELEASES}/latest | grep -o -E -m 1 "https://.+?_${TARGETOS}_${TARGETARCH}.tar.gz")" > hcledit.tgz \
|| curl -L "$(curl -s ${HCLEDIT_RELEASES} | grep -o -E -m 1 "https://.+?${HCLEDIT_VERSION}_${TARGETOS}_${TARGETARCH}.tar.gz")" > hcledit.tgz \ || curl -L "$(curl -s ${HCLEDIT_RELEASES} | grep -o -E -m 1 "https://.+?${HCLEDIT_VERSION}_${TARGETOS}_${TARGETARCH}.tar.gz")" > hcledit.tgz \
) && tar -xzf hcledit.tgz hcledit && rm hcledit.tgz \ ) && tar -xzf hcledit.tgz hcledit && rm hcledit.tgz \
; fi ; fi
@ -208,9 +208,8 @@ COPY --from=builder \
/usr/local/bin/pre-commit \ /usr/local/bin/pre-commit \
# Hooks and terraform binaries # Hooks and terraform binaries
/bin_dir/ \ /bin_dir/ \
/usr/bin/tofu \
/usr/local/bin/checkov* \ /usr/local/bin/checkov* \
/usr/bin/ /usr/bin/
# Copy pre-commit packages # Copy pre-commit packages
COPY --from=builder /usr/local/lib/python3.12/site-packages/ /usr/local/lib/python3.12/site-packages/ COPY --from=builder /usr/local/lib/python3.12/site-packages/ /usr/local/lib/python3.12/site-packages/
# Copy terrascan policies # Copy terrascan policies
@ -218,10 +217,10 @@ COPY --from=builder /root/ /root/
# Install hooks extra deps # Install hooks extra deps
RUN if [ "$(grep -o '^terraform-docs SKIPPED$' /usr/bin/tools_versions_info)" = "" ]; then \ RUN if [ "$(grep -o '^terraform-docs SKIPPED$' /usr/bin/tools_versions_info)" = "" ]; then \
apk add --no-cache perl=~5 \ apk add --no-cache perl=~5 \
; fi && \ ; fi && \
if [ "$(grep -o '^infracost SKIPPED$' /usr/bin/tools_versions_info)" = "" ]; then \ if [ "$(grep -o '^infracost SKIPPED$' /usr/bin/tools_versions_info)" = "" ]; then \
apk add --no-cache jq=~1 \ apk add --no-cache jq=~1 \
; fi && \ ; fi && \
# Fix git runtime fatal: # Fix git runtime fatal:
# unsafe repository ('/lint' is owned by someone else) # unsafe repository ('/lint' is owned by someone else)

View file

@ -60,7 +60,7 @@ If you are using `pre-commit-opentofu` already or want to support its developmen
</sup></sub></sup></sub></sup></sub></sup></sub></sup></sub></sup></sub></sup></sub></sup></sub></sup></sub><br><br> </sup></sub></sup></sub></sup></sub></sup></sub></sup></sub></sup></sub></sup></sub></sup></sub></sup></sub><br><br>
* [`checkov`](https://github.com/bridgecrewio/checkov) required for `tofu_checkov` hook. * [`checkov`](https://github.com/bridgecrewio/checkov) required for `tofu_checkov` hook.
* [`terraform-docs`](https://github.com/terraform-docs/terraform-docs) required for `tofu_docs` hook. * [`terraform-docs`](https://github.com/terraform-docs/terraform-docs) required for `tofu_docs` hook.
* [`terragrunt`](https://terragrunt.gruntwork.io/docs/getting-started/install/) required for `terragrunt_validate` and `terragrunt_validate_inputs` hooks. * [`terragrunt`](https://terragrunt.gruntwork.io/docs/getting-started/install/) required for `terragrunt_validate` hook.
* [`terrascan`](https://github.com/tenable/terrascan) required for `terrascan` hook. * [`terrascan`](https://github.com/tenable/terrascan) required for `terrascan` hook.
* [`TFLint`](https://github.com/terraform-linters/tflint) required for `tofu_tflint` hook. * [`TFLint`](https://github.com/terraform-linters/tflint) required for `tofu_tflint` hook.
* [`TFSec`](https://github.com/liamg/tfsec) required for `tofu_tfsec` hook. * [`TFSec`](https://github.com/liamg/tfsec) required for `tofu_tfsec` hook.
@ -266,35 +266,9 @@ TAG=latest
docker run --rm --entrypoint cat tofuutils/pre-commit-opentofu:$TAG /usr/bin/tools_versions_info docker run --rm --entrypoint cat tofuutils/pre-commit-opentofu:$TAG /usr/bin/tools_versions_info
``` ```
### Example: Terragrunt Input Validation
Use `terragrunt_validate_inputs` to check that Terragrunt inputs line up with the module variables they are passed into:
```yaml
repos:
- repo: https://github.com/tofuutils/pre-commit-opentofu
rev: <VERSION> # Get the latest from: https://github.com/tofuutils/pre-commit-opentofu/releases
hooks:
- id: terragrunt_fmt
- id: terragrunt_validate_inputs
args:
- --args=--terragrunt-strict-validate
```
> **Note**: This hook automatically uses `terragrunt validate-inputs` for older Terragrunt releases and `terragrunt hcl validate --inputs` for newer releases.
>
> If Terragrunt reports intermittent `.terragrunt-cache` download or `file exists` errors in your repository, run this hook serially in your consumer configuration:
>
> ```yaml
> - id: terragrunt_validate_inputs
> require_serial: true
> args:
> - --args=--terragrunt-strict-validate
> ```
## Available Hooks ## Available Hooks
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: 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:
<!-- 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> |
@ -312,7 +286,6 @@ There are several [pre-commit](https://pre-commit.com/) hooks to keep OpenTofu c
| `tofu_validate` | Validates all Terraform configuration files. [Hook notes](#tofu_validate) | `jq`, only for `--retry-once-with-cleanup` flag | | `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_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` | 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](#terraform_wrapper_module_for_each) | `hcledit` |
| `terrascan` | [terrascan](https://github.com/tenable/terrascan) Detect compliance and security violations. [Hook notes](#terrascan) | `terrascan` | | `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` | | `tfupdate` | [tfupdate](https://github.com/minamijoyo/tfupdate) Update version constraints of OpenTofu core, providers, and modules. [Hook notes](#tfupdate) | `tfupdate` |
@ -326,8 +299,6 @@ 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`
@ -581,7 +552,7 @@ To replicate functionality in `tofu_docs` hook:
- --args=--config=.terraform-docs.yml - --args=--config=.terraform-docs.yml
``` ```
### tofu_fmt ### terraftofu_fmtorm_fmt
1. `tofu_fmt` supports custom arguments so you can pass [supported flags](https://www.terraform.io/docs/cli/commands/fmt.html#usage). Eg: 1. `tofu_fmt` supports custom arguments so you can pass [supported flags](https://www.terraform.io/docs/cli/commands/fmt.html#usage). Eg:
@ -718,7 +689,7 @@ To replicate functionality in `tofu_docs` hook:
- --args=--config=__GIT_WORKING_DIR__/.tflint.hcl - --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 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: 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:
```yaml ```yaml
- id: tofu_tflint - id: tofu_tflint
@ -932,7 +903,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|tofu|tfvars)$ files: \.tf(vars)?$
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

@ -112,7 +112,7 @@ function common::parse_and_export_env_vars {
while true; do while true; do
# Check if at least 1 env var exists in `$arg` # Check if at least 1 env var exists in `$arg`
# shellcheck disable=SC2016 # '${' should not be expanded # shellcheck disable=SC2016 # '${' should not be expanded
if [[ "$arg" =~ .*'${'[A-Z_][A-Z0-9_]*'}'.* ]]; then if [[ "$arg" =~ .*'${'[A-Z_][A-Z0-9_]+?'}'.* ]]; then
# Get `ENV_VAR` from `.*${ENV_VAR}.*` # Get `ENV_VAR` from `.*${ENV_VAR}.*`
local env_var_name=${arg#*$\{} local env_var_name=${arg#*$\{}
env_var_name=${env_var_name%%\}*} env_var_name=${env_var_name%%\}*}
@ -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

@ -70,24 +70,19 @@ function infracost_breakdown_ {
# -h .totalHourlyCost > 0.1 # -h .totalHourlyCost > 0.1
# --hook-config=.currency == "USD" # --hook-config=.currency == "USD"
first_char=${check:0:1} first_char=${check:0:1}
last_char=${check:$((${#check} - 1)):1} last_char=${check: -1}
if [ "$first_char" == "$last_char" ] && { if [ "$first_char" == "$last_char" ] && {
[ "$first_char" == '"' ] || [ "$first_char" == "'" ] [ "$first_char" == '"' ] || [ "$first_char" == "'" ]
}; then }; then
check="${check:1:$((${#check} - 2))}" check="${check:1:-1}"
fi fi
# Replace mapfile with while read loop for bash 3.2 compatibility mapfile -t operations < <(echo "$check" | grep -oE '[!<>=]{1,2}')
operations=()
while IFS= read -r line; do
operations+=("$line")
done < <(echo "$check" | grep -oE '[!<>=]{1,2}')
# Get the very last operator, that is used in comparison inside `jq` query. # Get the very last operator, that is used in comparison inside `jq` query.
# From the example below we need to pick the `>` which is in between `add` and `1000`, # From the example below we need to pick the `>` which is in between `add` and `1000`,
# but not the `!=`, which goes earlier in the `jq` expression # but not the `!=`, which goes earlier in the `jq` expression
# [.projects[].diff.totalMonthlyCost | select (.!=null) | tonumber] | add > 1000 # [.projects[].diff.totalMonthlyCost | select (.!=null) | tonumber] | add > 1000
operation=${operations[$((${#operations[@]} - 1))]} operation=${operations[-1]}
IFS="$operation" read -r -a jq_check <<< "$check" IFS="$operation" read -r -a jq_check <<< "$check"
real_value="$(jq "${jq_check[0]}" <<< "$RESULTS")" real_value="$(jq "${jq_check[0]}" <<< "$RESULTS")"

View file

@ -12,7 +12,7 @@ function main {
common::parse_cmdline "$@" common::parse_cmdline "$@"
common::export_provided_env_vars "${ENV_VARS[@]}" common::export_provided_env_vars "${ENV_VARS[@]}"
common::parse_and_export_env_vars common::parse_and_export_env_vars
# JFYI: terragrunt hcl format color already suppressed via PRE_COMMIT_COLOR=never # JFYI: terragrunt hclfmt color already suppressed via PRE_COMMIT_COLOR=never
# shellcheck disable=SC2153 # False positive # shellcheck disable=SC2153 # False positive
common::per_dir_hook "$HOOK_ID" "${#ARGS[@]}" "${ARGS[@]}" "${FILES[@]}" common::per_dir_hook "$HOOK_ID" "${#ARGS[@]}" "${ARGS[@]}" "${FILES[@]}"
@ -40,7 +40,7 @@ function per_dir_hook_unique_part {
local -a -r args=("$@") local -a -r args=("$@")
# pass the arguments to hook # pass the arguments to hook
terragrunt hcl format "${args[@]}" terragrunt hclfmt "${args[@]}"
# return exit code to common::per_dir_hook # return exit code to common::per_dir_hook
local exit_code=$? local exit_code=$?
@ -57,7 +57,7 @@ function run_hook_on_whole_repo {
local -a -r args=("$@") local -a -r args=("$@")
# pass the arguments to hook # pass the arguments to hook
terragrunt hcl format "$(pwd)" "${args[@]}" terragrunt hclfmt "$(pwd)" "${args[@]}"
# return exit code to common::per_dir_hook # return exit code to common::per_dir_hook
local exit_code=$? local exit_code=$?

View file

@ -1,198 +0,0 @@
#!/usr/bin/env bash
set -eo pipefail
# globals variables
# shellcheck disable=SC2155 # No way to assign to readonly variable in separate lines
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
# shellcheck source=_common.sh
. "$SCRIPT_DIR/_common.sh"
function main {
common::initialize "$SCRIPT_DIR"
common::parse_cmdline "$@"
common::export_provided_env_vars "${ENV_VARS[@]}"
common::parse_and_export_env_vars
# JFYI: terragrunt validate color already suppressed via PRE_COMMIT_COLOR=never
if terragrunt_version_ge_0_78; then
normalize_validate_args_for_modern_terragrunt
readonly SUBCOMMAND=("hcl" "validate" "--inputs")
readonly RUN_ALL_SUBCOMMAND=("run" "--all" "hcl" "validate" "--inputs")
# shellcheck disable=SC2153 # False positive
common::per_dir_hook "$HOOK_ID" "${#ARGS[@]}" "${ARGS[@]}" "${FILES[@]}"
return
fi
run_legacy_validate_inputs
}
function normalize_validate_args_for_modern_terragrunt {
local arg_idx
for arg_idx in "${!ARGS[@]}"; do
case "${ARGS[$arg_idx]}" in
--terragrunt-strict-validate | --strict-validate)
ARGS[arg_idx]="--strict"
;;
esac
done
}
function terragrunt_version_ge_0_78 {
local version_raw
local version
local major
local minor
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/')
if [[ ! $version =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
return 1
fi
IFS=. read -r major minor _ <<< "$version"
if ((major > 0)); then
return 0
fi
if ((minor >= 78)); then
return 0
fi
return 1
}
function run_legacy_validate_inputs {
local -a unit_dirs=()
local final_exit_code=0
local dir_path
while read -r dir_path; do
if [[ -n $dir_path ]]; then
unit_dirs+=("$dir_path")
fi
done < <(legacy_unit_dirs_from_files)
if [[ ${#unit_dirs[@]} -eq 0 ]]; then
return 0
fi
# preserve errexit status
shopt -qo errexit && ERREXIT_IS_SET=true
set +e
for dir_path in "${unit_dirs[@]}"; do
pushd "$dir_path" > /dev/null || continue
terragrunt validate-inputs "${ARGS[@]}"
local exit_code=$?
if [ $exit_code -ne 0 ]; then
final_exit_code=$exit_code
fi
popd > /dev/null
done
[[ $ERREXIT_IS_SET ]] && set -e
exit $final_exit_code
}
function legacy_unit_dirs_from_files {
local -a unit_files=()
local file_with_path
local file_dir
local file_name
if common::is_hook_run_on_whole_repo "$HOOK_ID" "${FILES[@]}"; then
find . -type f -name terragrunt.hcl \
-not -path '*/.terragrunt-cache/*' \
-not -path '*/.terraform/*' |
sort -u | while read -r unit_file; do
dirname "$unit_file"
done
return
fi
for file_with_path in "${FILES[@]}"; do
file_dir=$(dirname "$file_with_path")
file_name=$(basename "$file_with_path")
if [[ $file_name == terragrunt.hcl ]]; then
unit_files+=("$file_with_path")
continue
fi
while read -r unit_file; do
if [[ -n $unit_file ]]; then
unit_files+=("$unit_file")
fi
done < <(find "$file_dir" -type f -name terragrunt.hcl \
-not -path '*/.terragrunt-cache/*' \
-not -path '*/.terraform/*' | sort -u)
done
if [[ ${#unit_files[@]} -eq 0 ]]; then
find . -type f -name terragrunt.hcl \
-not -path '*/.terragrunt-cache/*' \
-not -path '*/.terraform/*' |
sort -u | while read -r unit_file; do
dirname "$unit_file"
done
return
fi
printf '%s\n' "${unit_files[@]}" | sort -u | while read -r unit_file; do
dirname "$unit_file"
done
}
#######################################################################
# Unique part of `common::per_dir_hook`. The function is executed in loop
# on each provided dir path. Run wrapped tool with specified arguments
# Arguments:
# dir_path (string) PATH to dir relative to git repo root.
# Can be used in error logging
# change_dir_in_unique_part (string/false) Modifier which creates
# possibilities to use non-common chdir strategies.
# Availability depends on hook.
# args (array) arguments that configure wrapped tool behavior
# Outputs:
# If failed - print out hook checks status
#######################################################################
function per_dir_hook_unique_part {
# shellcheck disable=SC2034 # Unused var.
local -r dir_path="$1"
# shellcheck disable=SC2034 # Unused var.
local -r change_dir_in_unique_part="$2"
shift 2
local -a -r args=("$@")
# pass the arguments to hook
terragrunt "${SUBCOMMAND[@]}" "${args[@]}"
# return exit code to common::per_dir_hook
local exit_code=$?
return $exit_code
}
#######################################################################
# Unique part of `common::per_dir_hook`. The function is executed one time
# in the root git repo
# Arguments:
# args (array) arguments that configure wrapped tool behavior
#######################################################################
function run_hook_on_whole_repo {
local -a -r args=("$@")
# pass the arguments to hook
terragrunt "${RUN_ALL_SUBCOMMAND[@]}" "${args[@]}"
# return exit code to common::per_dir_hook
local exit_code=$?
return $exit_code
}
[ "${BASH_SOURCE[0]}" != "$0" ] || main "$@"

View file

@ -155,7 +155,7 @@ function tofu_docs {
# #
if $create_if_not_exist && [[ ! -f "$text_file" ]]; then if $create_if_not_exist && [[ ! -f "$text_file" ]]; then
dir_have_tf_files="$( dir_have_tf_files="$(
find . -maxdepth 1 -type f | sed 's|.*\.||' | sort -u | grep -oE '^tofu|^tf$|^tfvars$' || find . -maxdepth 1 -type f | sed 's|.*\.||' | sort -u | grep -oE '^tf$|^tfvars$' ||
exit 0 exit 0
)" )"

View file

@ -7,41 +7,30 @@ import sys
def main(argv=None): def main(argv=None):
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
description="""Run terraform-docs on a set of files. Follows the standard convention of description="""Run terraform-docs on a set of files. Follows the standard convention of
pulling the documentation from main.(tf|tofu) in order to replace the entire pulling the documentation from main.tf in order to replace the entire
README.md file each time.""" README.md file each time."""
) )
parser.add_argument( parser.add_argument(
"--dest", '--dest', dest='dest', default='README.md',
dest="dest",
default="README.md",
) )
parser.add_argument( parser.add_argument(
"--sort-inputs-by-required", '--sort-inputs-by-required', dest='sort', action='store_true',
dest="sort", help='[deprecated] use --sort-by-required instead',
action="store_true",
help="[deprecated] use --sort-by-required instead",
) )
parser.add_argument( parser.add_argument(
"--sort-by-required", '--sort-by-required', dest='sort', action='store_true',
dest="sort",
action="store_true",
) )
parser.add_argument( parser.add_argument(
"--with-aggregate-type-defaults", '--with-aggregate-type-defaults', dest='aggregate', action='store_true',
dest="aggregate", help='[deprecated]',
action="store_true",
help="[deprecated]",
) )
parser.add_argument("filenames", nargs="*", help="Filenames to check.") parser.add_argument('filenames', nargs='*', help='Filenames to check.')
args = parser.parse_args(argv) args = parser.parse_args(argv)
dirs = [] dirs = []
for filename in args.filenames: for filename in args.filenames:
if os.path.realpath(filename) not in dirs and ( if (os.path.realpath(filename) not in dirs and
filename.endswith(".tf") (filename.endswith(".tf") or filename.endswith(".tfvars"))):
or filename.endswith(".tofu")
or filename.endswith(".tfvars")
):
dirs.append(os.path.dirname(filename)) dirs.append(os.path.dirname(filename))
retval = 0 retval = 0
@ -49,12 +38,12 @@ def main(argv=None):
for dir in dirs: for dir in dirs:
try: try:
procArgs = [] procArgs = []
procArgs.append("terraform-docs") procArgs.append('terraform-docs')
if args.sort: if args.sort:
procArgs.append("--sort-by-required") procArgs.append('--sort-by-required')
procArgs.append("md") procArgs.append('md')
procArgs.append("./{dir}".format(dir=dir)) procArgs.append("./{dir}".format(dir=dir))
procArgs.append(">") procArgs.append('>')
procArgs.append("./{dir}/{dest}".format(dir=dir, dest=args.dest)) procArgs.append("./{dir}/{dest}".format(dir=dir, dest=args.dest))
subprocess.check_call(" ".join(procArgs), shell=True) subprocess.check_call(" ".join(procArgs), shell=True)
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
@ -63,5 +52,5 @@ def main(argv=None):
return retval return retval
if __name__ == "__main__": if __name__ == '__main__':
sys.exit(main()) sys.exit(main())

View file

@ -312,10 +312,10 @@ EOF
# Read content of all OpenTofu files # Read content of all OpenTofu files
# shellcheck disable=SC2207 # shellcheck disable=SC2207
all_tf_content=$(find "${full_module_dir}" -regex '.*\.(tf|tofu)' -maxdepth 1 -type f -exec cat {} +) all_tf_content=$(find "${full_module_dir}" -name '*.tf' -maxdepth 1 -type f -exec cat {} +)
if [[ ! $all_tf_content ]]; then if [[ ! $all_tf_content ]]; then
common::colorify "yellow" "Skipping ${full_module_dir} because there are no .tf or .tofu files." common::colorify "yellow" "Skipping ${full_module_dir} because there are no *.tf files."
continue continue
fi fi

View file

@ -360,7 +360,7 @@ getopt() {
} }
_getopt_resolve_abbrev() { _getopt_resolve_abbrev() {
# Resolves an abbreviation from a list of possibilities. # Resolves an abbrevation from a list of possibilities.
# If the abbreviation is unambiguous, echoes the expansion on stdout # If the abbreviation is unambiguous, echoes the expansion on stdout
# and returns 0. If the abbreviation is ambiguous, prints a message on # and returns 0. If the abbreviation is ambiguous, prints a message on
# stderr and returns 1. (For first parse this should convert to exit # stderr and returns 1. (For first parse this should convert to exit