chore(build): official Rsbuild plugin adoption — drop the standalone publint gate, register the framework-owned plugin set - #509
Conversation
🦋 Changeset detectedLatest commit: de25c1e The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
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 SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
commit: |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7f92ac1d36
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| * holes and plugins supplied as Promises (which Rsbuild also accepts) carry | ||
| * no name to compare until the build awaits them. | ||
| */ | ||
| export const frameworkOwnedPluginCollisions = (plugins: unknown): readonly string[] => { |
There was a problem hiding this comment.
Wire the collision helper into validation
When a project supplies pluginReact() through tools.rsbuild.plugins, validateTools in src/config/validate.ts still only validates that rsbuild is an object and never calls this helper, so AB4724 is not emitted and the duplicate rsbuild:react plugins continue into the synthesized config. Repository-wide search shows this new production module is imported only by its test, so wire it into validateTools in this commit rather than leaving the advertised collision diagnostic for a follow-up.
AGENTS.md reference: AGENTS.md:L11-L16
Useful? React with 👍 / 👎.
a71dff9 to
3966048
Compare
3966048 to
de25c1e
Compare
Adopt official Rsbuild/Rslib plugins where one covers a hand-rolled build/release step, and publish the framework-owned plugin set the
tools.rsbuildcollision diagnostic (#497) reads. Rspack/Rsbuild/Rslib only; nothing upgraded (@rslib/core0.23.2, workspace@rsbuild/core2.2.1, Rslib-nested 2.1.13).Adoption table
lint:package=publint <dir>×3 (script + "Package lint (publint)" CI step +local-cileg)rsbuild-plugin-publintrslib.config.tsalready registerspluginPublint({ throwOn: 'warning' }), which is stricter than the CLI (publint <dir>exits non-zero only on errors; the plugin also fails on warnings,onAfterBuild,order: 'post'). The standalone step was a second, weaker run of the same check.lint:releaseis now only the attw step; thepublintroot devDependency goes (the plugin carries its own).attw --pack --profile esm-only packages/agent-bundle(lint:release, release-gates job)rsbuild-plugin-arethetypeswrong@0.3.1areTheTypesWrongOptions: { ignoreResolutions: ['node10', 'node16-cjs'] }is what--profile esm-onlymaps to; it runspnpm packonapi.context.rootPathinonAfterBuild). It is unusable in this workspace: its bundled@arethetypeswrong/coreloads the TypeScript compiler API through the plugin'stypescriptpeer, which pnpm resolves to the workspace root'stypescript@7.0.2— the native compiler, no JS API — and the build crashes (TypeError: Cannot read properties of undefined (reading 'Latest')incore.js). The CLI works because@arethetypeswrong/corepins its owntypescriptdependency. pnpm cannot re-target a peer to a different version than the dependent's:overridesparent>childwith a range re-ranges the peer but still resolves the root's copy; annpm:alias moves it todependenciesat the same7.0.2;'-'plus apackageExtensionsdependency removes both. Revisit when the repo's root TypeScript regains a JS API or the plugin takes atypescriptmodule option.pnpm typecheck(roottsc --noEmit, project references over src + tests + workbench + create-agent-bundle)@rsbuild/plugin-type-checkts-checker-rspack-pluginover the environment'stsconfigPathonly (packages/agent-bundle/tsconfig.build.json, i.e. package source), whichrslib buildalready type-checks while emitting declarations (rsbuild-plugin-dts, tsgo). Adding it would be a third pass over a subset of whatpnpm typecheckcovers (7–8 s in CI), so it can only add time.@rsbuild/plugin-check-syntaxpluginCheckSyntaxreturns early unlesstarget === 'web', and every generatedbin/*.mjs, hook wrapper, and MCP shell builds withtarget: 'node'. Only its rawCheckSyntaxRspackPluginwith an explicitecmaVersioncould check node output, and that would be a new gate (there is nothing to replace;validate-artifact-modules.tsparses artifacts with acornecmaVersion: 'latest'for import-graph integrity, not target compatibility). The emitted syntax is bounded by the profile'ssyntax: 'es2022', which the documented Node floor (engines: >=22.19.0) covers. Documented as an MCP-App-view-only plugin in the reference.src/build/rslib.tsandsrc/build/mcp-apps.ts@rsbuild/plugin-reactcomposeEntryLibConfigregisterspluginReact({ fastRefresh: false })on every entry;composeMcpAppsRsbuildConfigregisterspluginReact()per.jsx/.tsxview. Nothing hand-rolled remained.rsbuild-plugin-source-builddeclaredDependencyRootsinrslib.tsis evidence classification (which modules count as authored source), not resolution. Examples consume the builtagent-bundlepackage by design (AGENTS.md: public exports only).Community plugins from awesome-rstack were also evaluated and none replace a framework path:
rsbuild-plugin-virtual-modulewrites scratch files (the framework'sexperiments.VirtualModulesPlugindesign decision explicitly avoids that),rsbuild-plugin-dts/rsbuild-plugin-rsc/rsbuild-plugin-mcp/@module-federation/rsbuild-plugin/rspack-manifest-plugintarget other problems.Exported plugin set
The registry is
packages/agent-bundle/src/build/framework-plugins.ts—frameworkOwnedRsbuildPlugins: ReadonlyMap<string, string>={ 'rsbuild:react' → '@rsbuild/plugin-react' }, plusframeworkOwnedPluginCollisions(plugins)for the diagnostic. It landed in #497 (fc4d6b6c7) and this PR is rebased onto it; the file dropped out of this diff (it was byte-identical). #497 wires the AB4724 diagnostic intovalidateTools; this PR adds the test that derives the set from the synthesized configs and the docs table. Nothing else is registered by the framework-generated builds (publint/attw/type-check/check-syntax/source-build were all not adopted for them, see the table above), so the map stays a single entry — the registration test would fail if a build path registered a plugin outside it.New test
tests/framework-plugin-registration.test.ts(unit pool) derives the set from what the framework actually registers:composeEntryLibConfig(...).pluginsandcomposeMcpAppsRsbuildConfig(...).environments[view].pluginsfor a React view must equal the map's keys exactly, a plain.tsview registers nothing, no name is registered twice, and no plugin sits at the root the consumer'stools.rsbuild.pluginsmerges into.Docs (
website/docs/{en,zh}/reference/configuration.mdx→tools→ new Plugins subsection): the framework-owned set, pointing at #497'sAB4724paragraph for why it must not be re-added, and a table of official plugins a project may add viatools.rsbuild.pluginswith the surface each is relevant to (artifact entries vs MCP App views;check-syntaxmarked views-only per its source), plus the not-applicable list (other-framework JSX plugins,umd, the publishing checks).CI proof that a publint failure fails the job
tests/publint-gate.test.ts(integration pool): (1) all three packagerslib.config.tsregisterplugin-publint; (2) a realcreateRslibbuild of a temp package with a warning-level finding (EXPORTS_MISSING_ROOT_ENTRYPOINT) under the samepluginPublint({ throwOn: 'warning' })rejects withPublint failed!; (3) the clean manifest builds. This is the gate the removed CI step relied on.Artifact diff
No profile in
src/build/**changes in this PR (the new module is not wired anywhere yet), soartifact/**forexamples/audiobook-curatorandexamples/host-testis unchanged by construction. The packagedist/**is unaffected too (rslib.config.tsuntouched here).CI timings (Verify job)
pnpm buildpnpm typecheckpnpm check:release:citest:packed; the removed publint call was ~1–3 s of it)Net: the Verify job loses the 3–4 s publint step and nothing is added, because
rsbuild-plugin-publintwas already running insidepnpm build.Other
docs/local-ci.md,scripts/local-ci.mjs,docs/effect-conventions.mdand two dated plan docs:lint:packagereferences updated.website/docs/{en,zh}/guide/distribution/preview-packages.mdx:lint:releasedescribed as attw-only, publint as in-build.detailkey that broke Docs site onmain);pnpm docs:site:buildgreen here.Review status
Codex reviewed
7f92ac1(PR opened). One thread, answered here rather than by reply (this PR posts no comments):src/build/framework-plugins.ts:31— "wireframeworkOwnedPluginCollisionsintovalidateToolsin this PR": resolved by feat(routes): include generated route declarations by default (AB4834); reject duplicated framework plugins in tools.rsbuild (AB4724) #497 landing (fc4d6b6c7), which owns the AB4724 diagnostic and wires this exact module intovalidateTools. After the rebase the module is no longer part of this diff; the wiring is onmainand this PR's docs section points at it.Last Codex-reviewed head:
7f92ac1. Unreviewed heads (no re-review arrived after the pushes; this PR posts no comments): the changeset-number commit, the rebases over #507, #510 and #497, and the docs sentence pointing at AB4724 — current headde25c1e87. Merged on green CI per the AGENTS.md fallback; any thread opened afterwards is answered in a follow-up PR.