test: add dual-major Rspack compatibility validation#1404
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
🦋 Changeset detectedLatest commit: 9fe506d The changes in this PR will be included in the next version bump. This PR includes changesets to release 6 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
codex review: The smoke suite does not cover the main Re.Pack In
The user-facing built command modules use Re.Pack's compiled static imports instead, for example Please exercise the installed |
|
codex review: Repeated local runs can pass against stale installed Re.Pack code.
I verified pnpm behavior separately: replacing a same-name/same-version local Please delete each fixture's install state before install, force reinstall, or otherwise make the tarball reference content-unique per run. |
|
codex review: The legacy cache warning assertion is testing the wrong layer and accepts the wrong Rspack 1 behavior.
As written, the smoke would not catch a regression where Rspack 1 users start seeing the Rspack 2 cache warning; it currently normalizes that behavior. Please assert this through the command-level path, or split expectations so Rspack 1 verifies no warning while Rspack 2 verifies one warning and no mutation. |
|
Addressed the review points in ebbc2d3; one is rebutted below with repro evidence. 1. "The smoke suite does not cover the main Re.Pack Correct — the dev build went through
Sabotage-verified: rewriting the installed 2. "Repeated local runs can pass against stale installed Re.Pack code." This does not reproduce with the toolchain in use (pnpm 10.x). Two checks:
3. "The legacy cache warning assertion is testing the wrong layer and accepts the wrong Rspack 1 behavior." Agreed — calling the helper directly under both majors normalized "Rspack 1 warns" as passing behavior. Fixed in ebbc2d3 using the split option: section 2 now loads Validation: full suite green on both fixtures (15 assertions each), |
|
codex review: Update after re-checking ebbc2d3.
There are no inline review threads to resolve. |
Formalize the built-dist verification harness from the Rspack 2 support effort into a committed suite at tests/rspack-compat. The suite builds and packs @callstack/repack, installs the tarball into two standalone fixtures (one per @rspack/core major) and asserts the dual-major behavior matrix against the real dist: config routing, warn-only legacy cache handling, the Node compatibility guard, and a full dev build with HMR + React Refresh wired from the correct source per major. The fixtures live outside the pnpm workspace (own workspace roots, tarball-installed repack) because in-workspace repack's @rspack/core@^2 devDependency shadows any v1 pin - a lane guard aborts the run if the resolved major or install layout ever stops matching the fixture's intent. Also adds a dedicated CI lane for the suite and the headline minor changeset for Rspack 2 support.
…warning assertions by major
- Load dist/commands/rspack/{bundle,start,Compiler}.js and the lazy
@callstack/repack/commands/rspack entry from the tarball-installed
package, and assert the rspack named export shape - this exercises the
eager require('@rspack/core') the compiled commands ship with
(require(esm) under Rspack 2), which the DevelopmentPlugin build alone
bypassed.
- Create the dev-build compiler through the same rspack named export the
compiled call sites use, dropping the '?? rspack' fallback that could
mask a missing export.
- Compose the legacy-cache warning assertions with the isRspack2 gate the
commands use: assert the gate reads the fixture's installed major,
Rspack 1 sees no warning, Rspack 2 warns exactly once and mutates
nothing.
- apps/tester-app becomes the Rspack 2 example: the manifest now pins the workspace default catalog and declares @rspack/plugin-react-refresh plus a direct react-refresh, matching what in-workspace apps actually run - apps/tester-app-rspack1 is a standalone Rspack 1 lab outside the pnpm workspace (negation glob + own workspace root), installing repack from a packed tarball so resolution behaves like a real user project - flip the workspace default catalog to @rspack/core@^2.1.2, @swc/helpers@^0.5.23 and @rspack/plugin-react-refresh@^2.0.2; both federation apps declare the refresh plugin like any real v2 app - adapt tests/integration NativeEntryPlugin coverage to Rspack 2 output formats (version-agnostic runtime markers, shorthand module factories, relaxed runtime-module order assertion) and harden bundle normalization against ANSI codes and URL-encoded machine paths; regenerate snapshots
@rspack/plugin-react-refresh has a non-optional react-refresh peer; with autoInstallPeers disabled these manifests relied on another workspace importer to satisfy it. Match tester-app so each app is self-contained.
Containment alone would not catch a regression that moves the embed runtime after __webpack_require__.x() is invoked. Assert each runtime chain against the startup call independently so the polyfill-vs-embed relative order stays flexible across Rspack majors.
The app's lockfile is intentionally untracked (it pins the locally packed tarball, which changes on every pack-repack), so a frozen install can never succeed. Set frozen-lockfile=false in a local .npmrc and document it, so plain pnpm install behaves the same everywhere.
ebbc2d3 to
753e255
Compare
83c76fb to
dd929c9
Compare
The delegated ModuleFederationPluginV1 does not use @module-federation/runtime-tools under either rspack major; only the enhanced MF 1.5 plugin resolves it and that plugin raises its own install error. See the evidence on #1400 (closed).
…e locations The cache accessor was renamed and now collects both the legacy and top-level locations (see the fix on the types/test-infra branch); the smoke assertions follow, plus a regression guard that both locations are collected when both keys are set.
| // fixture's actual install, then mirror the command wiring: Rspack 1 | ||
| // users must see no warning, Rspack 2 users exactly one - and the config | ||
| // is never mutated. | ||
| const gated = isRspack2(FIXTURE); |
There was a problem hiding this comment.
codex review: This still tests the cache-warning command behavior by composing helpers directly instead of exercising the user-facing command path. If bundle.ts or start.ts stopped calling warnLegacyRspackCacheConfig behind the isRspack2(cliConfig.root) gate, this smoke would remain green because it calls isRspack2(FIXTURE) and warnLegacyRspackCacheConfig([legacyCfg]) itself. The same pattern applies to the lazy command entry below: the suite checks descriptors and module loadability, but never invokes the installed command func wrappers. Please drive at least one minimal bundle/start command invocation through @callstack/repack/commands/rspack, or add an assertion that fails if the lazy wrappers stop calling the guard and the commands stop calling the warning helper.
| ); | ||
|
|
||
| try { | ||
| run('pnpm', ['install', '--no-frozen-lockfile'], { cwd: fixtureDir }); |
There was a problem hiding this comment.
codex review: This runner shells out to the first pnpm on PATH, so local runs are not guaranteed to use the repository package manager version. In this worktree, running the documented command through corepack pnpm 10.32.1 still made these child installs run with global pnpm 11.7.0; under that pnpm, replacing a same-name/same-version file:./pkg.tgz and rerunning pnpm install --no-frozen-lockfile left the old installed package in place. Because this suite copies a fresh tarball to the same callstack-repack.tgz path on every run, the stale-tarball false positive can still happen outside CI. Please invoke the same package manager executable that launched the script, force reinstall/delete fixture install state, or make the tarball reference content-unique per run.
| const { ensureNodeSupportsRspack } = repackRequire( | ||
| path.join(REPACK, 'dist/commands/rspack/ensureNodeCompat.js') | ||
| ); | ||
| try { |
There was a problem hiding this comment.
codex review: This only proves the guard does not throw on the current supported Node version. It would still pass if ensureNodeSupportsRspack() became a no-op, if the Rspack 2 semver range regressed, or if the lazy command wrappers stopped calling the guard before loading @rspack/core. Since the changeset promises a clear error below ^20.19.0 || >=22.12.0, please add a negative check for an unsupported Rspack 2 Node version, for example by spawning the installed dist with process.versions.node overridden to 20.18.0/22.11.0, while also asserting Rspack 1 remains allowed.
| # Marks this directory as its own workspace root, so pnpm treats it as a | ||
| # standalone project instead of a member of the repository workspace. | ||
| # See ../../README.md for why the fixtures must stay outside the workspace. | ||
| packages: [] |
There was a problem hiding this comment.
codex review: These standalone fixture workspaces do not carry over the repo’s autoInstallPeers: false policy, so generated fixture installs default to autoInstallPeers: true. That makes the smoke less strict than this repo’s package-manager policy and can mask accidental imports of optional peers: in my run, Re.Pack resolved auto-installed peers like webpack / @babel/core from the fixture virtual store even though the fixture manifests do not declare them. The current smoke still passes if I reinstall with --config.auto-install-peers=false, so please set that policy in both fixture pnpm-workspace.yaml files or pass it during install to keep future regressions from being hidden.
Summary
Combines the final Rspack 2 validation surfaces into one review unit:
This PR stays on the temporary integration base until its implementation prerequisites have merged into
dannyhw/rspack-2-support; it will then retarget to the feature branch for final combined verification.What changed
apps/tester-appthe Rspack 2 validation surface.apps/tester-app-rspack1with its own dependency graph.Detailed tester-app review and device-validation history remains in #1403.
References
agent_context/rspackv2-jul2026/design.mdValidation
The component branches previously passed:
pnpm turbo run typecheck test --force— 17/17 taskspnpm lint:ciThe combined branch will run the full validation matrix before it merges into the feature branch.