Skip to content

About

Use a standard Bazel remote cache server (REAPI v2) as the Gradle build cache backend

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

gradle-bazel-cache

CI License: MIT

Use a standard Bazel remote cache server as the backend for Gradle's build cache, so one cache serves both your Bazel and your Gradle builds.

Why this exists

Gradle's built-in HttpBuildCache cannot talk to a Bazel remote cache, even though both are content-addressed HTTP blob stores. Gradle PUTs to <url>/<key> where the key is a 32-character hash; bazel-remote routes on ^/?(.*/)?(ac/|cas/)([a-f0-9]{64})$ — 64 lowercase hex, SHA-256 only. The request is rejected before it reaches storage.

There is a deeper mismatch behind the key width. Bazel's cache is not a key-value store: the Action Cache holds ActionResult protos that point at blobs in the Content Addressable Store, and a CAS key must be the SHA-256 of the blob's own content. At load time Gradle hands you a cache key but not the content, so the CAS address cannot be recomputed. Bridging the two requires an AC indirection.

This plugin implements that bridge against the unmodified REAPI protocol — no server flags, no proprietary extensions — over Bazel's HTTP cache protocol or over gRPC.

Prior art, and the gap

The approach was presented in "Making a faster Gradle build cache with Bazel's Remote APIs" (Zach Gray, BazelCon). In that talk Bitrise describes building exactly this, then says they "considered open sourcing this project but … held off", and instead built a proprietary gRPC protocol for their own servers. Their plugin is a closed-source jar that cannot talk to bazel-remote. EngFlow's equivalent is likewise closed and vendor-locked.

No open-source Gradle build-cache backend speaks REAPI. This project is that missing piece.

For a working reference in another ecosystem, see Mill's BazelRemoteCache.scala.

Try it in two minutes

cd examples/quickstart
podman compose up -d                              # or docker compose up -d
../../gradlew :app:compileJava --build-cache      # cold: stores
rm -rf app/build .gradle
../../gradlew :app:compileJava --build-cache      # warm: FROM-CACHE

See examples/quickstart.

Usage

// settings.gradle.kts — pluginManagement must be the first block
pluginManagement { repositories { gradlePluginPortal() } }

plugins { id("io.github.pplr.bazel-cache") version "1.0.0" }

buildCache {
    remote(BazelRemoteBuildCache::class) {
        endpoint = "https://cache.internal:8080"
        isPush = System.getenv("CI") != null   // Gradle defaults remote push to false
    }
}

endpoint is spelled as Bazel's --remote_cache, and the scheme picks the transport: http:// / https:// for the HTTP cache protocol, grpc:// / grpcs:// for the Remote Execution API over gRPC (plaintext / TLS). As in Bazel, an endpoint with no scheme is gRPC over TLS.

endpoint = "grpcs://cache.internal:1985"
instanceName = "team-a"                    // optional

instanceName has the same meaning as Bazel's --remote_instance_name: sent over gRPC and — like Bazel — no effect over HTTP. For an HTTP path prefix, put it in the endpoint, as you would in Bazel's --remote_cache: endpoint = "https://cache.example.com/team-a/".

Credentials are referenced by environment variable name, never by value, so no secret is written into Gradle's configuration cache entry on disk:

tokenEnvironmentVariable = "BAZEL_CACHE_TOKEN"   // default

The token is sent as Authorization: Bearer … — an HTTP header, or gRPC metadata.

Server support

Server HTTP gRPC
bazel-remote ✅ verified against v2.6.2 ✅ verified against v2.6.2
nginx + WebDAV, S3 / GCS / MinIO, Artifactory expected, untested —
Buildbarn, BuildBuddy, NativeLink, EngFlow — (gRPC-only) expected, untested

Verified means the integration suite runs against a real server with AC validation enabled — its default. No server flags are required. Details in docs/SERVER-MATRIX.md.

Roadmap

  • 1.0 — HTTP /ac/ /cas/, resilience layer, quickstart, Plugin Portal + Maven Central
  • 1.1 — gRPC REAPI (grpc-okhttp), FindMissingBlobs
  • Next — Buildbarn / BuildBuddy interop in CI, custom CA and client certificates

Building

./gradlew build

Requires a JDK 17 or newer. No container needed: the tests that need a real cache server are tagged out of build. See CONTRIBUTING.md for the other test layers.

Compatibility

Gradle 8.0 and newer — each version in the matrix is exercised in CI
Java 17 and newer
Configuration cache supported

Availability

Published to the Gradle Plugin Portal, which plugins { } resolves from by default — no extra repository configuration. Maven Central is an optional mirror; see docs/RELEASING.md.

Documentation

Licence

MIT — see LICENSE. Vendored .proto files and the bundled (relocated) gRPC, Guava, gson, okio and perfmark libraries are Apache-2.0, protobuf is BSD-3-Clause; see NOTICE.

About

Use a standard Bazel remote cache server (REAPI v2) as the Gradle build cache backend

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages