How do we make go vet
, gofmt
, and other Go linter tools ignore third-party files in vendor/
, preferably with an accurate, cumulative exit status?
For example, would find . -name vendor -prune -o -name '*.go' -exec gofmt -s -w {} \;
present a meaningful exit status?
You can put all your source code into a subdirectory (e.g. internal
or lib
). Alternatively, you can do this:
go vet ./... | grep -v vendor/ && exit 1 || exit 0
Usually go list
is more helpful than find
here:
$ go list ./...
arp242.net/trackwall
arp242.net/trackwall/cmdline
arp242.net/trackwall/vendor/arp242.net/sconfig
arp242.net/trackwall/vendor/bitbucket.org/pkg/inflect
[..trim..]
As you see, this will list all the package names in the current directory. To filter the vendor
directory we can use grep
:
$ go list ./... | grep -v /vendor/
arp242.net/trackwall
arp242.net/trackwall/cmdline
If you want to run several linters, report all errors, and return 0
only if there is a success, you could use a loop and a status variable:
#!/bin/sh
st=0
for pkg in $(go list ./... | grep -v /vendor/); do
echo "==> $pkg"
go vet "$pkg"
[ $? -ne 0 ] && st=1
golint "$pkg"
[ $? -ne 0 ] && st=1
# gofmt works on files, not packages
gofmt -d "${f#arp242.net/trackwall}"*.go
[ $? -ne 0 ] && st=1
done
exit $st
Which will output something like:
==> arp242.net/trackwall
http.go:71: database/sql.NullString composite literal uses unkeyed fields
exit status 1
/home/martin/gocode/src/arp242.net/trackwall/http.go:70:2: don't use ALL_CAPS in Go names; use CamelCase
/home/martin/gocode/src/arp242.net/trackwall/http.go:75:9: if block ends with a return statement, so drop this else and outdent its block
==> arp242.net/trackwall/cmdline
Exit 1
Of course, you're not the first one with this problem, and there are tools which basically do the same as above, except better. gometalinter is probably the best known and I recommend you use this. It helpfully includes a --vendor
switch to ignore the vendor directory:
$ go get -u github.com/alecthomas/gometalinter
$ gometalinter --vendor ./...
helpers.go:25:1:warning: realpath is unused (deadcode)
http.go:32:1:warning: _list is unused (deadcode)
[..trim..]
In a cross platform fashion i do this philea -s "666 go vet %s" "666 go-fmt-fail %s"
yields,
$ ls -alh | grep ven
drwxr-xr-x 5 mh-cbon mh-cbon 4,0K 14 juin 20:43 vendor
$ philea -s "666 go vet %s" "666 go-fmt-fail %s"
go-fmt-fail ./local/local.go
✔ Success
go-fmt-fail ./dl/index.go
✔ Success
go vet ./local/local.go
✔ Success
go-fmt-fail ./gh/gh.go
✔ Success
go vet ./main.go
✔ Success
go vet ./gh/gh.go
✔ Success
go vet ./dl/index.go
✔ Success
go-fmt-fail ./main.go
✔ Success
I usually do
go fmt $(go list ./... | grep -v /vendor/)
go test $(go list ./... | grep -v /vendor/)
But since I started using govendor
discovered I can do the same using govendor with less typing
govendor fmt +l // +l is shorthand for local
Thanks for all the helpful suggestions! This works for my purposes:
https://github.com/mcandre/go-ios7crypt/blob/ea8dd957e8f146ea20a57122870008a968875b53/Makefile
With Go 1.10 (Q1 2018), the kind of tips mentioned by the OP mcandre's answer will be more robust:
go list ./... | grep -v vendor | xargs go vet -v
As illustrated in carpetsmoker's answer, a go vet
on packages depending on (yet non-compiled) vendored packages will fail:
==> arp242.net/trackwall
http.go:71: database/sql.NullString composite literal uses unkeyed fields
Note anymore, since go issue 16086 is resolved!
See this thread:
Go vet
The "
go vet
" command works best with full type information for the packages it is analyzing. Historically that's been problematic in a variety of situations: packages usingcgo
, packages using vendoring, and packages that don't have up-to-date installed dependencies have all been things that keptvet
from running with full type information.Not anymore. The "
go vet
" command now passes tovet
full information about all these things, building new.a
files if needed (CL 74355 and CL 74750).
Now "go vet
" is guaranteed to have up-to-date type information when it analyzes a package, which will improve the accuracy of its analyses.
Having the build cache to amortize the cost of building those.a
files was the final piece needed to make this happen.Only "
go vet
" has this guarantee. Do not use "go tool vet
", which is essentially only useful to people working onvet
(just like you don't typically run "go tool compile
").
Previously you needed to use "go tool vet
" if you wanted control over vet flags, but "go vet
" now accepts all the flags that "go tool vet
" does. (See "go help vet
".)