pre-commit
pre-commit runs a repository's checks on every git commit, against the files being committed, so formatting, scanning and layout mistakes are caught before a pull request exists. Every GCP repository except the GitOps repository ships a .pre-commit-config.yaml; the guard scripts, formatting checks, tflint and Checkov run again in the infrastructure plan workflows, so skipping a hook locally does not skip them.
What it does
pre-commit install adds a Git hook that runs the configured hooks; pre-commit run --all-files runs them on the whole repository. A hook comes from a pinned repository revision, or is a local hook that calls a script in the repository. Each hook declares which files it applies to.
How BuiltForProd uses it
Infrastructure repositories share a base set: whitespace and end-of-file fixers, YAML and merge-conflict checks and detect-private-key (pre-commit-hooks v6.0.0); tofu_fmt, tofu_validate and tofu_docs (pre-commit-opentofu v2.4.2); terragrunt_fmt, terraform_tflint and terraform_trivy (pre-commit-terraform v1.109.1); and Checkov 3.3.19. On top of that, each runs its guard scripts as local hooks:
| Guard script | Baseline | Web App | Data and ETL | Keeps |
|---|---|---|---|---|
check-no-hardcoded-cidrs.py | yes | Private ranges out of HCL; they come from network_map.yaml | ||
check-network-maps.py | yes | The address plan valid, nested and non-overlapping | ||
check-mock-outputs.py | yes | yes | yes | Complete mock outputs on every dependency |
check-stack-layout.py | yes | yes | yes | One stack file per region folder, every unit definition referenced |
check-module-versions.py | yes | yes | yes | Module versions.tf files repeating the root.hcl pins |
check-required-inputs.py | yes | yes | yes | Every required module input supplied by its unit |
check-contract.py | yes | One identical contract reader per module, and only parameters the landing zone publishes |
The Baseline also ships scripts/write-org-projects.py, which is not a hook: the organizations unit runs it to write org_projects.hcl; see Terragrunt.
Code repositories (acme-gcp-blueprint-webapp-code, -etl-code) run the pre-commit-hooks checks plus a JSON check, ruff 0.16.10 for linting and formatting (the same version CI pins), actionlint for the workflows, shellcheck for the deploy scripts, and Checkov 3.3.22 over the whole repository.
The secrets repository runs YAML, private-key and end-of-file checks and a local sops-encrypted hook that refuses any stage file under sandbox/, dev/, staging/ or prod/ that is not SOPS-encrypted, so a plaintext value cannot be committed by accident; see SOPS.
Terms you will see
| Term | Meaning |
|---|---|
| Hook | One check pre-commit runs, from a pinned repository or a local script. |
| Guard script | A Python check in scripts/ that enforces a layout or configuration rule. |
| Contract reader | The contract.tf file through which a blueprint module reads Parameter Manager. |
sops-encrypted | The secrets repository's hook that blocks plaintext stage files. |
Where to read more
- GCP Enterprise Baseline overview for the repository layout.
- Checkov, Trivy and tflint for the scanners.
- Policy as code for how the checks fit the controls.