This repository has no description
nixhooks README.md
5.2 kB · 168 lines
Markdown
at main

nixhooks #

A small, fast, drop-in replacement for git-hooks.nix. No flake required, no flake-parts, no systems, no Python, no slop, just plain ol' Nix and Bash.

Usage (non-flake) #

{ pkgs ? import <nixpkgs> { } }:

let
  nixhooks = import (fetchTarball "https://next.tangled.org/xrpc/sh.tangled.repo.archive?repo=at%3A%2F%2Fdid%3Aplc%3Ayaryxzbwui6ejiegzysy6ipp%2Fsh.tangled.repo%2Fnixhooks&ref=main&format=tar.gz") { inherit pkgs; };
in
nixhooks.mkHooks {
  hooks = {
    shellcheck = {
      entry = "${pkgs.shellcheck}/bin/shellcheck";
      files = "\\.sh$";
      stages = [ "pre-commit" "pre-push" ];
    };

    nixfmt-check = {
      entry = "${pkgs.nixfmt}/bin/nixfmt";
      args = [ "--check" ];
      files = "\\.nix$";
    };
  };
}
$ nix-build -A install-hooks && ./result/bin/install-hooks

Or, wire it into a shellHook so hooks install automatically on entry (see the devShells output in flake.nix).

Usage (flake) #

{
  inputs.nixhooks.url = "git+https://tangled.org/poacher.dev/nixhooks";
  outputs = { self, nixpkgs, nixhooks }: let
    pkgs = nixpkgs.legacyPackages.x86_64-linux;
    hooks = (nixhooks.lib { inherit pkgs; }).mkHooks {
      hooks = {
        shellcheck = {
          entry = "${pkgs.shellcheck}/bin/shellcheck";
          files = "\\.sh$";
        };
      };
    };
  in {
    apps.x86_64-linux = hooks.apps; 
    devShells.x86_64-linux.default = pkgs.mkShell {
      shellHook = ''
        ${hooks.install-hooks}/bin/install-hooks
      '';
    };
  };
}
$ nix run .#install-hooks

Hook spec #

hooks.<name> = {
  enable = true;                     # default true; set false to disable without deleting the entry
  entry = "/nix/store/.../bin/tool"; # required: the command to run
  args = [ ];                        # extra args passed before matched filenames
  files = ".*";                      # ERE regex (bash [[ =~ ]]) tested against each candidate path
  exclude = "^$";                    # ERE regex; "^$" (default) excludes nothing
  stages = [ "pre-commit" ];         # subset of [ "pre-commit" "pre-push" ]
  pass_filenames = true;             # append matched files as trailing args
  always_run = false;                # run once with no file filtering/passing 
  path = [ ];                        # packages whose bin/ dirs are prepended to PATH for entry
};

<name> must match [A-Za-z0-9_.-]+

path is for tools that internally dispatch to a sibling binary via PATH (e.g. cargo finding cargo-clippy) -- entry itself is always invoked by absolute path regardless of path.

Presets #

presets is a small built-in catalog of common tool configs -- plain hooks.<name>-shaped attrsets you can reference directly or override:

nixhooks.mkHooks {
  hooks = {
    shellcheck = nixhooksLib.presets.shellcheck;
    alejandra = nixhooksLib.presets.alejandra // { stages = [ "pre-push" ]; };
  };
}

See lib/presets.nix for the full list of presets.

Tangled pipelines #

mkHooks can also generate a Tangled Spindle pipeline:

nixhooks.mkHooks {
  hooks = { /* ... */ };
  tangled = {
    enable = true;
    attr = "run-hooks";
    flake = true;
    engine = "microvm";
    when = [
      {
        event = ["push" "pull_request"];
        branch = ["main"];
      }
    ];
  };
}
$ nix-build -A gen-tangled-pipeline && ./result/bin/gen-tangled-pipeline
gen-tangled-pipeline: wrote .tangled/workflows/hooks.yml

This writes a .tangled/workflows/hooks.yml in the same manner as install-hooks which you commit to the repo. Note that this isn't wired into shellHook like install-hooks, so you'll need to trigger it manually.

Benchmarks #

Measured against git-hooks.nix pinned to 27555e2

Evaluation #

nixhooks git-hooks.nix ratio
shellcheck+nixfmt
nrFunctionCalls 418,967 899,340 2.15×
nrLookups 217,953 474,046 2.17×
nrThunks 948,777 2,075,768 2.19×
values.number 1,867,274 4,366,397 2.34×
cpuTime 0.499 s 1.019 s 2.04×
no hooks
nrFunctionCalls 45,514 703,210 15.45×
nrLookups 26,666 378,436 14.19×
nrThunks 135,622 1,797,899 13.26×
values.number 585,871 4,066,662 6.94×
cpuTime 0.083 s 0.911 s 11.04×

Hook installation #

Command Mean Min Max
nixhooks -A install-hooks 647.7 ms ± 54.5 ms 594.1 ms 763.4 ms
git-hooks.nix (installationScript) 1.263 s ± 0.030 s 1.222 s 1.321 s

Hook execution #

Command Mean Min Max
nixhooks pre-commit hook 14.3 ms ± 1.4 ms 12.8 ms 23.4 ms
git-hooks.nix pre-commit hook 89.4 ms ± 2.0 ms 87.0 ms 94.8 ms

Store closure size #

Closure size
nixhooks install-hooks 83.65 MiB
git-hooks.nix workflow closure 359.03 MiB