Repository navigation
Expand file tree
/
Copy path.pre-commit-config.yaml
More file actions
208 lines (195 loc) · 8.53 KB
/
Copy path.pre-commit-config.yaml
File metadata and controls
208 lines (195 loc) · 8.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
# Pre-commit hooks configuration
# Install: pip install pre-commit
# Setup: pre-commit install
repos:
# Go formatting and module checks
- repo: local
hooks:
- id: go-fmt
name: Run gofmt
entry: bash scripts/gofmt-hook.sh
language: system
files: \.go$
- id: go-mod-tidy
name: Run go mod tidy
entry: make tidy-check
language: system
pass_filenames: false
require_serial: true
files: '(\.go$|(^|/)go\.(mod|sum)$)'
- repo: local
hooks:
- id: go-vet
name: Run go vet
entry: bash -c 'go vet ./...'
language: system
pass_filenames: false
files: \.go$
# General file checks
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: 3e8a8703264a2f4a69428a0aa4dcb512790b2c8c # v6.0.0
hooks:
- id: trailing-whitespace
name: Trim trailing whitespace
- id: end-of-file-fixer
name: Fix end of files
- id: check-yaml
name: Check YAML syntax
- id: check-json
name: Check JSON syntax
- id: check-added-large-files
name: Check for large files
args: ['--maxkb=1024']
- id: check-merge-conflict
name: Check for merge conflicts
- id: detect-private-key
name: Detect private keys
# Only these test fixtures embed PEM-shaped dummy keys; any other file is scanned.
exclude: '^(cmd/configure_test\.go|cmd/configure_gcp_test\.go|cmd/configure_gcp_store_test\.go)$'
- id: check-case-conflict
name: Check for case conflicts
# Dockerfile linting
#
# The upstream hadolint-docker hook (hadolint/hadolint's own
# .pre-commit-hooks.yaml) declares `entry: ghcr.io/hadolint/hadolint
# hadolint` with no image tag, so Docker resolves it to `:latest` on every
# run -- independent of any `rev:` pin, which only pins which commit of the
# *hook definition* is used, not the Docker image it runs. When upstream
# published hadolint 2.15.1 as `latest`, CI silently started linting with a
# newer ruleset (new DL3066/DL3025 findings on unchanged Dockerfiles) with no
# corresponding change in this repo, and `main` went red (issue #1695).
#
# Defined as a local hook instead, pinned to an immutable digest, so the
# linter version can only change through an explicit edit to this line.
#
# Pinned to 2.15.1 -- the version that surfaced the findings -- rather than
# back to 2.14.0. Pinning to the older image would also have made CI green,
# but only by un-seeing findings that are real; the four it reported are
# fixed in the Dockerfiles rather than silenced. Bumping this digest is
# expected to require fixing whatever the new version finds.
- repo: local
hooks:
- id: hadolint
name: Lint Dockerfiles
language: docker_image
entry: ghcr.io/hadolint/hadolint:v2.15.1@sha256:32dac94127fd60b7b7e3fbfc65e1383b9b5e25c9bfd7b8536de7a539fe68a12d hadolint
types: [dockerfile]
# GitHub Actions workflow linting
#
# Runs the same two linters as ci.yml's workflow-lint job, at the same pinned
# versions, so an expression injection is caught before the push rather than
# after. Keep the versions here and in ci.yml in lockstep.
#
# actionlint is a local docker_image hook rather than the upstream
# rhysd/actionlint hook for the reason spelled out above for hadolint: the
# upstream actionlint-docker hook's entry pins the image by mutable tag, and
# `rev:` only pins the hook definition, not the image it runs. This entry
# pins the digest, so the ruleset can only change by editing this line.
#
# The image bundles shellcheck. actionlint silently skips every run: block
# and still exits 0 when shellcheck is absent from PATH, which is how the
# rollback.yml injection (#1542) went unflagged, so a system hook that
# depends on each developer having shellcheck installed would reintroduce
# exactly that gap.
- repo: local
hooks:
- id: actionlint
name: Lint GitHub Actions workflows
language: docker_image
entry: rhysd/actionlint:1.7.12@sha256:b1934ee5f1c509618f2508e6eb47ee0d3520686341fec936f3b79331f9315667
types: [yaml]
files: ^\.github/workflows/
# zizmor is what actually closes the injection gap: actionlint only
# catches this class indirectly, through shellcheck on the expanded
# script, and against the pre-fix rollback.yml it never flagged the
# injected heredoc at all. zizmor's template-injection audit named that
# exact line. Upstream publishes no .pre-commit-hooks.yaml, so this is a
# local hook with the version pinned in additional_dependencies.
#
# Flags mirror ci.yml exactly; keep them in lockstep. --persona=pedantic
# because the default regular persona hides high-severity findings this
# repo had, and --min-severity=medium is a threshold rather than a
# suppression: no baseline file and no per-finding ignores, so every
# medium and high finding fails. The pre-fix injection scored high.
- id: zizmor
name: Audit GitHub Actions workflows for injection
language: python
additional_dependencies: ['zizmor==1.29.0']
entry: zizmor --offline --persona=pedantic --min-severity=medium
types: [yaml]
files: ^\.github/workflows/
# Markdown linting
- repo: https://github.com/igorshubovych/markdownlint-cli
rev: 76b3d32d3f4b965e1d6425253c59407420ae2c43 # v0.47.0
hooks:
- id: markdownlint
name: Lint Markdown files
args: ['--fix']
# Code quality checks
- repo: local
hooks:
- id: gocyclo
name: Check cyclomatic complexity
entry: bash -c 'gocyclo -over 10 $(git ls-files "*.go" | grep -v _test.go | grep -v vendor/) || (echo "⚠️ Functions with cyclomatic complexity over 10 detected. Please refactor." && exit 1)'
language: system
pass_filenames: false
files: \.go$
# Security scanning
- repo: local
hooks:
- id: git-secrets
name: Scan for AWS secrets
entry: git-secrets --scan
language: system
types: [file]
- id: gosec
name: Go security scanner (changed packages)
# Version, installation and strict policy are shared with Make and CI.
entry: bash scripts/gosec-hook.sh
language: system
pass_filenames: true
files: \.go$
- id: trivy-config
name: Trivy config scanner
# Trivy is a required tool: the previous fallback `|| echo
# "skipping"` masked an absent gate, which is worse than no gate.
# Install via `brew install trivy` or `apt install trivy`. CI
# installs trivy v0.69.3 via the workflow step in
# .github/workflows/pre-commit.yml, so PRs are always scanned
# regardless of a developer's local setup.
#
# `**/.terraform` is skipped because it is a gitignored, generated
# local cache (downloaded provider schemas + cached plan snapshots
# from `terraform init`) — never committed and never present in CI
# (which checks out from git), so findings there are local-only
# false positives on third-party provider cache, not on our source.
# The actual terraform module source files are still fully scanned.
entry: bash -c 'trivy config --severity HIGH,CRITICAL --exit-code 1 --skip-dirs terraform/environments/aws --skip-dirs "**/.terraform" --skip-dirs .claude .'
language: system
pass_filenames: false
# Heavy test execution: pre-push stage only.
#
# This rebuilds + runs the full Go test suite, which is the bulk of the
# CI pre-commit job's runtime. It is *redundant in CI* -- the same suite
# is run by ci.yml's `unit-tests` job with -race AND an integration pass
# with -tags=integration.
#
# Moving it to the pre-push stage keeps the local safety net (a plain
# `pre-commit install` arms pre-push too, via default_install_hook_types,
# so devs get it on `git push`) while letting the CI pre-commit workflow
# stay focused on style/security/syntax. Pre-commit's default stage filter is
# `pre-commit`, so the CI workflow's `pre-commit run --all-files` skips
# this hook automatically.
- repo: local
hooks:
- id: go-test
name: Run Go tests (pre-push only; CI covers via ci.yml)
entry: bash -c 'go test -short -race ./...'
language: system
pass_filenames: false
files: \.go$
stages: [pre-push]
# Global configuration
default_stages: [pre-commit, pre-push]
default_install_hook_types: [pre-commit, pre-push]
fail_fast: false