Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CLI: Support version specifiers in init, upgrade and sandbox #25526

Merged
merged 22 commits into from
Jan 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
7418581
apply https://github.com/storybookjs/storybook/pull/25517 on main
ndelangen Jan 9, 2024
dbf6a9d
add version modifier
ndelangen Jan 10, 2024
6f6ed73
new upgrade workflow based on https://github.com/storybookjs/storyboo…
JReinhold Jan 11, 2024
3f48968
use current version for sandbox cli command
ndelangen Jan 12, 2024
a89b141
add back deprecated flags
JReinhold Jan 12, 2024
6dff347
Merge branch 'jeppe/upgrade-versioned-main' into norbert/cli-sandbox-…
ndelangen Jan 12, 2024
2ac5b32
fix automigrations and readmes
JReinhold Jan 12, 2024
1d41227
Merge branch 'jeppe/upgrade-versioned-main' into norbert/cli-sandbox-…
ndelangen Jan 12, 2024
9cb3fe6
update message matches new upgrade API
JReinhold Jan 12, 2024
5f28374
Merge branch 'main' into norbert/init-versioning-main
ndelangen Jan 12, 2024
1d7f277
maybe fix
ndelangen Jan 12, 2024
9a628b5
Merge branch 'main' into norbert/init-versioning-main
ndelangen Jan 12, 2024
b24dcbd
Merge branch 'norbert/init-versioning-main' into jeppe/upgrade-versio…
ndelangen Jan 12, 2024
912dde5
Merge branch 'jeppe/upgrade-versioned-main' into norbert/cli-sandbox-…
ndelangen Jan 12, 2024
9f449a5
fix tests
ndelangen Jan 12, 2024
ded297c
Merge branch 'jeppe/upgrade-versioned-main' into norbert/cli-sandbox-…
ndelangen Jan 12, 2024
24f72ed
fix the call to init in the cwd & ignore if next tag is missing
ndelangen Jan 15, 2024
894825d
Merge pull request #25574 from storybookjs/norbert/cli-sandbox-versio…
ndelangen Jan 15, 2024
5ac3a15
Merge pull request #25573 from storybookjs/jeppe/upgrade-versioned-main
ndelangen Jan 15, 2024
a2055b3
Merge pull request #25596 from storybookjs/jeppe/versioned-canary-san…
JReinhold Jan 15, 2024
838d267
init when download-dir = before-storybook
ndelangen Jan 15, 2024
5c11b71
fixes
ndelangen Jan 16, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions .github/workflows/canary-release-pr.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
name: Publish canary release of PR
run-name: 'Canary release: PR #${{ inputs.pr }}, triggered by ${{ github.triggering_actor }}'
run-name: "Canary release: PR #${{ inputs.pr }}, triggered by ${{ github.triggering_actor }}"

on:
workflow_dispatch:
inputs:
pr:
description: 'Pull request number to create a canary release for'
Copy link
Member

Choose a reason for hiding this comment

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

why the formatting change? is this due to the prettier upgrade, or a configuration issue on your machine?

Copy link
Contributor

Choose a reason for hiding this comment

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

