Skip to content

Enable Bazel GCS remote cache for CI#101

Open
beaucollins wants to merge 8 commits into
mainfrom
bazel-remote-cache-gcs
Open

Enable Bazel GCS remote cache for CI#101
beaucollins wants to merge 8 commits into
mainfrom
bazel-remote-cache-gcs

Conversation

@beaucollins
Copy link
Copy Markdown
Collaborator

Summary

  • Add GCS remote cache via Workload Identity Federation to all Bazel CI workflows
  • Reusable composite action (.github/actions/bazel-cache) with per-repo config via GitHub repository variables
  • Disk cache + remote cache dual strategy for linux-ci jobs
  • Circuit breaker for graceful token expiry fallback
  • Larger runner (Valdi-Larger-Runner) for linux-ci
  • PRs get read-only cache access to prevent cache poisoning from forks

Results (from valdi_staging testing)

Job Before After
C++ Tests ~2 hrs (cold) 7-10 min
Smoke Tests ~1h 15m 25 min
Snapshot Tests 13 min
Build & Export never succeeded 10 min

Test plan

  • Tested on Snapchat/valdi_staging with full CI runs
  • Verify auth step passes on this repo
  • Verify remote cache hits in Bazel output

🤖 Generated with Claude Code

Add GCS remote cache via Workload Identity Federation to all Bazel CI
workflows. Uses a reusable composite action with per-repo config via
GitHub repository variables.

- Remote cache shared across all jobs and runs
- Disk cache for fast local hits on linux-ci jobs
- Circuit breaker for graceful fallback on token expiry
- Larger runner (Valdi-Larger-Runner) for linux-ci
- PRs get read-only cache (no upload) to prevent cache poisoning

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 28, 2026

Sensitive Files Detected

🔧 Build rules — Affects build rules for all Valdi consumers.

This is an automated notice. A maintainer will review after import.

@github-actions github-actions Bot added area/build-system Bazel build rules and config size/M labels May 28, 2026
@github-actions
Copy link
Copy Markdown

📊 PR Size: size/M

Total changes: 168 lines (5 files)

Top files changed:

  • .github/actions/bazel-cache/action.yml: +79 -0
  • .github/workflows/bzl-changes.yml: +38 -25
  • .github/workflows/publish-npm.yml: +11 -0
  • .github/workflows/release-test.yml: +11 -0
  • .bazelrc: +2 -2

Size calculated as additions + deletions. Labels: XS (<10), S (<50), M (<250), L (<1000), XL (1000+)

Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉 Thanks for your first contribution to Valdi!

