Skip to content

chore(ci): scope turbo cache by RUNNER_OS#1128

Merged
gu-stav merged 1 commit into
mainfrom
chore/scope-turbo-cache-per-os
May 26, 2026
Merged

chore(ci): scope turbo cache by RUNNER_OS#1128
gu-stav merged 1 commit into
mainfrom
chore/scope-turbo-cache-per-os

Conversation

@gu-stav
Copy link
Copy Markdown
Member

@gu-stav gu-stav commented May 22, 2026

Description

Follow-up to #1127. Scopes turbo cache entries by operating system to prevent cross-OS cache sharing.

Context

In #1127 we tracked down a CI flake where two build.app.test.ts / build.studio.test.ts cases crashed on Linux runners with ENOENT while statting symlinks under packages/@sanity/cli-test/fixtures/basic-app/node_modules/. The chain was:

  1. The Windows build copied node_modules into the bundled fixtures dir (because of a path-splitting bug in copy-fixtures.ts).
  2. fs.cp resolved those symlinks to absolute Windows paths.
  3. turbo.json declares fixtures/** as a build output, so the Windows-absolute symlinks got cached.
  4. Linux CI hit the same turbo cache (cache key wasn't OS-scoped — confirmed in the failing logs where the replay showed C:\a\cli\cli\... paths), and the symlinks became dangling on Linux.

#1127 fixes the root cause (the copy-fixtures filter) and adds defensive handling in testFixture. This PR addresses the deeper class of problem: build outputs can legitimately differ by OS (resolved symlinks, line endings, native binaries), so caches shouldn't be shared across operating systems.

Change

Add RUNNER_OS to globalEnv in turbo.json. Since cache keys hash declared env vars, this gives Linux/Windows/macOS runners separate cache entries.

This mirrors the existing NODE_VERSION entry — we already scope by Node version for the same reason.

Locally RUNNER_OS is unset, so the cache key gets the same empty value across machines and local sharing is unchanged.

What to review

  • turbo.json — single-line addition to globalEnv.

Testing

  • No test impact; this only changes how turbo hashes cache keys.
  • After merge, the first CI run on each OS will be a cache miss (expected one-time cost).

Note

Low Risk
Low risk: a single turbo.json config change that only affects Turbo cache key hashing across OSes and doesn’t alter build/test logic.

Overview
Scopes Turbo cache keys by operating system by adding RUNNER_OS to globalEnv in turbo.json, preventing cross-OS cache reuse for build outputs (e.g., cached fixtures/**). This will cause one-time cache misses per OS but avoids replaying incompatible artifacts between Linux/Windows/macOS runners.

Reviewed by Cursor Bugbot for commit 4304a63. Bugbot is set up for automated code reviews on this repo. Configure here.

Add RUNNER_OS to globalEnv so turbo cache entries are scoped per operating
system. Without this, Windows and Linux CI runners share the same cache for
tasks whose outputs are OS-sensitive (e.g. resolved symlink paths inside
@sanity/cli-test:build's fixtures/** output), which has caused
Windows-absolute symlink paths to be replayed on Linux runners and crashed
fixture loading.

Mirrors the existing NODE_VERSION scoping. Locally RUNNER_OS is unset, so
this has no effect on local cache sharing.
@gu-stav gu-stav requested a review from a team as a code owner May 22, 2026 08:26
@claude
Copy link
Copy Markdown

claude Bot commented May 22, 2026

Claude finished @gu-stav's task in 55s —— View job


Review

No issues found.

  • The change correctly adds RUNNER_OS (a GitHub Actions built-in) to turbo.json's globalEnv, mirroring the existing NODE_VERSION pattern.
  • Verified against the matrices in .github/workflows/test.yml (and e2e workflows): runners are ubuntu-latest / windows-8core, so RUNNER_OS will resolve to distinct Linux / Windows values and produce isolated cache entries.
  • Locally RUNNER_OS is unset, so the hash component is a consistent empty value across dev machines — local cache sharing is preserved as described.

Changeset: Not required. This is a CI/build-config change with no runtime impact on any package in packages/.

  • Read turbo.json change
  • Verify RUNNER_OS is the appropriate variable
  • Check changeset requirement
  • Post review
    Branch

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 22, 2026

📦 Bundle Stats — @sanity/cli

Compared against main (cd110e7c)

@sanity/cli

Metric Value vs main (cd110e7)
Internal (raw) 2.1 KB -
Internal (gzip) 799 B -
Bundled (raw) 10.97 MB -98 B, -0.0%
Bundled (gzip) 2.06 MB -24 B, -0.0%
Import time 926ms -1ms, -0.1%

bin:sanity

Metric Value vs main (cd110e7)
Internal (raw) 1023 B -
Internal (gzip) 486 B -
Bundled (raw) 9.84 MB -
Bundled (gzip) 1.77 MB -
Import time 2.21s -13ms, -0.6%

🗺️ View treemap · Artifacts

Details
  • Import time regressions over 10% are flagged with ⚠️
  • Sizes shown as raw / gzip 🗜️. Internal bytes = own code only. Total bytes = with all dependencies. Import time = Node.js cold-start median.

📦 Bundle Stats — @sanity/cli-core

Compared against main (cd110e7c)

Metric Value vs main (cd110e7)
Internal (raw) 96.3 KB -723 B, -0.7%
Internal (gzip) 22.7 KB -44 B, -0.2%
Bundled (raw) 21.61 MB -723 B, -0.0%
Bundled (gzip) 3.42 MB -65 B, -0.0%
Import time 873ms +8ms, +0.9%

🗺️ View treemap · Artifacts

Details
  • Import time regressions over 10% are flagged with ⚠️
  • Sizes shown as raw / gzip 🗜️. Internal bytes = own code only. Total bytes = with all dependencies. Import time = Node.js cold-start median.

📦 Bundle Stats — create-sanity

Compared against main (cd110e7c)

Metric Value vs main (cd110e7)
Internal (raw) 908 B -
Internal (gzip) 483 B -
Bundled (raw) 931 B -
Bundled (gzip) 491 B -
Import time ❌ ChildProcess denied: node -
Details
  • Import time regressions over 10% are flagged with ⚠️
  • Sizes shown as raw / gzip 🗜️. Internal bytes = own code only. Total bytes = with all dependencies. Import time = Node.js cold-start median.

@github-actions
Copy link
Copy Markdown
Contributor

Coverage Delta

No covered files changed in this PR.

Overall Coverage

Metric Coverage
Statements 84.3% (±0%)
Branches 74.3% (±0%)
Functions 84.2% (±0%)
Lines 84.8% (±0%)

Copy link
Copy Markdown
Member

@jonahsnider jonahsnider left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice catch!

@gu-stav gu-stav merged commit dafed5c into main May 26, 2026
50 of 52 checks passed
@gu-stav gu-stav deleted the chore/scope-turbo-cache-per-os branch May 26, 2026 13:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants