Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add hook installation test #423

Merged
merged 1 commit into from
Apr 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,5 @@ jobs:
name: pre-commit-hooks
signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}'
- run: rm -rf /opt&
- run: nix flake check --show-trace
- run: nix flake check -L --show-trace
- run: nix eval .#lib.x86_64-linux.run --show-trace
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ nix develop
ormolu.enable = true;
ormolu.package = pkgs.haskellPackages.ormolu;
ormolu.settings.defaultExtensions = [ "lhs" "hs" ];

# some hooks have more than one package, like clippy:
clippy.enable = true;
clippy.packageOverrides.cargo = pkgs.cargo;
Expand All @@ -109,7 +109,7 @@ nix develop
3. Integrate hooks to prepare environment as part of `shell.nix`:

```nix
let
let
pre-commit = import ./default.nix;
in (import <nixpkgs> {}).mkShell {
shellHook = ''
Expand Down Expand Up @@ -318,7 +318,7 @@ clang-format = {
};
```

Otherwise, the default internal list is used which includes everything that
Otherwise, the default internal list is used which includes everything that
clang-format supports.

## Git
Expand Down Expand Up @@ -373,6 +373,9 @@ Example configuration:
# Set this to false to not pass the changed files
# to the command (default: true):
pass_filenames = false;

# Which git hooks the command should run for (default: [ "pre-commit" ]):
stages = ["pre-push"];
};
};
};
Expand Down
2 changes: 1 addition & 1 deletion flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
}
// flake-utils.lib.eachSystem defaultSystems (system:
let
exposed = import ./nix { nixpkgs = nixpkgs; inherit system; gitignore-nix-src = gitignore; isFlakes = true; };
exposed = import ./nix { inherit nixpkgs system; gitignore-nix-src = gitignore; isFlakes = true; };
exposed-stable = import ./nix { nixpkgs = nixpkgs-stable; inherit system; gitignore-nix-src = gitignore; isFlakes = true; };
in
{
Expand Down
2 changes: 1 addition & 1 deletion modules/hook.nix
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ in
};

