This repository uses Bazel to provide a monorepo developer experience.
- Run
bazel run format
to re-format all files locally. - Run
bazel run format path/to/file
to re-format a single file. - Run
pre-commit install
to auto-format changed files ongit commit
; see https://pre-commit.com/.
We use rules_lint to run linting tools using Bazel's aspects feature. Linters produce report files, which are cached like any other Bazel actions. Printing the report files to the terminal can be done in a couple ways, as follows.
The lint
command is provided by Aspect CLI but is not part of the Bazel CLI provided by Google.
It collects the correct report files, presents them with nice colored boundaries, gives you interactive suggestions to apply fixes, produces a matching exit code, and more.
- Run
bazel lint //...
to check for lint violations.
See comments on aspect-build/bazel-examples#335 for some examples of how to exercise the linters.
Aspect CLI makes the developer experience for linting a lot nicer, but it's not required.
- Run
bazel build --config=lint //...
to produce lint reports. (See thebuild:lint
lines in.bazelrc
for the flags this config option expands to.) - Print the resulting reports, for example a simplistic one-liner using
find
looks like:find $(bazel info bazel-bin) -name "*AspectRulesLint*report" -exec cat {} \;
For a more robust developer experience, see the sample shell script in the rules_lint example.
For developers to be able to run a CLI tool without needing manual installation:
- Add the tool to
tools/tools.lock.json
cd tools; ln -s _run_under_cwd.sh name_of_tool
- Instruct developers to run
./tools/name_of_tool
rather than install that tool on their machine.
To update the versions of installed tools, run:
% cd $(bazel info workspace)/tools; ./multitool --lockfile tools.lock.json update
See https://blog.aspect.build/run-tools-installed-by-bazel for details.
To install a node_modules
tree locally for the editor or other tooling outside of Bazel,
run this command from any folder with a package.json
file:
% $(bazel info workspace)/tools/pnpm install
NB:
bazel info workspace
avoids having a bunch of../
segments when running tools from a subdirectory.
Similarly, you can run other pnpm
commands to add or remove packages.
% $(bazel info workspace)/tools/pnpm add http-server
This ensures you use the same pnpm version as other developers, and the lockfile format will stay constant.
After adding a new import
statement in Python code, run bazel configure
to update the BUILD file.
If the package is not already a dependency of the project, you'll have to do some additional steps:
# Update dependencies table to include your new dependency
% vim pyproject.toml
# Update lock files to pin this dependency
% bazel run //requirements:runtime.update
% bazel run //requirements:requirements.all.update
% bazel run //:gazelle_python_manifest.update
To create a runnable binary for a console script from a third-party package, run the following:
% cat<<'EOF' | ./tools/buildozer -f -
new_load @rules_python//python/entry_points:py_console_script_binary.bzl py_console_script_binary|new py_console_script_binary scriptname|tools:__pkg__
set pkg "@pip//package_name_snake_case"|tools:scriptname
EOF
Then edit the new entry in tools/BUILD
to replace package_name_snake_case
with the name of the package that exports a console script, and scriptname
with the name of the script.
Note
See https://rules-python.readthedocs.io/en/stable/api/python/entry_points/py_console_script_binary.html for more details.
After adding a new import
statement in Go code, run bazel configure
to update the BUILD file.
If the package is not already a dependency of the project, you'll have to do some additional steps. Run these commands from the workspace root:
# Update go.mod and go.sum, using same Go SDK as Bazel
% $(bazel info workspace)/tools/go mod tidy -v
# Update MODULE.bazel to include the package in `use_repo`
% bazel mod tidy
# Repeat
% bazel configure
Maven coordinates for third-party packages live in the MODULE.bazel
file.
After changing them, run bazel run @unpinned_maven//:pin
to update the maven_install.json
file.
This file is used by rules_jvm_external
to fetch packages.
Then use the artifact("some.org:coordinate")
helper to resolve a label to the resulting java_library
targets.
Stamping produces non-deterministic outputs by including information such as a version number or commit hash.
Read more: https://blog.aspect.build/stamping-bazel-builds-with-selective-delivery
To declare a build output which can be stamped, use a rule that is stamp-aware such as expand_template.
Available keys are listed in /tools/workspace_status.sh
and may include:
STABLE_GIT_COMMIT
: the commit hash of the HEAD (current) commitSTABLE_MONOREPO_VERSION
: a semver-compatible version in the form2020.44.123+abc1234
To request stamped build outputs, add the flag --config=release
.