Hive Hive
Sign in

feat(cli,server): Module Cache breakdown for local Xcode builds

GitHub issue · Closed

Metadata
Source
tuist/tuist #11087
Updated
Jun 24, 2026
Domains
CLI
Details

What

Local Xcode builds reported via tuist inspect build now show the Module Cache tab on their build run page, the same breakdown previously exclusive to tuist test / tuist xcodebuild build.

Rather than re-uploading the dependency graph on every build, a build is linked to the graph the last tuist generate already uploaded, via a new generation_id.

Why

The Module Cache tab is backed by xcode_targets rows, which are created only when a command event arrives carrying an xcode_graph (analytics_controllerXcode.create_xcode_graph). The build run page finds them through a command event whose build_run_id == build.id.

tuist inspect build emits no command event (shouldTrackAnalytics = false in TuistCommand.swift), so the graph never reaches the server for a local build and the tab stays hidden.

tuist generate already uploads the full graph + binary-cache hit breakdown as its own command event. The missing piece was a precise link from a local build back to that generation.

How

A CLI-minted generation_id (UUID) ties them together:

  1. tuist generate mints it, records it on the run so the generate command event (which already carries the graph) is stamped with it, and persists it per-project in the Tuist cache (GenerationMetadataStore, keyed by the generated workspace path, pruned after 30 days).
  2. UploadBuildRunService reads it back (by project path) and sends it on the createBuild upload, landing on build_runs.generation_id. Both tuist inspect build and tuist xcodebuild build benefit; a missing entry degrades gracefully.
  3. The build page resolves the generate command event via CommandEvents.get_command_event_by_generation_id/2 and reuses the existing has_binary_cache_data? / binary_cache_analytics / binary_cache_counts unchanged.

Why a CLI-minted id (not the server’s command-event id)

tuist generate uploads its command event through the background analytics-upload subprocess, so the main process never learns the server-assigned id. A CLI UUID sidesteps that and makes the link precise across developers, machines, and branches (a temporal “most recent generation” heuristic would mismatch on shared projects).

The new generation_id columns are nullable UUID on command_events (with an idx_generation_id bloom filter) and build_runs, mirroring the existing build_run_id plumbing exactly. The build’s own command_event is kept separate from the binary_cache_command_event so the page’s metadata row still shows the real build command, not “tuist generate”.

Impact

Customers who wire tuist inspect build into their Xcode builds get the Module Cache breakdown for plain Xcode builds, not just tuist test. No server schema change to xcode_targets; no extra command event per build (the graph is uploaded once per generation, not per build).

Accepted limitation

The breakdown reflects the project state at the last tuist generate, not manual Xcode edits made afterward.

Validation

  • Server (mix test): command_events + build_run_live (14/0, including an end-to-end test of build → generation_id → generate command event → Module Cache tab), plus builds + builds_controller (86/0). Migrations apply via the test alias. mix format + Credo clean (no new issues).
  • CLI: full workspace build-for-testing compiles with 0 errors (including the new GenerationMetadataStoreTests and the GenerateService / UploadBuildRunService / CommandEventFactory test changes); swiftformat + swiftlint clean (no new violations). Test execution is blocked only by the sandbox’s lack of a PTY, so the suites run in CI.

🤖 Generated with Claude Code

Comments
T
tuist[bot] Jun 4, 2026

🛠️ Tuist Run Report 🛠️

Tests 🧪
Scheme Status Cache hit rate Tests Skipped Ran Commit
TuistAcceptanceTests 0 % 0 0 0 2a266f338
TuistUnitTests 0 % 7132 5 7127 cf38580e0
Flaky Tests ⚠️
  • TuistUnitTests: 3 flaky tests (View all)
Test case Module Suite
parseTestStatuses_returnsPassingModuleNames() TuistXCResultServiceTests XCResultServiceTests
parseTestStatuses_extractsModuleAndSuiteNames() TuistXCResultServiceTests XCResultServiceTests
parseTestXCResult() TuistXCResultServiceTests XCResultServiceTests
Builds 🔨
Scheme Status Duration Commit
TuistAcceptanceTests 4m 15s 2a266f338
TuistUnitTests 5m 34s cf38580e0
TA
tuist-atlas[bot] Jun 6, 2026

The Module Cache breakdown for local Xcode builds is now available in Tuist 4.196.0. Update to enable this functionality on your build run pages.

TA
tuist-atlas[bot] Jun 6, 2026

This feature is now available in xcresult-processor-image@0.12.0. Update to this version to use it.

TA
tuist-atlas[bot] Jun 6, 2026

The Module Cache breakdown for local Xcode builds is now available in server@1.207.0. Update to get this feature.