Stamping

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.

Substitutions attribute

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.

Read the status files

The rollup_bundle rule just exposes the Bazel status files so that your custom rollup.config.js can read it. See Rollup.

Stamping with a Workspace status script

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 start 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

Release script

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.