feat: MUI 4 to BUI migration - foundation codemods (#108, #109, #110, #111)#128
feat: MUI 4 to BUI migration - foundation codemods (#108, #109, #110, #111)#128schultzp2020 wants to merge 12 commits into
Conversation
Use Promise.resolve returns, array destructuring, and find() to satisfy oxlint with --deny-warnings in CI. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Pull request overview
This PR introduces four new “foundation” codemods under codemods/misc/ to support a Backstage MUI v4 → BUI migration (bootstrap prerequisites, icon replacements, makeStyles→CSS Modules extraction, and layout primitive conversions), along with fixtures/metrics for each codemod and documentation/lockfile updates.
Changes:
- Add 4 new codemod packages (
migrate-mui-bootstrap-to-bui,migrate-mui-icons-to-remix-icons,migrate-mui-styles-to-bui-css-modules,migrate-mui-layout-to-bui-layout) with workflows, configs, and implementations. - Add JSSG test fixtures (input/expected + metrics) for each codemod behavior and TODO fallback cases.
- Update repo documentation and lockfile to include the new misc codemods and workspace entries.
Reviewed changes
Copilot reviewed 117 out of 118 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| yarn.lock | Adds workspace lock entries for the 4 new misc codemod packages |
| README.md | Documents the new misc codemods in the CODEMODS list |
| codemods/misc/migrate-mui-styles-to-bui-css-modules/workflow.yaml | Defines workflow step to run the styles codemod |
| codemods/misc/migrate-mui-styles-to-bui-css-modules/tsconfig.json | TS config for the styles codemod package |
| codemods/misc/migrate-mui-styles-to-bui-css-modules/tests/with-styles-todo/metrics.json | Fixture metrics for withStyles TODO path |
| codemods/misc/migrate-mui-styles-to-bui-css-modules/tests/with-styles-todo/input.tsx | Fixture input for withStyles TODO path |
| codemods/misc/migrate-mui-styles-to-bui-css-modules/tests/with-styles-todo/expected.tsx | Fixture expected output for withStyles TODO path |
| codemods/misc/migrate-mui-styles-to-bui-css-modules/tests/static-theme-tokens/metrics.json | Fixture metrics for static theme token extraction |
| codemods/misc/migrate-mui-styles-to-bui-css-modules/tests/static-theme-tokens/input.tsx | Fixture input for static theme token extraction |
| codemods/misc/migrate-mui-styles-to-bui-css-modules/tests/static-theme-tokens/expected.tsx | Fixture expected output for static theme token extraction |
| codemods/misc/migrate-mui-styles-to-bui-css-modules/tests/noop-no-import/input.tsx | Fixture input for no-op case (already CSS modules) |
| codemods/misc/migrate-mui-styles-to-bui-css-modules/tests/noop-no-import/expected.tsx | Fixture expected output for no-op case |
| codemods/misc/migrate-mui-styles-to-bui-css-modules/tests/multiple-classes/metrics.json | Fixture metrics for multiple extracted classes |
| codemods/misc/migrate-mui-styles-to-bui-css-modules/tests/multiple-classes/input.tsx | Fixture input for multiple extracted classes |
| codemods/misc/migrate-mui-styles-to-bui-css-modules/tests/multiple-classes/expected.tsx | Fixture expected output for multiple extracted classes |
| codemods/misc/migrate-mui-styles-to-bui-css-modules/tests/merge-existing-bui/metrics.json | Fixture metrics for existing CSS module scenario |
| codemods/misc/migrate-mui-styles-to-bui-css-modules/tests/merge-existing-bui/input.tsx | Fixture input for existing CSS module scenario |
| codemods/misc/migrate-mui-styles-to-bui-css-modules/tests/merge-existing-bui/input.module.css | Fixture existing CSS module content |
| codemods/misc/migrate-mui-styles-to-bui-css-modules/tests/merge-existing-bui/expected.tsx | Fixture expected output for existing CSS module scenario |
| codemods/misc/migrate-mui-styles-to-bui-css-modules/tests/dynamic-rule-todo/metrics.json | Fixture metrics for dynamic rule TODO path |
| codemods/misc/migrate-mui-styles-to-bui-css-modules/tests/dynamic-rule-todo/input.tsx | Fixture input for dynamic rule TODO path |
| codemods/misc/migrate-mui-styles-to-bui-css-modules/tests/dynamic-rule-todo/expected.tsx | Fixture expected output for dynamic rule TODO path |
| codemods/misc/migrate-mui-styles-to-bui-css-modules/tests/direct-object-arg/metrics.json | Fixture metrics for makeStyles(object) extraction |
| codemods/misc/migrate-mui-styles-to-bui-css-modules/tests/direct-object-arg/input.tsx | Fixture input for makeStyles(object) extraction |
| codemods/misc/migrate-mui-styles-to-bui-css-modules/tests/direct-object-arg/expected.tsx | Fixture expected output for makeStyles(object) extraction |
| codemods/misc/migrate-mui-styles-to-bui-css-modules/scripts/codemod.ts | Implements makeStyles/withStyles → CSS Modules extraction + metrics |
| codemods/misc/migrate-mui-styles-to-bui-css-modules/package.json | Declares the styles codemod package + test script |
| codemods/misc/migrate-mui-styles-to-bui-css-modules/codemod.yaml | Codemod registry metadata for the styles codemod |
| codemods/misc/migrate-mui-styles-to-bui-css-modules/CHANGELOG.md | Initializes styles codemod changelog |
| codemods/misc/migrate-mui-layout-to-bui-layout/workflow.yaml | Defines workflow step to run the layout codemod |
| codemods/misc/migrate-mui-layout-to-bui-layout/tsconfig.json | TS config for the layout codemod package |
| codemods/misc/migrate-mui-layout-to-bui-layout/tests/paper-simple/metrics.json | Fixture metrics for Paper→Surface mapping |
| codemods/misc/migrate-mui-layout-to-bui-layout/tests/paper-simple/input.tsx | Fixture input for Paper→Surface mapping |
| codemods/misc/migrate-mui-layout-to-bui-layout/tests/paper-simple/expected.tsx | Fixture expected output for Paper→Surface mapping |
| codemods/misc/migrate-mui-layout-to-bui-layout/tests/paper-elevation-todo/metrics.json | Fixture metrics for Paper elevation TODO path |
| codemods/misc/migrate-mui-layout-to-bui-layout/tests/paper-elevation-todo/input.tsx | Fixture input for Paper elevation TODO path |
| codemods/misc/migrate-mui-layout-to-bui-layout/tests/paper-elevation-todo/expected.tsx | Fixture expected output for Paper elevation TODO path |
| codemods/misc/migrate-mui-layout-to-bui-layout/tests/noop-no-import/input.tsx | Fixture input for no-op (already BUI) |
| codemods/misc/migrate-mui-layout-to-bui-layout/tests/noop-no-import/expected.tsx | Fixture expected output for no-op |
| codemods/misc/migrate-mui-layout-to-bui-layout/tests/merge-existing-bui/metrics.json | Fixture metrics for merging with existing BUI imports |
| codemods/misc/migrate-mui-layout-to-bui-layout/tests/merge-existing-bui/input.tsx | Fixture input for merging with existing BUI imports |
| codemods/misc/migrate-mui-layout-to-bui-layout/tests/merge-existing-bui/expected.tsx | Fixture expected output for merging with existing BUI imports |
| codemods/misc/migrate-mui-layout-to-bui-layout/tests/grid-todo/metrics.json | Fixture metrics for Grid TODO path (dynamic spacing/colspan) |
| codemods/misc/migrate-mui-layout-to-bui-layout/tests/grid-todo/input.tsx | Fixture input for Grid TODO path |
| codemods/misc/migrate-mui-layout-to-bui-layout/tests/grid-todo/expected.tsx | Fixture expected output for Grid TODO path |
| codemods/misc/migrate-mui-layout-to-bui-layout/tests/grid-simple/metrics.json | Fixture metrics for simple Grid conversion |
| codemods/misc/migrate-mui-layout-to-bui-layout/tests/grid-simple/input.tsx | Fixture input for simple Grid conversion |
| codemods/misc/migrate-mui-layout-to-bui-layout/tests/grid-simple/expected.tsx | Fixture expected output for simple Grid conversion |
| codemods/misc/migrate-mui-layout-to-bui-layout/tests/box-flex-container/metrics.json | Fixture metrics for Box flex container conversion |
| codemods/misc/migrate-mui-layout-to-bui-layout/tests/box-flex-container/input.tsx | Fixture input for Box flex container conversion |
| codemods/misc/migrate-mui-layout-to-bui-layout/tests/box-flex-container/expected.tsx | Fixture expected output for Box flex container conversion |
| codemods/misc/migrate-mui-layout-to-bui-layout/tests/box-component-todo/metrics.json | Fixture metrics for Box polymorphic TODO path |
| codemods/misc/migrate-mui-layout-to-bui-layout/tests/box-component-todo/input.tsx | Fixture input for Box polymorphic TODO path |
| codemods/misc/migrate-mui-layout-to-bui-layout/tests/box-component-todo/expected.tsx | Fixture expected output for Box polymorphic TODO path |
| codemods/misc/migrate-mui-layout-to-bui-layout/scripts/codemod.ts | Implements Box→Flex, Paper→Surface, Grid→Grid.Root/Grid.Item + TODOs + metrics |
| codemods/misc/migrate-mui-layout-to-bui-layout/package.json | Declares the layout codemod package + test script |
| codemods/misc/migrate-mui-layout-to-bui-layout/codemod.yaml | Codemod registry metadata for the layout codemod |
| codemods/misc/migrate-mui-layout-to-bui-layout/CHANGELOG.md | Initializes layout codemod changelog |
| codemods/misc/migrate-mui-icons-to-remix-icons/workflow.yaml | Defines workflow step to run the icons codemod |
| codemods/misc/migrate-mui-icons-to-remix-icons/tsconfig.json | TS config for the icons codemod package |
| codemods/misc/migrate-mui-icons-to-remix-icons/tests/unknown-icon-todo/metrics.json | Fixture metrics for unknown icon TODO path |
| codemods/misc/migrate-mui-icons-to-remix-icons/tests/unknown-icon-todo/input.tsx | Fixture input for unknown icon TODO path |
| codemods/misc/migrate-mui-icons-to-remix-icons/tests/unknown-icon-todo/expected.tsx | Fixture expected output for unknown icon TODO path |
| codemods/misc/migrate-mui-icons-to-remix-icons/tests/simple-known-icon/metrics.json | Fixture metrics for known icon mapping + JSX sizing |
| codemods/misc/migrate-mui-icons-to-remix-icons/tests/simple-known-icon/input.tsx | Fixture input for known icon mapping |
| codemods/misc/migrate-mui-icons-to-remix-icons/tests/simple-known-icon/expected.tsx | Fixture expected output for known icon mapping |
| codemods/misc/migrate-mui-icons-to-remix-icons/tests/noop-no-import/input.tsx | Fixture input for no-op (already remix import) |
| codemods/misc/migrate-mui-icons-to-remix-icons/tests/noop-no-import/expected.tsx | Fixture expected output for no-op |
| codemods/misc/migrate-mui-icons-to-remix-icons/tests/namespace-import-todo/metrics.json | Fixture metrics for namespace import TODO path |
| codemods/misc/migrate-mui-icons-to-remix-icons/tests/namespace-import-todo/input.tsx | Fixture input for namespace import TODO path |
| codemods/misc/migrate-mui-icons-to-remix-icons/tests/namespace-import-todo/expected.tsx | Fixture expected output for namespace import TODO path |
| codemods/misc/migrate-mui-icons-to-remix-icons/tests/multiple-icons/metrics.json | Fixture metrics for multiple icon mappings |
| codemods/misc/migrate-mui-icons-to-remix-icons/tests/multiple-icons/input.tsx | Fixture input for multiple icon mappings |
| codemods/misc/migrate-mui-icons-to-remix-icons/tests/multiple-icons/expected.tsx | Fixture expected output for multiple icon mappings |
| codemods/misc/migrate-mui-icons-to-remix-icons/tests/merge-existing-bui/metrics.json | Fixture metrics for merging into existing remix import |
| codemods/misc/migrate-mui-icons-to-remix-icons/tests/merge-existing-bui/input.tsx | Fixture input for merging into existing remix import |
| codemods/misc/migrate-mui-icons-to-remix-icons/tests/merge-existing-bui/expected.tsx | Fixture expected output for merging into existing remix import |
| codemods/misc/migrate-mui-icons-to-remix-icons/tests/extension-icon-slot/metrics.json | Fixture metrics for Backstage extension icon: slot wrapping |
| codemods/misc/migrate-mui-icons-to-remix-icons/tests/extension-icon-slot/input.tsx | Fixture input for Backstage extension icon: slot wrapping |
| codemods/misc/migrate-mui-icons-to-remix-icons/tests/extension-icon-slot/expected.tsx | Fixture expected output for Backstage extension icon: slot wrapping |
| codemods/misc/migrate-mui-icons-to-remix-icons/tests/aliased-import/metrics.json | Fixture metrics for default-import local alias mapping |
| codemods/misc/migrate-mui-icons-to-remix-icons/tests/aliased-import/input.tsx | Fixture input for default-import local alias mapping |
| codemods/misc/migrate-mui-icons-to-remix-icons/tests/aliased-import/expected.tsx | Fixture expected output for default-import local alias mapping |
| codemods/misc/migrate-mui-icons-to-remix-icons/scripts/codemod.ts | Implements MUI icons → Remix icon mappings, JSX sizing, TODO fallbacks + metrics |
| codemods/misc/migrate-mui-icons-to-remix-icons/package.json | Declares the icons codemod package + test script |
| codemods/misc/migrate-mui-icons-to-remix-icons/codemod.yaml | Codemod registry metadata for the icons codemod |
| codemods/misc/migrate-mui-icons-to-remix-icons/CHANGELOG.md | Initializes icons codemod changelog |
| codemods/misc/migrate-mui-bootstrap-to-bui/workflow.yaml | Defines workflow steps for package.json deps + CSS import bootstrap |
| codemods/misc/migrate-mui-bootstrap-to-bui/tsconfig.json | TS config for the bootstrap codemod package |
| codemods/misc/migrate-mui-bootstrap-to-bui/tests/package-with-mui-icons/metrics.json | Fixture metrics for adding BUI + Remix deps |
| codemods/misc/migrate-mui-bootstrap-to-bui/tests/package-with-mui-icons/input.json | Fixture input package.json with MUI icons dependency |
| codemods/misc/migrate-mui-bootstrap-to-bui/tests/package-with-mui-icons/expected.json | Fixture expected output with added BUI + Remix deps |
| codemods/misc/migrate-mui-bootstrap-to-bui/tests/package-with-mui-core/metrics.json | Fixture metrics for adding BUI dep when MUI core present |
| codemods/misc/migrate-mui-bootstrap-to-bui/tests/package-with-mui-core/input.json | Fixture input package.json with MUI core dependency |
| codemods/misc/migrate-mui-bootstrap-to-bui/tests/package-with-mui-core/expected.json | Fixture expected output with added BUI dep |
| codemods/misc/migrate-mui-bootstrap-to-bui/tests/noop-no-mui/input.tsx | Fixture input for no-op (no MUI imports) |
| codemods/misc/migrate-mui-bootstrap-to-bui/tests/noop-no-mui/expected.tsx | Fixture expected output for no-op |
| codemods/misc/migrate-mui-bootstrap-to-bui/tests/multiple-mui-imports/metrics.json | Fixture metrics for inserting global stylesheet import |
| codemods/misc/migrate-mui-bootstrap-to-bui/tests/multiple-mui-imports/input.tsx | Fixture input for inserting global stylesheet import |
| codemods/misc/migrate-mui-bootstrap-to-bui/tests/multiple-mui-imports/expected.tsx | Fixture expected output for inserting global stylesheet import |
| codemods/misc/migrate-mui-bootstrap-to-bui/tests/merge-existing-bui/metrics.json | Fixture metrics for already-bootstrapped stylesheet import |
| codemods/misc/migrate-mui-bootstrap-to-bui/tests/merge-existing-bui/input.tsx | Fixture input for already-bootstrapped stylesheet import |
| codemods/misc/migrate-mui-bootstrap-to-bui/tests/merge-existing-bui/expected.tsx | Fixture expected output for already-bootstrapped stylesheet import |
| codemods/misc/migrate-mui-bootstrap-to-bui/tests/icons-import/metrics.json | Fixture metrics for stylesheet insertion with icons import present |
| codemods/misc/migrate-mui-bootstrap-to-bui/tests/icons-import/input.tsx | Fixture input for stylesheet insertion with icons import present |
| codemods/misc/migrate-mui-bootstrap-to-bui/tests/icons-import/expected.tsx | Fixture expected output for stylesheet insertion with icons import present |
| codemods/misc/migrate-mui-bootstrap-to-bui/tests/app-entry-with-mui/metrics.json | Fixture metrics for stylesheet insertion in an entry-like file |
| codemods/misc/migrate-mui-bootstrap-to-bui/tests/app-entry-with-mui/input.tsx | Fixture input for stylesheet insertion in an entry-like file |
| codemods/misc/migrate-mui-bootstrap-to-bui/tests/app-entry-with-mui/expected.tsx | Fixture expected output for stylesheet insertion in an entry-like file |
| codemods/misc/migrate-mui-bootstrap-to-bui/tests/already-bootstrapped/metrics.json | Fixture metrics for already-bootstrapped case |
| codemods/misc/migrate-mui-bootstrap-to-bui/tests/already-bootstrapped/input.tsx | Fixture input for already-bootstrapped case |
| codemods/misc/migrate-mui-bootstrap-to-bui/tests/already-bootstrapped/expected.tsx | Fixture expected output for already-bootstrapped case |
| codemods/misc/migrate-mui-bootstrap-to-bui/scripts/package-json-codemod.ts | Implements package.json dependency bootstrap for BUI (+ Remix when applicable) |
| codemods/misc/migrate-mui-bootstrap-to-bui/scripts/codemod.ts | Implements stylesheet import insertion when MUI imports are present |
| codemods/misc/migrate-mui-bootstrap-to-bui/package.json | Declares the bootstrap codemod package + test script(s) |
| codemods/misc/migrate-mui-bootstrap-to-bui/codemod.yaml | Codemod registry metadata for the bootstrap codemod |
| codemods/misc/migrate-mui-bootstrap-to-bui/CHANGELOG.md | Initializes bootstrap codemod changelog |
| .changeset/mui-to-bui-foundation.md | Changeset to publish all 4 new codemods as minor releases |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Cursor <cursoragent@cursor.com>
Scan source files for remaining @material-ui/* imports, then remove unused MUI packages from each package.json. Intended as the final step after component migration codemods complete. Co-authored-by: Cursor <cursoragent@cursor.com>
Drop fs/promises scanning and the oxlint disable workaround. The JSON step reads usage recorded by the scan step in the same workflow run. Co-authored-by: Cursor <cursoragent@cursor.com>
Revert the metrics-only refactor. Keep metrics-first resolution with fs/promises fallback for src/ and dev/ scanning. Fix CI by moving the oxlint disable to an end-of-line comment so oxfmt accepts the import. Co-authored-by: Cursor <cursoragent@cursor.com>
…tern Split into codemod.ts (TSX scan) and package-json-codemod.ts (pure JSON transform via workflow metrics). Drop fs/promises fallback and --allow-fs tests to match bootstrap and add-jest-peer-dependency conventions. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…emod Look up @backstage/ui and @remixicon/react from the npm registry at run time instead of hard-coded defaults, with offline fallbacks for tests and fetch capability declared for production workflow runs. Co-authored-by: Cursor <cursoragent@cursor.com>
jssg tests run without workflow params but CI grants fetch via the codemod capability, causing flaky version-resolved metrics. Require resolveLatestVersions: true (the workflow default) before hitting npm. Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 135 out of 136 changed files in this pull request and generated 4 comments.
Comments suppressed due to low confidence (4)
codemods/misc/migrate-mui-bootstrap-to-bui/CHANGELOG.md:2
- This package CHANGELOG only contains the header. Other codemod packages in this repo include an initial version entry (e.g.
codemods/v1.51.0/migrate-nav-item-to-page/CHANGELOG.md). Adding an initial0.1.0entry makes releases and audit trails consistent.
# @backstage/migrate-mui-bootstrap-to-bui
codemods/misc/migrate-mui-icons-to-remix-icons/CHANGELOG.md:2
- This package CHANGELOG only contains the header. Other codemod packages in this repo include an initial version entry (e.g.
codemods/v1.51.0/migrate-nav-item-to-page/CHANGELOG.md). Adding an initial0.1.0entry makes releases and audit trails consistent.
codemods/misc/migrate-mui-layout-to-bui-layout/CHANGELOG.md:2 - This package CHANGELOG only contains the header. Other codemod packages in this repo include an initial version entry (e.g.
codemods/v1.51.0/migrate-nav-item-to-page/CHANGELOG.md). Adding an initial0.1.0entry makes releases and audit trails consistent.
codemods/misc/migrate-mui-styles-to-bui-css-modules/CHANGELOG.md:2 - This package CHANGELOG only contains the header. Other codemod packages in this repo include an initial version entry (e.g.
codemods/v1.51.0/migrate-nav-item-to-page/CHANGELOG.md). Adding an initial0.1.0entry makes releases and audit trails consistent.
| function transformExtensionIconSlots(rootNode: SgNode<TSX>, iconLocalNames: Set<string>, edits: Edit[]): void { | ||
| const iconPairs = rootNode.findAll({ | ||
| rule: { | ||
| kind: 'pair', | ||
| has: { |
| function hasBooleanProp(opening: SgNode<TSX>, propName: string): boolean { | ||
| return getPropAttr(opening, propName) !== null | ||
| } |
Narrow bootstrap entry detection to known app/plugin paths, restrict icon
slot wrapping to Blueprint.make config objects, treat Grid container={false}
as disabled, scope MUI dependency scans to src/ and dev/, and add initial
0.1.0 CHANGELOG entries for the new misc packages.
Co-authored-by: Cursor <cursoragent@cursor.com>
Summary
Add foundation codemods for the MUI 4 to BUI migration:
@backstage/migrate-mui-bootstrap-to-bui@backstage/migrate-mui-icons-to-remix-icons@material-ui/iconswith@remixicon/react@backstage/migrate-mui-styles-to-bui-css-modulesmakeStyles/withStylesto CSS modules@backstage/migrate-mui-layout-to-bui-layout@backstage/remove-mui-dependencies@material-ui/*deps frompackage.jsonafter source migrationAll codemods use AST-based transforms (JSSG/ast-grep). All tests pass. All workflows validate.
The cleanup codemod runs in two steps: scan
src/anddev/for remaining@material-ui/*imports, then drop packages frompackage.jsonthat are no longer referenced. Run it last, after component codemods finish.Closes #108
Closes #109
Closes #110
Closes #111