Skip to content

Hoisted pnpm store mixes jest 29.x and 30.x — name-resolved config can bind the wrong major #97

Description

@toruiwasa

Found in review of PR #94 (verdict: PLAUSIBLE — no live defect, forward-looking).

Field Contents
Goal A jest config value that resolves a package by name cannot silently bind to the other major, in either app.
Context Review of PR #94 (feat/mobile-scaffold), which introduced the mix: apps/mobile needs jest 29 because jest-expo (Expo SDK 57) requires it, while apps/api is on jest 30. Both pins are legitimate. The consequence is that pnpm's hoisted fallback store (node_modules/.pnpm/node_modules) now holds jest@30.4.2 beside jest-circus, jest-config, jest-runtime, jest-snapshot, expect and pretty-format at 29.7.0. PR #94 already hit this once: 28 apps/api suites failed until jest-environment-node@^30.4.1 was declared explicitly. That pin closes the one observed name, not the class. See plans/DEBUG_mobile_scaffold_jest_metro_resolution.md, which records the rule ("every consumer declares the pieces it resolves by name") but no mechanism that enforces it.
Scope Decide how to enforce the rule. Open decision: (a) declare the remaining by-name resolvable packages explicitly in apps/api devDependencies, (b) set a pnpm hoistPattern excluding jest* from the hoisted store — the DEBUG doc considered and deferred this ("reach for it if a second package hits the same class of collision"), or (c) leave as-is and rely on CI running both apps' suites, which is only true once #11 lands. Verify with pnpm why jest / ls node_modules/.pnpm/node_modules before choosing.
Test boundary Both apps' existing suites are the regression signal; no new tests.
Done when Adding a name-resolved config value (a reporter, jest-environment-jsdom, an explicit testRunner) to apps/api resolves to a 30.x package, demonstrably, and a future dependency change cannot re-flip the hoist winner unnoticed.
Branch infra/jest-major-isolation
Dependency Best done after #11 (CI runs both apps' suites), which is what would catch a re-flip.
Risk MEDIUM — currently latent (testEnvironment resolves 30.4.1 and testRunner 30.4.2 via jest-config's own deps, verified). The failure mode is a dependency change silently breaking the untouched app's entire suite, as already happened once.

The natural exit is jest-expo supporting Jest 30, at which point both apps go to 30 and the mix disappears. Close this if that lands first.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    infraCI/CD, Supabase config, env varstaskSDLC task unit — one issue per task-breakdown item

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions