Skip to content

feat: add new hooks for golang #222

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

Merged
merged 2 commits into from
Jan 9, 2023
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
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,11 @@ use nix

## Golang

- gofmt: Runs `go fmt`
- gotest: Runs `go test`
- [govet](https://pkg.go.dev/cmd/vet)
- [revive](https://github.com/mgechev/revive)
- [staticcheck](https://github.com/dominikh/go-tools)

## Shell

Expand Down
122 changes: 112 additions & 10 deletions modules/hooks.nix
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,16 @@ let
lib.optionalString
(settings.rust.cargoManifestPath != null)
"--manifest-path ${lib.escapeShellArg settings.rust.cargoManifestPath}";

mkCmdArgs = predActionList:
lib.concatStringsSep
" "
(builtins.foldl'
(acc: entry:
acc ++ lib.optional (builtins.elemAt entry 0) (builtins.elemAt entry 1))
[ ]
predActionList);

in
{
options.settings =
Expand Down Expand Up @@ -761,23 +771,86 @@ in
files = "\\.go$";
};

gotest = {
enable = true;
name = "gotest";
description = "Run go tests";
entry =
let
script = pkgs.writeShellScript "precommit-gotest" ''
set -e
# find all directories that contain tests
dirs=()
for file in "$@"; do
# either the file is a test
if [[ "$file" = *_test.go ]]; then
dirs+=("$(dirname "$file")")
continue
fi

# or the file has an associated test
filename="''${file%.go}"
test_file="''${filename}_test.go"
if [[ -f "$test_file" ]]; then
dirs+=("$(dirname "$test_file")")
continue
fi
done

# ensure we are not duplicating dir entries
IFS=$'\n' sorted_dirs=($(sort -u <<<"''${dirs[*]}")); unset IFS

# test each directory one by one
for dir in "''${sorted_dirs[@]}"; do
${tools.go}/bin/go test "./$dir"
done
'';
in
builtins.toString script;
files = "\\.go$";
raw = {
# to avoid multiple invocations of the same directory input, provide
# all file names in a single run.
require_serial = true;
};
};

gofmt =
{
name = "gofmt";
description = "A tool that automatically formats Go source code";
entry =
let
script = pkgs.writeShellScript "precommit-gofmt" ''
set -e
failed=false
for file in "$@"; do
# redirect stderr so that violations and summaries are properly interleaved.
if ! ${tools.go}/bin/gofmt -l -w "$file" 2>&1
then
failed=true
fi
done
if [[ $failed == "true" ]]; then
exit 1
fi
'';
in
builtins.toString script;
files = "\\.go$";
};

revive =
{
name = "revive";
description = "A linter for Go source code.";
entry =
let
cmdArgs =
lib.concatStringsSep
" "
(builtins.concatLists [
[ "-set_exit_status" ]
(if settings.revive.configPath != "" then
[ "-config ${settings.revive.configPath}" ]
else
[ ])
]
);
mkCmdArgs [
[ true "-set_exit_status" ]
[ (settings.revive.configPath != "") "-config ${settings.revive.configPath}" ]
];
# revive works with both files and directories; however some lints
# may fail (e.g. package-comment) if they run on an individual file
# rather than a package/directory scope; given this let's get the
Expand All @@ -798,6 +871,35 @@ in
};
};

staticcheck =
{
enable = true;
name = "staticcheck";
description = "State of the art linter for the Go programming language";
# staticheck works with directories.
entry =
let
script = pkgs.writeShellScript "precommit-staticcheck" ''
err=0
for dir in $(echo "$@" | xargs -n1 dirname | sort -u); do
${tools.go-tools}/bin/staticcheck ./"$dir"
code="$?"
if [[ "$err" -eq 0 ]]; then
err="$code"
fi
done
exit $err
'';
in
builtins.toString script;
files = "\\.go$";
raw = {
# to avoid multiple invocations of the same directory input, provide
# all file names in a single run.
require_serial = true;
};
};

editorconfig-checker =
{
name = "editorconfig-checker";
Expand Down
3 changes: 2 additions & 1 deletion nix/tools.nix
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
, writeScript
, writeText
, go
, go-tools
, revive ? null
}:

Expand All @@ -52,7 +53,7 @@ let
};
in
{
inherit actionlint alejandra cabal-fmt cabal2nix cargo clang-tools clippy deadnix dhall editorconfig-checker hadolint hindent hlint hpack html-tidy nix-linter nixfmt nixpkgs-fmt ormolu rustfmt shellcheck shfmt statix stylish-haskell stylua typos go mdsh revive;
inherit actionlint alejandra cabal-fmt cabal2nix cargo clang-tools clippy deadnix dhall editorconfig-checker hadolint hindent hlint hpack html-tidy nix-linter nixfmt nixpkgs-fmt ormolu rustfmt shellcheck shfmt statix stylish-haskell stylua typos go mdsh revive go-tools;
inherit (elmPackages) elm-format elm-review elm-test;
# TODO: these two should be statically compiled
inherit (haskellPackages) brittany fourmolu;
Expand Down