Skip to content

test(cli): stop checkForUpdates from crashing test workers#1111

Merged
runeb merged 1 commit into
mainfrom
fix/stabilize-checkforupdates-test
May 20, 2026
Merged

test(cli): stop checkForUpdates from crashing test workers#1111
runeb merged 1 commit into
mainfrom
fix/stabilize-checkforupdates-test

Conversation

@gu-stav
Copy link
Copy Markdown
Member

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

Why

checkForUpdates.test.ts flips process.stdout.isTTY = true in beforeEach to simulate an interactive terminal. The first time anything in that worker touches @oclif/core after that, @oclif/core/lib/screen.js runs its module-init code, sees isTTY = true, and calls process.stdout.getWindowSize(). Vitest's stdout proxy doesn't implement getWindowSize, so the whole worker crashes with:

TypeError: stream.getWindowSize is not a function
  ❯ termwidth @oclif/core/lib/screen.js:9:26
  ❯ Object.<anonymous> @oclif/core/lib/screen.js:19:35

It's order-dependent — only the shard where checkForUpdates.test.ts happens to be the first file to drag in @oclif/core flakes, which is why different individual tests fail across shards (see the failing jobs on #1110: shard 4/6 on ubuntu, shard 3/4 on Windows).

What

Install a getWindowSize shim once per worker in test/setup.ts. Now screen.js can load safely whether isTTY is true or false at the time.

Minimal, test-only, no production code touched.


Note

Medium Risk
Touches core dev/build orchestration, Vite config generation, and adds a new on-disk dev-server registry/lock mechanism; regressions could affect local development startup/port handling across platforms (notably Windows).

Overview
Adds an experimental federation.enabled CLI config option and wires it through dev and build flows.

When federation is enabled, sanity dev now tries to start a shared workbench server (singleton lock + registry under ~/.sanity{-staging}/dev-servers/), bumps the app/studio port, enables cross-server React refresh via reactRefreshHost, and registers running dev servers plus extracted manifests for workbench discovery.

Builds gain a federation mode that skips runtime/static asset steps, applies user Vite config to federation builds, and injects the @sanity/federation/vite plugin; auto-updates import-map generation is disabled for federation builds. Also adds uncached CLI config loading for long-lived processes, centralizes config/data dir resolution, and updates CI snapshot release tagging plus new federated-studio fixture/test coverage.

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

`@oclif/core/lib/screen.js` reads `process.stdout.getWindowSize()` once,
at module init, but only if `process.stdout.isTTY` is truthy. Vitest's
stdout proxy doesn't implement `getWindowSize`, so when a test sets
`isTTY = true` before oclif is loaded in that worker (the situation in
`checkForUpdates.test.ts`), screen.js crashes the whole worker with
`TypeError: stream.getWindowSize is not a function`.

It's order-dependent: only the shard where checkForUpdates is the first
oclif-touching file flakes, which is why we see different individual
tests fail across shards in CI.

Install a `getWindowSize` shim once per worker so screen.js can load
safely no matter when isTTY gets flipped.
@gu-stav gu-stav requested a review from a team as a code owner May 20, 2026 09:15
@claude
Copy link
Copy Markdown

claude Bot commented May 20, 2026

Claude finished @gu-stav's task in 1m 8s —— View job


Review

No blocking issues. The change is small, test-only, and the rationale checks out.

Verified:

  • checkForUpdates.test.ts:87 does flip process.stdout.isTTY = true in beforeEach, matching the described failure mode.
  • The shim signature () => [80, 24] matches Node's tty.WriteStream.getWindowSize() return shape ([columns, rows]), so anything downstream of @oclif/core/lib/screen.js will get sensible values.
  • Guard if (typeof stream.getWindowSize !== 'function') avoids clobbering a real implementation in workers that happen to have a TTY.
  • configurable: true, writable: true means tests that want to override window size later can still do so.

