Requested on Slack: at the end of a tuist cache warm run, print how many targets were served from the remote cache, so setup/CI logs can report the remote hit rate without a server round-trip.
What changed
tuist cache warm now prints a single machine-readable summary line at the end of the warm step:
Cache warm summary: 42 remote hits, 3 local hits, 12 misses
It’s emitted on both end states of a warm run:
- after a successful build + store (right after “All cacheable targets have been cached successfully as xcframeworks”)
- in the “All cacheable targets are already cached” early return
Why
The CLI already computes these counts during a warm run and posts them to the server (e.g. remote_cache_target_hits), but they were only readable back after the fact (via tuist cache-run show or GET /cache-runs). They were never surfaced during the run, and the existing “Using cache binaries: …” output mixes local and remote hits, so clients couldn’t cleanly tell how many came from the remote cache.
Printing it inline lets setup and CI logs report the cache result locally, without a server round-trip each time. Including misses alongside the hits lets reporting clients compute a hit rate (hits / (hits + misses)) directly from the CLI output.
Why this approach
All three counts are derived from the same RunMetadataStorage.current.binaryCacheItems (grouped by source: .remote / .local / .miss) that flows into CommandEventFactory and gets posted to the server. So the printed numbers are consistent by construction with what tuist cache-run show and GET /cache-runs report — no separate computation that could drift. On a clean CI machine (empty local cache) hits come back from CacheStorage.fetch as .remote, so the numbers are meaningful for the reporting use case.
Scope notes:
- Upload failures are intentionally not aggregated here. They’re already surfaced per-target as
Failed to upload <name> … warnings from CacheRemoteStorage, and an aggregate count would require threading through archive/store for marginal gain. Easy to add later if needed.
- The
--generate-only path is intentionally not covered, since it doesn’t build or store anything.
misses equals the existing Targets to be cached: … count; it’s included as a structured field so the summary is grep-able as one line.
How to test locally
Run tuist cache warm against a project with a remote cache configured and authenticated. At the end of the run you’ll see a line such as:
Cache warm summary: 42 remote hits, 3 local hits, 12 misses
The remote hits value matches remote_cache_target_hits for the same run in tuist cache-run show / GET /cache-runs.
Validation
TUIST_EE=1 tuist generate tuist + xcodebuild build -scheme tuist → BUILD SUCCEEDED (recompiles CacheWarmCommandService.swift).
- SwiftFormat clean; SwiftLint introduces no new warnings.