Caused by the prettier upgrade removing the root config, Kasper brought it back again here: 4997513 (#25601)

description: "Pull request number to create a canary release for"
required: true
type: number

Expand Down Expand Up @@ -58,7 +58,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version-file: '.nvmrc'
node-version-file: ".nvmrc"
- name: Cache dependencies
uses: actions/cache@v3
with:
Expand Down Expand Up @@ -91,10 +91,10 @@ jobs:
with:
githubToken: ${{ secrets.GH_TOKEN }}
prNumber: ${{ inputs.pr }}
find: 'CANARY_RELEASE_SECTION'
find: "CANARY_RELEASE_SECTION"
isHtmlCommentTag: true
replace: |
This pull request has been released as version [`${{ steps.version.outputs.next-version }}`](https://npmjs.com/package/@storybook/cli/v/${{ steps.version.outputs.next-version }}). Install it by pinning all your Storybook dependencies to that version.
This pull request has been released as version `${{ steps.version.outputs.next-version }}`. Try it out in a new sandbox by running `npx storybook@${{ steps.version.outputs.next-version }} sandbox` or in an existing project with `npx storybook@${{ steps.version.outputs.next-version }} upgrade`.
<details>
<summary>More information</summary>

Expand Down
2 changes: 1 addition & 1 deletion code/frameworks/nextjs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ npx storybook@latest init
This framework is designed to work with Storybook 7. If you’re not already using v7, upgrade with this command:

```bash
npx storybook@latest upgrade --prerelease
npx storybook@latest upgrade
```

#### Automatic migration
Expand Down
2 changes: 1 addition & 1 deletion code/frameworks/preact-vite/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ npx storybook@latest init
This framework is designed to work with Storybook 7. If you’re not already using v7, upgrade with this command:

```bash
npx storybook@latest upgrade --prerelease
npx storybook@latest upgrade
```

#### Manual migration
Expand Down
3 changes: 1 addition & 2 deletions code/frameworks/sveltekit/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ Check out our [Frameworks API](https://storybook.js.org/blog/framework-api/) ann
- [Mocking links](#mocking-links)
- [Troubleshooting](#troubleshooting)
- [Error: `ERR! SyntaxError: Identifier '__esbuild_register_import_meta_url__' has already been declared` when starting Storybook](#error-err-syntaxerror-identifier-__esbuild_register_import_meta_url__-has-already-been-declared-when-starting-storybook)
- [Error: `Cannot read properties of undefined (reading 'disable_scroll_handling')` in preview](#error-cannot-read-properties-of-undefined-reading-disable_scroll_handling-in-preview)
- [Acknowledgements](#acknowledgements)

## Supported features
Expand Down Expand Up @@ -64,7 +63,7 @@ npx storybook@latest init
This framework is designed to work with Storybook 7. If you’re not already using v7, upgrade with this command:

```bash
npx storybook@latest upgrade --prerelease
npx storybook@latest upgrade
```

#### Automatic migration
Expand Down
1 change: 0 additions & 1 deletion code/lib/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@
"puppeteer-core": "^2.1.1",
"read-pkg-up": "^7.0.1",
"semver": "^7.3.7",
"simple-update-notifier": "^2.0.0",
"strip-json-comments": "^3.0.1",
"tempy": "^1.0.1",
"ts-dedent": "^2.0.0",
Expand Down
6 changes: 5 additions & 1 deletion code/lib/cli/src/automigrate/fixes/builder-vite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { writeConfig } from '@storybook/csf-tools';
import type { Fix } from '../types';
import type { PackageJson } from '../../js-package-manager';
import { updateMainConfig } from '../helpers/mainConfigFile';
import { getStorybookVersionSpecifier } from '../../helpers';

const logger = console;

Expand Down Expand Up @@ -68,8 +69,11 @@ export const builderVite: Fix<BuilderViteOptions> = {

logger.info(`✅ Adding '@storybook/builder-vite' as dev dependency`);
if (!dryRun) {
const versionToInstall = getStorybookVersionSpecifier(
await packageManager.retrievePackageJson()
);
await packageManager.addDependencies({ installAsDevDependencies: true }, [
'@storybook/builder-vite',
`@storybook/builder-vite@${versionToInstall}`,
]);
}

Expand Down
6 changes: 4 additions & 2 deletions code/lib/cli/src/automigrate/helpers/checkWebpack5Builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ export const checkWebpack5Builder = async ({

To upgrade to the latest stable release, run this from your project directory:

${chalk.cyan('npx storybook upgrade')}
${chalk.cyan('npx storybook@latest upgrade')}

Add the ${chalk.cyan('--prerelease')} flag to get the latest prerelease.
To upgrade to the latest pre-release, run this from your project directory:

${chalk.cyan('npx storybook@next upgrade')}
`.trim()
);
return null;
Expand Down
11 changes: 7 additions & 4 deletions code/lib/cli/src/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,16 +73,19 @@ command('babelrc')
.action(() => generateStorybookBabelConfigInCWD());

command('upgrade')
.description('Upgrade your Storybook packages to the latest')
.description(`Upgrade your Storybook packages to v${versions.storybook}`)
.option(
'--package-manager <npm|pnpm|yarn1|yarn2>',
'Force package manager for installing dependencies'
)
.option('-N --use-npm', 'Use NPM to install dependencies (deprecated)')
.option('-y --yes', 'Skip prompting the user')
.option('-n --dry-run', 'Only check for upgrades, do not install')
.option('-t --tag <tag>', 'Upgrade to a certain npm dist-tag (e.g. next, prerelease)')
.option('-p --prerelease', 'Upgrade to the pre-release packages')
.option(
'-t --tag <tag>',
'Upgrade to a certain npm dist-tag (e.g. next, prerelease) (deprecated)'
)
.option('-p --prerelease', 'Upgrade to the pre-release packages (deprecated)')
.option('-s --skip-check', 'Skip postinstall version and automigration checks')
.option('-c, --config-dir <dir-name>', 'Directory where to load Storybook configurations from')
.action(async (options: UpgradeOptions) => upgrade(options).catch(() => process.exit(1)));
Expand Down Expand Up @@ -153,7 +156,7 @@ command('sandbox [filterValue]')
.option('-b --branch <branch>', 'Define the branch to download from', 'next')
.option('--no-init', 'Whether to download a template without an initialized Storybook', false)
.action((filterValue, options) =>
sandbox({ filterValue, ...options }).catch((e) => {
sandbox({ filterValue, ...options }, pkg).catch((e) => {
logger.error(e);
process.exit(1);
})
Expand Down
2 changes: 1 addition & 1 deletion code/lib/cli/src/generators/NEXTJS/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const generator: Generator = async (packageManager, npmOptions, options) => {
{ ...options, builder: CoreBuilder.Webpack5 },
'react',
{
extraAddons: ['@storybook/addon-onboarding'],
extraAddons: ['@storybook/addon-onboarding@^1.0.0'],
},
'nextjs'
);
Expand Down
2 changes: 1 addition & 1 deletion code/lib/cli/src/generators/REACT/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const generator: Generator = async (packageManager, npmOptions, options) => {
await baseGenerator(packageManager, npmOptions, options, 'react', {
extraPackages,
useSWC: ({ builder }) => builder === CoreBuilder.Webpack5,
extraAddons: ['@storybook/addon-onboarding'],
extraAddons: ['@storybook/addon-onboarding@^1.0.0'],
});
};

Expand Down
4 changes: 2 additions & 2 deletions code/lib/cli/src/generators/REACT_NATIVE/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,14 @@ const generator = async (
'@storybook/addon-controls@^6.5.16',
];

const resolvedPackages = await packageManager.getVersionedPackages(packagesToResolve);
const versionedPackages = await packageManager.getVersionedPackages(packagesToResolve);

const babelDependencies = await getBabelDependencies(packageManager, packageJson);

const packages = [
...babelDependencies,
...packagesWithFixedVersion,
...resolvedPackages,
...versionedPackages,
missingReactDom && reactVersion && `react-dom@${reactVersion}`,
].filter(Boolean);

Expand Down
7 changes: 1 addition & 6 deletions code/lib/cli/src/generators/REACT_SCRIPTS/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import dedent from 'ts-dedent';
import { baseGenerator } from '../baseGenerator';
import type { Generator } from '../types';
import { CoreBuilder } from '../../project_types';
import versions from '../../versions';

const generator: Generator = async (packageManager, npmOptions, options) => {
const monorepoRootPath = path.join(__dirname, '..', '..', '..', '..', '..', '..');
Expand Down Expand Up @@ -47,11 +46,7 @@ const generator: Generator = async (packageManager, npmOptions, options) => {
// Miscellaneous dependency to add to be sure Storybook + CRA is working fine with Yarn PnP mode
extraPackages.push('prop-types');

const version = versions['@storybook/preset-create-react-app'];
const extraAddons = [
`@storybook/preset-create-react-app@${version}`,
'@storybook/addon-onboarding',
];
const extraAddons = [`@storybook/preset-create-react-app`, '@storybook/addon-onboarding@^1.0.0'];

await baseGenerator(
packageManager,
Expand Down
2 changes: 1 addition & 1 deletion code/lib/cli/src/generators/WEBPACK_REACT/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type { Generator } from '../types';

const generator: Generator = async (packageManager, npmOptions, options) => {
await baseGenerator(packageManager, npmOptions, options, 'react', {
extraAddons: ['@storybook/addon-onboarding'],
extraAddons: ['@storybook/addon-onboarding@^1.0.0'],
useSWC: ({ builder }) => builder === CoreBuilder.Webpack5,
});
};
Expand Down
11 changes: 5 additions & 6 deletions code/lib/cli/src/generators/baseGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -328,8 +328,6 @@ export async function baseGenerator(
const versionedPackages = await packageManager.getVersionedPackages(packages);
versionedPackagesSpinner.succeed();

const depsToInstall = [...versionedPackages];

// Add basic babel config for a select few frameworks that need it, if they do not have a babel config file already
if (builder !== CoreBuilder.Vite && !skipBabel) {
const frameworksThatNeedBabelConfig = [
Expand All @@ -349,7 +347,7 @@ export async function baseGenerator(
if (hasNoBabelFile && needsBabelConfig) {
const isTypescript = language !== SupportedLanguage.JAVASCRIPT;
const isReact = rendererId === 'react';
depsToInstall.push(
versionedPackages.push(
...getBabelPresets({
typescript: isTypescript,
jsx: isReact,
Expand All @@ -370,7 +368,7 @@ export async function baseGenerator(

if (hasEslint && !isStorybookPluginInstalled) {
if (skipPrompts || (await suggestESLintPlugin())) {
depsToInstall.push('eslint-plugin-storybook');
versionedPackages.push('eslint-plugin-storybook');
await configureEslintPlugin(eslintConfigFile, packageManager);
}
}
Expand All @@ -379,12 +377,13 @@ export async function baseGenerator(
// any failure regarding configuring the eslint plugin should not fail the whole generator
}

if (depsToInstall.length > 0) {
if (versionedPackages.length > 0) {
const addDependenciesSpinner = ora({
indent: 2,
text: 'Installing Storybook dependencies',
}).start();
await packageManager.addDependencies({ ...npmOptions, packageJson }, depsToInstall);

await packageManager.addDependencies({ ...npmOptions, packageJson }, versionedPackages);
addDependenciesSpinner.succeed();
}

Expand Down
41 changes: 31 additions & 10 deletions code/lib/cli/src/initiate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { NxProjectDetectedError } from '@storybook/core-events/server-errors';
import dedent from 'ts-dedent';
import boxen from 'boxen';
import { readdirSync } from 'fs-extra';
import { lt, prerelease } from 'semver';
import { installableProjectTypes, ProjectType } from './project_types';
import { detect, isStorybookInstantiated, detectLanguage, detectPnp } from './detect';
import { commandLog, codeLog, paddedLog } from './helpers';
Expand All @@ -35,6 +36,7 @@ import { JsPackageManagerFactory, useNpmWarning } from './js-package-manager';
import type { NpmOptions } from './NpmOptions';
import type { CommandOptions, GeneratorOptions } from './generators/types';
import { HandledError } from './HandledError';
import versions from './versions';

const logger = console;

Expand Down Expand Up @@ -272,7 +274,7 @@ const getEmptyDirMessage = (packageManagerType: PackageManagerName) => {
`;
};

async function doInitiate(
export async function doInitiate(
options: CommandOptions,
pkg: PackageJson
): Promise<
Expand All @@ -296,15 +298,6 @@ async function doInitiate(
cwdFolderEntries.length === 0 || cwdFolderEntries.every((entry) => entry.startsWith('.'));

const packageManager = JsPackageManagerFactory.getPackageManager({ force: pkgMgr });
const welcomeMessage = 'storybook init - the simplest way to add a Storybook to your project.';
logger.log(chalk.inverse(`\n ${welcomeMessage} \n`));

// Update notify code.
const { default: updateNotifier } = await import('simple-update-notifier');
await updateNotifier({
pkg: pkg as any,
updateCheckInterval: 1000 * 60 * 60, // every hour (we could increase this later on.)
});

if (options.force !== true && isEmptyDir) {
logger.log(
Expand All @@ -317,6 +310,34 @@ async function doInitiate(
throw new HandledError('Project was initialized in an empty directory.');
}

const latestVersion = await packageManager.latestVersion('@storybook/cli');
const currentVersion = versions['@storybook/cli'];
const isPrerelease = prerelease(currentVersion);
const isOutdated = lt(currentVersion, latestVersion);
const borderColor = isOutdated ? '#FC521F' : '#F1618C';

const messages = {
welcome: `Adding Storybook version ${chalk.bold(currentVersion)} to your project..`,
notLatest: chalk.red(dedent`
This version is behind the latest release, which is: ${chalk.bold(latestVersion)}!
You likely ran the init command through npx, which can use a locally cached version, to get the latest please run:
${chalk.bold('npx storybook@latest init')}

You may want to CTRL+C to stop, and run with the latest version instead.
`),
prelease: chalk.yellow('This is a pre-release version.'),
};

logger.log(
boxen(
[messages.welcome]
.concat(isOutdated && !isPrerelease ? [messages.notLatest] : [])
.concat(isPrerelease ? [messages.prelease] : [])
.join('\n'),
{ borderStyle: 'round', padding: 1, borderColor }
)
);

let projectType: ProjectType;
const projectTypeProvided = options.type;
const infoText = projectTypeProvided
Expand Down
20 changes: 19 additions & 1 deletion code/lib/cli/src/js-package-manager/JsPackageManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ export abstract class JsPackageManager {

done = commandLog('Installing dependencies');

logger.log();

try {
await this.runInstall();
done();
Expand Down Expand Up @@ -325,13 +327,29 @@ export abstract class JsPackageManager {
/**
* Return an array of strings matching following format: `<package_name>@<package_latest_version>`
*
* For packages in the storybook monorepo, when the latest version is equal to the version of the current CLI
* the version is not added to the string.
*
* When a package is in the monorepo, and the version is not equal to the CLI version, the version is taken from the versions.ts file and added to the string.
*
* @param packages
*/
public getVersionedPackages(packages: string[]): Promise<string[]> {
return Promise.all(
packages.map(async (pkg) => {
const [packageName, packageVersion] = getPackageDetails(pkg);
return `${packageName}@${await this.getVersion(packageName, packageVersion)}`;
const latestInRange = await this.latestVersion(packageName, packageVersion);

const k = packageName as keyof typeof storybookPackagesVersions;
const currentVersion = storybookPackagesVersions[k];

if (currentVersion === latestInRange) {
return `${packageName}`;
}
if (currentVersion) {
return `${packageName}@${currentVersion}`;
}
return `${packageName}@^${latestInRange}`;
})
);
}
Expand Down
Loading