Repository navigation
feat(gamut-codemods): rename packages and replace gamut-kit in scope-swap - #39
Conversation
…eset Adds @skillsoft/gamut-codemods: the CLI (clean-tree guard, --dry, --only, --no-report, --force), the runner for ast, splice, and file migrations, the shared helpers (module-string finder, leftovers report, version-range checks, flat ESLint config detection), the preset registry, and the fixture harness. The scope-swap preset has its package map but no migrations yet, so a run only reports the lines that still name an old package. Each breaking change lands its migration in its own PR. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…swap scope-rename swaps @Codecademy/gamut* and eslint-plugin-gamut for their @SkillSoft names in every module position and in comments. package-json, mdx-imports, and yarnrc cover dependencies, MDX ESM blocks, and .yarnrc.yml lists. @codecademy/gamut-kit has no replacement, so package-json and mf-shared expand it into the packages it bundled. In Module Federation config that makes Gamut a real singleton, which the checklist calls out. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CodeQL read `migration.match(file)` in cli.ts as String.prototype.match on a command-line argument and flagged js/regex-injection. Nothing builds a regex from the path; the method just had the same name. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…migrations Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The package-json warning already names each range that's newer than the fork point, so the extra next step only repeated it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
LinKCoding
left a comment
There was a problem hiding this comment.
LGTM!
FWIW, the 2nd run with --force omitted the first 2 steps that mentioned gamut-kit and Module Federation:
- gamut-kit is gone. Delete anything that reads it for versions, such as a sync-gamut-deps script. @skillsoft/gamut-styles has @emotion/cache and stylis peer dependencies, so add them if yarn warns that they aren't provided.
- Module Federation shared config changed. Gamut is now a real singleton: run the host and every remote together, and update the remotes' shared config to match.
Tgat seems intentional since after the changes were made from the first run, the 2nd run doesn't know about any files that referenced gamut-kit but flagging just in case.
Left a Q, but the 🤖 seems to think it's ok
| sourceVersions: { | ||
| '@codecademy/gamut': '73.6.1', | ||
| '@codecademy/gamut-styles': '21.2.0', | ||
| '@codecademy/gamut-icons': '10.2.0', | ||
| '@codecademy/gamut-illustrations': '1.1.0', | ||
| '@codecademy/gamut-patterns': '1.1.0', | ||
| '@codecademy/gamut-tests': '7.1.0', | ||
| '@codecademy/variance': '1.1.0', | ||
| 'eslint-plugin-gamut': '3.1.0', | ||
| }, |
There was a problem hiding this comment.
are these just the latest versions? is there any worry about other repos having more dated versions?
after running it through with the robot:
A user gets no warning when the lowest version their range allows is at or below the sourceVersions entry. That's 73.6.1 for @codecademy/gamut, for example. The warning fires only when that minimum is strictly higher. The check is isNewerThan in src/lib/manifest.ts:91, applied to the range from src/migrations/package-json/index.ts:69.
Using @codecademy/gamut (ceiling 73.6.1) as the example:
┌────────────────────────────┬───────────────┬─────────────────────────────────┐
│ Consumer's range │ Minimum │ Warning? │
├────────────────────────────┼───────────────┼─────────────────────────────────┤
│ 73.6.1, ^73.6.1 │ 73.6.1 │ No, since it equals the ceiling │
├────────────────────────────┼───────────────┼─────────────────────────────────┤
│ ^73.0.0, ~73.5.0, >=70.0.0 │ below ceiling │ No │
├────────────────────────────┼───────────────┼─────────────────────────────────┤
│ ^73.7.0 │ 73.7.0 │ Yes │
├────────────────────────────┼───────────────┼─────────────────────────────────┤
│ ^74.0.0 │ 74.0.0 │ Yes │
└────────────────────────────┴───────────────┴─────────────────────────────────┘
Some cases never warn, whatever the range says:
- Ranges the parser can't read. minVersion returns null for , latest, workspace:, URLs and tarballs, file: paths, and compound ranges like >=1 <2 or 1.x. isNewerThan then returns false. That includes the preview-tarball setups the file's comment mentions.
- Prerelease tags. ^74.0.0-beta.1 is read as 74.0.0. A bare 73.6.1-beta counts as 73.6.1, so it wouldn't warn.
- Packages with no sourceVersions entry. covered is undefined, so the check is skipped. Every package in manifest.packages has an entry today.
- A package.json where the old name isn't present. Only packages being renamed are checked, so a consumer already on @skillsoft/* is never warned.
A caret range also only looks at its floor. ^73.0.0 could resolve to 73.9.0 at install time, but the lockfile version never gets checked. A consumer whose lockfile has 73.9.0 and whose package.json says ^73.0.0 gets no warning, even though their code may use newer upstream APIs.
If the lockfile gap matters, the fix is to read the installed version from node_modules or the lockfile instead of relying on the declared range. I haven't looked at whether the migration has access to either.
Keep this branch's gamut-codemods version for the files main's squashed scaffold (#38) conflicted with. Main's only new changes there, the match -> appliesTo rename, are already on this branch. Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #39 +/- ##
==========================================
+ Coverage 88.81% 95.81% +7.00%
==========================================
Files 421 16 -405
Lines 7302 526 -6776
Branches 2319 149 -2170
==========================================
- Hits 6485 504 -5981
+ Misses 807 22 -785
+ Partials 10 0 -10
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
@skillsoft/eslint-plugin-gamut
@skillsoft/gamut
@skillsoft/gamut-agent-tools
@skillsoft/gamut-codemods
@skillsoft/gamut-icons
@skillsoft/gamut-illustrations
@skillsoft/gamut-patterns
@skillsoft/gamut-styles
@skillsoft/gamut-tests
@skillsoft/variance
commit: |
Overview
Breaking change: every
@codecademy/gamut*package moves to@skillsoft/*, and@codecademy/gamut-kitis removed with no replacement.Stack (split from #28, merge in order):
mainmainscope-renameswaps the old names in every module position: imports, exports,require,import(),jest.mock/vi.mock,declare module, andimport('x').T. It also covers exact package strings liketranspilePackages, warning once per file, and package names in comments. It runs last, so every other migration matches on@codecademynames.package-jsonrenames dependencies and sets their versions. It keeps any@skillsoft/*entry that's already listed (such as a preview URL) and keeps*peer ranges. It warns when a range is newer than the upstream release the fork matches (sourceVersions).gamut-kitremoval:package-jsonexpands it into the packages it bundled.mf-shareddoes the same in Module Federationsharedconfig. That makes Gamut a real singleton across host and remotes, and the checklist says to deploy them together.mdx-importsruns the source migrations over.mdxESM blocks.yarnrcrenames or drops old names in.yarnrc.ymllists.Video, deep imports, ESLint, and Next.js are separate PRs stacked on this one.
PR Checklist
Testing Instructions
yarn nx test gamut-codemods. Expect 65 tests to pass. That includes the fixtures for each migration and an end-to-end fixture that runs the whole preset.Build and run on a throwaway repo:
Check
git diff:doc.mdxuse@skillsoft/*package.jsonlists each package thatgamut-kitbundled, with nogamut-kitmf.tsshares each package individuallyCheck that the next steps include the
gamut-kitand Module Federation items.Rerun with
--force. Nothing should change.PR Links and Envs
🤖 Generated with Claude Code