feat(misc): multi-version support compliance for detox, expo, react-native, and remix#35885
Conversation
✅ Deploy Preview for nx-docs ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
✅ Deploy Preview for nx-dev ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
View your CI Pipeline Execution ↗ for commit 1ff37bd
☁️ Nx Cloud last updated this comment at |
|
Warning Review the following alerts detected in dependencies. According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.
|
1a7caf4 to
43c37bb
Compare
fb78eb1 to
d116009
Compare
130c1cf to
d2f0b7d
Compare
7978edb to
9e45fc5
Compare
There was a problem hiding this comment.
Important
At least one additional CI pipeline execution has run since the conclusion below was written and it may no longer be applicable.
Nx Cloud has identified a possible root cause for your failed CI:
We investigated the e2e-gradle:e2e-ci--src/gradle-plugin-v1.test.ts failure and determined it is unrelated to the changes in this PR. The failure is caused by a Gradle daemon lock contention error ("Timeout waiting to lock build logic queue") triggered by stale CI infrastructure state — no Gradle plugin code was modified here. We recommend re-running the task to allow the Gradle daemon state to clear.
No code changes were suggested for this issue.
Trigger a rerun:
🎓 Learn more about Self-Healing CI on nx.dev
assertGeneratorsEnforceVersionFloor now resolves a generator's factory from either `factory` or `implementation` in generators.json, so plugins that use `implementation` (e.g. @nx/remix) can adopt the shared floor spec.
- Add assertSupportedDetoxVersion (floor 20.0.0; v19 is unmaintained upstream) to the init, application, and convert-to-inferred generators. - Preserve user-pinned versions: keepExistingVersions now defaults to true. - Split migration 22.0.0 so the cross-major @config-plugins/detox bump is gated on `expo >=53 <54`, while the detox/jest-dom bumps stay ungated for bare React Native + Detox workspaces. - Add the parameterized all-generators-enforce-floor spec. NXC-4385
- Add the SDK 55 install lane (RN 0.83.6, React 19.2) and make it the default; add isExpoV55 detection. The v53 and v54 lanes are retained. - Declare `expo` as a peer dependency; add assertSupportedExpoVersion (floor SDK 53) to every generator; keepExistingVersions defaults to true. - Route SDK 55 jest setup through the v54 winter-runtime path. - Gate SDK-specific migrations with `requires` and tighten 22.2.0 to a bilateral expo range. - Add the floor spec; update the supported-versions docs. NXC-4389
- Replace the single 0.79.3 literal with a per-minor version map (0.83/0.84/0.85, default 0.85) routed through versions(tree). - Declare `react-native` as a peer dependency; add assertSupportedReactNativeVersion (floor 0.83.0) to every generator; keepExistingVersions defaults to true. - Gate the remove-deprecated-deps migration on `react-native >=0.76 <0.79`. - Add the floor spec; update the supported-versions docs. NXC-4400
- @nx/remix stays Remix v2 (React Router v7 lives in @nx/react); document the split. Add assertSupportedRemixVersion (floor 2.0.0) to every generator. - Stop generators from overwriting installed react/vite/@remix-run versions via keepExistingVersions, fixing conflicting pins with @nx/react. - Add the parameterized all-generators-enforce-floor spec. NXC-4402
The react-native compliance change added `semver` (catalog:) to the plugin's dependencies; record its resolved entry in the lockfile so frozen installs stay in sync.
… them in the lockfile Marks the `expo` and `react-native` peerDependencies optional (their inferred plugins are gated on app-config presence) and records the resolved peers in the lockfile so `pnpm install --frozen-lockfile` (CI) stays in sync.
The plugins detect support by major version (expo) / minor version (react-native), so they work with any patch within each supported version, not just the .0.x line. Caret reflects that; for the 0.x react-native versions caret and tilde are equivalent.
Moves each per-plugin assertSupported*Version wrapper into the plugin's versions.ts (next to the minSupported*Version floor it already uses) and removes the standalone assert-supported-*-version.ts files. No behavior change; the all-generators-enforce-floor specs still exercise every generator's assert.
Defers RN 0.85 to a follow-up: 0.85 relocated its Jest preset to the new @react-native/jest-preset package, which needs a separate generator change to @nx/react-native's jest config. 0.83 and 0.84 still ship the old self-contained jest, so they work with the current generator. Default install is now 0.84 (Active line); a 0.85 workspace falls through to latest constants.
…s pass The expo and react-native peers are optional (peerDependenciesMeta), so they need no lockfile entries. Earlier full re-resolves churned ~2000 lines and engaged @vitejs/plugin-react's optional babel-plugin-react-compiler peer, which made @nx/react fail @nx/dependency-checks (green on master). The lockfile is now master plus the one real addition — react-native's semver dependency.
Gated requires expo >=54.0.0 <55.0.0 to continue the existing SDK ladder. Versions mirror the expoV55* install constants.
…0.84 Gated requires react-native >=0.83.0 <0.84.0 (within the supported window). Versions mirror the 0.84 install constants.
…edExpoMajorVersion Collapse the three duplicated isExpoV5x detection blocks into one getInstalledExpoMajor helper (graph-first detection unchanged), route via a per-major lookup table so the project graph is traversed once, and remove the unused getInstalledExpoMajorVersion. Also reword two stale "For Expo v54" jest comments. Behavior unchanged.
Remove the as-CompatMinors cast and widen versionMap to Partial<Record<number, ReactNativeVersions>> so indexing by minor() is type-safe without the cast. Behavior unchanged.
… detox peer optional Pass keepExistingVersions to addDependenciesToPackageJson in the application and add-linting generators so re-runs no longer overwrite a user's pinned versions. Mark the detox peer as optional, matching the gated executor/inferred-plugin surfaces (consistent with the expo/react-native peers).
…unused version helpers Pass keepExistingVersions to addDependenciesToPackageJson in the ensure-dependencies and add-linting helpers so the application/library generators stop overwriting a user's pinned Expo ecosystem versions. Remove the unused isExpoV54/isExpoV55 helpers (no src callers; the only question the code asks is isExpoV53) and their specs.
…or and simplify versions() Pass keepExistingVersions to addDependenciesToPackageJson in add-linting so it no longer overwrites a user's pins. Drop the dead tree-less branch from versions()/getInstalledReactNativeVersion (every caller passes a tree) and inline the one-line helper.
The generator floor asserts detox >=20.0.0, but the peer advertised ^20.9.0, leaving a [20.0.0, 20.9.0) gap that passes the assert but fails the peer. Widen to ^20.0.0 so the two agree.
…rsion floor The generator floor asserts @remix-run/dev >=2.0.0, but the peer advertised ^2.17.3. Widen to ^2.0.0 so the advertised peer agrees with the asserted floor.
@remix-run/dev is consumed only through opt-in surfaces — the build/serve executors (require.resolve at runtime) and the createNodesV2 inferred plugin gated on a remix.config file. The eager imports are type-only. Declare it optional via peerDependenciesMeta, matching the detox/expo/react-native primaries in this PR.
…indow The peer was open-ended (>=0.83.0), advertising 0.85+ which the plugin explicitly defers (0.85 relocated its Jest preset to @react-native/jest-preset). Cap to >=0.83.0 <0.85.0 so the advertised window matches the install lanes. This also pulls the repo's own react-native dev resolution from 0.85.3 down to the supported 0.84.1. versions() still silently falls through to the latest lane above the window (no throw).
9e45fc5 to
1ff37bd
Compare
Current Behavior
The React Native ecosystem plugins (
@nx/detox,@nx/expo,@nx/react-native) and@nx/remixwere not compliant with the multi-version support initiative (nx migrate --first-party-only). None of them enforced a supported-version floor on their generators or preserved user-pinned versions, and:@nx/detoxpinned a singledetoxversion with no floor; the22.0.0migration bundled a cross-major@config-plugins/detoxbump together with same-major bumps, ungated.@nx/expohad SDK 53/54 lanes but not the current SDK 55; several SDK-specific migrations ran unconditionally;expowas not declared as a peer.@nx/react-nativewas hardcoded to a single, upstream-Unsupported RN0.79.3— no version map, no floor,react-nativeundeclared as a peer.@nx/remixgenerators overwrote installedreact/vite/@remix-run/*versions and had no floor enforcement.Expected Behavior
Each plugin now follows the canonical multi-version compliance shape (
assertSupported<Pkg>Versionon every generator entry point, user-pin preservation viakeepExistingVersions, source-major-gated migrations, and a parameterized floor spec):@nx/detox— v20-only floor (detoxis v20-only upstream; v19 has been unmaintained since 2022). The22.0.0migration is split so the cross-major@config-plugins/detoxbump is gated onexpo >=53 <54, while thedetox/jest-dombumps stay ungated for bare React Native + Detox workspaces.@nx/expo— adds the SDK 55 lane (RN0.83.6, React19.2) as the new default withisExpoV55detection (53/54 lanes retained); declaresexpoas a peer; floor at SDK 53; SDK-specific migrations gated withrequires.@nx/react-native— per-minor version map for the Active line (0.83/0.84/0.85, default0.85) routed throughversions(tree); declaresreact-nativeas a peer; floor at0.83.0; theremove-deprecated-depsmigration gated onreact-native >=0.76 <0.79.@nx/remix— stays Remix v2 (React Router v7 remains in@nx/react) and documents the split; floor at@remix-run/dev >=2.0.0; generators preserve installedreact/vite/@remix-run/*versions instead of overwriting them.A shared test utility in
@nx/devkit/internal-testing-utils(assertGeneratorsEnforceVersionFloor) was extended to resolve generators declared viaimplementationas well asfactory, so@nx/remixcan use the shared floor spec.Supported-version docs for
@nx/expo,@nx/react-native, and@nx/remixare updated.Related Issue(s)
Tracked in Linear (not GitHub Issues): NXC-4385, NXC-4389, NXC-4400, NXC-4402.