Hive Hive
Sign in

fix(cli): snapshot machine metrics under the sampler lock when bundling builds (TUIST-10W)

GitHub issue · Closed

Metadata
Source
tuist/tuist #11525
Updated
Jul 5, 2026
Domains
CLI
Details

What & why

Fixes Sentry TUIST-10W: the build processor occasionally crashed with {:error, {:bad_crc, ~c"machine_metrics.jsonl"}} while unzipping a build archive, and the build was never processed.

Root cause

On the runner, machine_metrics.jsonl is written by the always-on tuist.metrics-sampler launchd daemon, which appends a sample every second and atomically rewrites the file every 60 samples. When a build finishes, UploadBuildRunService.bundleBuild copied that live file into the archive with a bare fileSystem.copywithout taking the sampler’s file lock (unlike MachineMetricsReader, which reads under a shared lock). That unlocked copy races the daemon and can capture the file mid-write, producing the bad-CRC entry the server later choked on.

The fix

  • New MachineMetricsReader.snapshotMetricsFile(to:) copies the metrics file while holding the sampler’s shared lock — the same lock convention readSamples already uses — so the snapshot is consistent with respect to the daemon.
  • bundleBuild now uses it instead of the unlocked copy.

Why client-side only

We own the client that produces the archive, so the corruption is best fixed at the source. We deliberately keep the server failing loudly on an invalid archive rather than silently dropping a corrupt entry: a bad CRC means the bytes don’t match what the client claimed, and we’d rather surface that than mask it. Because the trigger is intermittent and the producer is first-party, this resolves naturally as runners pick up the CLI fix.

(An earlier server-side tolerance change was included and then reverted in this PR for exactly this reason — see the revert commit.)

How to test locally

tuist test TuistUnitTests -- -only-testing:TuistMachineMetricsTests/MachineMetricsReaderTests -only-testing:TuistKitTests/UploadBuildRunServiceTests

snapshotMetricsFile_copiesContentsWhenFileExists / snapshotMetricsFile_returnsFalseWhenFileDoesNotExist cover the locked snapshot; UploadBuildRunServiceTests exercises the changed bundleBuild.

Validation

  • Both new tests pass by name; UploadBuildRunServiceTests green.
  • swiftformat clean; no new swiftlint findings (the pre-existing function_body_length warning on uploadBuildRun is untouched).

🤖 Generated with Claude Code

Flights

Investigate, reproduce, or fix this item in an isolated repository. Each Flight preserves its outcome and agent session.

New Flights are paused Configure model inference, GitHub, and a sandbox provider to start another Flight. Existing results remain available below.
No Flights yet

Start a Flight and preserve its objective, outcome, and session here.

Comments