Skip to main content
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 https://github.com/spf13/cobra-cli/blob/main/README.md 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.
Now just run ./tools/go mod tidy again, to add the cobra-cli tool to our Bazel repository.
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:

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 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 run tools installed by bazel for more on this pattern.
  1. Create a tools/cobra symlink to the tools/_run_under_cwd.sh script by running ln -s ./_run_under_cwd.sh tools/cobra
  2. In tools/_run_under_cwd.sh add the cobra case:
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.
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:
And then update BUILD files:
Now we can run our newly-generated program:

Using the tool as a build step

This section is coming soon.