Quick tools.go invocation
Sick of long `go run` commands when using tools.go to vendor CLI utilities?
Many places (including the wiki) recommend managing your CLI tool dependencies with a tools.go
file.
I’ve found this helpful as well. My contribution to this is a bash/zsh function (gt
) that allows a shorthand invocation of a vendored tool.
function gt {
arg=$1;
shift 2> /dev/null
[[ $? == 1 ]] && echo "Usage: gt tool" && return 1
root=$(dirname "$(go env GOMOD)")
cd "$root" || return 1
cmd=$(go list -f '{{ join .Imports "\n" }}' -tags tools tools.go | grep -E "\/$arg\$" )
if [[ $cmd == "" ]]; then
echo cmd \""$arg"\" not in tools.go
else
go run "$cmd" "$@"
fi;
cd - 1> /dev/null || return 1
}
So now instead of invoking go run github.com/bufbuild/buf/cmd/buf lint
, you can run gt buf lint
.
This will only work within a Go project where a tools.go
file exists.
If you’re using zsh, here’s tab completion:
function _gt {
if ((CURRENT == 2)); then
root=$(dirname "$(go env GOMOD)")
cd "$root" || return 1
compadd $(go list -f '{{ join .Imports "\n" }}' -tags tools tools.go | sed -e "s#.*/##" )
cd - 1> /dev/null || return 1
elif ((CURRENT > 2)); then
shift words
((CURRENT--))
_normal -p mycmd
fi
}
compdef _gt gt
If you haven’t seen tools.go
before, the TL;DR is:
- Invoke cli utilities – specifically Go commands (
package main
) in other modules – viago run
. For examplego run github.com/bufbuild/buf/cmd/buf lint
. - Reference the cli utilities in a stub
tools.go
file in the root of your projects.
//go:build tools
// +build tools
package foobar
import (
_ "github.com/bufbuild/buf/cmd/buf"
_ "github.com/golangci/golangci-lint/cmd/golangci-lint"
_ "github.com/mfridman/tparse"
_ "github.com/twitchtv/twirp/protoc-gen-twirp"
_ "golang.org/x/vuln/cmd/govulncheck"
_ "google.golang.org/protobuf/cmd/protoc-gen-go"
)
Your command-line utilities will be versioned like everything else in your project & will benefit from the ecosystem around that (Dependabot, govulncheck
, etc.).