Add Bazel hot cache build helper

This commit is contained in:
starr-openai
2026-06-02 21:06:19 -07:00
parent d36a3ead3c
commit 4f4a816f41
3 changed files with 273 additions and 0 deletions

View File

@@ -0,0 +1,115 @@
---
name: bazel-hot-cache
description: Use the CI-warmed BuildBuddy cache for fast local or Applied devbox Bazel builds without uploading local artifacts.
---
# Bazel Hot Cache
Use this skill when a Codex developer wants a fast Bazel build from the
BuildBuddy cache warmed by post-merge CI, especially for
`//codex-rs/cli:codex`.
## Why This Exists
The checked-in helper `scripts/run-bazel-hot-cache-build.sh` consumes the
BuildBuddy keyspace warmed by the platform-matching `verify-release-build` lane
on successful `main` pushes. That CI lane is the relevant writer because it
builds release-shaped Rust code in Bazel `fastbuild` mode with Rust debug
assertions disabled, which matches the developer build shape this helper is
for.
The helper is read-only from a developer machine or devbox:
```text
--noremote_upload_local_results
```
Do not change this to upload laptop or devbox artifacts unless the user
explicitly asks for a cache-warming writer flow.
## Local Flow
From a Codex checkout with `gh` auth and `BUILDBUDDY_API_KEY` in the command
environment:
```bash
hot_sha="$(scripts/run-bazel-hot-cache-build.sh --print-latest-hot-main-commit)"
git worktree add ../codex-hot-cache "${hot_sha}"
cd ../codex-hot-cache
scripts/run-bazel-hot-cache-build.sh
```
If the current checkout is already at the desired hot SHA, run the helper in
place. Pass Bazel target patterns after the script name to build something
other than the default `//codex-rs/cli:codex`.
For routine developer use, keep Bazel's normal persistent user root and
repository cache. A fresh worktree already gives Bazel a fresh workspace/output
base while preserving the shared local Bazel state that makes the workflow
predictable. Only set `BAZEL_OUTPUT_USER_ROOT` when intentionally running an
isolated diagnostic proof; that discards useful local Bazel state and can be
substantially slower even when remote cache hits are 100%.
## Applied Devbox Flow
The same helper works on a Linux Applied devbox mirror. The helper selects
`ci-linux` on Linux and `ci-macos` on macOS. Applied rsync mirrors commonly
exclude `.git`, so forward the checkout SHA as `CODEX_BAZEL_COMMIT_SHA` for
that remote command. The helper itself does not use `tmux`.
Portable shape:
```bash
commit_sha="$(git rev-parse HEAD)"
remote_repo="<remote-codex-repo>"
BUILDBUDDY_API_KEY_STDIN="$BUILDBUDDY_API_KEY" \
ssh <devbox-host> "bash -lc 'read -r BUILDBUDDY_API_KEY; export BUILDBUDDY_API_KEY; export CODEX_BAZEL_COMMIT_SHA=${commit_sha}; cd ${remote_repo}; export PATH=\$HOME/code/openai/project/dotslash-gen/bin:\$HOME/.local/bin:\$PATH; scripts/run-bazel-hot-cache-build.sh'" \
<<< "$BUILDBUDDY_API_KEY_STDIN"
```
Replace `<devbox-host>` and `<remote-codex-repo>` with the caller's actual host
and mirrored checkout path. Do not persist the BuildBuddy key on the devbox for
this flow.
## Cache-Key Rules
The helper intentionally owns the Bazel option order. Keep the explicit Rust
debug-assertion flags before the platform CI config. The CI config adds Rust
flags too, and Bazel action keys include generated Rust params-file bytes, so
moving `--config=ci-macos` or `--config=ci-linux` before those explicit flags
can turn a CI-hot action into a remote miss.
The helper sets:
- `--config=buildbuddy-openai-rbe`
- `--compilation_mode=fastbuild`
- Rust `-Cdebug-assertions=no` flags for target and exec Rust actions
- `--build_metadata=COMMIT_SHA=<checkout-sha>`
- `--build_metadata=TAG_job=verify-release-build`
- `--build_metadata=TAG_rust_debug_assertions=off`
- `--config=ci-macos` on macOS or `--config=ci-linux` on Linux
- `--remote_download_toplevel`
- `--noremote_upload_local_results`
## Reading Results
Read Bazel summaries as:
```text
cacheable_hit_rate = remote cache hit / (all processes - internal)
```
Do not include Bazel `internal` processes in the denominator; they are local
bookkeeping, not cache misses.
## Limits
- Build mode supports macOS and Linux only.
- `--print-latest-hot-main-commit` requires `gh` auth.
- Build mode requires `BUILDBUDDY_API_KEY`.
- This is command/config specific. A successful `main` Bazel run is a good hot
default for this helper's `verify-release-build` shape, not proof that every
other Bazel command is hot.
- Routine latency claims should be measured from fresh worktrees using the
normal persistent Bazel user root, not from fresh `BAZEL_OUTPUT_USER_ROOT`
diagnostics.

View File