stages = mkOption {
type = types.listOf types.str;
type = (import ./supported-hooks.nix { inherit lib; }).supportedHooksType;
description = lib.mdDoc ''
Confines the hook to run at a particular stage.
'';
Expand Down
23 changes: 12 additions & 11 deletions modules/pre-commit.nix
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,15 @@ let
mkIf
mkOption
types
remove
;

inherit (pkgs) runCommand writeText git;

cfg = config;
install_stages = lib.unique (cfg.default_stages ++ (builtins.concatLists (lib.mapAttrsToList (_: h: h.stages) enabledHooks)));
install_stages = lib.unique (builtins.concatLists (lib.mapAttrsToList (_: h: h.stages) enabledHooks));

supportedHooksLib = import ./supported-hooks.nix { inherit lib; };

hookType = types.submodule {
imports = [
Expand Down Expand Up @@ -175,7 +178,7 @@ in
The predefined hooks are:

${
lib.concatStringsSep
concatStringsSep
"\n"
(lib.mapAttrsToList
(hookName: hookConf:
Expand Down Expand Up @@ -253,14 +256,14 @@ in

default_stages =
mkOption {
type = types.listOf types.str;
type = supportedHooksLib.supportedHooksType;
description = lib.mdDoc
''
A configuration wide option for the stages property.
Installs hooks to the defined stages.
See [https://pre-commit.com/#confining-hooks-to-run-at-certain-stages](https://pre-commit.com/#confining-hooks-to-run-at-certain-stages).
'';
default = [ "commit" ];
default = [ "pre-commit" ];
};

rawConfig =
Expand Down Expand Up @@ -332,12 +335,11 @@ in

# These update procedures compare before they write, to avoid
# filesystem churn. This improves performance with watch tools like lorri
# and prevents installation loops by via lorri.
# and prevents installation loops by lorri.

if ! readlink "''${GIT_WC}/.pre-commit-config.yaml" >/dev/null \
|| [[ $(readlink "''${GIT_WC}/.pre-commit-config.yaml") != ${configFile} ]]; then
echo 1>&2 "pre-commit-hooks.nix: updating $PWD repo"

[ -L .pre-commit-config.yaml ] && unlink .pre-commit-config.yaml

if [ -e "''${GIT_WC}/.pre-commit-config.yaml" ]; then
Expand All @@ -349,24 +351,23 @@ in
else
ln -fs ${configFile} "''${GIT_WC}/.pre-commit-config.yaml"
# Remove any previously installed hooks (since pre-commit itself has no convergent design)
hooks="pre-commit pre-merge-commit pre-push prepare-commit-msg commit-msg post-checkout post-commit"
hooks="${concatStringsSep " " (remove "manual" supportedHooksLib.supportedHooks )}"
for hook in $hooks; do
pre-commit uninstall -t $hook
done
${git}/bin/git config --local core.hooksPath ""
# Add hooks for configured stages (only) ...
if [ ! -z "${concatStringsSep " " install_stages}" ]; then
for stage in ${concatStringsSep " " install_stages}; do
if [[ "$stage" == "manual" ]]; then
continue
fi
case $stage in
manual)
;;
# if you amend these switches please also review $hooks above
commit | merge-commit | push)
stage="pre-"$stage
pre-commit install -t $stage
;;
prepare-commit-msg | commit-msg | post-checkout | post-commit)
${concatStringsSep "|" supportedHooksLib.supportedHooks})
pre-commit install -t $stage
;;
*)
Expand Down
30 changes: 30 additions & 0 deletions modules/supported-hooks.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{ lib }:
let inherit (lib) types;
# according to https://pre-commit.com/#supported-git-hooks
supportedHooks = [
"commit-msg"
"post-checkout"
"post-commit"
"post-merge"
"post-rewrite"
"pre-commit"
"pre-merge-commit"
"pre-push"
"pre-rebase"
"prepare-commit-msg"
"manual"
];
in
{
inherit supportedHooks;

supportedHooksType =
let
deprecatedHooks = [
"commit"
"push"
"merge-commit"
];
in
types.listOf (types.enum (supportedHooks ++ deprecatedHooks));
}
1 change: 1 addition & 0 deletions nix/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ let
typos.enable = true;
};
};
installation-test = pkgs.callPackage ./installation-test.nix { inherit run; };
all-tools-eval =
let
config = lib.evalModules {
Expand Down
99 changes: 99 additions & 0 deletions nix/installation-test.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# Test that checks whether the correct hooks are created in the hooks folder.
{ git, perl, coreutils, runCommand, run, lib, mktemp }:
let
tests = {
basic-test = {
expectedHooks = [ "pre-commit" ];
conf.hooks.shellcheck.enable = true;
};

multiple-hooks-test = {
expectedHooks = [ "commit-msg" "pre-commit" ];
conf.hooks = {
shellcheck.enable = true;
nixpkgs-fmt = {
enable = true;
stages = [ "commit-msg" ];
};
};
};

non-default-stage-test = {
expectedHooks = [ "commit-msg" ];
conf.hooks.nixpkgs-fmt = {
enable = true;
stages = [ "commit-msg" ];
};
};

default-stage-test = {
expectedHooks = [ "commit-msg" ];
conf = {
default_stages = [ "commit-msg" ];
hooks.nixpkgs-fmt.enable = true;
};
};

manual-default-stage-test = {
expectedHooks = [ ];
conf = {
default_stages = [ "manual" ];
hooks.nixpkgs-fmt.enable = true;
};
};

multiple-default-stages-test = {
expectedHooks = [ "pre-push" ];
conf = {
default_stages = [ "manual" "pre-push" ];
hooks.nixpkgs-fmt.enable = true;
};
};

deprecated-gets-prefixed-test = {
expectedHooks = [ "pre-push" ];
conf.hooks.nixpkgs-fmt = {
enable = true;
stages = [ "push" ];
};
};
};

executeTest = lib.mapAttrsToList
(name: test:
let runDerivation = run ({ src = null; } // test.conf);
in ''
rm -f ~/.git/hooks/*
${runDerivation.shellHook}
actualHooks=(`find ~/.git/hooks -type f -printf "%f "`)
read -a expectedHooks <<< "${builtins.toString test.expectedHooks}"
if ! assertArraysEqual actualHooks expectedHooks; then
echo "${name} failed: Expected hooks '${builtins.toString test.expectedHooks}' but found '$actualHooks'."
return 1
fi
'')
tests;
in
runCommand "installation-test" { nativeBuildInputs = [ git perl coreutils mktemp ]; } ''
set -eoux

HOME=$(mktemp -d)
cd $HOME
git init

assertArraysEqual() {
local -n _array_one=$1
local -n _array_two=$2
diffArray=(`echo ''${_array_one[@]} ''${_array_two[@]} | tr ' ' '\n' | sort | uniq -u`)
if [ ''${#diffArray[@]} -eq 0 ]
then
return 0
else
return 1
fi
}

${lib.concatStrings executeTest}

echo "success" > $out
''
Loading