A maintainer will review your PR soon. Here are a few things to check while you wait:

  • ✅ All tests pass (bazel test //...)
  • ✅ Your changes follow our coding standards
  • ✅ You've added tests for your changes (if applicable)
  • ✅ You've updated documentation (if needed)

Join our Discord community if you have questions!

@github-actions
Copy link
Copy Markdown

⚠️ Bazel & CI Test Results

Test Suite Result
Linux: Build & Export ❌ failure
Snapshot Tests ❌ failure
Linux: C++ Tests ❌ failure
Valdi Smoke Tests ❌ failure
Comment Test Results / Post Results Comment ❌ null

Some tests failed. Please check the workflow logs for details.

🚀 Bazel remote cache is now enabled - future builds will be faster!

Workflow: Valdi CI

Remove @types/istanbul-lib-coverage and gulp-typescript from deps
(no longer available), add types: [] to tsconfig to prevent implicit
type resolution failures.

Cherry-picked from Snapchat/mobile#99614

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added the area/compiler Valdi compiler label May 28, 2026
TODO: Restore PR read-only after cache is warm

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Comment on lines +36 to +50
run: |
# Checkout directory config
echo "build --config=ci" >> .bazelrc.local
echo "build --remote_cache=https://storage.googleapis.com/${{ inputs.cache_bucket }}" >> .bazelrc.local
echo "build \"--remote_header=Authorization=Bearer ${{ steps.auth.outputs.access_token }}\"" >> .bazelrc.local
# TODO: Restore PR read-only after initial cache seeding
# Only upload cache results on push (trusted) events, not pull requests
echo "build --remote_upload_local_results=true" >> .bazelrc.local
# User-level config for bootstrapped projects (e.g. /tmp/valdi_app)
# Use > for first write to prevent unbounded growth on persistent runners
echo "build --remote_cache=https://storage.googleapis.com/${{ inputs.cache_bucket }}" > ~/.bazelrc
echo "build \"--remote_header=Authorization=Bearer ${{ steps.auth.outputs.access_token }}\"" >> ~/.bazelrc
echo "build --experimental_circuit_breaker_strategy=failure" >> ~/.bazelrc
echo "build --remote_upload_local_results=true" >> ~/.bazelrc

Copy link
Copy Markdown

@semgrep-code-snapchat semgrep-code-snapchat Bot May 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using variable interpolation ${{...}} with github context data in a run: step could allow an attacker to inject their own code into the runner. This would allow them to steal secrets and code. github context data can have arbitrary user input and should be treated as untrusted. Instead, use an intermediate environment variable with env: to store the data and use the environment variable in the run: script. Be sure to use double-quotes the environment variable, like this: "$ENVVAR".

🎈 Fixed in commit c81d9c7 🎈

@github-actions
Copy link
Copy Markdown

⚠️ Bazel & CI Test Results

Test Suite Result
Valdi Smoke Tests ✅ success
Linux: Build & Export ✅ success
Linux: C++ Tests ✅ success
Snapshot Tests ✅ success
Comment Test Results / Post Results Comment ❌ null

Some tests failed. Please check the workflow logs for details.

🚀 Bazel remote cache is now enabled - future builds will be faster!

Workflow: Valdi CI

@github-actions
Copy link
Copy Markdown

⚠️ Bazel & CI Test Results

Test Suite Result
Linux: Build & Export ❌ failure
Valdi Smoke Tests ✅ success
Linux: C++ Tests ✅ success
Snapshot Tests ✅ success
Comment Test Results / Post Results Comment ❌ null

Some tests failed. Please check the workflow logs for details.

🚀 Bazel remote cache is now enabled - future builds will be faster!

Workflow: Valdi CI

1 similar comment
@github-actions
Copy link
Copy Markdown

⚠️ Bazel & CI Test Results

Test Suite Result
Linux: Build & Export ❌ failure
Valdi Smoke Tests ✅ success
Linux: C++ Tests ✅ success
Snapshot Tests ✅ success
Comment Test Results / Post Results Comment ❌ null

Some tests failed. Please check the workflow logs for details.

🚀 Bazel remote cache is now enabled - future builds will be faster!

Workflow: Valdi CI

@github-actions
Copy link
Copy Markdown

⚠️ Bazel & CI Test Results

Test Suite Result
Linux: Build & Export ❌ failure
Valdi Smoke Tests ✅ success
Snapshot Tests ✅ success
Linux: C++ Tests ✅ success
Comment Test Results / Post Results Comment ❌ null

Some tests failed. Please check the workflow logs for details.

🚀 Bazel remote cache is now enabled - future builds will be faster!

Workflow: Valdi CI

…ork hardening

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Comment on lines +37 to +74
run: |
# Always write config=ci for non-remote flags (circuit breaker, etc.)
echo "build --config=ci" >> .bazelrc.local

# Write user-level bazelrc to a job-specific file to avoid race conditions
# on persistent runners where multiple matrix jobs share ~/.bazelrc
JOB_BAZELRC="${GITHUB_WORKSPACE}/.bazelrc.user-cache"
> "$JOB_BAZELRC"

if [ "${{ steps.auth.outcome }}" != "success" ]; then
echo "Auth failed (expected for fork PRs). Skipping remote cache."
# Still set up the user-level bazelrc symlink (empty) for bootstrapped projects
ln -sf "$JOB_BAZELRC" ~/.bazelrc
exit 0
fi

# Checkout directory config
echo "build --remote_cache=https://storage.googleapis.com/${{ inputs.cache_bucket }}" >> .bazelrc.local
echo "build \"--remote_header=Authorization=Bearer ${{ steps.auth.outputs.access_token }}\"" >> .bazelrc.local
# Only upload cache results on push (trusted) events, not pull requests
if [ "${{ github.event_name }}" = "push" ] || [ "${{ github.event_name }}" = "workflow_dispatch" ] || [ "${{ github.event_name }}" = "release" ]; then
echo "build --remote_upload_local_results=true" >> .bazelrc.local
else
echo "build --remote_upload_local_results=false" >> .bazelrc.local
fi

# User-level config for bootstrapped projects (e.g. /tmp/valdi_app)
echo "build --remote_cache=https://storage.googleapis.com/${{ inputs.cache_bucket }}" >> "$JOB_BAZELRC"
echo "build \"--remote_header=Authorization=Bearer ${{ steps.auth.outputs.access_token }}\"" >> "$JOB_BAZELRC"
echo "build --experimental_circuit_breaker_strategy=failure" >> "$JOB_BAZELRC"
if [ "${{ github.event_name }}" = "push" ] || [ "${{ github.event_name }}" = "workflow_dispatch" ] || [ "${{ github.event_name }}" = "release" ]; then
echo "build --remote_upload_local_results=true" >> "$JOB_BAZELRC"
else
echo "build --remote_upload_local_results=false" >> "$JOB_BAZELRC"
fi
# Symlink so Bazel picks it up as ~/.bazelrc
ln -sf "$JOB_BAZELRC" ~/.bazelrc

Copy link
Copy Markdown

@semgrep-code-snapchat semgrep-code-snapchat Bot May 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using variable interpolation ${{...}} with github context data in a run: step could allow an attacker to inject their own code into the runner. This would allow them to steal secrets and code. github context data can have arbitrary user input and should be treated as untrusted. Instead, use an intermediate environment variable with env: to store the data and use the environment variable in the run: script. Be sure to use double-quotes the environment variable, like this: "$ENVVAR".

🎉 Fixed in commit 8f6fb87 🎉

@github-actions
Copy link
Copy Markdown

⚠️ Bazel & CI Test Results

Test Suite Result
Snapshot Tests ✅ success
Valdi Smoke Tests ✅ success
Linux: Build & Export ❌ failure
Linux: C++ Tests ❌ failure
Comment Test Results / Post Results Comment ❌ null

Some tests failed. Please check the workflow logs for details.

🚀 Bazel remote cache is now enabled - future builds will be faster!

Workflow: Valdi CI

@github-actions
Copy link
Copy Markdown

⚠️ Bazel & CI Test Results

Test Suite Result
Snapshot Tests ✅ success
Valdi Smoke Tests ✅ success
Linux: C++ Tests ✅ success
Linux: Build & Export ❌ failure
Comment Test Results / Post Results Comment ❌ null

Some tests failed. Please check the workflow logs for details.

🚀 Bazel remote cache is now enabled - future builds will be faster!

Workflow: Valdi CI

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Comment on lines +37 to +69
run: |
# Always write config=ci for non-remote flags (circuit breaker, etc.)
echo "build --config=ci" >> .bazelrc.local

# Write user-level bazelrc directly (not symlinked) for bootstrapped projects
# Content is identical across same-repo matrix jobs so concurrent writes are safe
> ~/.bazelrc

if [ "${{ steps.auth.outcome }}" != "success" ]; then
echo "Auth skipped (expected for fork PRs). Building without remote cache."
exit 0
fi

# Checkout directory config
echo "build --remote_cache=https://storage.googleapis.com/${{ inputs.cache_bucket }}" >> .bazelrc.local
echo "build \"--remote_header=Authorization=Bearer ${{ steps.auth.outputs.access_token }}\"" >> .bazelrc.local
# Only upload cache results on push (trusted) events, not pull requests
if [ "${{ github.event_name }}" = "push" ] || [ "${{ github.event_name }}" = "workflow_dispatch" ] || [ "${{ github.event_name }}" = "release" ]; then
echo "build --remote_upload_local_results=true" >> .bazelrc.local
else
echo "build --remote_upload_local_results=false" >> .bazelrc.local
fi

# User-level config for bootstrapped projects (e.g. /tmp/valdi_app)
echo "build --remote_cache=https://storage.googleapis.com/${{ inputs.cache_bucket }}" > ~/.bazelrc
echo "build \"--remote_header=Authorization=Bearer ${{ steps.auth.outputs.access_token }}\"" >> ~/.bazelrc
echo "build --experimental_circuit_breaker_strategy=failure" >> ~/.bazelrc
if [ "${{ github.event_name }}" = "push" ] || [ "${{ github.event_name }}" = "workflow_dispatch" ] || [ "${{ github.event_name }}" = "release" ]; then
echo "build --remote_upload_local_results=true" >> ~/.bazelrc
else
echo "build --remote_upload_local_results=false" >> ~/.bazelrc
fi

Copy link
Copy Markdown

@semgrep-code-snapchat semgrep-code-snapchat Bot May 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using variable interpolation ${{...}} with github context data in a run: step could allow an attacker to inject their own code into the runner. This would allow them to steal secrets and code. github context data can have arbitrary user input and should be treated as untrusted. Instead, use an intermediate environment variable with env: to store the data and use the environment variable in the run: script. Be sure to use double-quotes the environment variable, like this: "$ENVVAR".

🌟 Fixed in commit a2e080d 🌟

@github-actions
Copy link
Copy Markdown

⚠️ Bazel & CI Test Results

Test Suite Result
Valdi Smoke Tests ✅ success
Snapshot Tests ✅ success
Linux: C++ Tests ❌ failure
Linux: Build & Export ❌ failure
Comment Test Results / Post Results Comment ❌ null

Some tests failed. Please check the workflow logs for details.

🚀 Bazel remote cache is now enabled - future builds will be faster!

Workflow: Valdi CI

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Comment on lines +37 to +76
run: |
# Always write config=ci for non-remote flags (circuit breaker, etc.)
echo "build --config=ci" >> .bazelrc.local

# Write cache config to a job-specific file. Bootstrapped projects
# (e.g. /tmp/valdi_app) import this via BAZEL_CACHE_RC env var,
# avoiding races on ~/.bazelrc when concurrent jobs share a runner.
CACHE_RC="/tmp/bazelrc-cache-${GITHUB_RUN_ID}-${GITHUB_JOB}"
> "$CACHE_RC"
echo "BAZEL_CACHE_RC=$CACHE_RC" >> "$GITHUB_ENV"

if [ "${{ steps.auth.outcome }}" != "success" ]; then
echo "Auth skipped (expected for fork PRs). Building without remote cache."
exit 0
fi

# Checkout directory config
echo "build --remote_cache=https://storage.googleapis.com/${{ inputs.cache_bucket }}" >> .bazelrc.local
echo "build \"--remote_header=Authorization=Bearer ${{ steps.auth.outputs.access_token }}\"" >> .bazelrc.local
# Only upload cache results on push (trusted) events, not pull requests
if [ "${{ github.event_name }}" = "push" ] || [ "${{ github.event_name }}" = "workflow_dispatch" ] || [ "${{ github.event_name }}" = "release" ]; then
echo "build --remote_upload_local_results=true" >> .bazelrc.local
else
echo "build --remote_upload_local_results=false" >> .bazelrc.local
fi

# Point ~/.bazelrc to the job-specific file via try-import.
# Single atomic write — no truncation window for concurrent jobs.
echo "try-import $CACHE_RC" > ~/.bazelrc

# Cache config for bootstrapped projects (discovered via try-import above)
echo "build --remote_cache=https://storage.googleapis.com/${{ inputs.cache_bucket }}" >> "$CACHE_RC"
echo "build \"--remote_header=Authorization=Bearer ${{ steps.auth.outputs.access_token }}\"" >> "$CACHE_RC"
echo "build --experimental_circuit_breaker_strategy=failure" >> "$CACHE_RC"
if [ "${{ github.event_name }}" = "push" ] || [ "${{ github.event_name }}" = "workflow_dispatch" ] || [ "${{ github.event_name }}" = "release" ]; then
echo "build --remote_upload_local_results=true" >> "$CACHE_RC"
else
echo "build --remote_upload_local_results=false" >> "$CACHE_RC"
fi

Copy link
Copy Markdown

@semgrep-code-snapchat semgrep-code-snapchat Bot May 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using variable interpolation ${{...}} with github context data in a run: step could allow an attacker to inject their own code into the runner. This would allow them to steal secrets and code. github context data can have arbitrary user input and should be treated as untrusted. Instead, use an intermediate environment variable with env: to store the data and use the environment variable in the run: script. Be sure to use double-quotes the environment variable, like this: "$ENVVAR".

🚀 Fixed in commit 5049f9b 🚀

@github-actions
Copy link
Copy Markdown

⚠️ Bazel & CI Test Results

Test Suite Result
Linux: C++ Tests ✅ success
Linux: Build & Export ✅ success
Snapshot Tests ✅ success
Valdi Smoke Tests ✅ success
Comment Test Results / Post Results Comment ❌ null

Some tests failed. Please check the workflow logs for details.

🚀 Bazel remote cache is now enabled - future builds will be faster!

Workflow: Valdi CI

beaucollins and others added 2 commits May 29, 2026 08:04
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

⚠️ Bazel & CI Test Results

Test Suite Result
Linux: Build & Export ✅ success
Linux: C++ Tests ✅ success
Snapshot Tests ✅ success
Valdi Smoke Tests ✅ success
Comment Test Results / Post Results Comment ❌ null

Some tests failed. Please check the workflow logs for details.

🚀 Bazel remote cache is now enabled - future builds will be faster!

Workflow: Valdi CI

@github-actions
Copy link
Copy Markdown

⚠️ Bazel & CI Test Results

Test Suite Result
Linux: Build & Export ✅ success
Snapshot Tests ✅ success
Valdi Smoke Tests ✅ success
Linux: C++ Tests ✅ success
Comment Test Results / Post Results Comment ❌ null

Some tests failed. Please check the workflow logs for details.

🚀 Bazel remote cache is now enabled - future builds will be faster!

Workflow: Valdi CI

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/build-system Bazel build rules and config area/compiler Valdi compiler size/M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant