Repository navigation
feat(cli-modules): add Rsdoctor CLI module and workspace - #4898
christoph-jerolimov wants to merge 5 commits into
Conversation
|
This pull request adds a new top-level directory under |
Changed Packages
|
PR Summary by QodoAdd Rsdoctor CLI commands and bundle-size checks workspace
AI Description
Diagram
High-Level Assessment
Files changed (56)
|
Code Review by Qodo
1. The new command group never loads
|
|
Important The |
|
This PR has been automatically marked as stale because it has not had recent activity from the author. It will be closed if no further activity occurs. If the PR was closed and you want it re-opened, let us know and we'll re-open the PR so that you can continue the contribution! |
|
Signed-off-by: Christoph Jerolimov <jerolimov+git@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com> Signed-off-by: Christoph Jerolimov <jerolimov+git@redhat.com>
Signed-off-by: Christoph Jerolimov <jerolimov+git@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com>
Signed-off-by: Christoph Jerolimov <jerolimov+git@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com>
Add chunk analysis for the example frontend plugin
Documents how many JS chunks the browser fetches for
@internal/backstage-plugin-example when it is registered synchronously
(package discovery) versus asynchronously (feature loader), plus the
6-chunk group behind its /example page. Adds scripts to reproduce the
analysis from the Rspack bundle stats and to confirm it in Chromium.
Integrate Rsdoctor for analysing the Rspack app build
The Backstage CLI does not expose its Rspack configuration, so
scripts/rsdoctor-cli.cjs patches the CLI's internal createConfig to
append RsdoctorRspackPlugin to the frontend bundler config and then
runs the regular backstage-cli command. Adds `build:rsdoctor` and
`start:rsdoctor` scripts for packages/app, a root `build:rsdoctor`
shortcut and `rsdoctor:analyze` to re-open a saved report.
On CI the wrapper switches to Rsdoctor's brief mode (single HTML
report) and keeps Rsdoctor's lint findings out of the Rspack warnings,
since the Backstage CLI treats warnings as errors there.
Add Rsdoctor scripts for analysing the example plugin on its own
build:rsdoctor runs the module federation remote build of the plugin
with Rspack so Rsdoctor can report on just the plugin and its
dependencies; start:rsdoctor does the same for the plugin dev app.
Add a Backstage CLI module with rsdoctor commands
Replaces the standalone wrapper script with @internal/cli-module-rsdoctor,
a Backstage CLI module discovered from the root package.json. It adds:
backstage-cli rsdoctor build Rspack build of the current package with a report
backstage-cli rsdoctor start dev server with a live Rsdoctor report
backstage-cli rsdoctor analyze re-open a saved report
build/start wrap the CLI's own package build/start commands, appending
RsdoctorRspackPlugin to the frontend bundler config. Inside plugin
packages the build defaults to the module federation remote build, the
only Rspack production build of a plugin. Flags the commands do not own
are forwarded in order. On CI the module switches to brief mode and
keeps Rsdoctor's lint findings out of the Rspack warnings so the build
does not fail. The package scripts now call the CLI commands.
Add size budgets, baseline diffs and CI summary to the rsdoctor CLI module
rsdoctor build now writes .rsdoctor/sizes.json (gzipped size of every
JS/CSS file with a hash-less key), prints a console summary with the
Rsdoctor findings (on by default on CI), and checks rsdoctor.budgets.json:
static limits for the initial JS total, the JS total, any single file
and named chunks, plus growth limits against a baseline sizes.json.
A violation fails the build. The same static checks run as a custom
Rsdoctor rule so they show up under Bundle Alerts in the report, and
--json adds a JSON report in brief mode.
New commands: `rsdoctor check` evaluates an existing sizes.json against
the budgets and a baseline without rebuilding; `rsdoctor diff` prints
the per-file size changes between two builds, applies the baseline
limits, and can generate Rsdoctor's bundle diff (--html/--json/--serve).
packages/app ships a starting rsdoctor.budgets.json.
Add size budgets for the example plugin build
Adds plugins/example/rsdoctor.budgets.json with limits for the plugin's
module federation build, check:rsdoctor scripts for the app and the
plugin, and documents the plugin budget flow. Rsdoctor report folders
are excluded from the Prettier check.
Check unlisted and new chunks in size budgets
Budget keys may now contain wildcards (module-*, static/*.chunk.js) and
match a file's basename; the key "*" is a catch-all limit for every file
no other key matches, so unlisted and newly appearing chunks are
checked without naming them. maxChunks limits the number of emitted JS
files. Baseline checks now treat files that are new compared to the
baseline explicitly via newChunks (allow | fail | size limit) and
maxNewChunks, and list removed files; maxChunkIncrease only applies to
files that exist in both builds.
The app and example plugin budgets use the catch-all and new-chunk
limits.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Christoph Jerolimov <jerolimov+git@redhat.com>
892a956 to
9e9d12d
Compare
|
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #4898 +/- ##
==========================================
- Coverage 64.07% 63.95% -0.13%
==========================================
Files 2719 2733 +14
Lines 107707 108277 +570
Branches 30328 30508 +180
==========================================
+ Hits 69012 69247 +235
- Misses 36901 37236 +335
Partials 1794 1794
*This pull request uses carry forward flags. Click here to find out more. Continue to review full report in Codecov by Harness.
🚀 New features to boost your workflow:
|
9e9d12d to
556bd8a
Compare
|
aecd951 to
7371182
Compare
Signed-off-by: Debsmita Santra <debsmita.santra@gmail.com>
7371182 to
7c8efaf
Compare
|
|
Code review by qodo was updated up to the latest commit 7c8efaf |
|
/fs-review |
|
🤖 Finished Review · ✅ Success · Started 3:12 PM UTC · Completed 3:38 PM UTC Commit: Runtime: claude · Model: opus → claude-opus-4-6 · Effort: high · Cost: $9.85 |
|
Risk Assessment: elevated (3/5) DetailsLarge new workspace scaffold (56 files, 24720 lines dominated by a 21K-line yarn.lock) with four dependency files changed and a low test-file ratio (0.09), added by an established contributor with no linked issue, pushing risk above moderate despite the all-new-file nature of the change. |
ReviewFindingsHigh
Medium
Low
Next steps:
|
| /workspaces/intelligent-assistant @redhat-developer/rhdh-plugins-maintainers @redhat-developer/rhdh-ui @redhat-developer/rhdh-ai @karthikjeeyar @rohitkrai03 @yangcao77 | ||
| /workspaces/mcp-integrations @redhat-developer/rhdh-plugins-maintainers @johnmcollier @gabemontero @redhat-developer/rhdh-ai | ||
| /workspaces/konflux @redhat-developer/rhdh-plugins-maintainers @rrosatti @sahil143 @milantaky | ||
| /workspaces/mcp-integrations @redhat-developer/rhdh-plugins-maintainers @johnmcollier @gabemontero @redhat-developer/rhdh-ai |
There was a problem hiding this comment.
[high] scope-defect
The /workspaces/mcp-integrations entry appears twice (lines 32 and 34) with identical owners after the alphabetical reordering. GitHub CODEOWNERS uses last-matching-pattern semantics, so the second silently overrides the first.
Suggested fix: Remove line 32 (the first /workspaces/mcp-integrations entry). The entry at line 34 (after konflux at line 33) is in the correct alphabetical position.
| apiVersion: backstage.io/v1alpha1 | ||
| kind: Component | ||
| metadata: | ||
| name: cli-modules |
There was a problem hiding this comment.
[high] naming-conventions
The catalog-info.yaml retains scaffold placeholder values: name: cli-modules, description: An example of a Backstage application, type: website, owner: john@example.com, lifecycle: experimental. All standard annotations and subcomponentOf field are absent.
Suggested fix: Follow the pattern in workspaces/homepage/catalog-info.yaml: set name to red-hat-developer-hub-cli-modules, provide a real description, set type: backstage-plugin, lifecycle: active, a real owner, and add standard annotations.
| @@ -0,0 +1,28 @@ | |||
| # [Backstage](https://backstage.io) | |||
|
|
|||
| This is your newly scaffolded Backstage App, Good Luck! | |||
There was a problem hiding this comment.
[high] stale-doc
The workspace README retains full scaffold boilerplate: header, TODO banner, placeholder description, and a broken link to non-existent ./plugins/plugin-backend/README. The actual plugin is rsdoctor-test.
Suggested fix: Replace the scaffold text with a real workspace description and update the plugin list to reference rsdoctor-test.
| /workspaces/app-defaults @redhat-developer/rhdh-plugins-maintainers @redhat-developer/rhdh-ui @rohitkrai03 @christoph-jerolimov | ||
| /workspaces/bulk-import @redhat-developer/rhdh-plugins-maintainers @redhat-developer/rhdh-plugins @rm3l @redhat-developer/rhdh-ui @debsmita1 @its-mitesh-kumar | ||
| /workspaces/cost-management @redhat-developer/rhdh-plugins-maintainers @ydayagi @mareklibra @batzionb @PreetiW @asmasarw @Aurobinda55 @r14chandra @kgaikwad | ||
| /workspaces/cli-modules @redhat-developer/rhdh-plugins-maintainers @redhat-developer/rhdh-cope @redhat-developer/rhdh-ui @christoph-jerolimov |
There was a problem hiding this comment.
[medium] architecture-coherence
The file header states the workspace list is alphabetically ordered. /workspaces/cli-modules (line 25) appears after /workspaces/cost-management (line 24), but cli sorts before cos.
Suggested fix: Move /workspaces/cli-modules to before /workspaces/cost-management.
| ```sh | ||
| yarn build:rsdoctor # app (= yarn workspace app build:rsdoctor) | ||
| yarn workspace app start:rsdoctor # app dev server | ||
| yarn workspace @internal/backstage-plugin-example build:rsdoctor |
There was a problem hiding this comment.
[medium] stale-doc
The README uses @internal/backstage-plugin-example in multiple example commands, but this package does not exist. The actual test plugin is @red-hat-developer-hub/backstage-plugin-rsdoctor-test.
Suggested fix: Replace all occurrences of @internal/backstage-plugin-example with @red-hat-developer-hub/backstage-plugin-rsdoctor-test.
| contains and lets you drill into a chunk. The **Bundle > Treemap** view shows | ||
| which packages dominate each chunk, and the **Module Graph** answers why a | ||
| module is in the bundle at all (its import chain). For the plugin chunk | ||
| analysis in `docs/example-plugin-chunk-analysis.md`, search the Bundle Size |
There was a problem hiding this comment.
[medium] missing-doc
The README references docs/example-plugin-chunk-analysis.md as further reading, but this file does not exist anywhere in the workspace.
Suggested fix: Either create the referenced docs/example-plugin-chunk-analysis.md or remove the sentence referencing it.
| "name": "@red-hat-developer-hub/cli-module-rsdoctor", | ||
| "version": "0.1.0", | ||
| "license": "Apache-2.0", | ||
| "private": true, |
There was a problem hiding this comment.
[medium] architecture-coherence
The package declares private: true alongside publishConfig with access: public, prepack/postpack scripts, and a files field. These are contradictory: npm blocks publishing a private package.
Suggested fix: If intended for publishing, remove private: true. If it must remain private, remove publishConfig.
| @@ -0,0 +1,32 @@ | |||
| #!/usr/bin/env node | |||
| /* | |||
| * Copyright 2026 The Backstage Authors | |||
There was a problem hiding this comment.
[medium] naming-conventions
The copyright header reads Copyright 2026 The Backstage Authors while every other source file uses Copyright Red Hat, Inc.
Suggested fix: Change to Copyright Red Hat, Inc.
| continue; | ||
| } | ||
| const content = readContent(asset.name); | ||
| const gzip = content ? zlib.gzipSync(content).length : 0; |
There was a problem hiding this comment.
[low] silent-fallback
When an asset content cannot be read, gzip is silently set to 0 while size retains the raw value, causing budget checks to erroneously pass.
Suggested fix: Skip the asset or log a warning when content is unreadable.
| initial: asset.chunks.some(c => c.initial), | ||
| type, | ||
| size: asset.size, | ||
| gzip: asset.gzipSize ?? asset.size, |
There was a problem hiding this comment.
[low] inconsistent-measurement
Uses asset.gzipSize ?? asset.size as the gzip fallback. The raw size is 2-5x larger than gzip, creating opposite-direction errors from the sizes.ts fallback.
Suggested fix: Omit assets from evaluation when gzipSize is undefined, or note the approximation in violation messages.
|
This PR has been automatically marked as stale because it has not had recent activity from the author. It will be closed if no further activity occurs. If the PR was closed and you want it re-opened, let us know and we'll re-open the PR so that you can continue the contribution! |



Summary
workspaces/cli-modulesworkspace (CODEOWNERS entry included) for Backstage CLI modules.@red-hat-developer-hub/cli-module-rsdoctor, which registers anrsdoctorcommand group onbackstage-cli(build,start,analyze,check,diff) by injectingRsdoctorRspackPlugininto the frontend bundler without forking the CLI config.rsdoctor.budgets.json), baseline growth checks, and CI-friendly brief reports; include anrsdoctor-testfrontend plugin for exercising the module.Test plan
workspaces/cli-modules, runyarn installandyarn workspace @red-hat-developer-hub/backstage-plugin-rsdoctor-test build:rsdoctor(or the equivalent package script) and confirm a report/sizes.jsonis written under.rsdoctor/backstage-cli rsdoctor checkagainst that build with the plugin’srsdoctor.budgets.jsonand confirm budget pass/fail behaves as expectedbackstage-cli rsdoctor analyzeto reopen a saved report, andrsdoctor diff --baseline …against a second buildyarn testforcli-module-rsdoctor(budget/options unit tests).rsdoctor/remains gitignored and workspace lint/prettier still passMade with Cursor