Seamless integration of pre-commit git hooks with Nix
pre-commit manages a set of hooks that are executed by git before committing code:
The goal is to manage these hooks with Nix and solve the following:
-
Simpler 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 package set of hooks for popular languages like Haskell, Elm, etc.
-
Two trivial Nix functions to run hooks as part of development and on your CI
-
Create
.pre-commit-config.yaml
with hooks you want to run in your git repository:repos: - repo: .pre-commit-hooks/ rev: master hooks: - id: ormolu - id: shellcheck - id: elm-format
-
(optional) Use binary caches to avoid compilation:
$ nix-env -iA cachix -f https://cachix.org/api/v1/install $ cachix use hercules-ci
-
Integrate hooks to be built as part of
default.nix
:let inherit (import (builtins.fetchTarball "https://github.com/hercules-ci/gitignore/tarball/master" {})) gitignoreSource; nix-pre-commit-hooks = import (builtins.fetchTarball "https://github.com/hercules-ci/nix-pre-commit-hooks/tarball/master"); in { pre-commit-check = nix-pre-commit-hooks.run { src = gitignoreSource ./.; }; }
Run
$ nix-build -A pre-commit-check
to perform the checks as a Nix derivation. -
Integrate hooks to prepare environment as part of
shell.nix
:(import <nixpkgs> {}).mkShell { inherit ((import ./. {}).pre-commit-check) shellHook; }
Run
$ nix-shell
to executeshellHook
which will:- install git hooks
- symlink hooks to
.pre-commit-hooks/
- provide
pre-commit
executable thatgit commit
will invoke
Everyone is encouraged to add new hooks.
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
- The tool must not be very specific (e.g. language tooling is OK, but project specific tooling is not)