Repository navigation
CLI: Fix automigration bugs found in real monorepos - #36476
Closed
valentinpalkovic wants to merge 22 commits into
Closed
valentinpalkovic wants to merge 22 commits into
valentinpalkovic wants to merge 22 commits into
Conversation
2 of 9 tasks
Contributor
|
2 of 9 tasks
- findConfigFile now finds main.mts, main.cts and the other config extensions Storybook loads, so automigrations no longer skip those projects. - findFilesUp no longer reads every .gitignore below the project root on each call; the vitest-setup-file check took about 18 seconds in a monorepo with 130 Storybooks. - wrap-getAbsolutePath renames its dirname import when the main config already declares dirname, instead of writing a duplicate declaration.
findStorybookProjects relied on .gitignore to skip node_modules, but globby misses patterns like **/**/node_modules/. In twenty, upgrade detected four .storybook templates from @nx/storybook as projects and reported errors for them.
…orybook add storybook add printed the absolute path of the main config, which wraps across several lines in an upgrade of a monorepo.
…k log addon-mcp and angular-to-angular-vite call add(), whose Verifying, Installing and Adding lines broke up the list of fix results. They now pass a logger that sends log lines to debug; storybook add itself prints the same as before.
pnpm 12 treats `pnpm install -w` as an install of the workspace root project only, so the upgrade left every other workspace project on its old Storybook version in the lockfile. Keep `-w` for `pnpm add`, where pnpm requires it at the workspace root.
With --yes, the upgrade printed "Running all detected automigrations" but silently left out the opt-in ones it had just counted as detected. List them separately with how to apply one.
… dir When no .storybook directory is found, upgrade asked for its path even with --yes, and did so while the detection spinner was still running, so an unattended run hung. Stop the spinner before prompting, and with --yes fail with a pointer to --config-dir.
setupAddonInConfig wrote recast's output as is, so adding an addon printed the new addons entry with recast's default indentation, for example 8 spaces in a tab-indented file. Run the project's formatter before writing, as the automigrations do.
ConfigFile prepended every new import, so a main config that starts with a license comment got the imports above it (seen in elastic/eui). When the first statement has a leading comment, add new imports below the existing ones, or take the comment over when the file has no imports.
configureFlatConfig reprinted the whole config with recast, so adding the plugin re-indented every object in grommet's eslint.config.mjs (219 changed lines) and wrote a double-quoted import into a single-quoted file. Insert the import after the existing imports and the spread after the last array or argument item as text, in the file's quote style and layout, and run the project's formatter on the result.
Clack redraws a whole task log on every update, so a log taller than the terminal repeats in the scrollback: the automigration detection over dxos' 130 Storybooks rewrote each line about 125 times, and its package.json list showed twice. Show the latest ten lines by default and retain the rest, so a log shown on error is still complete.
…config The check logged a warning for every such Storybook, 130 times in dxos, for a fix that simply does not apply there.
Upgrading to a prerelease took each satellite addon's `next` version, which for @storybook/addon-svelte-csf is 5.0.0-next.30 while `latest` is 5.1.4, so podman-desktop went from 5.1.2 down to a prerelease. Take whichever of the two tags is newer.
… dependencies upgrade-storybook-related-dependencies moved @nx/storybook from 22 to 23 while every other @nx package stayed on 22 (spartan), leaving unmet peers and a version that still does not support Storybook 11. A package whose scope has installed siblings that are not upgraded now stays within its major.
…cies Upgrading a project whose Storybook packages come from a pnpm catalog replaced every `catalog:` reference in package.json with a pinned version and left the catalog in pnpm-workspace.yaml on the old version (calcite). Update the catalog entry, keeping its range modifier and the file's comments, and leave the `catalog:` reference alone.
…the file Parsing a config whose default export is not an object literal, such as `export default createConfig()`, printed a warning without saying which file. The upgrade over dxos' 131 Storybooks printed about 1,250 such lines. A later mutation of that config already fails with its own diagnostic, so log the parse notice at debug level and name the file.
wrap-getAbsolutePath wraps core.builder, so the builder reaches Storybook as a directory such as .../@storybook/builder-vite, and importing a directory fails in ES modules (calcite's build: ERR_UNSUPPORTED_DIR_IMPORT). Resolve a package directory to its entry point before importing it.
… import Removing setProjectAnnotations also removes imports that become unused, and when that was the file's first statement its leading comment went with it (dxos' tools/storybook-react/.storybook/vitest.setup.ts lost its copyright header). Move that comment onto the new first statement.
The optional addon-mcp migration failed on every main config that spreads a shared config or exports a factory call: 129 of dxos' 130 Storybooks and one of gutenberg's two ended with a failed migration. Try the edit in memory during the check and skip such configs.
`storybook automigrate --yes` accepted every detected fix, including opt-in framework switches such as nextjs-to-nextjs-vite, while `upgrade --yes` leaves them out. Apply the same rule: with --yes, an opt-in fix runs only when the user named it, as in `storybook automigrate nextjs-to-nextjs-vite --yes`.
storybook add's edit of vue-dsfr's main.ts (no Prettier config, only an .editorconfig) rewrote 79 lines with Prettier's default quotes and semicolons, and gutenberg's lost wp-prettier's paren spacing on 66 lines.
Clack counts a task log line's terminal rows by its length including color codes and erases that many rows on the next update. Colored lines close to the terminal width therefore erased lines printed before the log: with the manual steps of twenty's failing vitest-setup-file shown in the task log, the list of opt-in automigrations above it vanished. Drop the colors of a line only when they push it onto an extra row.
valentinpalkovic
force-pushed
the
fix/automigrate-main-mts-and-dirname
branch
from
October 1, 2026 13:43
ff880f8 to
1fad805
Compare
This was referenced Oct 1, 2026
This was referenced Oct 1, 2026
Contributor
Author
|
Split into one PR per fix, so each can be reviewed and merged on its own:
Two fixes from this PR are dropped because they already landed on |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #
What I did
Running
storybook upgradefrom a local registry against ten open-source projects on Storybook 10 (calcite-design-system, vue-dsfr, pmndrs/docs, podman-desktop, eui, grommet, twenty, gutenberg, spartan, dxos) turned up these bugs onnext.Every one of them reproduced with and without #36462, so they are fixed here rather than there.
Each one is small, but together they make an upgrade slow, incomplete, or broken in exactly the projects with many Storybooks.
vitest-setup-filecheck reads every.gitignorein the repo, once per projectfindConfigFiledoes not knowmain.mts/main.ctsmain.mtsmainsilently skip those projectswrap-getAbsolutePathimportsdirnamenext to an existingconst dirnametwenty-ui,twenty-front-component-renderer)main.tsno longer parsesupgradefinds.storybookdirectories insidenode_modules@nx/storybook)storybook addprogress lines print inside the automigration task log, with an absolute pathaddon-mcp)pnpm install -wafter the upgradebuildfails on the frozen lockfilecatalog:dependency is upgraded in package.jsoncatalog:references are replaced by pinned versions, the catalog stays on 10.3.6nexttag@storybook/addon-svelte-csfgoes from 5.1.2 down to 5.0.0-next.30upgrade-storybook-related-dependenciescrosses a major inside a package family@nx/storybook22 → 23 while every other@nx/*package stays on 22core.builderwrapped bywrap-getAbsolutePathis imported as a directorystorybook buildfails withERR_UNSUPPORTED_DIR_IMPORTupgrade --yesasks for a config directory when there is no.storybookstorybook/)automigrate --yesruns opt-in fixes,upgrade --yessilently leaves them outstorybook addwrites recast's output,eslintPluginreprints the whole config, imports go above a license headeraddon-mcpfails on a main config thatstorybook addcannot edit, detection only counts fixes that apply to every project, a failed fix shows no reasonvitest-setup-file's manual steps only reach the debug logvitest-setup-fileremoves the first import together with its leading comment1.
findFilesUpscans every.gitignorefor a top-level file lookupfindFilesUplooks forvitest.config.*andvite.config.*in each directory from the project up to the root, withglobby({ gitignore: true }).The patterns only match files directly in each directory, but
gitignore: truemakes globby read every.gitignorebelow it first.In a monorepo the
vitest-setup-filecheck runs this from the workspace root for every project.Detection plus apply of the automigrations on dxos (131 Storybooks, of which 130 load: 131
main.*, 127preview.*, 3manager.*, and 1,310 story files), median of 3 runs, before and after this PR:nextpackages/plugins/plugin-github/.gitignore)The CPU profile of the
nextrun attributes 18.1 s of the 18.2 s detection tofindFilesUpinside thevitest-setup-filecheck.2.
findConfigFilemisses.mtsand.ctsconfigsfindConfigFilekept its own extension list (ts, js, tsx, jsx, mjs, cjs), while Storybook loads configs with the sharedstorybookConfigExtensions, which also includes.mts,.cts,.mtsx, and.ctsx.For a
main.mtsprojectgetStorybookDatareturns nomainConfigPath, so every automigration that editsmaintreats the project as having none.findConfigFilenow uses the shared list, which also makes its lookup order match the loader's.3.
wrap-getAbsolutePathwrites a duplicatedirnameThe fix always imported
dirnamefromnode:path, even when the main config declares its own.This is what
nextwrites fortwenty-ui, captured from a real run:The fix now imports under an alias when the name is taken, and the generated helper calls that alias:
After this PR, all three migrated
main.tsfiles in twenty parse again.4. Project discovery relies on .gitignore to skip
node_modulesfindStorybookProjectsglobs for**/.storybookwithgitignore: trueand nothing else.twenty ignores
node_moduleswith the pattern**/**/node_modules/, which git honors but globby does not, soupgradedetected the.storybooktemplates that@nx/storybookships:Discovery now always ignores
**/node_modules/**.upgrade --dry-runon twenty now reports3 projects detected.5.
storybook addoutput inside the automigration logaddon-mcpandangular-to-angular-vitecalladd(), which loggedVerifying,Installing, andAdding '@storybook/addon-mcp' to the "addons" field in /absolute/path/main.tsbetween the per-fix results.Those automigrations now pass a logger that sends these lines to debug, so the result list stays a clean column of ✔ and ✕.
A standalone
storybook addprints the same lines as before, with the main config path now relative to the working directory.6. pnpm 12 installs only the workspace root
The upgrade ran
pnpm install -wat a workspace root.pnpm 12 treats that as an install of the root project only, so no other workspace project is re-resolved.
A two-package workspace shows the difference when the child's dependency changes from
6.0.0to7.0.0:installnow runs without-w;pnpm addkeeps it, since pnpm requires it there.On podman-desktop the upgrade now logs
Scope: all 26 workspace projects, andstorybook build --testpasses the frozen-lockfile check.7. Dependency upgrades that went the wrong way
pnpm-workspace.yaml, keeping the entry's range modifier and the file's comments, and keeps itscatalog:reference.latestandnexttags, so podman-desktop's@storybook/addon-svelte-csfgoes to 5.1.4.@nx/storybookgoes to 22.7.12 instead of 23.8. A builder given as its package directory
wrap-getAbsolutePathwrapscore.builder, so the builder reaches Storybook as…/node_modules/@storybook/builder-vite, and ES modules cannot import a directory.Storybook now resolves a package directory to its entry point before importing it.
9.
--yesruns that need a human, or skip fixes without saying soWith no
.storybookdirectory,upgrade --yesnow stops the spinner and exits:upgrade --yesnow names the opt-in fixes it leaves out:storybook automigrate --yesapplies the same rule and runs an opt-in fix, such as a framework switch, only when the user names it.10. Edits that restyled whole files
storybook addwrote recast's output as is, which collapsed grommet's multi-lineaddonsarray into one line and indented spartan's tab-indentedmain.tswith 8 spaces. It now formats its edit with the Prettier the project installed and the project's Prettier config, and leaves it as printed when the project has none. It does not use the sharedformatFileContent, whose fallback to Prettier's defaults for an.editorconfigwould restyle a whole file that was only edited.eslint.config.mjschanges by 3 lines instead of 219.vitest-setup-filekeeps that comment when it removes the first import.11. Terminal output in large monorepos
On dxos (131 Storybooks: 131
main.*, 127preview.*, 3manager.*, 702 story files) the upgrade printed 3,606,836 bytes.Four changes bring it to 220,913 bytes:
A task log line whose color codes would push it onto an extra terminal row loses its colors, because clack counts rows by the raw length and erased the lines printed above the log.
A failed fix now shows its message in the project's task log, so
vitest-setup-file's manual steps reach the terminal.addon-mcpskips a main config thatstorybook addcannot edit instead of failing on 129 of dxos' 130 projects.Checklist for Contributors
Testing
The changes in this PR are covered in the following automated tests:
Manual testing
Caution
This section is mandatory for all contributions. If you believe no manual test is necessary, please state so explicitly. Thanks!
yarn install --mode=skip-build).npx storybook@<canary> automigrate wrap-getAbsolutePath --config-dir packages/twenty-ui/.storybook --yes.Confirm
packages/twenty-ui/.storybook/main.tsimports{ dirname as pathDirname } from 'node:path'and thatnpx storybook dev --config-dir packages/twenty-ui/.storybookstill starts..storybook/main.mts, runnpx storybook@<canary> automigrate --yesand confirm migrations that editmain(for exampleenable-experimental-review --yes) now updatemain.mts.npx storybook@<canary> upgrade --yesand confirm automigration detection no longer stalls on thevitest-setup-filecheck.npx storybook@<canary> upgrade --dry-runand confirm it reports3 projects detected, with no paths insidenode_modules.npx storybook@<canary> upgrade --yesand confirm each project's list shows only ✔ and ✕ lines, withoutVerifyingorAdding ... to the "addons" fieldlines.storybook/), install, and runnpx storybook@<canary> upgrade --yes.Confirm it exits right away with the
Pass --config-dir <path>hint instead of waiting for input.Run it again with
--config-dir storybookand confirmeslint.config.mjsgains only the plugin import and one spread, and thatstorybook/main.jskeeps its multi-lineaddonsarray.npx storybook@<canary> upgrade --yes.Confirm
pnpm-lock.yamlnow resolves every workspace package to the new Storybook version, and that@storybook/addon-svelte-csfis not downgraded to anextprerelease.npx storybook@<canary> upgrade --yes.Confirm the Storybook entries of the catalog in
pnpm-workspace.yamlare upgraded andpackage.jsonkeeps itscatalog:references.vitest-setup-file, confirm the terminal shows the fix's manual steps under its ✕ line.Documentation
MIGRATION.MD
Checklist for Maintainers
When this PR is ready for testing, make sure to add
ci:normal,ci:mergedorci:dailyGH label to it to run a specific set of sandboxes. The particular set of sandboxes can be found incode/lib/cli-storybook/src/sandbox-templates.tsDeclare whether manual QA will be needed for this PR during the next release, through
qa:neededorqa:skipMake sure this PR contains one of the labels below:
Available labels
bug: Internal changes that fixes incorrect behavior.maintenance: User-facing maintenance tasks.dependencies: Upgrading (sometimes downgrading) dependencies.build: Internal-facing build tooling & test updates. Will not show up in release changelog.cleanup: Minor cleanup style change. Will not show up in release changelog.documentation: Documentation only changes. Will not show up in release changelog.feature request: Introducing a new feature.BREAKING CHANGE: Changes that break compatibility in some way with current major version.other: Changes that don't fit in the above categories.🤖 Generated with Claude Code