Changeset: not required — this is a test-only fix with no runtime/public-API impact. Per the repo's changeset policy, that's the correct call (no .changeset/*.md added).

Minor (optional, non-blocking) observations:

  • The shim runs only once per worker. If a test later replaces process.stdout or process.stderr wholesale (rather than mutating properties), the shim is gone — but no existing test does this, so it's not worth defending against now.
  • The comment block is justified because the why (oclif's module-init getWindowSize read + Vitest stdout proxy) is genuinely non-obvious; keep it.

Nothing to fix.
Branch: fix/stabilize-checkforupdates-test

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 20, 2026

📦 Bundle Stats — @sanity/cli

Compared against feat/workbench (fcf69a8c)

@sanity/cli

Metric Value vs feat/workbench (fcf69a8)
Internal (raw) 2.1 KB -8 B, -0.4%
Internal (gzip) 799 B -2 B, -0.2%
Bundled (raw) 10.97 MB -8 B, -0.0%
Bundled (gzip) 2.06 MB -8 B, -0.0%
Import time 861ms +22ms, +2.6%

bin:sanity

Metric Value vs feat/workbench (fcf69a8)
Internal (raw) 1023 B -
Internal (gzip) 486 B -
Bundled (raw) 9.84 MB -
Bundled (gzip) 1.77 MB -
Import time 2.32s +26ms, +1.2%

🗺️ 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 feat/workbench (fcf69a8c)

Metric Value vs feat/workbench (fcf69a8)
Internal (raw) 98.7 KB -
Internal (gzip) 23.2 KB -
Bundled (raw) 21.64 MB -
Bundled (gzip) 3.43 MB -
Import time 801ms +11ms, +1.5%

🗺️ 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 feat/workbench (fcf69a8c)

Metric Value vs feat/workbench (fcf69a8)
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

github-actions Bot commented May 20, 2026

Coverage Delta

File Statements
packages/@sanity/cli-core/src/config/cli/getCliConfig.ts 100.0% (±0%)
packages/@sanity/cli-core/src/config/cli/schemas.ts 100.0% (±0%)
packages/@sanity/cli-core/src/services/cliUserConfig.ts 100.0% (±0%)
packages/@sanity/cli-core/src/util/getSanityConfigDir.ts 66.7% (new)
packages/@sanity/cli/src/actions/build/buildApp.ts 95.3% (±0%)
packages/@sanity/cli/src/actions/build/buildStaticFiles.ts 97.6% (+ 1.0%)
packages/@sanity/cli/src/actions/build/buildStudio.ts 96.7% (±0%)
packages/@sanity/cli/src/actions/build/getViteConfig.ts 100.0% (±0%)
packages/@sanity/cli/src/actions/build/writeSanityRuntime.ts 96.2% (+ 0.7%)
packages/@sanity/cli/src/actions/deploy/deployApp.ts 80.5% (±0%)
packages/@sanity/cli/src/actions/dev/devAction.ts 96.8% (- 3.2%)
packages/@sanity/cli/src/actions/dev/devServerRegistry.ts 93.8% (new)
packages/@sanity/cli/src/actions/dev/extractDevServerManifest.ts 20.0% (new)
packages/@sanity/cli/src/actions/dev/getDevServerConfig.ts 100.0% (±0%)
packages/@sanity/cli/src/actions/dev/startAppDevServer.ts 100.0% (+ 13.0%)
packages/@sanity/cli/src/actions/dev/startDevManifestWatcher.ts 90.9% (new)
packages/@sanity/cli/src/actions/dev/startFederationRegistration.ts 100.0% (new)
packages/@sanity/cli/src/actions/dev/startStudioDevServer.ts 100.0% (+ 5.0%)
packages/@sanity/cli/src/actions/dev/startWorkbenchDevServer.ts 98.7% (new)
packages/@sanity/cli/src/actions/dev/writeWorkbenchRuntime.ts 100.0% (new)
packages/@sanity/cli/src/actions/init/bootstrapLocalTemplate.ts 89.7% (±0%)
packages/@sanity/cli/src/actions/init/bootstrapTemplate.ts 0.0% (±0%)
packages/@sanity/cli/src/actions/init/createAppCliConfig.ts 100.0% (±0%)
packages/@sanity/cli/src/actions/init/createCliConfig.ts 100.0% (+ 50.0%)
packages/@sanity/cli/src/actions/init/createStudioConfig.ts 83.3% (±0%)
packages/@sanity/cli/src/actions/init/initAction.ts 97.2% (+ 0.1%)
packages/@sanity/cli/src/actions/init/initApp.ts 96.0% (±0%)
packages/@sanity/cli/src/actions/init/initStudio.ts 87.0% (±0%)
packages/@sanity/cli/src/actions/init/scaffoldTemplate.ts 100.0% (±0%)
packages/@sanity/cli/src/actions/init/types.ts 100.0% (±0%)
packages/@sanity/cli/src/actions/manifest/extractCoreAppManifest.ts 93.1% (new)
packages/@sanity/cli/src/actions/manifest/extractManifest.ts 100.0% (±0%)
packages/@sanity/cli/src/actions/manifest/types.ts 100.0% (±0%)
packages/@sanity/cli/src/actions/manifest/writeManifestFile.ts 100.0% (±0%)
packages/@sanity/cli/src/commands/dev.ts 100.0% (±0%)
packages/@sanity/cli/src/commands/init.ts 100.0% (±0%)
packages/@sanity/cli/src/commands/manifest/extract.ts 100.0% (±0%)
packages/@sanity/cli/src/prompts/init/federation.ts 100.0% (new)
packages/@sanity/cli/src/server/devServer.ts 94.1% (±0%)
packages/@sanity/cli/src/util/resolveReactStrictMode.ts 100.0% (new)

Comparing 40 changed files against main @ 5b4d3c089fce9266552982808bb5f2457fd50cf8

Overall Coverage

Metric Coverage
Statements 84.6% (+ 0.3%)
Branches 74.7% (+ 0.4%)
Functions 84.5% (+ 0.3%)
Lines 85.1% (+ 0.4%)

@gu-stav gu-stav force-pushed the fix/stabilize-checkforupdates-test branch from 5190c2d to 159d36a Compare May 20, 2026 09:35
@gu-stav gu-stav changed the base branch from main to feat/workbench May 20, 2026 09:35
@gu-stav gu-stav force-pushed the fix/stabilize-checkforupdates-test branch from 159d36a to 5190c2d Compare May 20, 2026 09:41
@gu-stav gu-stav changed the base branch from feat/workbench to main May 20, 2026 09:41
Copy link
Copy Markdown
Member

@runeb runeb left a comment

Choose a reason for hiding this comment

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

LGTM, picking this over #1108 which has the same fix

@runeb runeb merged commit a2532c0 into main May 20, 2026
105 of 108 checks passed
@runeb runeb deleted the fix/stabilize-checkforupdates-test branch May 20, 2026 16:21
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