Skip to content

Core: Fix internal yarn build command#33445

Merged
ndelangen merged 4 commits into
nextfrom
sidnioulz/issue-33432
Dec 31, 2025
Merged

Core: Fix internal yarn build command#33445
ndelangen merged 4 commits into
nextfrom
sidnioulz/issue-33432

Conversation

@Sidnioulz
Copy link
Copy Markdown
Member

@Sidnioulz Sidnioulz commented Dec 30, 2025

Closes #33432

What I did

  • Fixed regression caused by an upgrade to the commander dependency (thanks @ia319 for diagnosing it)
  • Repaired yarn build --all which incorrectly caused the script to exit
  • Fixed bug when passing --all storybook which incorrectly assumed storybook is an invalid package name due to incorrect package name filtering
  • Restored old package order with the main storybook package appearing first, as it's the most useful
  • Made --watch and --prod flags skip relevant prompts when passed without package name
  • Added --no-watch and --no-prod counterparts with the same effect
  • Documented yarn build flags

Checklist for Contributors

Testing

ø

Manual testing

Run commands:

  • yarn build, you will get fully prompted (watch + prod + packages, `storybook appears first)
  • yarn build --all, build will start
  • yarn build --all storybook, build will start
  • yarn build --all addon-a11y, build will start
  • yarn build storybook addon-a11y, build will start with only 2 packages
  • yarn build --all --watch, build will start in watch mode
  • yarn build --watch --no-prod, you will be prompted only package names, and build will start in watch mode and development mode

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 don'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

  • Documentation

    • Added documentation for the yarn build command, covering --all, --watch, --prod (and examples for building specific packages).
  • Chores

    • Improved the build CLI: clearer package selection ordering, explicit disable options, better validation and error messages, conditional prompts, and clearer build/output messaging.

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

@Sidnioulz Sidnioulz requested review from ia319 and ndelangen December 30, 2025 13:48
@Sidnioulz Sidnioulz added the bug label Dec 30, 2025
@Sidnioulz Sidnioulz requested a review from kylegach as a code owner December 30, 2025 13:48
@Sidnioulz Sidnioulz added the build Internal-facing build tooling & test updates label Dec 30, 2025
@nx-cloud
Copy link
Copy Markdown

nx-cloud Bot commented Dec 30, 2025

View your CI Pipeline Execution ↗ for commit ef3f9ca

Command Status Duration Result
nx run-many -t compile,check,knip,test,pretty-d... ✅ Succeeded 11m 28s View ↗

☁️ Nx Cloud last updated this comment at 2025-12-30 14:47:24 UTC

@Sidnioulz Sidnioulz added ci:normal and removed bug labels Dec 30, 2025
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Dec 30, 2025

📝 Walkthrough

Walkthrough

Adds documentation for yarn build flags and refactors the build script into an explicit CLI with added flags, in-memory package task mapping, package name validation, and conditional prompt logic for watch/prod options.

Changes

Cohort / File(s) Summary
Documentation
docs/contribute/code.mdx
Inserts a new section describing yarn build options (--all, --watch, --prod) and example usage for building specific packages with --watch.
Build script (CLI & orchestration)
scripts/build-package.ts
Replaces previous prompt-heavy flow with an explicit CLI: adds --no-watch/--no-prod flags, builds an in-memory tasks map for workspaces (main package first), validates package names and errors on invalid input, changes how per-package tasks/suffixes are determined, and adjusts final invocation/output to use process.stdout.write with per-package prefixes.
Prompting & selection behavior
scripts/build-package.ts (same file)
Prompts for watch/prod only when not provided via flags; selection prompt updated to reference actual package names; removed previous ad-hoc per-package option augmentation.
Error handling & exit behavior
scripts/build-package.ts (same file)
Adds explicit stderr error messages and non-zero exit on invalid package selection input.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    actor User
    participant CLI as build-package.ts (CLI)
    participant Prompt as Inquirer/Prompts
    participant Workspaces as Monorepo Workspaces
    participant Yarn as yarn subprocess
    Note over CLI,Workspaces: Startup: parse args, load workspaces
    User->>CLI: invokes `yarn build [--all|<pkg>...] [--watch|--no-watch] [--prod|--no-prod]`
    CLI->>Workspaces: read & sort package list (main first)
    alt explicit packages or --all provided
        CLI->>CLI: validate package names
    else no explicit inputs
        CLI->>Prompt: ask user to select packages
        Prompt-->>CLI: selected packages
    end
    alt watch/prod flags missing
        CLI->>Prompt: ask for watch/prod choices
        Prompt-->>CLI: watch/prod selections
    end
    CLI->>Yarn: spawn per-package yarn build (with suffixes, watch/prod flags)
    Yarn-->>CLI: stream package output (prefixed)
    CLI->>User: stdout "Building selected packages..."
    Yarn-->>User: package build logs
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

✨ Finishing touches
  • 📝 Generate docstrings

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

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
scripts/build-package.ts (1)

152-184: Race condition with lastName in concurrent builds.

The forEach with async callback starts all builds concurrently, and the shared lastName variable is accessed by multiple concurrent event handlers. This can cause output interleaving where the package prefix is incorrectly shown or omitted when multiple processes emit data simultaneously.

If parallel execution is intentional, consider either:

  1. Always prefixing each line with the package name (removing the lastName optimization), or
  2. Using a per-process tracking approach.
Example: Always prefix output
     sub.stdout?.on('data', (data) => {
-      if (lastName !== v.name) {
-        const prefix = `${picocolors.cyan(v.name)}:\n`;
-        process.stdout.write(prefix);
-      }
-      lastName = v.name;
-      process.stdout.write(data);
+      const prefix = `${picocolors.cyan(v.name)}: `;
+      const lines = data.toString().split('\n');
+      lines.forEach((line, i) => {
+        if (line || i < lines.length - 1) {
+          process.stdout.write(`${prefix}${line}\n`);
+        }
+      });
     });
🧹 Nitpick comments (1)
docs/contribute/code.mdx (1)

105-116: Consider documenting --no-watch and --no-prod flags.

The documentation covers --all, --watch, and --prod, but the implementation in build-package.ts also includes --no-watch and --no-prod counterparts. According to the PR objectives, these flags "skip related prompts when passed without a package name." Consider adding them for completeness:

 * `--all` will cause all packages to be built
 * `--watch` will enable watch mode (and skip the watch mode prompt)
 * `--prod` will build for production (and skip the production mode prompt)
+* `--no-watch` will disable watch mode (and skip the watch mode prompt)
+* `--no-prod` will disable production mode (and skip the production mode prompt)
 * individual package names can be passed, without the `@storybook/` prefix, e.g. `storybook`, `addon-docs`, etc.
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b439f83 and 85994b4.

📒 Files selected for processing (2)
  • docs/contribute/code.mdx
  • scripts/build-package.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{js,jsx,ts,tsx,json,md,html,css,scss}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Format code using Prettier with yarn prettier --write <file>

Files:

  • scripts/build-package.ts
**/*.{js,jsx,json,html,ts,tsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Run ESLint checks using yarn lint:js:cmd <file> or the full command cross-env NODE_ENV=production eslint --cache --cache-location=../.cache/eslint --ext .js,.jsx,.json,.html,.ts,.tsx,.mjs --report-unused-disable-directives to fix linting errors before committing

Files:

  • scripts/build-package.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Enable TypeScript strict mode across all packages

Files:

  • scripts/build-package.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{ts,tsx,js,jsx}: Export functions from modules if they need to be tested
Do not use console.log, console.warn, or console.error directly unless in isolated files where importing loggers would significantly increase bundle size

Files:

  • scripts/build-package.ts
🧠 Learnings (8)
📓 Common learnings
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-22T22:03:40.123Z
Learning: Applies to **/*.{js,jsx,json,html,ts,tsx,mjs} : Run ESLint checks using `yarn lint:js:cmd <file>` or the full command `cross-env NODE_ENV=production eslint --cache --cache-location=../.cache/eslint --ext .js,.jsx,.json,.html,.ts,.tsx,.mjs --report-unused-disable-directives` to fix linting errors before committing
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-22T22:03:40.123Z
Learning: Applies to **/*.{js,jsx,ts,tsx,json,md,html,css,scss} : Format code using Prettier with `yarn prettier --write <file>`
📚 Learning: 2025-10-02T09:22:13.215Z
Learnt from: JReinhold
Repo: storybookjs/storybook PR: 32607
File: code/package.json:243-243
Timestamp: 2025-10-02T09:22:13.215Z
Learning: The Storybook repository uses Yarn v^4 (any 4.x version) as the package manager, configured via .yarnrc.yml and package.json packageManager field. Specific patch versions within v4 can be upgraded as needed.

Applied to files:

  • docs/contribute/code.mdx
📚 Learning: 2025-12-22T22:03:40.123Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-22T22:03:40.123Z
Learning: Applies to {code/addons,code/frameworks}/**/README.md : Update README files for significant changes and include code examples in addon/framework documentation

Applied to files:

  • docs/contribute/code.mdx
📚 Learning: 2025-12-22T22:03:40.123Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-22T22:03:40.123Z
Learning: Applies to **/*.{js,jsx,ts,tsx,json,md,html,css,scss} : Format code using Prettier with `yarn prettier --write <file>`

Applied to files:

  • docs/contribute/code.mdx
📚 Learning: 2025-12-22T22:03:40.123Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-22T22:03:40.123Z
Learning: Applies to **/*.{js,jsx,json,html,ts,tsx,mjs} : Run ESLint checks using `yarn lint:js:cmd <file>` or the full command `cross-env NODE_ENV=production eslint --cache --cache-location=../.cache/eslint --ext .js,.jsx,.json,.html,.ts,.tsx,.mjs --report-unused-disable-directives` to fix linting errors before committing

Applied to files:

  • docs/contribute/code.mdx
📚 Learning: 2025-12-22T22:03:40.123Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-22T22:03:40.123Z
Learning: Run compilation with NX using `yarn nx run-many -t compile -c production` for better caching and dependency management

Applied to files:

  • docs/contribute/code.mdx
📚 Learning: 2025-09-29T13:20:23.346Z
Learnt from: mrginglymus
Repo: storybookjs/storybook PR: 32556
File: code/core/package.json:309-313
Timestamp: 2025-09-29T13:20:23.346Z
Learning: The `fast-printf` dependency in Storybook's core package is bundled into the final distribution during the build process, so it should remain in devDependencies rather than being moved to dependencies, following the same pattern as other bundled dependencies like `open`.

Applied to files:

  • docs/contribute/code.mdx
📚 Learning: 2025-11-24T17:49:31.838Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-24T17:49:31.838Z
Learning: Applies to code/vitest.workspace.ts : Vitest configuration is centralized in `code/vitest.workspace.ts` for workspace setup

Applied to files:

  • scripts/build-package.ts
🧬 Code graph analysis (1)
scripts/build-package.ts (1)
scripts/task.ts (1)
  • tasks (81-105)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: normal
  • GitHub Check: nx
🔇 Additional comments (3)
scripts/build-package.ts (3)

63-82: LGTM!

The Commander setup correctly handles the --all, --watch/--no-watch, and --prod/--no-prod flags. Using allowExcessArguments(true) combined with main.args is an appropriate approach for accepting package names as positional arguments.


109-149: LGTM!

The prompt flow correctly skips watch/prod prompts when flags are explicitly provided, while still allowing interactive selection when no packages are specified. The conditional prompt inclusion pattern using watchMode === undefined && is a valid approach for filtering prompts.


30-33: The sort condition is correct. The main Storybook package in code/core/package.json is indeed named 'storybook' (without the @storybook/ prefix), so the condition a.name === 'storybook' will correctly identify and place it first in the option list. All other packages follow the @storybook/... naming convention and will be sorted after the main package.

Comment thread scripts/build-package.ts Outdated
Comment thread scripts/build-package.ts
Comment thread scripts/build-package.ts Outdated
Comment thread scripts/build-package.ts Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
scripts/build-package.ts (1)

152-182: Async callbacks in forEach are not awaited, causing premature script exit in non-watch mode.

The script spawns subprocesses but doesn't await their completion. The forEach loop on line 152 creates unresolved promises with async callbacks, and run() at line 185 is never awaited. In non-watch mode (the default), the script exits immediately after spawning builds, before any build processes can complete. Additionally, subprocess failures are never propagated to the script's exit code.

Fix by awaiting the completion of all subprocesses:

  • Use Promise.all() to wait for all builds to finish before returning from run()
  • Add error handling to capture subprocess exit codes and failures
  • Ensure the script exits with non-zero status if any build fails
♻️ Duplicate comments (1)
scripts/build-package.ts (1)

88-101: Handle invalid package names with no close match.

The exit code fix was applied, but the second part of the past review issue remains: when findMostMatchText returns falsy (no close match found), hasInvalidName is never set to true, so the invalid argument is silently ignored and the script continues with an incomplete selection.

Proposed fix
   for (const arg of main.args) {
     if (!suffixList.includes(arg)) {
       const matchText = findMostMatchText(suffixList, arg);
+      hasInvalidName = true;
 
       if (matchText) {
-        hasInvalidName = true;
         process.stderr.write(
           `${picocolors.red('Error')}: ${picocolors.cyan(
             arg
           )} is not a valid package name, Did you mean ${picocolors.cyan(matchText)}?\n`
         );
+      } else {
+        process.stderr.write(
+          `${picocolors.red('Error')}: ${picocolors.cyan(arg)} is not a valid package name.\n`
+        );
       }
     }
   }
🧹 Nitpick comments (1)
scripts/build-package.ts (1)

28-30: Consider using both comparator arguments for clarity.

The sort callback only uses the first argument. While this achieves the goal of placing storybook first, it's unconventional and could confuse future readers.

Proposed fix
   const packages = (await getCodeWorkspaces())
     .filter(({ name }) => name !== '@storybook/code')
-    .sort((a) => (a.name === 'storybook' ? -1 : 0)); // Place main package first in option list
+    .sort((a, b) => {
+      if (a.name === 'storybook') return -1;
+      if (b.name === 'storybook') return 1;
+      return 0;
+    }); // Place main package first in option list
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 85994b4 and ef3f9ca.

📒 Files selected for processing (1)
  • scripts/build-package.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{js,jsx,ts,tsx,json,md,html,css,scss}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Format code using Prettier with yarn prettier --write <file>

Files:

  • scripts/build-package.ts
**/*.{js,jsx,json,html,ts,tsx,mjs}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Run ESLint checks using yarn lint:js:cmd <file> or the full command cross-env NODE_ENV=production eslint --cache --cache-location=../.cache/eslint --ext .js,.jsx,.json,.html,.ts,.tsx,.mjs --report-unused-disable-directives to fix linting errors before committing

Files:

  • scripts/build-package.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Enable TypeScript strict mode across all packages

Files:

  • scripts/build-package.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{ts,tsx,js,jsx}: Export functions from modules if they need to be tested
Do not use console.log, console.warn, or console.error directly unless in isolated files where importing loggers would significantly increase bundle size

Files:

  • scripts/build-package.ts
🧠 Learnings (4)
📓 Common learnings
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-22T22:03:40.123Z
Learning: Applies to **/*.{js,jsx,json,html,ts,tsx,mjs} : Run ESLint checks using `yarn lint:js:cmd <file>` or the full command `cross-env NODE_ENV=production eslint --cache --cache-location=../.cache/eslint --ext .js,.jsx,.json,.html,.ts,.tsx,.mjs --report-unused-disable-directives` to fix linting errors before committing
📚 Learning: 2025-12-22T22:03:40.123Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-22T22:03:40.123Z
Learning: Applies to **/*.{ts,tsx} : Enable TypeScript strict mode across all packages

Applied to files:

  • scripts/build-package.ts
📚 Learning: 2025-12-22T22:03:40.123Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-22T22:03:40.123Z
Learning: Applies to **/*.{js,jsx,json,html,ts,tsx,mjs} : Run ESLint checks using `yarn lint:js:cmd <file>` or the full command `cross-env NODE_ENV=production eslint --cache --cache-location=../.cache/eslint --ext .js,.jsx,.json,.html,.ts,.tsx,.mjs --report-unused-disable-directives` to fix linting errors before committing

Applied to files:

  • scripts/build-package.ts
📚 Learning: 2025-11-24T17:49:31.838Z
Learnt from: CR
Repo: storybookjs/storybook PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-24T17:49:31.838Z
Learning: Applies to code/vitest.workspace.ts : Vitest configuration is centralized in `code/vitest.workspace.ts` for workspace setup

Applied to files:

  • scripts/build-package.ts
🧬 Code graph analysis (1)
scripts/build-package.ts (2)
scripts/task.ts (1)
  • tasks (81-105)
scripts/utils/tools.ts (1)
  • picocolors (118-118)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: normal
  • GitHub Check: nx
  • GitHub Check: Core Unit Tests, windows-latest
🔇 Additional comments (2)
scripts/build-package.ts (2)

110-125: LGTM!

The conditional prompt logic correctly skips watch/prod prompts when the respective flags are explicitly provided via CLI. The prompts library handles falsy values in the questions array gracefully.


72-80: LGTM!

The options parsing and per-package flag checking logic is clear. Using main.args to detect package suffixes and combining with opts.all correctly handles both explicit package selection and the --all flag.

@ndelangen ndelangen merged commit 6afaabe into next Dec 31, 2025
69 checks passed
@ndelangen ndelangen deleted the sidnioulz/issue-33432 branch December 31, 2025 08:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

build Internal-facing build tooling & test updates ci:normal

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: yarn build fails with Commander error: "option creation failed due to no flags found in 'addon-a11y'"

2 participants