Error installing nodejs hooks with pre-commit

Hi everybody. I’m diving into nix and my goal right now is to be able to build a docker image to use it in our CI, and I started with the simplest point: pre-commit.

Up until now, we’ve been long-standing happy pre-commit users, and I just want to leverage that same framework, but using nix under the hood.

This is the images/pre-commit.nix file I have:

# SPDX-FileCopyrightText: 2022 Moduon <https://www.moduon.team>
# SPDX-License-Identifier: AGPL-3.0-or-later

{ pkgs ? import <nixpkgs> { } }:

let splitSystem = builtins.split "-" pkgs.system;
in pkgs.dockerTools.buildLayeredImage {
  name = "pre-commit";
  tag = "latest";

  config = {
    author = "Moduon";

    architecture = builtins.elemAt splitSystem 0;
    os = builtins.elemAt splitSystem 2;

    Cmd = ["bash"];

    Env = [
      "SSL_CERT_FILE=${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt"
    ];
  };

  contents = with pkgs; [
    bashInteractive
    cacert
    coreutils
    dockerTools.fakeNss
    git
    pre-commit
  ];
}

This is the relevant part of my .pre-commit-config.yaml:

default_language_version:
  python: python3
  node: "14.14.0"
repos:
  - repo: https://github.com/pre-commit/mirrors-prettier
    rev: v2.2.1
    hooks:
      - id: prettier
        additional_dependencies:
          - prettier@2.1.2
          - "@prettier/plugin-xml@0.12.0"
        args:
          - --plugin=@prettier/plugin-xml

Now, let’s use it:

> nix-channel --list
nixpkgs https://nixos.org/channels/nixos-21.11
nixpkgs-unstable https://nixos.org/channels/nixpkgs-unstable

> nix-channel --update
unpacking channels...

> nix-build images/pre-commit.nix
/nix/store/32jk8wf3lyp6l6w0hb8bmmqgv12yq8l8-pre-commit.tar.gz

> nix-shell -p bash --run 'cat result' | podman load
[...]

> podman run --rm -it -v $(pwd):$(pwd):z -w $(pwd) pre-commit pre-commit run -a
[INFO] Initializing environment for https://github.com/pre-commit/mirrors-prettier.
[INFO] Initializing environment for https://github.com/pre-commit/mirrors-prettier:@prettier/plugin-xml@0.12.0,prettier@2.1.2.
[INFO] Installing environment for https://github.com/pre-commit/mirrors-prettier.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
An unexpected error has occurred: CalledProcessError: command: ('/var/empty/.cache/pre-commit/repoft91autp/node_env-14.14.0/bin/node', '/var/empty/.cache/pre-commit/repoft91autp/node_env-14.14.0/bin/npm', 'install', '--dev', '--prod', '--ignore-prepublish', '--no-progress', '--no-save')
return code: 1
expected return code: 0
stdout:
    [Errno 2] No such file or directory: '/var/empty/.cache/pre-commit/repoft91autp/node_env-14.14.0/bin/node'
    
stderr: (none)
Check the log at /var/empty/.cache/pre-commit/pre-commit.log

Well… there’s the error. It seems like it cannot find node.

I tried adding it to the image, but fails with the same. According to pre-commit docs:

node hooks work without any system-level dependencies

So AFAIK it should be good to go.

Any ideas on how to make the nodejs hook install and run? Thanks!

PS: if you prefer real logs, just check out this pipeline: https://gitlab.com/moduon/devsecops/public-ci-templates/-/pipelines/450294758

I’m using NixOS as my host OS and having the same problem with node pre-hooks.
I’m guessing it’s something special about NixOS, as it works on “regular” distros such as Debian etc.

What I found out so far:

  • node hooks work without any system-level dependencies - might not be 100% true - it needs python nodeenv module to initialize the node environment
  • it fails to initalize for some reason
  • even if it would work, the node binary would not start correctly on NixOS - as it is downlaoded, prebuilt binary with loader path set to /lib64/ld-linux-x86-64.so.2 - such path does not exist on NixOS

I think the solution is to let nix manage packages, and pre-commit manage the rest of stuff. See DevShell native pre commit hooks · Issue #16 · numtide/devshell · GitHub.

FWIW I created a solution based on that approach: Moduon / Precommix · GitLab