Repository navigation
Expand file tree
/
Copy pathlefthook.yml
More file actions
169 lines (161 loc) · 7.78 KB
/
Copy pathlefthook.yml
File metadata and controls
169 lines (161 loc) · 7.78 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
# lefthook configuration -- fast, cross-language Git hooks manager.
#
# Install: go install github.com/evilmartians/lefthook@latest
# or via npm/cargo/homebrew: https://github.com/evilmartians/lefthook
# Setup: lefthook install
# Run all: lefthook run pre-commit --all-files
pre-commit:
parallel: true
commands:
catalog-validate:
run: uv run --no-project scripts/validate.py
catalog-reference-current:
run: uv run --no-project scripts/build_reference.py --check
review-current:
run: uv run --no-project uphold_check.py --review --check
catalog-tests:
run: uv run --no-project python -m unittest discover -s tests
uphold-check:
run: cargo run --quiet -- check
content-policy:
run: cargo run --quiet -- scan
guards:
run: cargo run --quiet -- guard --stage pre-commit
# gitleaks over the index, the commit-time half of the secret scan the
# `credentials` set leaves to it. The command hooks/lefthook.yml tells a
# lefthook consumer to write; no stdin, because it reads the index itself.
supply-chain-staged:
run: cargo run --quiet -- supply-chain --staged
# The lint profile lives in Cargo.toml, so all three runners hold the crate
# to the same set. What differs is when a contributor hears about it: a
# profile only CI reads is one whose first reader is a failed push.
engine-fmt:
run: cargo fmt --check
# Report rather than fix, which is the one difference from the ruff hook the
# other two runners get: pre-commit and prek own the staged file after a
# hook rewrites it, and a linter that edits a file lefthook has already
# handed to git is a commit that does not contain what was linted.
ruff-check:
glob: "*.py"
run: ruff check {staged_files}
ruff-format:
glob: "*.py"
run: ruff format --check {staged_files}
actionlint:
glob: ".github/workflows/*.{yml,yaml}"
# dist owns .github/workflows/release.yml and rewrites it on
# `dist generate`; a hand edit for a lint does not survive the next one.
# A glob, not a regex: lefthook 2 reads `exclude` as a list of globs, and
# the regex string it replaced matched nothing there.
exclude:
- .github/workflows/release.yml
run: actionlint {staged_files}
# The two shell files this repository ships: the consumer harness and the
# extensionless wrapper a lefthook consumer ran out of the clone, which
# `*.sh` alone would have missed. That wrapper existed to reach a Python
# reconciler PATH could not; the reconcile is `uphold check` now, the
# directory is gone, and the pattern is the plain one again.
shellcheck:
glob: "scripts/*.sh"
run: shellcheck {staged_files}
bashate:
glob: "scripts/*.sh"
run: bashate --ignore E006 {staged_files}
# The same two commands as .pre-commit-config.yaml, over the whole tree.
ast-grep:
run: ast-grep scan
ast-grep-rule-tests:
run: ast-grep test
# Not git hooks. lefthook has no equivalent of pre-commit's manual stage, so the
# checks that are too slow or too host-dependent to sit in front of a commit are
# named groups instead: `lefthook run preflight`, `lefthook run coverage`,
# `lefthook run proofs` and `lefthook run uphold-manual`. Same entry points as
# the manual hooks in .pre-commit-config.yaml, so the three runners are still
# answering one question each.
preflight:
commands:
deps-check:
run: scripts/deps.sh check
coverage:
commands:
coverage:
run: scripts/coverage.sh
# The Kani harnesses. Not pre-push, for the reasons CONTRIBUTING gives under
# "Proving the fail-closed property": minutes of solver time, and a toolchain
# `cargo kani setup` has to fetch first.
proofs:
commands:
kani:
run: cargo kani -j --output-format=terse
# The guards that ask a network the same question once per distinct name or pin:
# too slow for a commit, and too important to leave to whoever pushes next. This
# group is what a scheduled run invokes, and it is the seam the retired
# `hook-pins-resolve` script used to hold at pre-commit's manual stage -- named
# `uphold-manual` because that is what hooks/lefthook.yml publishes to consumers,
# and a repository that runs itself under a different name is documenting a
# workflow nobody else has.
uphold-manual:
commands:
# The pin check is not a command of its own any more. It was
# `hook-pins-resolve`, a Python script asking whether every `rev:` still
# named a ref that exists, beside a `no-stale-hook-pins` guard asking
# whether the pin had fallen behind -- two checkers over one answer, free to
# disagree, and they did: the guard counted a pin it could not reach as
# passed. One `git ls-remote` answers both questions now, inside the guard
# this command runs, and a pin it could not check is exit 2. It ran at
# pre-push as well until the `stale-pins` set gave that stage up; this group
# is the whole of where it runs.
guards:
run: cargo run --quiet -- guard --stage manual
# The `rev:` half of pin freshness, which the guard above leaves to prek:
# the same entry as `prek-pins-current` in .pre-commit-config.yaml.
prek-pins-current:
run: prek update --check
commit-msg:
commands:
# The host-identity rules over the message, which a tree scan never reads:
# the command hooks/lefthook.yml runs as `uphold-scan-text`.
scan-text:
run: cargo run --quiet -- scan --text {1}
guards:
run: cargo run --quiet -- guard --stage commit-msg --message {1}
pre-merge-commit:
commands:
guards:
run: cargo run --quiet -- guard --stage pre-merge-commit
pre-push:
parallel: true
commands:
# The suite and the lint profile, one rung up from the commit. A full
# compile-and-run in front of every commit is how a gate teaches
# `--no-verify`, and a flag learned to skip a slow test run skips the
# guards standing beside it; once per push is where the same two still
# refuse before anything leaves the machine.
# Without the variables git exports to a hook: the fixtures strip them for
# their own `git`, but the tests that spawn the `uphold` binary
# inherit them and read the repository this hook fired in, which is the
# wrong tree for every one of them and a writable one for `hooks install`.
engine-tests:
run: env -u GIT_DIR -u GIT_COMMON_DIR -u GIT_INDEX_FILE -u GIT_WORK_TREE -u GIT_PREFIX -u GIT_OBJECT_DIRECTORY -u GIT_ALTERNATE_OBJECT_DIRECTORIES -u GIT_CONFIG_PARAMETERS cargo test --quiet
engine-clippy:
run: cargo clippy --quiet --all-targets
# `use_stdin: true`, which this was missing. lefthook runs a command under a
# pseudo-TTY by default and that stdin never closes, so git's ref lines
# never arrived and the guards that read the pushed range were asked about
# a push they could not see. They now refuse rather than fall through to
# the working tree, so the omission is a failed push instead of a green
# tick over the wrong tree -- but it is still an omission, and this repo
# had it in the file it publishes as the example.
guards:
use_stdin: true
run: cargo run --quiet -- guard --stage pre-push --remote {1} --remote-url {2}
# The scanners over the pushed range, the command hooks/lefthook.yml tells a
# lefthook consumer to write in their own file. `use_stdin: true` for the
# reason the guards need it: the range is git's ref lines, and without them
# the command refuses. The whole-tree `--all` form is not in `uphold-manual`,
# to match .pre-commit-config.yaml, which leaves it off the manual stage
# because CI runs that stage without the scanners. That file also explains
# why the first push of a branch scans every workflow.
supply-chain:
use_stdin: true
run: cargo run --quiet -- supply-chain