git-hooks.nix icon indicating copy to clipboard operation
git-hooks.nix copied to clipboard

Supported pre-commit hook

Open PierreR opened this issue 4 years ago • 7 comments

How can I integrate the supported hook from pre-commit such as end-of-file-fixer or trailing-whitespace into pre-commit-hooks.nix ?

PierreR avatar Nov 25 '19 13:11 PierreR

As an aside question, is there a way to integrate local hooks ?

PierreR avatar Nov 25 '19 13:11 PierreR

tldr; supported hooks: requires change, local hooks: already possible

supported hooks

Looks like you want to add hooks from pre-commit's standard repo https://github.com/pre-commit/pre-commit-hooks

This possibility is not properly exposed through an option yet, but it can be added via the rawConfig option. Since only a small set of options is exposed via run.nix, this means changing pre-commit-hooks.nix.

local hooks

The latest version has been simplified from what it used to be and basically only works exclusively via the local hooks feature. To put it differently, pre-commit.nix translates everything to local hooks. Basically where you define enable = true in your config, you can define all the other attributes as well. This should be tested and documented (#2).

roberth avatar Nov 25 '19 14:11 roberth

Supported hooks

If I add to the rawConfig option something like:

{
  repo = "https://github.com/pre-commit/pre-commit-hooks";
  rev = "v2.4.0";
  hooks = [ { id = "trailing-whitespace"; } ];
}

How can I ensure that the hook is pinned (and goes in a binary cache) ? The integrity and self-encapsulation of pre-commit-hooks.nix is on my side the biggest motivation/use case for pre-commit-hooks.nix

PierreR avatar Nov 26 '19 09:11 PierreR

Precisely those are possibly most elegantly addressed in an .editorconfig - special case, though.

[*]
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

blaggacao avatar Jul 02 '20 04:07 blaggacao

I managed to get the trailing-whitespace hook to run by adding the pre-commit-hooks to nixpkgs (pr) and activate it in my config like this:

trailing-whitespace = {
  enable = true;

  name = "Trim Trailing Whitespace";
  description = "This hook trims trailing whitespace.";
  entry = "${pkgs.python3Packages.pre-commit-hooks}/bin/trailing-whitespace-fixer";
  types = ["text"];
};

Ideal because it's now self-contained within the Nix store, not ideal because you have to replicate the hook's settings.

kalbasit avatar Dec 14 '20 19:12 kalbasit

It took me a while to figure out how to use rawConfig? So here's a gist for someone looking (and a request to make it simpler :sweat_smile: ):

pre-commit = {
  hooks = {
    nil.enable = true; # HACK: some hook needs to be enabled for pre-commit to enable itself - but will be overwritten anyways
  };
  rawConfig = {
    repos = [
      {
        "repo" = "https://github.com/codingjoe/relint";
        "rev" = "1.2.1";
        "hooks" = [
          { "id" = "relint"; "exclude" = ''...''; }
        ];
      }
    ];
  };
};

tennox avatar Nov 22 '23 10:11 tennox

I managed to get the trailing-whitespace hook to run by adding the pre-commit-hooks to nixpkgs (pr) and activate it in my config like this:

trailing-whitespace = {
  enable = true;

  name = "Trim Trailing Whitespace";
  description = "This hook trims trailing whitespace.";
  entry = "${pkgs.python3Packages.pre-commit-hooks}/bin/trailing-whitespace-fixer";
  types = ["text"];
};

Ideal because it's now self-contained within the Nix store, not ideal because you have to replicate the hook's settings.

I ended up writing this to make them all available in the same vein:

    pre-commit.settings.hooks = lib.trivial.pipe source [
      (pkg: "${pkg.src}/.pre-commit-hooks.yaml")
      fromYAMLFile
      (builtins.map (hook: lib.attrsets.nameValuePair hook.id hook))
      builtins.listToAttrs
      (builtins.mapAttrs (_: hook: lib.trivial.pipe hook [
        (hook: hook // {enable = false; entry = "${source}/bin/${hook.entry}";})
        # stages are excluded to support setting pre-commit.settings.default_stages
        (hook: builtins.removeAttrs hook ["id" "stages"])
        (builtins.mapAttrs (_: lib.mkDefault))
      ]))
    ];

where source is pkgs.python311Packages.pre-commit-hooks and fromYAMLFile is my custom yaml parsing function:

    fromYAMLFile = input_f:
      lib.trivial.pipe input_f [
        (file: "remarshal -if yaml -i \"${file}\" -of json -o \"$out\"")
        (pkgs.runCommand "from-yaml" {nativeBuildInputs = [pkgs.remarshal];})
        lib.trivial.importJSON
      ];

In a separate module I then enable and override the ones I want:

    pre-commit.settings.default_stages = ["pre-push" "manual"];
    pre-commit.settings.hooks = {
      check-merge-conflict.enable = true;
      check-merge-conflict.raw.args = ["--assume-in-merge"];
      no-commit-to-branch.enable = true;
      no-commit-to-branch.raw.args = ["--branch" "trunk"];
      trailing-whitespace.enable = true;
};

There's probably something horribly wrong with this approach (lib.mkDefault all attributes, for example) but seems to be working. Maybe generating options instead is a better idea for this public library? Happy to contribute this / improve it if it's helpful.

schradert avatar Dec 21 '23 20:12 schradert

The built-in pre-commit hooks should now be exposed. See #401.

sandydoo avatar Apr 04 '24 10:04 sandydoo