- integrations
- Bazel
- Run shellcheck in a Bazel test without installing it
Run shellcheck in a Bazel test without installing it
In this tutorial you add rules_ocx to a Bazel workspace and run shellcheck in an sh_test.
You never install shellcheck on your machine.
It takes about ten minutes.
You need Bazel 8 or later.
You also need the ocx CLI to write the lock file (install it).
rules_ocx wraps ocx. It downloads a pinned ocx build itself and runs it for every fetch.
Pin the tool
Section titled “Pin the tool”Create an empty directory, then declare the tool in ocx.toml.
[tools]shellcheck = "ocx.sh/shellcheck/shellcheck:latest"Resolve it to digests in ocx.lock.
$ ocx lockCommit both files later. The lock file is what makes every build use the same bytes.
Declare the module
Section titled “Declare the module”Create MODULE.bazel.
module(name = "tutorial")
bazel_dep(name = "rules_ocx", version = "0.5.0")bazel_dep(name = "rules_shell", version = "0.6.1")
ocx = use_extension("@rules_ocx//ocx:extensions.bzl", "ocx")ocx.project( name = "tools", ocx_toml = "//:ocx.toml", ocx_lock = "//:ocx.lock",)use_repo(ocx, "tools")Write the test
Section titled “Write the test”Create lint_test.sh and make it executable.
#!/usr/bin/env bashset -euo pipefail
"$SHELLCHECK_BIN" --version | grep -q "version:"echo "shellcheck OK"$ chmod +x lint_test.shCreate BUILD.bazel.
The test gets the tool through data and finds its path through $(location ...).
load("@rules_shell//shell:sh_test.bzl", "sh_test")
sh_test( name = "lint", srcs = ["lint_test.sh"], data = ["@tools//:shellcheck"], env = {"SHELLCHECK_BIN": "$(location @tools//:shellcheck)"},)Run it
Section titled “Run it”$ bazel test //:lintThe first run fetches ocx and shellcheck, then reports //:lint as PASSED.
Check what you got
Section titled “Check what you got”List the targets that rules_ocx created.
$ bazel query @tools//...The list contains @tools//:shellcheck.
A tool that is declared but missing from this list raises no error, so run this query whenever a target you expect is absent.