Skip to content

Codemod: Fix csf-2-to-3 failing due to quoted filenames#33646

Merged
kasperpeulen merged 2 commits into
nextfrom
kasper/fix-csf-factories-codemod-33639
Jan 28, 2026
Merged

Codemod: Fix csf-2-to-3 failing due to quoted filenames#33646
kasperpeulen merged 2 commits into
nextfrom
kasper/fix-csf-factories-codemod-33639

Conversation

@kasperpeulen
Copy link
Copy Markdown
Member

@kasperpeulen kasperpeulen commented Jan 26, 2026

Closes #33639

What I did

Fixed the csf-2-to-3 codemod silently failing with "file does not exist" errors.

The Bug

When running npx storybook migrate csf-2-to-3 --glob "**/*.stories.tsx", files were not being transformed and jscodeshift reported files as not existing.

Root Cause

The bug was introduced by an incomplete refactor. Here's the history:

Date PR Author Change Result
Jul 2023 #23498 Norbert Created file with shell: true, no quotes ❌ Broke on filenames with ()
Mar 2024 #26430 Yuki Added quotes to fix shell escaping ✅ Fixed
Nov 2025 #32984 Valentin Removed shell: true for security, but left quotes ❌ Broke everything

Why quotes were needed with shell: true:

# Without quotes, parentheses cause shell syntax errors:
$ bash -c 'echo foo(bar).tsx'
bash: syntax error near unexpected token `('

# With quotes, shell treats it as literal:
$ bash -c 'echo "foo(bar).tsx"'
foo(bar).tsx

Why quotes break without shell: true:

When using spawnSync with an array of arguments (no shell), Node.js passes each element directly to the child process. The quotes become literal characters in the filename:

// With shell: true - quotes are interpreted by shell
spawnSync('node', ['jscodeshift', '"file.tsx"'], { shell: true })
// → jscodeshift receives: file.tsx ✅

// Without shell - quotes are literal
spawnSync('node', ['jscodeshift', '"file.tsx"'])
// → jscodeshift receives: "file.tsx" (with quotes!) ❌
// → Error: file "file.tsx" does not exist

The Fix

Simply remove the quotes since spawnSync with an array handles argument escaping automatically:

// Before (broken):
...files.map((file) => `"${file}"`),

// After (fixed):
...files,

Checklist for Contributors

Testing

The changes in this PR are covered in the following automated tests:

  • stories
  • unit tests
  • integration tests
  • end-to-end tests

Manual testing

Caution

This section is mandatory for all contributions. If you believe no manual test is necessary, please state so explicitly. Thanks!

Tested in the green repo (from the original issue):

# All these patterns now work:
npx storybook migrate csf-2-to-3 --glob "libs/react-charts/src/lib/chart.stories.tsx"  # Direct path
npx storybook migrate csf-2-to-3 --glob "libs/react-charts/src/lib/*.stories.tsx"      # Wildcard
npx storybook migrate csf-2-to-3 --glob "libs/**/*.stories.tsx"                        # Recursive
npx storybook migrate csf-2-to-3 --glob "/absolute/path/to/file.stories.tsx"           # Absolute
npx storybook migrate csf-2-to-3 --glob "libs/my components/src/file.stories.tsx"      # Spaces in path

Documentation

  • Add or update documentation reflecting your changes
  • If you are deprecating/removing a feature, make sure to update
    MIGRATION.MD

Checklist for Maintainers

  • When this PR is ready for testing, make sure to add ci:normal, ci:merged or ci:daily GH label to it to run a specific set of sandboxes. The particular set of sandboxes can be found in code/lib/cli-storybook/src/sandbox-templates.ts

  • Make 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 doesn't fit in the above categories.

🦋 Canary release

This PR does not have a canary release associated. You can request a canary release of this pull request by mentioning the @storybookjs/core team here.

core team members can create a canary release here or locally with gh workflow run --repo storybookjs/storybook publish.yml --field pr=<PR_NUMBER>

Summary by CodeRabbit

  • Tests
    • Added a comprehensive test suite for the CSF2→CSF3 codemod, covering template-to-export conversions, filenames with spaces, and various glob matching scenarios.
  • Bug Fixes
    • Improved how file paths are passed to the codemod tool to ensure correct processing across different patterns and nested files.

✏️ Tip: You can customize this high-level summary in your review settings.

@nx-cloud
Copy link
Copy Markdown

nx-cloud Bot commented Jan 26, 2026

View your CI Pipeline Execution ↗ for commit aec048e

Command Status Duration Result
nx run-many -t compile,check,knip,test,pretty-d... ❌ Failed 8m 19s View ↗

☁️ Nx Cloud last updated this comment at 2026-01-27 09:08:21 UTC

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jan 26, 2026

📝 Walkthrough

Walkthrough

Adds Vitest tests for runCodemod exercising the CSF2-to-CSF3 transform and adjusts jscodeshift invocation to pass raw file paths (removes per-file quotation marks).

Changes

Cohort / File(s) Summary
CSF2-to-CSF3 tests
code/lib/codemod/src/index.test.ts
New Vitest test suite that creates temporary fixtures, writes CSF2 stories, runs runCodemod with various glob patterns, and asserts CSF2 Template.bind({}) is converted to CSF3 export objects. Tests cover filenames with spaces, multiple-file globs, and recursive globs.
Codemod invocation change
code/lib/codemod/src/index.ts
Modified how jscodeshift is invoked: removed per-file quotation marks and now passes raw file path arguments to the transformer. No other behavior or public API changes.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

✨ Finishing touches
  • 📝 Generate docstrings

Comment @coderabbitai help to get the list of available commands and usage tips.

@storybook-app-bot
Copy link
Copy Markdown

storybook-app-bot Bot commented Jan 26, 2026

Package Benchmarks

Commit: aec048e, ran on 30 January 2026 at 16:53:53 UTC

The following packages have significant changes to their size or dependencies:

@storybook/builder-vite

Before After Difference
Dependency count 11 17 🚨 +6 🚨
Self size 123 KB 125 KB 🚨 +2 KB 🚨
Dependency size 1.30 MB 2.00 MB 🚨 +701 KB 🚨
Bundle Size Analyzer Link Link

@storybook/builder-webpack5

Before After Difference
Dependency count 188 192 🚨 +4 🚨
Self size 75 KB 75 KB 🚨 +20 B 🚨
Dependency size 32.05 MB 32.26 MB 🚨 +215 KB 🚨
Bundle Size Analyzer Link Link

storybook

Before After Difference
Dependency count 49 49 0
Self size 20.40 MB 20.31 MB 🎉 -94 KB 🎉
Dependency size 16.52 MB 16.52 MB 🎉 -2 B 🎉
Bundle Size Analyzer Link Link

@storybook/angular

Before After Difference
Dependency count 188 192 🚨 +4 🚨
Self size 139 KB 139 KB 🎉 -4 B 🎉
Dependency size 30.27 MB 30.48 MB 🚨 +215 KB 🚨
Bundle Size Analyzer Link Link

@storybook/ember

Before After Difference
Dependency count 192 196 🚨 +4 🚨
Self size 15 KB 15 KB 🎉 -21 B 🎉
Dependency size 28.77 MB 28.98 MB 🚨 +215 KB 🚨
Bundle Size Analyzer Link Link

@storybook/html-vite

Before After Difference
Dependency count 14 20 🚨 +6 🚨
Self size 22 KB 22 KB 🚨 +8 B 🚨
Dependency size 1.46 MB 2.16 MB 🚨 +703 KB 🚨
Bundle Size Analyzer Link Link

@storybook/nextjs

Before After Difference
Dependency count 534 538 🚨 +4 🚨
Self size 646 KB 646 KB 🚨 +6 B 🚨
Dependency size 59.54 MB 59.26 MB 🎉 -279 KB 🎉
Bundle Size Analyzer Link Link

@storybook/nextjs-vite

Before After Difference
Dependency count 123 127 🚨 +4 🚨
Self size 1.12 MB 1.12 MB 🚨 +31 B 🚨
Dependency size 22.11 MB 21.84 MB 🎉 -277 KB 🎉
Bundle Size Analyzer Link Link

@storybook/preact-vite

Before After Difference
Dependency count 14 20 🚨 +6 🚨
Self size 13 KB 13 KB 🎉 -4 B 🎉
Dependency size 1.44 MB 2.15 MB 🚨 +703 KB 🚨
Bundle Size Analyzer Link Link

@storybook/react-native-web-vite

Before After Difference
Dependency count 155 159 🚨 +4 🚨
Self size 30 KB 30 KB 🚨 +13 B 🚨
Dependency size 23.41 MB 23.13 MB 🎉 -277 KB 🎉
Bundle Size Analyzer Link Link

@storybook/react-vite

Before After Difference
Dependency count 113 117 🚨 +4 🚨
Self size 35 KB 35 KB 🚨 +14 B 🚨
Dependency size 19.91 MB 19.63 MB 🎉 -277 KB 🎉
Bundle Size Analyzer Link Link

@storybook/react-webpack5

Before After Difference
Dependency count 274 278 🚨 +4 🚨
Self size 24 KB 24 KB 🎉 -5 B 🎉
Dependency size 44.44 MB 44.16 MB 🎉 -279 KB 🎉
Bundle Size Analyzer Link Link

@storybook/server-webpack5

Before After Difference
Dependency count 200 204 🚨 +4 🚨
Self size 16 KB 16 KB 🚨 +7 B 🚨
Dependency size 33.30 MB 33.52 MB 🚨 +215 KB 🚨
Bundle Size Analyzer Link Link

@storybook/svelte-vite

Before After Difference
Dependency count 19 24 🚨 +5 🚨
Self size 55 KB 55 KB 🎉 -4 B 🎉
Dependency size 26.58 MB 26.82 MB 🚨 +243 KB 🚨
Bundle Size Analyzer Link Link

@storybook/sveltekit

Before After Difference
Dependency count 20 25 🚨 +5 🚨
Self size 56 KB 56 KB 🚨 +19 B 🚨
Dependency size 26.63 MB 26.88 MB 🚨 +243 KB 🚨
Bundle Size Analyzer Link Link

@storybook/vue3-vite

Before After Difference
Dependency count 108 114 🚨 +6 🚨
Self size 35 KB 35 KB 🎉 -4 B 🎉
Dependency size 43.67 MB 43.96 MB 🚨 +293 KB 🚨
Bundle Size Analyzer Link Link

@storybook/web-components-vite

Before After Difference
Dependency count 15 21 🚨 +6 🚨
Self size 19 KB 19 KB 🎉 -4 B 🎉
Dependency size 1.50 MB 2.21 MB 🚨 +703 KB 🚨
Bundle Size Analyzer Link Link

@storybook/cli

Before After Difference
Dependency count 183 183 0
Self size 776 KB 775 KB 🎉 -999 B 🎉
Dependency size 67.57 MB 67.47 MB 🎉 -96 KB 🎉
Bundle Size Analyzer Link Link

@storybook/codemod

Before After Difference
Dependency count 176 176 0
Self size 32 KB 30 KB 🎉 -2 KB 🎉
Dependency size 66.14 MB 66.04 MB 🎉 -94 KB 🎉
Bundle Size Analyzer Link Link

create-storybook

Before After Difference
Dependency count 50 50 0
Self size 1000 KB 999 KB 🎉 -274 B 🎉
Dependency size 36.92 MB 36.82 MB 🎉 -94 KB 🎉
Bundle Size Analyzer node node

@storybook/react

Before After Difference
Dependency count 57 57 0
Self size 1.23 MB 732 KB 🎉 -494 KB 🎉
Dependency size 12.95 MB 12.95 MB 🎉 -9 B 🎉
Bundle Size Analyzer Link Link

The codemod was wrapping filenames in quotes when passing them to spawnSync.
Since spawnSync with an array handles argument escaping automatically, the
quotes became literal characters in the filename, causing "file does not exist"
errors.

Fixes: #33639

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
@kasperpeulen kasperpeulen force-pushed the kasper/fix-csf-factories-codemod-33639 branch from 227635c to 2c72d92 Compare January 26, 2026 12:03
@kasperpeulen kasperpeulen changed the title Codemod: Fix csf-2-to-3 silently failing due to quoted filenames Codemod: Fix csf-2-to-3 failing due to quoted filenames Jan 26, 2026
@kasperpeulen kasperpeulen merged commit acf98b3 into next Jan 28, 2026
120 of 125 checks passed
@kasperpeulen kasperpeulen deleted the kasper/fix-csf-factories-codemod-33639 branch January 28, 2026 09:10
@github-actions github-actions Bot mentioned this pull request Jan 28, 2026
24 tasks
@valentinpalkovic valentinpalkovic restored the kasper/fix-csf-factories-codemod-33639 branch January 30, 2026 07:50
@kasperpeulen kasperpeulen added the patch:yes Bugfix & documentation PR that need to be picked to main branch label Jan 30, 2026
@github-actions github-actions Bot mentioned this pull request Feb 2, 2026
11 tasks
valentinpalkovic pushed a commit that referenced this pull request Feb 2, 2026
…odemod-33639

Codemod: Fix csf-2-to-3 failing due to quoted filenames
(cherry picked from commit acf98b3)
@github-actions github-actions Bot mentioned this pull request Feb 2, 2026
13 tasks
@github-actions github-actions Bot added the patch:done Patch/release PRs already cherry-picked to main/release branch label Feb 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug ci:normal patch:done Patch/release PRs already cherry-picked to main/release branch patch:yes Bugfix & documentation PR that need to be picked to main branch

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Followup CSF factories: Codemod fails for different use cases

2 participants