-
Notifications
You must be signed in to change notification settings - Fork 163
/
Copy pathREADME.md
328 lines (232 loc) · 8.66 KB
/
README.md
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
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
# Seamless integration of [pre-commit](https://pre-commit.com/) git hooks with [Nix](https://nixos.org/nix)
![pre-commit.png](pre-commit.png)
The goal is to **manage commit hooks with Nix** and solve the following:
- **Trivial integration for Nix projects** (wires up a few things behind the scenes)
- Provide a low-overhead build of all the tooling available for the hooks to use
(naive implementation of calling nix-shell does bring some latency when committing)
- **Common hooks for languages** like Python, Haskell, Elm, etc.
- Run hooks **as part of development** and **on your CI**
# Getting started
## devenv.sh
https://devenv.sh/pre-commit-hooks/
## Nix
1. (optional) Use binary caches to avoid compilation:
```bash
nix-env -iA cachix -f https://cachix.org/api/v1/install
cachix use pre-commit-hooks
```
2. Integrate hooks to be built as part of `default.nix`:
```nix
let
nix-pre-commit-hooks = import (builtins.fetchTarball "https://github.com/cachix/pre-commit-hooks.nix/tarball/master");
in {
pre-commit-check = nix-pre-commit-hooks.run {
src = ./.;
# If your hooks are intrusive, avoid running on each commit with a default_states like this:
# default_stages = ["manual" "push"];
hooks = {
elm-format.enable = true;
ormolu.enable = true;
shellcheck.enable = true;
};
# Some hooks offer custom settings that affect how they execute
settings = {
ormolu.defaultExtensions = [ "lhs" "hs" ];
};
};
}
```
Run `$ nix-build -A pre-commit-check` to perform the checks as a Nix derivation.
3. Integrate hooks to prepare environment as part of `shell.nix`:
```nix
(import <nixpkgs> {}).mkShell {
shellHook = ''
${(import ./default.nix).pre-commit-check.shellHook}
'';
}
```
Add `/.pre-commit-config.yaml` to `.gitignore`.
Run `$ nix-shell` to execute `shellHook` which will:
- build the tools and `.pre-commit-config.yaml` config file symlink which
references the binaries, for speed and safe garbage collection
- provide the `pre-commit` executable that `git commit` will invoke
## Optional
### Direnv
`.envrc`:
```
use nix
```
# Hooks
## Nix
- [alejandra](https://github.com/kamadorueda/alejandra)
- [deadnix](https://github.com/astro/deadnix)
- [nixpkgs-fmt](https://github.com/nix-community/nixpkgs-fmt)
- [nixfmt](https://github.com/serokell/nixfmt/)
- [statix](https://github.com/nerdypepper/statix)
## Haskell
- [ormolu](https://github.com/tweag/ormolu)
- [fourmolu](https://github.com/parsonsmatt/fourmolu)
- [hindent](https://github.com/chrisdone/hindent)
- [stylish-haskell](https://github.com/jaspervdj/stylish-haskell)
- [hlint](https://github.com/ndmitchell/hlint)
- [cabal-fmt](https://github.com/phadej/cabal-fmt)
- [hpack](https://github.com/sol/hpack)
## Clojure
- [zprint](https://github.com/kkinnear/zprint)
## Elm
- [elm-format](https://github.com/avh4/elm-format)
- [elm-review](https://github.com/jfmengels/elm-review)
- [elm-test](https://github.com/rtfeldman/node-test-runner)
## OCaml
- [dune-opam-sync](https://dune.build/)
- [opam-lint](https://opam.ocaml.org/)
- [ocp-indent](http://www.typerex.org/ocp-indent.html)
## Purescript
- [purty](https://gitlab.com/joneshf/purty)
## Python
- [autoflake](https://github.com/PyCQA/autoflake)
- [black](https://github.com/psf/black)
- [ruff](https://github.com/charliermarsh/ruff)
- [isort](https://github.com/PyCQA/isort)
- [pylint](https://github.com/PyCQA/pylint)
- [flake8](https://github.com/PyCQA/flake8)
## PHP
- [php-cs-fixer](https://github.com/PHP-CS-Fixer/PHP-CS-Fixer)
- [phpcbf](https://github.com/squizlabs/PHP_CodeSniffer)
- [phpcs](https://github.com/squizlabs/PHP_CodeSniffer)
## Rust
- [rustfmt](https://github.com/rust-lang/rustfmt)
- [clippy](https://github.com/rust-lang/rust-clippy)
- cargo-check: Runs `cargo check`
## Golang
- gofmt: Runs `go fmt`
- gotest: Runs `go test`
- [govet](https://pkg.go.dev/cmd/vet)
- [revive](https://github.com/mgechev/revive)
- [staticcheck](https://github.com/dominikh/go-tools)
## Shell
- [shellcheck](https://github.com/koalaman/shellcheck)
- [shfmt](https://github.com/mvdan/sh)
- [bats](https://github.com/bats-core/bats-core)
## LaTeX
- [chktex](https://www.nongnu.org/chktex/)
- [latexindent](https://github.com/cmhughes/latexindent.pl)
## Lua
- [luacheck](https://github.com/mpeterv/luacheck)
- [stylua](https://github.com/JohnnyMorganz/StyLua)
## HTML
- [html-tidy](https://github.com/htacg/tidy-html5)
## Markdown
- [markdownlint](https://github.com/DavidAnson/markdownlint)
- [mdsh](https://zimbatm.github.io/mdsh/)
## Terraform
- `terraform-format`: built-in formatter
## TOML
- [taplo fmt](https://github.com/tamasfe/taplo)
## Spell checkers
- [hunspell](https://github.com/hunspell/hunspell)
- [typos](https://github.com/crate-ci/typos)
## Other Formatters
- [prettier](https://prettier.io)
- `dhall format`: built-in formatter
- [clang-format](https://clang.llvm.org/docs/ClangFormat.html)
- [hadolint](https://github.com/hadolint/hadolint)
- [editorconfig-checker](https://github.com/editorconfig-checker/editorconfig-checker)
- [actionlint](https://github.com/rhysd/actionlint)
You must configure which languages should be formatted by `clang_format` using
`clang-format.types_or`. For example to check both C and C++ files:
```nix
clang-format = {
enable = true;
types_or = [ "c" "c++" ];
};
```
## Git
- [commitizen](https://github.com/commitizen-tools/commitizen)
## Custom hooks
Sometimes it is useful to add a project specific command as an extra check that
is not part of the pre-defined set of hooks provided by this project.
Example configuration:
```nix
let
nix-pre-commit-hooks = import (builtins.fetchTarball "https://github.com/cachix/pre-commit-hooks.nix/tarball/master");
in {
pre-commit-check = nix-pre-commit-hooks.run {
hooks = {
# ...
# Example custom hook for a C project using Make:
unit-tests = {
enable = true;
# The name of the hook (appears on the report table):
name = "Unit tests";
# The command to execute (mandatory):
entry = "make check";
# The pattern of files to run on (default: "" (all))
# see also https://pre-commit.com/#hooks-files
files = "\\.(c|h)$";
# List of file types to run on (default: [ "file" ] (all files))
# see also https://pre-commit.com/#filtering-files-with-types
# You probably only need to specify one of `files` or `types`:
types = [ "text" "c" ];
# Exclude files that were matched by these patterns (default: [ ] (none)):
excludes = [ "irrelevant\\.c" ];
# The language of the hook - tells pre-commit
# how to install the hook (default: "system")
# see also https://pre-commit.com/#supported-languages
language = "system";
# Set this to false to not pass the changed files
# to the command (default: true):
pass_filenames = false;
};
};
};
}
```
Custom hooks are defined with the same schema as [pre-defined
hooks](modules/pre-commit.nix).
# Nix Flakes support
Given the following `flake.nix` example:
```nix
{
description = "An example project.";
inputs.pre-commit-hooks.url = "github:cachix/pre-commit-hooks.nix";
inputs.flake-utils.url = "github:numtide/flake-utils";
outputs = { self, nixpkgs, pre-commit-hooks, flake-utils }:
flake-utils.lib.eachDefaultSystem (system:
{
checks = {
pre-commit-check = pre-commit-hooks.lib.${system}.run {
src = ./.;
hooks = {
nixpkgs-fmt.enable = true;
};
};
};
devShell = nixpkgs.legacyPackages.${system}.mkShell {
inherit (self.checks.${system}.pre-commit-check) shellHook;
};
}
);
}
```
Add `/.pre-commit-config.yaml` to the `.gitignore`.
To run the all the hooks on CI:
```bash
nix flake check
```
To install pre-commit hooks developers would run:
```bash
nix develop
```
# Contributing hooks
Everyone is encouraged to add new hooks.
<!-- TODO generate option docs -->
Have a look at the [existing hooks](modules/hooks.nix) and the [options](modules/pre-commit.nix).
There's no guarantee the hook will be accepted, but the general guidelines are:
- Nix closure of the tool should be small e.g. `< 50MB`. A problematic example:
```
$ du -sh $(nix-build -A go)
463M /nix/store/v4ys4lrjngf62lvvrdbs7r9kbxh9nqaa-go-1.18.6
```
- The tool must not be very specific (e.g. language tooling is OK, but project specific tooling is not)
- The tool needs to live in a separate repository (even if a simple bash script, unless it's a oneliner)