@@ -132,6 +132,41 @@ run in `openai/codex`. A missing or malformed pull request event
payload fails closed to the generic host. For local OpenAI host access, use
the `user.bazelrc` configuration above.
### Use the CI-warmed developer cache
The platform-matching `verify-release-build` Bazel lane on `main` warms a
developer fastbuild keyspace for release-shaped Rust builds with debug
assertions off. On a local Mac or Linux Applied devbox with
`BUILDBUDDY_API_KEY` set in that command's environment, use
`scripts/run-bazel-hot-cache-build.sh` to consume that cache without uploading
locally built artifacts:
```bash
hot_sha="$(scripts/run-bazel-hot-cache-build.sh --print-latest-hot-main-commit)"
git worktree add ../codex-hot-cache "${hot_sha}"
cd ../codex-hot-cache
scripts/run-bazel-hot-cache-build.sh
```
If the current checkout is already at a known hot commit, run the script in
place instead of creating another worktree. On an Applied Linux devbox, run
the same script from the synced mirror with `BUILDBUDDY_API_KEY` and
`CODEX_BAZEL_COMMIT_SHA` forwarded only for that remote command; it selects the
Linux `verify-release-build` cache keyspace instead of the macOS one. Pass
Bazel target patterns after the script name to build something other than the
default `//codex-rs/cli:codex`.
For routine developer use, keep Bazel's normal persistent user root and
repository cache. A fresh worktree already gives Bazel a fresh workspace/output
base while preserving the shared local Bazel state that makes this workflow
predictable. Set `BAZEL_OUTPUT_USER_ROOT` only for isolated diagnostic proofs;
that discards useful local Bazel state and can be much slower even when remote
cache hits are 100%.
Keep the script-owned option order. Bazel action keys include the generated
Rust params-file bytes, so moving the platform CI config before the explicit
Rust debug-assertion flags can turn a hot CI action into a local cache miss.
## Evolving the setup
When you add or change Rust dependencies, update the Cargo.toml/Cargo.lock as normal.

View File

@@ -0,0 +1,123 @@
#!/usr/bin/env bash
set -euo pipefail
readonly OPENAI_REPOSITORY="openai/codex"
readonly DEFAULT_TARGET="//codex-rs/cli:codex"
usage() {
cat <<'EOF'
Usage:
scripts/run-bazel-hot-cache-build.sh [bazel target patterns...]
scripts/run-bazel-hot-cache-build.sh --print-latest-hot-main-commit
Build the current checkout against the BuildBuddy keyspace warmed by the
platform-matching verify-release-build Bazel CI lane. If no target is
provided, builds //codex-rs/cli:codex.
Requires:
- macOS or Linux for build mode
- BUILDBUDDY_API_KEY in the environment for build mode
- gh auth for --print-latest-hot-main-commit
EOF
}
print_latest_hot_main_commit() {
if ! command -v gh >/dev/null 2>&1; then
echo "gh is required to find the latest hot main commit." >&2
exit 1
fi
local hot_commit
hot_commit="$(
gh run list \
--repo "${OPENAI_REPOSITORY}" \
--workflow Bazel \
--branch main \
--event push \
--limit 20 \
--json headSha,status,conclusion \
--jq '[.[] | select(.status == "completed" and .conclusion == "success") | .headSha][0] // empty'
)"
if [[ -z "${hot_commit}" ]]; then
echo "No successful Bazel main push run found." >&2
exit 1
fi
printf '%s\n' "${hot_commit}"
}
case "${1:-}" in
--help | -h)
usage
exit 0
;;
--print-latest-hot-main-commit)
print_latest_hot_main_commit
exit 0
;;
esac
if [[ -z "${BUILDBUDDY_API_KEY:-}" ]]; then
echo "BUILDBUDDY_API_KEY must be set to read the OpenAI BuildBuddy cache." >&2
exit 1
fi
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
repo_root="$(cd "${script_dir}/.." && pwd -P)"
cd "${repo_root}"
targets=("$@")
if [[ ${#targets[@]} -eq 0 ]]; then
targets=("${DEFAULT_TARGET}")
fi
bazel_bin="${CODEX_BAZEL_BIN:-bazel}"
repository_cache="${BAZEL_REPOSITORY_CACHE:-${HOME}/.cache/bazel-repo-cache}"
commit_sha="${CODEX_BAZEL_COMMIT_SHA:-${GITHUB_SHA:-}}"
if [[ -z "${commit_sha}" ]] && command -v git >/dev/null 2>&1; then
commit_sha="$(git rev-parse HEAD 2>/dev/null || true)"
fi
if [[ -z "${commit_sha}" ]]; then
echo "Could not determine COMMIT_SHA; set CODEX_BAZEL_COMMIT_SHA for rsynced mirrors without .git." >&2
exit 1
fi
bazel_ci_config=""
case "$(uname -s)" in
Darwin)
bazel_ci_config="ci-macos"
;;
Linux)
bazel_ci_config="ci-linux"
;;
*)
echo "scripts/run-bazel-hot-cache-build.sh supports macOS and Linux only." >&2
exit 1
;;
esac
bazel_startup_args=()
if [[ -n "${BAZEL_OUTPUT_USER_ROOT:-}" ]]; then
bazel_startup_args+=("--output_user_root=${BAZEL_OUTPUT_USER_ROOT}")
fi
# Keep the explicit Rust debug-assertion flags before the platform CI config.
# That matches the verify-release-build CI action key ordering that warms this
# cache.
exec "${bazel_bin}" \
"${bazel_startup_args[@]}" \
--noexperimental_remote_repo_contents_cache \
build \
--config=buildbuddy-openai-rbe \
"--remote_header=x-buildbuddy-api-key=${BUILDBUDDY_API_KEY}" \
--compilation_mode=fastbuild \
--@rules_rust//rust/settings:extra_rustc_flag=-Cdebug-assertions=no \
--@rules_rust//rust/settings:extra_exec_rustc_flag=-Cdebug-assertions=no \
"--build_metadata=COMMIT_SHA=${commit_sha}" \
--build_metadata=TAG_job=verify-release-build \
--build_metadata=TAG_rust_debug_assertions=off \
"--config=${bazel_ci_config}" \
--remote_download_toplevel \
"--repository_cache=${repository_cache}" \
--noremote_upload_local_results \
-- \
"${targets[@]}"