I have setup some Git hooks that help me catch tests that fail, show golint , go vet errors.
Git hooks are located in .git/hooks
.
Go test
My pre-push git hook file contains
#!/bin/bash
echo -e "\nRunning tests for you"
go test $(go list github.com/dgraph-io/dgraph/...| grep -v vendor)
So it runs all tests except those in the vendor folder for me before I push.
Golint and Go Vet
Taking some inspiration from here https://github.com/youtube/vitess/tree/master/misc/git/hooks, I setup a pre-commit
hook which checks for go vet
and golint
errors for the staged files whose content was changed.
Contents of the pre-commit file
#!/bin/bash
sh .git/hooks/golint.sh
sh .git/hooks/govet.sh
golint.sh
#!/bin/bash
if [ -z "$GOPATH" ]; then
echo "ERROR: pre-commit hook for golint: \$GOPATH is empty."
exit 1
fi
if [ -z "$(which golint)" ]; then
echo "golint not found, please run: go get github.com/golang/lint/golint"
exit 1
fi
# This script does not handle file names that contain spaces.
gofiles=$(git diff --cached --name-only --diff-filter=ACM | grep '\.go$')
errors=
# Run on one file at a time because a single invocation of golint
# with multiple files requires the files to all be in one package.
gofiles_with_warnings=()
for gofile in $gofiles
do
errcount=$(golint $gofile | wc -l)
if [ "$errcount" -gt "0" ]; then
errors=YES
echo "$errcount suggestions for:"
echo "golint $gofile"
gofiles_with_warnings+=($gofile)
fi
done
[ -z "$errors" ] && exit 0
# git doesn't give us access to user input, so let's steal it.
exec < /dev/tty
if [[ $? -eq 0 ]]; then
# interactive shell. Prompt the user.
echo
echo "Lint suggestions were found. They're not enforced, but we're pausing"
echo "to let you know before they get clobbered in the scrollback buffer."
echo
read -r -p 'Press enter to cancel, "s" to step through the warnings or type "ack" to continue: '
if [ "$REPLY" = "ack" ]; then
exit 0
fi
if [ "$REPLY" = "s" ]; then
first_file="true"
for gofile in "${gofiles_with_warnings[@]}"
do
echo
if [ "$first_file" != "true" ]; then
echo "Press enter to show the warnings for the next file."
read
fi
golint $gofile
first_file="false"
done
fi
else
# non-interactive shell (e.g. called from Eclipse). Just display the errors.
for gofile in "${gofiles_with_warnings[@]}"
do
golint $gofile
done
fi
exit 1
govet.sh
#!/bin/bash
#!/bin/sh
# Copyright 2012 The Go Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# git go vet pre-commit hook
#
# To use, store as .git/hooks/pre-commit inside your repository and make sure
# it has execute permissions.
if [ -z "$GOPATH" ]; then
echo "ERROR: pre-commit hook for go vet: \$GOPATH is empty. Please run 'source dev.env' to set the correct \$GOPATH."
exit 1
fi
# This script does not handle file names that contain spaces.
gofiles=$(git diff --cached --name-only --diff-filter=ACM | grep '\.go$')
# If any checks are found to be useless, they can be disabled here.
# See the output of "go tool vet" for a list of flags.
vetflags="-all=true"
errors=
# Run on one file at a time because a single invocation of "go tool vet"
# with multiple files requires the files to all be in one package.
for gofile in $gofiles
do
if ! go tool vet $vetflags $gofile 2>&1; then
errors=YES
fi
done
[ -z "$errors" ] && exit 0
echo
echo "Please fix the go vet warnings above. To disable certain checks, change vetflags in misc/git/hooks/govet."
exit 1
Though this takes a bit more time, it helps catch obvious errors and avoid the back and forth while doing a PR review.