Skip to content

feat(v1.55.0): add remove-bui-anchor-render-props codemod - #165

Merged
schultzp2020 merged 5 commits into
mainfrom
feat/v1.55.0/remove-bui-anchor-render-props
Oct 13, 2026
Merged

schultzp2020 merged 5 commits into
mainfrom
feat/v1.55.0/remove-bui-anchor-render-props

Conversation

@schultzp2020

@schultzp2020 schultzp2020 commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

Summary

-<Link href="/catalog" render={<RouterLink render={<a />} />}>Catalog</Link>
+<Link href="/catalog" /* TODO(backstage-codemod): review render migration manually (custom render prop or spread props) */ render={<RouterLink render={<a />} />}>Catalog</Link>

-<Link href="/catalog" render={(<a />)}>Catalog</Link>
+<Link href="/catalog">Catalog</Link>

Follow-up for #151 on top of f2476ae:

  • P1: stop recursive opening.findAll({ kind: 'jsx_attribute' }) scans. Only inspect direct opening attributes so nested render props inside custom render trees are untouched.
  • P2: treat parenthesized bare anchors (render={(<a />)}) as safe anchor render and remove them.
  • Preserve existing semantic import-binding and shadowing protections/fixtures.

Closes #151.

Evidence

Red/green fixtures

  • Added tests/nested-render-prop-todo/* (red on previous head): proved nested <RouterLink render={<a />} /> was incorrectly counted as render-prop-removed and mutated.
  • Added tests/parenthesized-anchor-safe/* (red on previous head): proved render={(<a />)} incorrectly emitted TODO.
  • After fix both fixtures pass; full package fixture set now 13/13.

Validation @ HEAD 8553f3c

  • yarn workspace @backstage/remove-bui-anchor-render-props test ✅ (13 tests + workflow validate)
  • yarn format:check ✅
  • yarn lint ✅
  • yarn test ✅
  • yarn check:changed ✅

Performance audit (JSSG guidance: no-op baseline vs real, same workflow entry path)

Corpus: synthetic mostly-inert TSX tree (1545 files: 1500 inert, 30 @backstage/ui no-render, 10 safe renders, 5 custom nested renders).

Ran codemod workflow run -w workflow.yaml --target <corpus> --dry-run --no-interactive --allow-dirty and equivalent no-op workflow 3x each:

  • no-op ms: 1931, 1900, 2006 (median 1931)
  • real ms: 1905, 1896, 1914 (median 1905)
  • median slowdown ratio: 0.987x (within noise; no substantive slowdown)

Idempotence / edit evidence on apply copy:

  • apply run metrics: render-prop-removed(Link)=10, todo-manual-review(Link, custom-render-prop)=5
  • content checks: 10/10 safe render files removed render; 5/5 custom files gained TODO and preserved nested render={<RouterLink render={<a />} />}
  • rerun dry-run produced no metrics (idempotent)

Approved clean-source QA (read-only)

  • Local workflow dry-run on Backstage snapshot 0863f0349c63fa7475b89aed71b6fb8214791394: rc=0, no diff/TODO candidates emitted; snapshot remained clean.
  • Local workflow dry-run on clean detached community-plugins snapshot 4c760a005dd582df1a61aec39ae50ad565f6dbbc: rc=0, no diff/TODO candidates emitted; snapshot remained clean. Original dirty checkout untouched.
  • No real-source positive candidates were found in these snapshots; positive behavior is evidenced by the 13 fixtures and 1545-file synthetic benchmark above. CLI does not emit an explicit match counter for these no-op dry-runs.

Full-suite fixture side effect (post-#164 integration)

Merge Danger

Door: two-way

Codemod package can be reverted before publication; migration output still requires user review of TODO cases.

Blast Radius: BUI link render prop migration

Changes are constrained to direct opening attributes on imported target components; nested custom-render trees are now explicitly protected from accidental recursive attribute edits.

@schultzp2020
schultzp2020 marked this pull request as draft October 12, 2026 21:03
@schultzp2020

Copy link
Copy Markdown
Contributor Author

Review-blocked: imported component provenance currently matches JSX names by text, so a local Link or namespace alias shadowing the @backstage/ui import could have its unrelated render prop removed. Adding shadowed-binding fixtures and binding-aware guard; keep draft until corrected diff receives fresh review.

@schultzp2020
schultzp2020 marked this pull request as ready for review October 12, 2026 21:39
@schultzp2020
schultzp2020 merged commit 53b1076 into main Oct 13, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: Backstage 1.55.0 migration - Remove obsolete BUI anchor render props

1 participant