This means you don’t even need Bazel installed on your local machine to initiate a Bazel build! Plus, our remote runners support any bash commands, not just Bazel commands.
Benefits of Remote Bazel
Remote Bazel makes it easy to configure the OS, architecture, and container image of the remote runner. This makes it easy to run builds on a specific platform. Remote Bazel also has the following performance benefits:Fast Network Connection
Colocation with BuildBuddy servers, ensuring a fast network connection between Bazel and BuildBuddy’s RBE & caching servers.
Warm Bazel Instances
Bazel workspaces are recycled between runs, allowing subsequent runs to take advantage of warm Bazel instances.
Remote Bazel uses the same backend technology as our CI product, BuildBuddy Workflows. See our docs on BuildBuddy Workflows for a more in-depth description of the performance optimizations and mechanism for workspace recycling.
Uses for Remote Bazel
CI
Remote Bazel is powered by the same backend as our CI product, BuildBuddy Workflows. However, Remote Bazel is a much more flexible entrypoint to our CI platform. Workflows must be configured with a config YAML that is checked in to GitHub. Despite the performance benefits of running on Workflows, many companies have legacy CI workflows that would be challenging and error-prone to migrate to a new CI platform. As Remote Bazel commands are dynamically constructed, it is also easier to pass in short-lived credentials or to run a wider range of commands, because they don’t have to be codified in a YAML.Developer day-to-day
Remote Bazel also has a wide range of applications in the day-to-day of developers.Cross-platform development
Cross-platform development
Sample Command
Accessing powerful remote machines
Accessing powerful remote machines
Sample Command
Running multiple builds in parallel
Running multiple builds in parallel
Remote Bazel lets you spin up multiple simultaneous builds without conflict, and without utilizing all the resources on your machine.For example, when debugging a flaky test, you might run the test with
--runs_per_test=100 to root out the flake. While that slow build is running, you might want to work on something else. Remote Bazel lets you run these workloads simultaneously.Running builds from the UI
Running builds from the UI
Now that we can initiate a Bazel build via CURL request, even a web browser can run builds. We’ve added several useful Remote Bazel backed UI features to solve common customer pain points:
- Why did this seemingly unrelated target build? - From an invocation link, you can run a
bazel queryto visualize the dependency graph between two targets. - What invalidated the cache between these builds? - From an invocation link, you can initiate a Remote Bazel run that compares the compact execution logs of two invocations.
- What is the code coverage of this test? - From an invocation link for a test run, you can run a
bazel coverageto see stats on code coverage.
Getting started
You can invoke Remote Bazel with the BuildBuddy CLI or by CURL request. See Troubleshooting for details on more requirements and common troubleshooting issues.Using the CLI
Download the CLI
Download the bb CLI: https://www.buildbuddy.io/cli/
Trigger a remote run
From a local git repo, trigger a remote run with
bb remote <bazel command>- Ex.
bb remote build //...bb remote test //...
Configure (optional)
You can configure the remote run with flags between
remote and the bazel command- See Configuring the remote runner below for more details
Automatic git state mirroring
In order to facilitate convenient local development, the CLI will automatically upload any local git diffs to the remote runner. This ensures that the remote git workspace matches your local one. This is helpful if you are quickly iterating on code changes, and want the changes to be reflected on the remote runner without having to push and pull changes from GitHub. If you wish to disable git mirroring and want the remote runner to run from a specific git ref, you can use--run_from_branch or --run_from_commit.
Configuring the remote runner
In order to configure the remote runner, you can add the following flags betweenremote and the bazel command.
The operating system of the remote runner.
linux is supported by default. darwin is supported with self-hosted Mac executors.The CPU architecture of the remote runner.
amd64 is supported by default. arm64 is supported with self-hosted executors.The Linux container image to use. Has no effect on Mac runners.
Environment variables to set on the remote runner. Ex.
--env=K1=V1 --env=K2=V2Platform properties to configure the remote runner. Ex. To run on a self-hosted executor pool, you could use
--runner_exec_properties=use-self-hosted-executors=true --runner_exec_properties=Pool=custom-poolRemote headers to be applied to the execution request for the remote runner. These are useful for passing platform properties containing secrets. Platform properties set via remote header will not be displayed on the UI and will not be included in the snapshot key.
If set, remote runs that have been running for longer than this duration will be canceled automatically. This only applies to a single attempt, and does not include multiple retry attempts. Ex. ‘30m’, ‘1h’
If set, the remote runner will run off the specified GitHub branch. By default if neither this nor
--run_from_commit is set, the remote GitHub workspace will mirror the local state (including any non-committed local diffs).If set, the remote runner will run off the specified GitHub commit. By default if neither this nor
--run_from_branch is set, the remote GitHub workspace will mirror the local state (including any non-committed local diffs).If set, the bash code to run on the remote runner instead of a Bazel command. See Running bash scripts below for more details.
By default, remote runs are automatically retried on transient errors. If your remote command is not idempotent (such as if you’re running a deploy command), you should set this to true to disable retries.
Authorization
To authorize your Remote Bazel run via CLI, you can use one of these options:- bb login
- Environment Variable
- Remote Header
Use
bb login.When you run a Remote Bazel command without authorization, the CLI will automatically bring you to our UI and prompt you to log in and select an API key. That API key will be cached locally, and all future commands will use it. This API key can be edited in .git/config on your local machine, or by rerunning bb login.Running bash scripts
To run arbitrary bash code on the remote runner, use the--script flag.
Not all features - such as fetching outputs built remotely, or running remotely built outputs locally - are supported when running with a bash script. If you only need to run a single bazel command on the remote runner, we recommend not using
--script and using the syntax bb remote <bazel command> (like bb remote build //...) to access the richer feature-set.Speeding up the CLI
For more details on CLI performance, run Remote Bazel with--verbose=1 to see where the CLI is spending its time.
- Disabling git mirroring and directing the runner to run from a specific ref using
--run_from_branchor--run_from_commit. - Manually setting the default git branch by setting the environment variable
GIT_REPO_DEFAULT_BRANCHin your local environment.
CURL request
See the API definition here. Sample CURL request:Checking for invocation completion
Checking for invocation completion
If using the CLI, it will automatically stream logs for your remote run and exit when the remote run is complete.If using the
Run API, you must manually check for invocation completion.If async=true in the API request, the Run API will return after the remote run has been dispatched to the scheduler. If async=false, the API will return after the remote run has started executing (i.e. after scheduling and queueing).You can poll the GetInvocation API with the invocation ID returned in the Run response to check for completion of the remote run.You can use the GetLog API to fetch logs for your remote run.Applying git patches
Applying git patches
If using the CLI, it will automatically upload local git diffs to the remote runner to ensure the remote git workspace matches your local one.If using the
Run API, you can pass patch sets as Base64-encoded strings.Retry behavior
By default, Remote Bazel runs are assumed to be idempotent and are automatically retried on transient errors. If this is not the case and it is important that your commands run at most once, you should disable automatic retries with--disable_retry.
Private GitHub repos
If your GitHub repo is private, you must first link it at https://app.buildbuddy.io/workflows/ to authorize the remote runner to access it.Custom Docker images
If you’d like to specify a custom Docker image for the remote runner, you can use the--container_image flag. Be aware of the following requirements when using a custom image:
- By default, the remote runner assumes a non-root user named
buildbuddyis provisioned on the runner.- Either make sure your image has a provisioned user named
buildbuddy, or specify a custom user with--runner_exec_properties=dockerUser=myUser.
- Either make sure your image has a provisioned user named
- Images are expected to be prefixed with
docker://.- Ex.
docker://gcr.io/flame-public/rbe-ubuntu20-04-workflows:latest
- Ex.
Private Docker images
If you would like the remote runner to start from a private container image, you can pass credentials via remote headers. See /rbe-platforms#passing-credentials-for-docker-images for more details on passing credentials for private images.Accessing secrets
To access long-lived secrets on the remote runner, we recommend saving them as BuildBuddy Secrets. To populate secrets as environment variables on the remote runner, pass--runner_exec_properties=include-secrets=true to the Remote Bazel command. You can then access them as you would any environment variable.
GitHub Enterprise
In order to use Remote Bazel with GitHub Enterprise, you must set--use_system_git_credentials and use self-hosted executors that are configured with SSH credentials to access your repo.
Troubleshooting and Common Issues
Using an API key with Action Cache write permissions
To take advantage of recycled runners, you must use an API key that has permission to write to the remote Action Cache.Snapshot metadata is stored in the Action Cache. If this metadata is not successfully cached, future runs will not be able to use it to restore from a recycled runner.
Why was my remote run unexpectedly slow?
If a remote run was unexpectedly slow, one common culprit is that it didn’t resume from a snapshot. If your run started from a snapshot, you should expect to see:Syncing existing repo...at the top of the remote runner logs. If it started from a clean runner, it would saygit initinstead.VM resumed from snapshot IDin the execution metadata in theExecutionstab for your remote run invocation. This section contains information about the snapshot key and invocation your current run resumed from.
Why isn’t my remote run using a recycled runner?
If your remote runs aren’t using a recycled runner when you expected them to, there are a couple common culprits.Not using an API key with Action Cache write permissions
Not using an API key with Action Cache write permissions
See above for more details.
The snapshot was evicted
The snapshot was evicted
Recycled runner snapshots are stored in the remote cache and are subject to eviction like any other cache artifacts. If the cache TTL has expired, the snapshot may have been evicted and may no longer be accessible.
Snapshot key mismatch
Snapshot key mismatch
Remote runs can only share snapshots with runs that share the same snapshot key. If any of the following fields differ between runs (other than the git branch, which has more complicated logic explained below), you will not get a snapshot match.The snapshot key contains:
- The remote instance name for the request.
- A hash of the platform properties (set via
--runner_exec_properties). - A hash of the VM configuration, which contains parameters like the number of CPUs, memory, and disk size.
- The git branch.
Not enough time to save a snapshot
Not enough time to save a snapshot
Especially if you are snapshotting a clean runner for the first time, it can take some time for a snapshot to be saved, because the entire machine must be serialized and cached.If you’re running two remote runs in fast succession, there’s a chance the first snapshot hasn’t been saved before you start the second. You may want to wait a couple minutes to ensure enough time has passed for a snapshot to be saved.Once a snapshot exists, saving snapshots in the future will be faster because only diffs have to be saved.