Enable BuildBuddy integration in CI with API key injection#1166
Conversation
Inject the API key into a gitignored .bazelrc.user at CI time so build/test runs upload to BuildBuddy and read/write the remote cache. Falls back gracefully when the secret is missing (e.g. fork PRs). Also splits --remote_executor out of build:buildbuddy into the platform-specific *-remote configs so --config=buildbuddy is safe to use on Linux/macOS/Windows runners for cache+BES only.
Adds --build_metadata=VISIBILITY=PUBLIC to the buildbuddy config so invocation result pages are viewable without a BuildBuddy account.
There was a problem hiding this comment.
Pull request overview
Integrates BuildBuddy BES/remote caching into CI by injecting an API key at runtime via a generated .bazelrc.user, and refactors Bazel configs to keep remote execution platform-specific while allowing optional user/CI overrides.
Changes:
- Add CI step to generate
.bazelrc.userfromBUILDBUDDY_API_KEYwhen available. - Refactor
.bazelrcBuildBuddy config to be platform-agnostic, moving--remote_executorinto platform-specific configs. - Add
.bazelrc.usersupport viatry-importand ignore it in git.
Reviewed changes
Copilot reviewed 2 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
.gitignore |
Ignores generated .bazelrc.user to avoid committing injected secrets/config. |
.github/workflows/bazel.yml |
Adds conditional BuildBuddy configuration step using a secret-injected environment variable. |
.bazelrc |
Splits BuildBuddy configuration (base vs. platform-specific) and adds optional user/CI import. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| run: | | ||
| if [ -n "${BUILDBUDDY_API_KEY}" ]; then | ||
| echo "build --config=buildbuddy --remote_header=x-buildbuddy-api-key=${BUILDBUDDY_API_KEY}" >> .bazelrc.user | ||
| echo "BuildBuddy enabled." |
There was a problem hiding this comment.
This is incorrect. The bazel test command inherits options from build, including --config=foo resolution against build:foo. Per Bazel's bazelrc docs, when bazel test --config=buildbuddy runs, it activates common:buildbuddy, test:buildbuddy, and build:buildbuddy. So flags under build:buildbuddy (BES + remote cache) do apply during bazel test in our CI.
Generated by Claude Code
|
|
||
| # BuildBuddy.io | ||
| # BuildBuddy.io: BES + remote cache (safe to use on any platform). | ||
| # Pass the API key with: --remote_header=x-buildbuddy-api-key=$BUILDBUDDY_API_KEY |
There was a problem hiding this comment.
Good catch. Fixed in 4dfc7b8 — the workflow now writes both --remote_header=x-buildbuddy-api-key=... (for remote cache) and --bes_header=x-buildbuddy-api-key=... (for BES) into .bazelrc.user. The .bazelrc comment was updated to document both flags.
Generated by Claude Code
| build:buildbuddy --bes_results_url=https://app.buildbuddy.io/invocation/ | ||
| build:buildbuddy --bes_backend=grpcs://remote.buildbuddy.io | ||
| build:buildbuddy --remote_cache=grpcs://remote.buildbuddy.io | ||
| build:buildbuddy --noremote_upload_local_results # Uploads logs & artifacts without writing to cache | ||
| build:buildbuddy --remote_timeout=10m |
There was a problem hiding this comment.
Same as the comment on the workflow file — this is incorrect. bazel test inherits options from build, so bazel test --config=buildbuddy does activate build:buildbuddy flags (BES + remote cache). See Bazel's bazelrc docs. No move to common:buildbuddy needed; CI tests will use BES and remote cache as intended.
Generated by Claude Code
--remote_header is documented as applying to remote cache/execution gRPC channels; BES uses a separate channel and the dedicated --bes_header flag. Set both so BuildBuddy's BES backend is authenticated regardless of any cross-channel header sharing.
Summary
This PR integrates BuildBuddy remote caching and build event streaming into the CI/CD pipeline by securely injecting the API key at runtime, while maintaining flexibility for local development and fork PRs.
Key Changes
.bazelrc.userwhen theBUILDBUDDY_API_KEYsecret is available. The step gracefully handles missing secrets (e.g., in fork PRs) with an informative message.buildbuddyconfig to be platform-agnostic by removing the remote executor settinglinux-x86_64-remoteandlinux-arm64-remote)--build_metadata=VISIBILITY=PUBLICso invocation result pages are viewable without a BuildBuddy account--remote_header=x-buildbuddy-api-key.bazelrc.userto.gitignoreand configured.bazelrcto import it withtry-import, allowing CI and local development to inject environment-specific settings without version controlLocal Development Is Unaffected
BuildBuddy is opt-in — it is only activated in CI, not during local development:
build:buildbuddyconfig namespace, so they only apply when--config=buildbuddyis explicitly passed.build --config=buildbuddy --remote_header=x-buildbuddy-api-key=…into.bazelrc.userat job start. That file is gitignored and never exists locally..bazelrcloads it viatry-import %workspace%/.bazelrc.user, which silently no-ops when the file is absent.Net effect:
bazel build //...→ no.bazelrc.user, no--config=buildbuddy→ zero traffic to BuildBuddy..bazelrc.user→ BES upload + remote cache enabled automatically.A developer who wants BuildBuddy locally can either create their own
.bazelrc.userwith their personal API key, or pass--config=buildbuddy --remote_header=x-buildbuddy-api-key=$KEYad hoc.Implementation Details
buildbuddyconfig handles BES and remote caching (safe for all platforms), while platform-specific configs add remote execution capabilities.bazelrc.userfile is generated at runtime and ignored by git, enabling secure credential injection without exposing secrets in the repositoryhttps://claude.ai/code/session_01KVRC2eMbe6ShHJqaTLPxPj