Skip to content

Commit

Permalink
add installation test
Browse files Browse the repository at this point in the history
  • Loading branch information
m1-s committed Apr 1, 2024
1 parent c11e43a commit 649fb51
Show file tree
Hide file tree
Showing 8 changed files with 151 additions and 17 deletions.
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
''

0 comments on commit 649fb51

Please sign in to comment.