Skip to content

feat(gamut-codemods): rename packages and replace gamut-kit in scope-swap - #39

Merged
dreamwasp merged 12 commits into
mainfrom
cass-gmt-1790-scope-rename
Oct 28, 2026
Merged

dreamwasp merged 12 commits into
mainfrom
cass-gmt-1790-scope-rename

Conversation

@dreamwasp

@dreamwasp dreamwasp commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Overview

Breaking change: every @codecademy/gamut* package moves to @skillsoft/*, and @codecademy/gamut-kit is removed with no replacement.

Stack (split from #28, merge in order):

  1. feat(gamut-codemods): add the codemods CLI and an empty scope-swap preset #38 Scaffold, based on main
  2. feat(gamut-codemods): rename packages and replace gamut-kit in scope-swap #39 Package scope rename and gamut-kit removal, based on feat(gamut-codemods): add the codemods CLI and an empty scope-swap preset #38 👈 this PR
  3. feat(gamut-codemods): move Video imports and add Markdown video overrides #40 Video and Markdown, based on feat(gamut-codemods): rename packages and replace gamut-kit in scope-swap #39
  4. feat(gamut)!: promote deep imports to the root, renaming Menu and SelectDropdown elements #41 Deep imports and Menu/SelectDropdown renames, based on feat(gamut-codemods): rename packages and replace gamut-kit in scope-swap #39
  5. feat(gamut-codemods): rename the ESLint plugin prefix in scope-swap #42 ESLint plugin prefix, based on feat(gamut-codemods): rename packages and replace gamut-kit in scope-swap #39
  6. feat(gamut-codemods): warn about esmExternals: false in next.config #43 Next.js esmExternals warning, based on feat(gamut-codemods): rename packages and replace gamut-kit in scope-swap #39
  7. build(deps): make @skillsoft packages easier to install #44 Simpler dependencies (independent), based on main
  8. feat(gamut-agent-tools): add the gamut-scope-swap skill #45 gamut-scope-swap skill (open last), based on feat(gamut-codemods): rename packages and replace gamut-kit in scope-swap #39, includes feat(gamut-codemods): move Video imports and add Markdown video overrides #40–feat(gamut-codemods): warn about esmExternals: false in next.config #43
  • scope-rename swaps the old names in every module position: imports, exports, require, import(), jest.mock/vi.mock, declare module, and import('x').T. It also covers exact package strings like transpilePackages, warning once per file, and package names in comments. It runs last, so every other migration matches on @codecademy names.
  • package-json renames 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-kit removal:
    • package-json expands it into the packages it bundled.
    • mf-shared does the same in Module Federation shared config. That makes Gamut a real singleton across host and remotes, and the checklist says to deploy them together.
  • mdx-imports runs the source migrations over .mdx ESM blocks.
  • yarnrc renames or drops old names in .yarnrc.yml lists.

Video, deep imports, ESLint, and Next.js are separate PRs stacked on this one.

PR Checklist

  • Related to designs: N/A
  • Related to JIRA ticket: GMT-1790
  • Changeset added
  • I have run this code to verify it works
  • This PR includes unit tests for the code change
  • This PR includes testing instructions for the code change
  • Package previews from this PR are passing end-to-end tests in all relevant consuming repositories

Testing Instructions

  1. 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.

  2. Build and run on a throwaway repo:

    yarn nx build gamut-codemods
    mkdir -p /tmp/swap && cd /tmp/swap && git init -q
    printf "import { Box } from '@codecademy/gamut';\njest.mock('@codecademy/gamut-styles');\n" > a.tsx
    printf "import { Box } from '@codecademy/gamut';\n\n# Doc\n" > doc.mdx
    echo '{ "dependencies": { "@codecademy/gamut": "^73.0.0", "@codecademy/gamut-kit": "^73.0.0" } }' > package.json
    echo "export const shared = { '@codecademy/gamut-kit': { singleton: true } };" > mf.ts
    git add -A && git commit -qm init
    node <repo>/packages/gamut-codemods/dist/bin.js scope-swap .
  3. Check git diff:

    • imports, mocks, and doc.mdx use @skillsoft/*
    • package.json lists each package that gamut-kit bundled, with no gamut-kit
    • mf.ts shares each package individually
  4. Check that the next steps include the gamut-kit and Module Federation items.

  5. Rerun with --force. Nothing should change.

PR Links and Envs

Repository PR Link
Mono N/A

🤖 Generated with Claude Code

dreamwasp and others added 2 commits October 20, 2026 10:07
…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>
dreamwasp and others added 4 commits October 20, 2026 11:10
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>
@dreamwasp
dreamwasp marked this pull request as ready for review October 20, 2026 15:37
@dreamwasp
dreamwasp requested a review from a team as a code owner October 20, 2026 15:37

@LinKCoding LinKCoding left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

FWIW, the 2nd run with --force omitted the first 2 steps that mentioned gamut-kit and Module Federation:

  1. 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.
  1. 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

Comment on lines +81 to +90
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',
},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Base automatically changed from cass-gmt-1790-scaffold to main October 28, 2026 12:29
dreamwasp and others added 2 commits October 28, 2026 08:41
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

codecov Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.97436% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 95.81%. Comparing base (fa7d3c4) to head (030ec26).
⚠️ Report is 5 commits behind head on main.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
...s/gamut-codemods/src/migrations/mf-shared/index.ts 95.83% 2 Missing ⚠️
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     
Flag Coverage Δ
main ?
pull-request 95.81% <98.97%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@pkg-pr-new

pkg-pr-new Bot commented Oct 28, 2026

Copy link
Copy Markdown

Open in StackBlitz

@skillsoft/eslint-plugin-gamut

npm i https://pkg.pr.new/Codecademy/skillsoft-gamut/@skillsoft/eslint-plugin-gamut@39
yarn add https://pkg.pr.new/Codecademy/skillsoft-gamut/@skillsoft/eslint-plugin-gamut@39.tgz

@skillsoft/gamut

npm i https://pkg.pr.new/Codecademy/skillsoft-gamut/@skillsoft/gamut@39
yarn add https://pkg.pr.new/Codecademy/skillsoft-gamut/@skillsoft/gamut@39.tgz

@skillsoft/gamut-agent-tools

npm i https://pkg.pr.new/Codecademy/skillsoft-gamut/@skillsoft/gamut-agent-tools@39
yarn add https://pkg.pr.new/Codecademy/skillsoft-gamut/@skillsoft/gamut-agent-tools@39.tgz

@skillsoft/gamut-codemods

npm i https://pkg.pr.new/Codecademy/skillsoft-gamut/@skillsoft/gamut-codemods@39
yarn add https://pkg.pr.new/Codecademy/skillsoft-gamut/@skillsoft/gamut-codemods@39.tgz

@skillsoft/gamut-icons

npm i https://pkg.pr.new/Codecademy/skillsoft-gamut/@skillsoft/gamut-icons@39
yarn add https://pkg.pr.new/Codecademy/skillsoft-gamut/@skillsoft/gamut-icons@39.tgz

@skillsoft/gamut-illustrations

npm i https://pkg.pr.new/Codecademy/skillsoft-gamut/@skillsoft/gamut-illustrations@39
yarn add https://pkg.pr.new/Codecademy/skillsoft-gamut/@skillsoft/gamut-illustrations@39.tgz

@skillsoft/gamut-patterns

npm i https://pkg.pr.new/Codecademy/skillsoft-gamut/@skillsoft/gamut-patterns@39
yarn add https://pkg.pr.new/Codecademy/skillsoft-gamut/@skillsoft/gamut-patterns@39.tgz

@skillsoft/gamut-styles

npm i https://pkg.pr.new/Codecademy/skillsoft-gamut/@skillsoft/gamut-styles@39
yarn add https://pkg.pr.new/Codecademy/skillsoft-gamut/@skillsoft/gamut-styles@39.tgz

@skillsoft/gamut-tests

npm i https://pkg.pr.new/Codecademy/skillsoft-gamut/@skillsoft/gamut-tests@39
yarn add https://pkg.pr.new/Codecademy/skillsoft-gamut/@skillsoft/gamut-tests@39.tgz

@skillsoft/variance

npm i https://pkg.pr.new/Codecademy/skillsoft-gamut/@skillsoft/variance@39
yarn add https://pkg.pr.new/Codecademy/skillsoft-gamut/@skillsoft/variance@39.tgz

commit: 030ec26

@dreamwasp
dreamwasp merged commit 5de7194 into main Oct 28, 2026
14 checks passed
@dreamwasp
dreamwasp deleted the cass-gmt-1790-scope-rename branch October 28, 2026 12:47
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.

2 participants