Some Go packages ship runnable programs. We’d like to be able to invoke these programs with Bazel, either for side-effects (with bazel run
) or as steps that produce build outputs (with bazel build
).
For this exercise, we’ll use the Cobra tool, https://cobra.dev/. It provides a CLI tool at Embed GitHub which we can run with Bazel, instead of using go install
to make a local installation.
Fetching the tool
Create a file at tools/tools.go
which contains only unused imports. This pattern allows the standard Go tooling to fetch the tool, even though none of our application code depends on it.
//go:build tools
// +build tools
package go_tools
import (
_ "github.com/spf13/cobra-cli"
)
Now just run ./tools/go mod tidy
again, to add the cobra-cli tool to our Bazel repository.
Note that it’s also possible to have tools in a separate go.mod
file so they don’t have their dependencies constraint-solved along with application code in a monorepo. This is currently experimental, using a new --experimental_isolated_extension_usages
flag in Bazel. See https://github.com/bazel-contrib/rules_go/blob/master/docs/go/core/bzlmod.md#depending-on-tools.
To see that it’s working, we could use a query
command to see what targets exist in the new external repository, like the following:
% bazel query --output=label_kind @com_github_spf13_cobra_cli//:al
l
go_binary rule @com_github_spf13_cobra_cli//:cobra-cli
go_library rule @com_github_spf13_cobra_cli//:cobra-cli_lib
_package_info rule @com_github_spf13_cobra_cli//:gazelle_generated_package_info
Run the tool
First let’s verify that the cobra-cli
executes correctly. We’ll run the --help
flag. Note the extra --
argument, which is a delimiter used to note where the flags to bazel
end, and the flags to the program begin.
% bazel run @com_github_spf13_cobra_cli//:cobra-cli -- --help
Cobra is a CLI library for Go that empowers applications.
...
bazel run
has some bugs with handling the working directory. Since we want the cobra tool to create files in our source folder, the working directory matters. Since we already have a pattern in the tools/
folder, we’ll follow that. See https://blog.aspect.build/run-tools-installed-by-bazel for more on this pattern.
- Create a
tools/cobra
symlink to thetools/_run_under_cwd.sh
script by runningln -s ./_run_under_cwd.sh tools/cobra
- In
tools/_run_under_cwd.sh
add thecobra
case:
cobra)
target="@com_github_spf13_cobra_cli//:cobra-cli"
;;
Now you can run the init
command provided by Cobra to create a new application. Since this is a monorepo, we’ll make a subfolder for this project first.
% mkdir dice
% cd dice
% ../tools/cobra init
% cd ..
This will create some files that provide our CLI application: main.go
and cmd/root.go
. These files contain some new dependencies we haven’t already installed, so we need to update go.mod
again:
% ./tools/go mod tidy
And then update BUILD
files:
% bazel configure
Now we can run our newly-generated program:
% bazel run dice
A longer description...
Using the tool as a build step
This section is coming soon.