Bazel is generally only a build tool, and is unaware of your version control system. However, when publishing releases, you may want to embed version information in the resulting distribution. Bazel supports this with the concept of a “Workspace status” which is evaluated before each build. See the Bazel workspace status docs
To stamp a build, you must pass the --stamp
argument to Bazel.
Stamping is typically performed on a later action in the graph, like on a packaging rule (pkg_*
). This means that
a changed status variable only causes re-packaging, not re-compilation and thus does not cause cascading re-builds.
Bazel provides a couple of statuses by default, such as BUILD_EMBED_LABEL
which is the value of the --embed_label
argument, as well as BUILD_HOST
and BUILD_USER
. You can supply more with the workspace status script, see below.
Some rules accept an attribute that uses the status variables.
In a pkg_npm
or pkg_web
you can use the substitutions
attribute like:
pkg_npm(
name = "npm_package",
substitutions = {"0.0.0-PLACEHOLDER": "{STABLE_GIT_COMMIT}"},
)
In a --stamp
build, this will replace the string “0.0.0-PLACEHOLDER” in any file included in the package with the current value of the STABLE_GIT_COMMIT
variable.
However without stamping the placeholder will be left as-is.
The rollup_bundle
rule just exposes the Bazel status files so that your custom rollup.config.js
can read it.
See Rollup.
To define additional statuses, pass the --workspace_status_command
argument to bazel
.
The value of this flag is a path to a script that prints space-separated key/value pairs, one per line, such as
#!/usr/bin/env bash
echo STABLE_GIT_COMMIT $(git rev-parse HEAD)
For a more full-featured script, take a look at the bazel_stamp_vars in Angular
Make sure you set the executable bit, eg. chmod 755 tools/bazel_stamp_vars.sh
.
NOTE keys that start with
STABLE_
will cause a re-build when they change. Other keys will NOT cause a re-build, so stale values can appear in your app. Non-stable (volatile) keys should typically be things like timestamps that always vary between builds.
You might like to encode your setup using an entry in .bazelrc
such as:
# This tells Bazel how to interact with the version control system
# Enable this with --config=release
build:release --stamp --workspace_status_command=./tools/bazel_stamp_vars.sh
If you publish more than one package from your workspace, you might want a release script around Bazel.
A nice pattern is to do a bazel query
to find publishable targets, build them in parallel, then publish in a loop.
Here is a template to get you started:
#!/usr/bin/env bash
set -u -e -o pipefail
# Call the script with argument "pack" or "publish"
readonly NPM_COMMAND=${1:-publish}
# Don't rely on $PATH to have the right version
readonly BAZEL=./node_modules/.bin/bazel
# Find all the npm packages in the repo
readonly PKG_NPM_LABELS=`$BAZEL query --output=label 'kind("pkg_npm", //...)'`
# Build them in one command to maximize parallelism
$BAZEL build --config=release $PKG_NPM_LABELS
# publish one package at a time to make it easier to spot any errors or warnings
for pkg in $PKG_NPM_LABELS ; do
$BAZEL run --config=release -- ${pkg}.${NPM_COMMAND} --access public --tag latest
done
See https://www.kchodorow.com/blog/2017/03/27/stamping-your-builds/ for more background. Make sure you use a “STABLE_” status key, or else Bazel may use a cached npm artifact rather than building a new one with your current version info.