🛠️ Tuist Run Report 🛠️
Tests 🧪
| Scheme | Status | Cache hit rate | Tests | Skipped | Ran | Commit |
|---|---|---|---|---|---|---|
| TuistUnitTests | ✅ | 99 % | 28 | 39 | -11 | fb87b13e3 |
Builds 🔨
| Scheme | Status | Duration | Commit |
|---|---|---|---|
| TuistUnitTests | ✅ | 22.4s | fb87b13e3 |
Hive
GitHub issue · Closed
The tuist bazel credential-helper now refreshes a user’s access token proactively when it is within a 60s safety margin of expiring, and reports expires to Bazel brought forward by that same margin (exp − 60s). Project tokens (no expiry) and account tokens (cannot be refreshed) are reported unchanged.
Bazel remote-cache builds against Kura burst with UNAUTHENTICATED a few minutes into a build — on whichever operation dominates at that instant — and then recover. In two captured gRPC logs:
bazel-grpc-4: 104× UNAUTHENTICATED on Write in a 2.0s burst at +348sbazel-grpc-6: 1089× UNAUTHENTICATED on Read in a 0.6s burst at +414sBoth bursts are tight and land on the access token’s 10-minute (600s) TTL boundary (the token was already partially aged at build start).
Bazel’s CredentialCacheExpiry caches the credential-helper response until exactly the expires we report and only re-invokes the helper lazily, on the first request issued after that timestamp — it never refreshes early (the --credential_helper_cache_duration flag is only the no-expires fallback). The helper reported the access token’s exact exp, leaving zero margin, so Bazel kept attaching the token to requests right up to the boundary. The in-flight batch of remote-cache RPCs around the boundary then reached Kura after exp and was rejected.
Kura validates the Tuist JWT statelessly (signature + exp, locally, via kura.jwt_verify), so issuing a new access token via refresh never revokes a previously issued one — the only thing that produces UNAUTHENTICATED is exp passing. This rules out the alternative theory (parallel credential-helper calls minting tokens that invalidate each other): stateless JWTs are not revoked on refresh.
The boundary failure is fundamentally that Bazel reuses a cached credential up to the instant it expires. Reporting an earlier expires makes Bazel reload the helper ~60s before the real expiry; pairing that with a proactive refresh at the same threshold means the helper hands back a token with a full lifetime ahead of it. The result: no in-flight request can ever carry a token within 60s of being rejected, which comfortably covers request latency and clock skew between a developer machine and the cache. The 60s margin is well under the 600s TTL, so it costs roughly one extra refresh per ~9 minutes of continuous building.
The refresh is best-effort: if it fails (e.g. a transient network error) the helper falls back to the token it already has, which is still valid for up to the safety margin, rather than failing the request outright.
Developers running long Bazel builds against the Tuist/Kura remote cache no longer hit a mid-build wave of UNAUTHENTICATED errors (and the costly stall/retry that followed) when their short-lived access token crosses its expiry.
expires exactly 60s before the JWT exp.UNAUTHENTICATED.🤖 Generated with Claude Code
| Scheme | Status | Cache hit rate | Tests | Skipped | Ran | Commit |
|---|---|---|---|---|---|---|
| TuistUnitTests | ✅ | 99 % | 28 | 39 | -11 | fb87b13e3 |
| Scheme | Status | Duration | Commit |
|---|---|---|---|
| TuistUnitTests | ✅ | 22.4s | fb87b13e3 |
The fix for refreshing the Bazel credential-helper token before the expiry boundary is now available in 4.201.0-canary.9. The helper now proactively refreshes access tokens when within a 60 second safety margin of expiring, preventing mid-build UNAUTHENTICATED errors during long Bazel builds against remote caches. Update to 4.201.0-canary.9 to get this fix.
The fix for refreshing the Bazel credential-helper token before expiry is now available in 4.201.0-canary.12. The credential helper now proactively refreshes access tokens when within a 60-second safety margin of expiration, preventing mid-build waves of UNAUTHENTICATED errors during long Bazel builds. Update to this version to get the fix.
The fix for refreshing Bazel credential-helper tokens before the expiry boundary is now available in 4.201.0-canary.11. The token is now proactively refreshed when within a 60s safety margin of expiring, preventing mid-build UNAUTHENTICATED errors during long Bazel builds against the Tuist remote cache.
Update to 4.201.0-canary.11 to use this fix.
This is now available in 4.201.0-canary.10. Update to pick up the fix that refreshes the Bazel credential-helper token before the expiry boundary.