Seamless integration of pre-commit 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:
a) Simpler integration for Nix projects (wires up a few things behind the scenes)
b) 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)
c) Common package set of hooks for popular languages like Haskell, Elm, etc.
d) 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: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 = nix-pre-commit-hooks.run { src = gitignoreSource ./.; }; }
Run
$ nix-build -A pre-commit
. -
Integrate hooks to prepare environment as part of
shell.nix
:let pkgs = import <nixpkgs> {}; in pkgs.stdenv.mkDerivation { shellHook = '' ${(import ./. {}).pre-commit.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)