From 880479789f6cdadf5b47874ae1eb78ecd64ba786 Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Thu, 7 Mar 2024 14:54:07 +0100 Subject: [PATCH 01/16] add an automigration for upgrading dependencies --- code/lib/cli/src/automigrate/fixes/index.ts | 8 +- .../upgrade-storybook-related-dependencies.ts | 105 ++++++++++++++++++ code/lib/cli/src/automigrate/index.ts | 21 +++- code/lib/cli/src/automigrate/types.ts | 7 +- .../getIncompatibleStorybookPackages.ts | 12 ++ code/lib/cli/src/upgrade.ts | 3 +- 6 files changed, 144 insertions(+), 12 deletions(-) create mode 100644 code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts diff --git a/code/lib/cli/src/automigrate/fixes/index.ts b/code/lib/cli/src/automigrate/fixes/index.ts index 17b3d4942be1..01bdc2b2aa94 100644 --- a/code/lib/cli/src/automigrate/fixes/index.ts +++ b/code/lib/cli/src/automigrate/fixes/index.ts @@ -26,10 +26,11 @@ import { removeJestTestingLibrary } from './remove-jest-testing-library'; import { addonsAPI } from './addons-api'; import { mdx1to3 } from './mdx-1-to-3'; import { addonPostCSS } from './addon-postcss'; +import { upgradeStorybookRelatedDependencies } from './upgrade-storybook-related-dependencies'; export * from '../types'; -export const allFixes: Fix[] = [ +export const allFixes = [ addonsAPI, newFrameworks, cra5, @@ -56,6 +57,7 @@ export const allFixes: Fix[] = [ removeLegacyMDX1, webpack5CompilerSetup, mdx1to3, -]; + upgradeStorybookRelatedDependencies, +] satisfies Fix[]; -export const initFixes: Fix[] = [eslintPlugin]; +export const initFixes = [eslintPlugin] satisfies Fix[]; diff --git a/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts b/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts new file mode 100644 index 000000000000..234b35a1451c --- /dev/null +++ b/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts @@ -0,0 +1,105 @@ +import { dedent } from 'ts-dedent'; +import type { Fix } from '../types'; +import { underline } from 'chalk'; +import { getIncompatibleStorybookPackages } from '../../doctor/getIncompatibleStorybookPackages'; + +interface Options { + list: { packageName: string; version: string }[]; +} + +type ExcludesFalse = (x: T | undefined) => x is T; + +/** + * Is the user upgrading to the `latest` version of Storybook? + * Let's try to pull along some of the storybook related dependencies to `latest` as well! + * + * We communicate clearly that this migration is a helping hand, but not a complete solution. + * The user should still manually check for other dependencies that might be incompatible. + * + * see: https://github.com/storybookjs/storybook/issues/25731#issuecomment-1977346398 + */ +export const upgradeStorybookRelatedDependencies = { + id: 'upgradeStorybookRelatedDependencies', + + versionRange: ['<8', '>=8'], + + async check({ packageManager, storybookVersion }) { + const out = await getIncompatibleStorybookPackages({ + currentStorybookVersion: storybookVersion, + packageManager, + skipErrors: true, + }); + + const list = await Promise.all( + out.map(async ({ packageName, hasIncompatibleDependencies }) => { + if (!hasIncompatibleDependencies) { + return; + } + + return { + packageName, + version: await packageManager.latestVersion(packageName), + }; + }) + ); + + const filtered = list.filter(Boolean as any as ExcludesFalse); + return { list: filtered }; + }, + + promptType: 'auto-no', + + prompt({ list }) { + return dedent` + You're upgrading to the latest version of Storybook. We recommend upgrading the following packages: + ${list.map(({ packageName, version }) => `${packageName}@${version}`).join(', ')} + + We detected those packages are incompatible with the latest version of Storybook. + ${underline( + `The list might be incomplete, so it's advised to upgrade dependencies manually, but this automigration can help you get started.` + )} + + After upgrading, we will run the dedupe command, which could possibly have effects on dependencies that are not storybook related. + see: https://docs.npmjs.com/cli/commands/npm-dedupe + + Do you want to proceed (upgrade the detected packages)? + `; + }, + + async run({ result: { list }, packageManager, dryRun, mainConfigPath }) { + if (dryRun) { + console.log(dedent` + would have upgrade the following: + ${list.map(({ packageName, version }) => `${packageName}@${version}`).join('\n')} + `); + return; + } + + const packageJson = await packageManager.readPackageJson(); + + // mutate the packageJson data + list.forEach((item) => { + if (!item) { + return; + } + + const { packageName, version } = item; + const prefixed = `^${version}`; + + if (packageJson.dependencies?.[packageName]) { + packageJson.dependencies[packageName] = prefixed; + } + if (packageJson.devDependencies?.[packageName]) { + packageJson.devDependencies[packageName] = prefixed; + } + if (packageJson.peerDependencies?.[packageName]) { + packageJson.peerDependencies[packageName] = prefixed; + } + }); + + await packageManager.writePackageJson(packageJson); + await packageManager.installDependencies(); + + await packageManager.getRunCommand('dedupe'); + }, +} satisfies Fix; diff --git a/code/lib/cli/src/automigrate/index.ts b/code/lib/cli/src/automigrate/index.ts index 8a84476b5e93..843b8f4371d6 100644 --- a/code/lib/cli/src/automigrate/index.ts +++ b/code/lib/cli/src/automigrate/index.ts @@ -29,6 +29,8 @@ import { getMigrationSummary } from './helpers/getMigrationSummary'; import { getStorybookData } from './helpers/mainConfigFile'; import { doctor } from '../doctor'; +import { upgradeStorybookRelatedDependencies } from './fixes/upgrade-storybook-related-dependencies'; + const logger = console; const LOG_FILE_NAME = 'migration-storybook.log'; const LOG_FILE_PATH = join(process.cwd(), LOG_FILE_NAME); @@ -121,8 +123,17 @@ export const automigrate = async ({ return null; } - const selectedFixes = inputFixes || allFixes; - const fixes = fixId ? selectedFixes.filter((f) => f.id === fixId) : selectedFixes; + const selectedFixes: Fix[] = + inputFixes || + allFixes.filter((fix) => { + // we only allow this automigration when the user explicitly asks for it, or they are upgrading to the latest version of storybook + if (fix.id === upgradeStorybookRelatedDependencies.id && isUpgrade !== 'latest') { + return false; + } + + return true; + }); + const fixes: Fix[] = fixId ? selectedFixes.filter((f) => f.id === fixId) : selectedFixes; if (fixId && fixes.length === 0) { logger.info(`📭 No migrations found for ${chalk.magenta(fixId)}.`); @@ -143,7 +154,7 @@ export const automigrate = async ({ mainConfigPath, storybookVersion, beforeVersion, - isUpgrade, + isUpgrade: !!isUpgrade, dryRun, yes, }); @@ -308,13 +319,13 @@ export async function runFixes({ fixResults[f.id] = FixStatus.MANUAL_SKIPPED; break; } - } else if (promptType === 'auto') { + } else if (promptType === 'auto' || promptType === 'auto-no') { runAnswer = await prompts( { type: 'confirm', name: 'fix', message: `Do you want to run the '${chalk.cyan(f.id)}' migration on your project?`, - initial: true, + initial: promptType === 'auto-no' ? false : true, }, { onCancel: () => { diff --git a/code/lib/cli/src/automigrate/types.ts b/code/lib/cli/src/automigrate/types.ts index d8cc9f06af3e..45f2b4b72c01 100644 --- a/code/lib/cli/src/automigrate/types.ts +++ b/code/lib/cli/src/automigrate/types.ts @@ -22,10 +22,11 @@ export interface RunOptions { /** * promptType defines how the user will be prompted to apply an automigration fix * - auto: the fix will be applied automatically + * - auto-no: the fix will be applied automatically, but only when the user opts-in * - manual: the user will be prompted to apply the fix * - notification: the user will be notified about some changes. A fix isn't required, though */ -export type Prompt = 'auto' | 'manual' | 'notification'; +export type Prompt = 'auto' | 'auto-no' | 'manual' | 'notification'; type BaseFix = { id: string; @@ -45,7 +46,7 @@ type PromptType = export type Fix = ( | { - promptType?: PromptType; + promptType?: PromptType; run: (options: RunOptions) => Promise; } | { @@ -74,7 +75,7 @@ export interface AutofixOptions extends Omit compare with existing CLI version + +// const norbertStuff = async (dependency: string, context: Context) => { +// const { packageManager } = context; + +// const res = await checkPackageCompatibility(dependency, context); +// if (res.hasIncompatibleDependencies) { +// const hasUpdate = await packageManager.latestVersion(dependency); +// } +// }; + export const checkPackageCompatibility = async (dependency: string, context: Context) => { const { currentStorybookVersion, skipErrors, packageManager } = context; try { diff --git a/code/lib/cli/src/upgrade.ts b/code/lib/cli/src/upgrade.ts index 179c7d806a2f..757ad89bdd7c 100644 --- a/code/lib/cli/src/upgrade.ts +++ b/code/lib/cli/src/upgrade.ts @@ -22,6 +22,7 @@ import { } from '@storybook/core-common'; import { automigrate } from './automigrate/index'; import { autoblock } from './autoblock/index'; +import { is } from '@babel/types'; type Package = { package: string; @@ -261,7 +262,7 @@ export const doUpgrade = async ({ mainConfigPath, beforeVersion, storybookVersion: currentVersion, - isUpgrade: true, + isUpgrade: isOutdated ? true : 'latest', }); } From 54eccd103d247a33c2f3e1b3b9f171e02533938f Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Thu, 7 Mar 2024 17:31:50 +0100 Subject: [PATCH 02/16] improvements --- .../upgrade-storybook-related-dependencies.ts | 130 ++++++++++++------ code/lib/cli/src/automigrate/index.ts | 29 +++- code/lib/cli/src/automigrate/types.ts | 6 +- 3 files changed, 112 insertions(+), 53 deletions(-) diff --git a/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts b/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts index 234b35a1451c..2a0630960226 100644 --- a/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts +++ b/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts @@ -2,13 +2,13 @@ import { dedent } from 'ts-dedent'; import type { Fix } from '../types'; import { underline } from 'chalk'; import { getIncompatibleStorybookPackages } from '../../doctor/getIncompatibleStorybookPackages'; +import { valid, coerce } from 'semver'; interface Options { - list: { packageName: string; version: string }[]; + upgradable: { packageName: string; version: string }[]; + problematicPackages: { packageName: string; version: string }[]; } -type ExcludesFalse = (x: T | undefined) => x is T; - /** * Is the user upgrading to the `latest` version of Storybook? * Let's try to pull along some of the storybook related dependencies to `latest` as well! @@ -20,36 +20,62 @@ type ExcludesFalse = (x: T | undefined) => x is T; */ export const upgradeStorybookRelatedDependencies = { id: 'upgradeStorybookRelatedDependencies', - - versionRange: ['<8', '>=8'], + versionRange: ['*.*.*', '*.*.*'], + promptType: 'auto', + promptDefaultValue: false, async check({ packageManager, storybookVersion }) { - const out = await getIncompatibleStorybookPackages({ + const packageJson = await packageManager.readPackageJson(); + const analyzed = await getIncompatibleStorybookPackages({ currentStorybookVersion: storybookVersion, packageManager, skipErrors: true, }); - const list = await Promise.all( - out.map(async ({ packageName, hasIncompatibleDependencies }) => { - if (!hasIncompatibleDependencies) { - return; - } + const all = await packageManager.getAllDependencies(); + + const associated = Object.keys(all).filter((dep) => dep.includes('storybook')); + const detected = analyzed + .filter((m) => m.hasIncompatibleDependencies) + .map((m) => m.packageName); + const list = await Promise.all( + Array.from(new Set([...associated, ...detected])).map(async (packageName) => { return { packageName, - version: await packageManager.latestVersion(packageName), + version: await packageManager.latestVersion(packageName).catch((e) => null), }; }) ); - const filtered = list.filter(Boolean as any as ExcludesFalse); - return { list: filtered }; - }, + const data = list.reduce( + (acc, k) => { + const upgradable = !( + !valid(k.version) || + k.version === coerce(packageJson?.dependencies?.[k.packageName])?.toString() || + k.version === coerce(packageJson?.devDependencies?.[k.packageName])?.toString() || + k.version === coerce(packageJson?.peerDependencies?.[k.packageName])?.toString() + ); + + if (upgradable) { + acc.upgradable.push(k); + } else { + acc.problematicPackages.push(k); + } + + return acc; + }, + { upgradable: [], problematicPackages: [] } + ); + + if (data.upgradable.length > 0) { + return data; + } - promptType: 'auto-no', + return null; + }, - prompt({ list }) { + prompt({ upgradable: list }) { return dedent` You're upgrading to the latest version of Storybook. We recommend upgrading the following packages: ${list.map(({ packageName, version }) => `${packageName}@${version}`).join(', ')} @@ -66,40 +92,58 @@ export const upgradeStorybookRelatedDependencies = { `; }, - async run({ result: { list }, packageManager, dryRun, mainConfigPath }) { + async run({ result: { upgradable, problematicPackages }, packageManager, dryRun }) { if (dryRun) { console.log(dedent` - would have upgrade the following: - ${list.map(({ packageName, version }) => `${packageName}@${version}`).join('\n')} + We would have upgrade the following: + ${upgradable.map(({ packageName, version }) => `${packageName}@${version}`).join('\n')} `); return; } - const packageJson = await packageManager.readPackageJson(); + if (upgradable.length > 0) { + const packageJson = await packageManager.readPackageJson(); - // mutate the packageJson data - list.forEach((item) => { - if (!item) { - return; - } - - const { packageName, version } = item; - const prefixed = `^${version}`; - - if (packageJson.dependencies?.[packageName]) { - packageJson.dependencies[packageName] = prefixed; - } - if (packageJson.devDependencies?.[packageName]) { - packageJson.devDependencies[packageName] = prefixed; - } - if (packageJson.peerDependencies?.[packageName]) { - packageJson.peerDependencies[packageName] = prefixed; - } - }); + upgradable.forEach((item) => { + if (!item) { + return; + } + + const { packageName, version } = item; + const prefixed = `^${version}`; + + if (packageJson.dependencies?.[packageName]) { + packageJson.dependencies[packageName] = prefixed; + } + if (packageJson.devDependencies?.[packageName]) { + packageJson.devDependencies[packageName] = prefixed; + } + if (packageJson.peerDependencies?.[packageName]) { + packageJson.peerDependencies[packageName] = prefixed; + } + }); + + await packageManager.writePackageJson(packageJson); + await packageManager.installDependencies(); - await packageManager.writePackageJson(packageJson); - await packageManager.installDependencies(); + await packageManager + .executeCommand({ command: 'dedupe', args: [], stdio: 'ignore' }) + .catch((e) => {}); - await packageManager.getRunCommand('dedupe'); + console.log(dedent` + We upgraded ${upgradable.length} packages: + ${upgradable.map(({ packageName, version }) => `- ${packageName}@${version}`).join('\n')} + `); + } + + if (problematicPackages.length) { + console.log(dedent` + The following packages, could not be upgraded, likely because there's no update available that's compatible with the latest version of Storybook: + ${problematicPackages.map(({ packageName }) => `- ${packageName}`).join('\n')} + + We suggest your reach out to the authors of these packages to get them updated. + But before reporting, please check if there is already an open issue or PR for this. + `); + } }, } satisfies Fix; diff --git a/code/lib/cli/src/automigrate/index.ts b/code/lib/cli/src/automigrate/index.ts index 843b8f4371d6..20cbf98a4166 100644 --- a/code/lib/cli/src/automigrate/index.ts +++ b/code/lib/cli/src/automigrate/index.ts @@ -30,6 +30,7 @@ import { getStorybookData } from './helpers/mainConfigFile'; import { doctor } from '../doctor'; import { upgradeStorybookRelatedDependencies } from './fixes/upgrade-storybook-related-dependencies'; +import dedent from 'ts-dedent'; const logger = console; const LOG_FILE_NAME = 'migration-storybook.log'; @@ -58,8 +59,16 @@ const cleanup = () => { }; const logAvailableMigrations = () => { - const availableFixes = allFixes.map((f) => chalk.yellow(f.id)).join(', '); - logger.info(`\nThe following migrations are available: ${availableFixes}`); + const availableFixes = allFixes + .map((f) => chalk.yellow(f.id)) + .map((x) => `- ${x}`) + .join('\n'); + + console.log(); + logger.info(dedent` + The following migrations are available: + ${availableFixes} + `); }; export const doAutomigrate = async (options: AutofixOptionsFromCLI) => { @@ -86,7 +95,7 @@ export const doAutomigrate = async (options: AutofixOptionsFromCLI) => { throw new Error('Could not determine main config path'); } - await automigrate({ + const outcome = await automigrate({ ...options, packageManager, storybookVersion, @@ -96,7 +105,9 @@ export const doAutomigrate = async (options: AutofixOptionsFromCLI) => { isUpgrade: false, }); - await doctor({ configDir, packageManager: options.packageManager }); + if (outcome) { + await doctor({ configDir, packageManager: options.packageManager }); + } }; export const automigrate = async ({ @@ -127,7 +138,11 @@ export const automigrate = async ({ inputFixes || allFixes.filter((fix) => { // we only allow this automigration when the user explicitly asks for it, or they are upgrading to the latest version of storybook - if (fix.id === upgradeStorybookRelatedDependencies.id && isUpgrade !== 'latest') { + if ( + fix.id === upgradeStorybookRelatedDependencies.id && + isUpgrade !== 'latest' && + fixId !== upgradeStorybookRelatedDependencies.id + ) { return false; } @@ -319,13 +334,13 @@ export async function runFixes({ fixResults[f.id] = FixStatus.MANUAL_SKIPPED; break; } - } else if (promptType === 'auto' || promptType === 'auto-no') { + } else if (promptType === 'auto') { runAnswer = await prompts( { type: 'confirm', name: 'fix', message: `Do you want to run the '${chalk.cyan(f.id)}' migration on your project?`, - initial: promptType === 'auto-no' ? false : true, + initial: f.promptDefaultValue ?? true, }, { onCancel: () => { diff --git a/code/lib/cli/src/automigrate/types.ts b/code/lib/cli/src/automigrate/types.ts index 45f2b4b72c01..8dad3d3d2fa9 100644 --- a/code/lib/cli/src/automigrate/types.ts +++ b/code/lib/cli/src/automigrate/types.ts @@ -22,11 +22,10 @@ export interface RunOptions { /** * promptType defines how the user will be prompted to apply an automigration fix * - auto: the fix will be applied automatically - * - auto-no: the fix will be applied automatically, but only when the user opts-in * - manual: the user will be prompted to apply the fix * - notification: the user will be notified about some changes. A fix isn't required, though */ -export type Prompt = 'auto' | 'auto-no' | 'manual' | 'notification'; +export type Prompt = 'auto' | 'manual' | 'notification'; type BaseFix = { id: string; @@ -38,6 +37,7 @@ type BaseFix = { versionRange: [from: string, to: string]; check: (options: CheckOptions) => Promise; prompt: (result: ResultType) => string; + promptDefaultValue?: boolean; }; type PromptType = @@ -46,7 +46,7 @@ type PromptType = export type Fix = ( | { - promptType?: PromptType; + promptType?: PromptType; run: (options: RunOptions) => Promise; } | { From 604771126c573dfd2c6cd35df592e96c06847f9a Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Thu, 7 Mar 2024 18:16:38 +0100 Subject: [PATCH 03/16] make it look prettier --- .../upgrade-storybook-related-dependencies.ts | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts b/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts index 2a0630960226..bed260a4af66 100644 --- a/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts +++ b/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts @@ -1,6 +1,6 @@ import { dedent } from 'ts-dedent'; import type { Fix } from '../types'; -import { underline } from 'chalk'; +import { cyan, underline, yellow } from 'chalk'; import { getIncompatibleStorybookPackages } from '../../doctor/getIncompatibleStorybookPackages'; import { valid, coerce } from 'semver'; @@ -78,7 +78,9 @@ export const upgradeStorybookRelatedDependencies = { prompt({ upgradable: list }) { return dedent` You're upgrading to the latest version of Storybook. We recommend upgrading the following packages: - ${list.map(({ packageName, version }) => `${packageName}@${version}`).join(', ')} + ${list + .map(({ packageName, version }) => `- ${cyan(packageName)}@${cyan(version)}`) + .join('\n')} We detected those packages are incompatible with the latest version of Storybook. ${underline( @@ -130,20 +132,26 @@ export const upgradeStorybookRelatedDependencies = { .executeCommand({ command: 'dedupe', args: [], stdio: 'ignore' }) .catch((e) => {}); + console.log(); console.log(dedent` - We upgraded ${upgradable.length} packages: - ${upgradable.map(({ packageName, version }) => `- ${packageName}@${version}`).join('\n')} - `); + We upgraded ${yellow(upgradable.length)} packages: + ${upgradable + .map(({ packageName, version }) => `- ${cyan(packageName)}@${cyan(version)}`) + .join('\n')} + `); } if (problematicPackages.length) { + console.log(); console.log(dedent` - The following packages, could not be upgraded, likely because there's no update available that's compatible with the latest version of Storybook: - ${problematicPackages.map(({ packageName }) => `- ${packageName}`).join('\n')} + The following packages, could not be upgraded, + likely because there's no update available compatible with the latest version of Storybook: + ${problematicPackages.map(({ packageName }) => `- ${cyan(packageName)}`).join('\n')} We suggest your reach out to the authors of these packages to get them updated. But before reporting, please check if there is already an open issue or PR for this. - `); + `); } + console.log(); }, } satisfies Fix; From 6c5bb5ea71260dcfa056ab00d1a88e88ebb9d39c Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Thu, 7 Mar 2024 18:42:00 +0100 Subject: [PATCH 04/16] revert the use of satisfies --- code/lib/cli/src/automigrate/fixes/index.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/lib/cli/src/automigrate/fixes/index.ts b/code/lib/cli/src/automigrate/fixes/index.ts index 01bdc2b2aa94..022074fa8301 100644 --- a/code/lib/cli/src/automigrate/fixes/index.ts +++ b/code/lib/cli/src/automigrate/fixes/index.ts @@ -30,7 +30,7 @@ import { upgradeStorybookRelatedDependencies } from './upgrade-storybook-related export * from '../types'; -export const allFixes = [ +export const allFixes: Fix[] = [ addonsAPI, newFrameworks, cra5, @@ -58,6 +58,6 @@ export const allFixes = [ webpack5CompilerSetup, mdx1to3, upgradeStorybookRelatedDependencies, -] satisfies Fix[]; +]; -export const initFixes = [eslintPlugin] satisfies Fix[]; +export const initFixes: Fix[] = [eslintPlugin]; From 4c60e7b900f1d8903ba0de5eadad1e1b5be6bd18 Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Thu, 7 Mar 2024 18:53:13 +0100 Subject: [PATCH 05/16] minor typing issues fixed --- .../fixes/upgrade-storybook-related-dependencies.ts | 4 ++-- code/lib/cli/src/upgrade.ts | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts b/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts index bed260a4af66..1356c07d4c09 100644 --- a/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts +++ b/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts @@ -43,7 +43,7 @@ export const upgradeStorybookRelatedDependencies = { Array.from(new Set([...associated, ...detected])).map(async (packageName) => { return { packageName, - version: await packageManager.latestVersion(packageName).catch((e) => null), + version: await packageManager.latestVersion(packageName).catch(() => null), }; }) ); @@ -130,7 +130,7 @@ export const upgradeStorybookRelatedDependencies = { await packageManager .executeCommand({ command: 'dedupe', args: [], stdio: 'ignore' }) - .catch((e) => {}); + .catch(() => {}); console.log(); console.log(dedent` diff --git a/code/lib/cli/src/upgrade.ts b/code/lib/cli/src/upgrade.ts index 757ad89bdd7c..e49f668f4f87 100644 --- a/code/lib/cli/src/upgrade.ts +++ b/code/lib/cli/src/upgrade.ts @@ -22,7 +22,6 @@ import { } from '@storybook/core-common'; import { automigrate } from './automigrate/index'; import { autoblock } from './autoblock/index'; -import { is } from '@babel/types'; type Package = { package: string; From 586ba186ae140f7d300755b7abdc121c1168d282 Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Thu, 7 Mar 2024 19:00:46 +0100 Subject: [PATCH 06/16] fix another typing issue --- .../upgrade-storybook-related-dependencies.ts | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts b/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts index 1356c07d4c09..4f1ab90b818b 100644 --- a/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts +++ b/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts @@ -50,17 +50,20 @@ export const upgradeStorybookRelatedDependencies = { const data = list.reduce( (acc, k) => { - const upgradable = !( - !valid(k.version) || - k.version === coerce(packageJson?.dependencies?.[k.packageName])?.toString() || - k.version === coerce(packageJson?.devDependencies?.[k.packageName])?.toString() || - k.version === coerce(packageJson?.peerDependencies?.[k.packageName])?.toString() - ); - - if (upgradable) { - acc.upgradable.push(k); - } else { - acc.problematicPackages.push(k); + if (k.version !== null) { + const { packageName, version } = k; + const upgradable = !( + !valid(k.version) || + k.version === coerce(packageJson?.dependencies?.[k.packageName])?.toString() || + k.version === coerce(packageJson?.devDependencies?.[k.packageName])?.toString() || + k.version === coerce(packageJson?.peerDependencies?.[k.packageName])?.toString() + ); + + if (upgradable) { + acc.upgradable.push({ packageName, version }); + } else { + acc.problematicPackages.push({ packageName, version }); + } } return acc; From fa2b315bcc30ad7d13e3134fcd64e3f6bd18438a Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Fri, 8 Mar 2024 13:56:16 +0100 Subject: [PATCH 07/16] Update code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts Co-authored-by: Michael Shilman --- .../automigrate/fixes/upgrade-storybook-related-dependencies.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts b/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts index 4f1ab90b818b..b2804e1496bf 100644 --- a/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts +++ b/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts @@ -147,7 +147,7 @@ export const upgradeStorybookRelatedDependencies = { if (problematicPackages.length) { console.log(); console.log(dedent` - The following packages, could not be upgraded, + The following packages could not be upgraded, likely because there's no update available compatible with the latest version of Storybook: ${problematicPackages.map(({ packageName }) => `- ${cyan(packageName)}`).join('\n')} From af63b0fd0191acb067cfc3036d991c9040f96cde Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Fri, 8 Mar 2024 14:48:26 +0100 Subject: [PATCH 08/16] wip --- .../upgrade-storybook-related-dependencies.ts | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts b/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts index b2804e1496bf..afa17b5440c6 100644 --- a/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts +++ b/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts @@ -1,8 +1,9 @@ import { dedent } from 'ts-dedent'; import type { Fix } from '../types'; -import { cyan, underline, yellow } from 'chalk'; +import { cyan, yellow } from 'chalk'; import { getIncompatibleStorybookPackages } from '../../doctor/getIncompatibleStorybookPackages'; import { valid, coerce } from 'semver'; +import { isCorePackage } from '@storybook/core-common'; interface Options { upgradable: { packageName: string; version: string }[]; @@ -34,7 +35,9 @@ export const upgradeStorybookRelatedDependencies = { const all = await packageManager.getAllDependencies(); - const associated = Object.keys(all).filter((dep) => dep.includes('storybook')); + const associated = Object.keys(all) + .filter((dep) => dep.includes('storybook')) + .filter(isCorePackage); const detected = analyzed .filter((m) => m.hasIncompatibleDependencies) .map((m) => m.packageName); @@ -85,12 +88,7 @@ export const upgradeStorybookRelatedDependencies = { .map(({ packageName, version }) => `- ${cyan(packageName)}@${cyan(version)}`) .join('\n')} - We detected those packages are incompatible with the latest version of Storybook. - ${underline( - `The list might be incomplete, so it's advised to upgrade dependencies manually, but this automigration can help you get started.` - )} - - After upgrading, we will run the dedupe command, which could possibly have effects on dependencies that are not storybook related. + After upgrading, we will run the dedupe command, which could possibly have effects on dependencies that are not Storybook related. see: https://docs.npmjs.com/cli/commands/npm-dedupe Do you want to proceed (upgrade the detected packages)? From 9dfb3aaaceb29d621d9dbcf28b05174123a42956 Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Fri, 8 Mar 2024 15:11:38 +0100 Subject: [PATCH 09/16] make it better --- .../upgrade-storybook-related-dependencies.ts | 124 +++++++++++------- 1 file changed, 75 insertions(+), 49 deletions(-) diff --git a/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts b/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts index afa17b5440c6..aefa841f91c2 100644 --- a/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts +++ b/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts @@ -3,11 +3,59 @@ import type { Fix } from '../types'; import { cyan, yellow } from 'chalk'; import { getIncompatibleStorybookPackages } from '../../doctor/getIncompatibleStorybookPackages'; import { valid, coerce } from 'semver'; +import type { JsPackageManager } from '@storybook/core-common'; import { isCorePackage } from '@storybook/core-common'; +type PackageMetadata = { + packageName: string; + beforeVersion: string; + afterVersion: string | null; +}; + interface Options { - upgradable: { packageName: string; version: string }[]; - problematicPackages: { packageName: string; version: string }[]; + upgradable: PackageMetadata[]; + problematicPackages: PackageMetadata[]; +} + +async function getLatestVersions( + packageManager: JsPackageManager, + packages: [string, string][] +): Promise { + return Promise.all( + packages.map(async ([packageName, beforeVersion]) => ({ + packageName, + beforeVersion, + afterVersion: await packageManager.latestVersion(packageName).catch(() => null), + })) + ); +} + +function isPackageUpgradable( + version: string, + packageName: string, + allDependencies: Record +) { + const installedVersion = coerce(allDependencies[packageName])?.toString(); + + return valid(version) && version !== installedVersion; +} + +function categorizePackages( + packageVersions: PackageMetadata[], + allDependencies: Record +) { + return packageVersions.reduce( + (acc, { packageName, afterVersion, beforeVersion }) => { + if (afterVersion === null) return acc; + + const isUpgradable = isPackageUpgradable(afterVersion, packageName, allDependencies); + const category = isUpgradable ? 'upgradable' : 'problematicPackages'; + acc[category].push({ packageName, afterVersion, beforeVersion }); + + return acc; + }, + { upgradable: [], problematicPackages: [] } as Options + ); } /** @@ -26,66 +74,37 @@ export const upgradeStorybookRelatedDependencies = { promptDefaultValue: false, async check({ packageManager, storybookVersion }) { - const packageJson = await packageManager.readPackageJson(); - const analyzed = await getIncompatibleStorybookPackages({ + const analyzedPackages = await getIncompatibleStorybookPackages({ currentStorybookVersion: storybookVersion, packageManager, skipErrors: true, }); - const all = await packageManager.getAllDependencies(); - - const associated = Object.keys(all) + const allDependencies = (await packageManager.getAllDependencies()) as Record; + const storybookDependencies = Object.keys(allDependencies) .filter((dep) => dep.includes('storybook')) .filter(isCorePackage); - const detected = analyzed - .filter((m) => m.hasIncompatibleDependencies) - .map((m) => m.packageName); - - const list = await Promise.all( - Array.from(new Set([...associated, ...detected])).map(async (packageName) => { - return { - packageName, - version: await packageManager.latestVersion(packageName).catch(() => null), - }; - }) - ); - - const data = list.reduce( - (acc, k) => { - if (k.version !== null) { - const { packageName, version } = k; - const upgradable = !( - !valid(k.version) || - k.version === coerce(packageJson?.dependencies?.[k.packageName])?.toString() || - k.version === coerce(packageJson?.devDependencies?.[k.packageName])?.toString() || - k.version === coerce(packageJson?.peerDependencies?.[k.packageName])?.toString() - ); - - if (upgradable) { - acc.upgradable.push({ packageName, version }); - } else { - acc.problematicPackages.push({ packageName, version }); - } - } + const incompatibleDependencies = analyzedPackages + .filter((pkg) => pkg.hasIncompatibleDependencies) + .map((pkg) => pkg.packageName); - return acc; - }, - { upgradable: [], problematicPackages: [] } - ); + const uniquePackages = Array.from( + new Set([...storybookDependencies, ...incompatibleDependencies]) + ).map((packageName) => [packageName, allDependencies[packageName]]) as [string, string][]; - if (data.upgradable.length > 0) { - return data; - } + const packageVersions = await getLatestVersions(packageManager, uniquePackages); + const categorizedPackages = categorizePackages(packageVersions, allDependencies); - return null; + return categorizedPackages.upgradable.length > 0 ? categorizedPackages : null; }, prompt({ upgradable: list }) { return dedent` You're upgrading to the latest version of Storybook. We recommend upgrading the following packages: ${list - .map(({ packageName, version }) => `- ${cyan(packageName)}@${cyan(version)}`) + .map(({ packageName, afterVersion, beforeVersion }) => { + return `- ${cyan(packageName)}: ${cyan(beforeVersion)} => ${cyan(afterVersion)}`; + }) .join('\n')} After upgrading, we will run the dedupe command, which could possibly have effects on dependencies that are not Storybook related. @@ -99,7 +118,12 @@ export const upgradeStorybookRelatedDependencies = { if (dryRun) { console.log(dedent` We would have upgrade the following: - ${upgradable.map(({ packageName, version }) => `${packageName}@${version}`).join('\n')} + ${upgradable + .map( + ({ packageName, afterVersion, beforeVersion }) => + `${packageName}: ${beforeVersion} => ${afterVersion}` + ) + .join('\n')} `); return; } @@ -112,7 +136,7 @@ export const upgradeStorybookRelatedDependencies = { return; } - const { packageName, version } = item; + const { packageName, afterVersion: version } = item; const prefixed = `^${version}`; if (packageJson.dependencies?.[packageName]) { @@ -137,7 +161,9 @@ export const upgradeStorybookRelatedDependencies = { console.log(dedent` We upgraded ${yellow(upgradable.length)} packages: ${upgradable - .map(({ packageName, version }) => `- ${cyan(packageName)}@${cyan(version)}`) + .map(({ packageName, afterVersion, beforeVersion }) => { + return `- ${cyan(packageName)}: ${cyan(beforeVersion)} => ${cyan(afterVersion)}`; + }) .join('\n')} `); } From 9d552b2bcd4037cf9c48e1817b46e43a464ca087 Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Fri, 8 Mar 2024 15:14:47 +0100 Subject: [PATCH 10/16] even better --- .../fixes/upgrade-storybook-related-dependencies.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts b/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts index aefa841f91c2..d325ad0f7887 100644 --- a/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts +++ b/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts @@ -172,10 +172,10 @@ export const upgradeStorybookRelatedDependencies = { console.log(); console.log(dedent` The following packages could not be upgraded, - likely because there's no update available compatible with the latest version of Storybook: + likely because there's no stable update available which is compatible with the latest version of Storybook: ${problematicPackages.map(({ packageName }) => `- ${cyan(packageName)}`).join('\n')} - We suggest your reach out to the authors of these packages to get them updated. + We suggest you to reach out to the maintainers of these packages to get them updated. But before reporting, please check if there is already an open issue or PR for this. `); } From becdbd935851d45b67eba6659b3d05bc5479becf Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Fri, 8 Mar 2024 15:35:40 +0100 Subject: [PATCH 11/16] remove the problematicPackages feature --- .../upgrade-storybook-related-dependencies.ts | 53 +++++-------------- 1 file changed, 14 insertions(+), 39 deletions(-) diff --git a/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts b/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts index d325ad0f7887..3f6ea69f29bc 100644 --- a/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts +++ b/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts @@ -14,7 +14,6 @@ type PackageMetadata = { interface Options { upgradable: PackageMetadata[]; - problematicPackages: PackageMetadata[]; } async function getLatestVersions( @@ -31,31 +30,13 @@ async function getLatestVersions( } function isPackageUpgradable( - version: string, + afterVersion: string, packageName: string, allDependencies: Record ) { const installedVersion = coerce(allDependencies[packageName])?.toString(); - return valid(version) && version !== installedVersion; -} - -function categorizePackages( - packageVersions: PackageMetadata[], - allDependencies: Record -) { - return packageVersions.reduce( - (acc, { packageName, afterVersion, beforeVersion }) => { - if (afterVersion === null) return acc; - - const isUpgradable = isPackageUpgradable(afterVersion, packageName, allDependencies); - const category = isUpgradable ? 'upgradable' : 'problematicPackages'; - acc[category].push({ packageName, afterVersion, beforeVersion }); - - return acc; - }, - { upgradable: [], problematicPackages: [] } as Options - ); + return valid(afterVersion) && afterVersion !== installedVersion; } /** @@ -83,7 +64,7 @@ export const upgradeStorybookRelatedDependencies = { const allDependencies = (await packageManager.getAllDependencies()) as Record; const storybookDependencies = Object.keys(allDependencies) .filter((dep) => dep.includes('storybook')) - .filter(isCorePackage); + .filter((dep) => !isCorePackage(dep)); const incompatibleDependencies = analyzedPackages .filter((pkg) => pkg.hasIncompatibleDependencies) .map((pkg) => pkg.packageName); @@ -93,15 +74,21 @@ export const upgradeStorybookRelatedDependencies = { ).map((packageName) => [packageName, allDependencies[packageName]]) as [string, string][]; const packageVersions = await getLatestVersions(packageManager, uniquePackages); - const categorizedPackages = categorizePackages(packageVersions, allDependencies); + const upgradablePackages = packageVersions.filter(({ packageName, afterVersion }) => { + if (afterVersion === null) { + return false; + } - return categorizedPackages.upgradable.length > 0 ? categorizedPackages : null; + return isPackageUpgradable(afterVersion, packageName, allDependencies); + }); + + return upgradablePackages.length > 0 ? upgradablePackages : null; }, - prompt({ upgradable: list }) { + prompt({ upgradable }) { return dedent` You're upgrading to the latest version of Storybook. We recommend upgrading the following packages: - ${list + ${upgradable .map(({ packageName, afterVersion, beforeVersion }) => { return `- ${cyan(packageName)}: ${cyan(beforeVersion)} => ${cyan(afterVersion)}`; }) @@ -114,7 +101,7 @@ export const upgradeStorybookRelatedDependencies = { `; }, - async run({ result: { upgradable, problematicPackages }, packageManager, dryRun }) { + async run({ result: { upgradable }, packageManager, dryRun }) { if (dryRun) { console.log(dedent` We would have upgrade the following: @@ -167,18 +154,6 @@ export const upgradeStorybookRelatedDependencies = { .join('\n')} `); } - - if (problematicPackages.length) { - console.log(); - console.log(dedent` - The following packages could not be upgraded, - likely because there's no stable update available which is compatible with the latest version of Storybook: - ${problematicPackages.map(({ packageName }) => `- ${cyan(packageName)}`).join('\n')} - - We suggest you to reach out to the maintainers of these packages to get them updated. - But before reporting, please check if there is already an open issue or PR for this. - `); - } console.log(); }, } satisfies Fix; From 80a112de3c2a2446ab5253d6b9efbe83822d8fb0 Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Fri, 8 Mar 2024 15:37:44 +0100 Subject: [PATCH 12/16] fix --- .../automigrate/fixes/upgrade-storybook-related-dependencies.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts b/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts index 3f6ea69f29bc..3bc835050972 100644 --- a/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts +++ b/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts @@ -82,7 +82,7 @@ export const upgradeStorybookRelatedDependencies = { return isPackageUpgradable(afterVersion, packageName, allDependencies); }); - return upgradablePackages.length > 0 ? upgradablePackages : null; + return upgradablePackages.length > 0 ? { upgradable: upgradablePackages } : null; }, prompt({ upgradable }) { From b4e944d608fe02a951482e2258e770c129cacc7e Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Fri, 8 Mar 2024 15:43:43 +0100 Subject: [PATCH 13/16] ship it --- .../upgrade-storybook-related-dependencies.ts | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts b/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts index 3bc835050972..c780d5eff59e 100644 --- a/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts +++ b/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts @@ -8,7 +8,7 @@ import { isCorePackage } from '@storybook/core-common'; type PackageMetadata = { packageName: string; - beforeVersion: string; + beforeVersion: string | null; afterVersion: string | null; }; @@ -23,7 +23,7 @@ async function getLatestVersions( return Promise.all( packages.map(async ([packageName, beforeVersion]) => ({ packageName, - beforeVersion, + beforeVersion: coerce(beforeVersion)?.toString() || null, afterVersion: await packageManager.latestVersion(packageName).catch(() => null), })) ); @@ -74,13 +74,18 @@ export const upgradeStorybookRelatedDependencies = { ).map((packageName) => [packageName, allDependencies[packageName]]) as [string, string][]; const packageVersions = await getLatestVersions(packageManager, uniquePackages); - const upgradablePackages = packageVersions.filter(({ packageName, afterVersion }) => { - if (afterVersion === null) { - return false; - } + const upgradablePackages = packageVersions.filter( + ({ packageName, afterVersion, beforeVersion }) => { + if (beforeVersion === null) { + return false; + } + if (afterVersion === null) { + return false; + } - return isPackageUpgradable(afterVersion, packageName, allDependencies); - }); + return isPackageUpgradable(afterVersion, packageName, allDependencies); + } + ); return upgradablePackages.length > 0 ? { upgradable: upgradablePackages } : null; }, From 909cb23f3876abc7f642c40f7f365fbee4745458 Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Fri, 8 Mar 2024 15:57:34 +0100 Subject: [PATCH 14/16] remove hard-coded login in inner command --- .../upgrade-storybook-related-dependencies.ts | 6 ++++++ code/lib/cli/src/automigrate/index.ts | 16 +--------------- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts b/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts index c780d5eff59e..7a57e38c7d8d 100644 --- a/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts +++ b/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts @@ -55,6 +55,12 @@ export const upgradeStorybookRelatedDependencies = { promptDefaultValue: false, async check({ packageManager, storybookVersion }) { + const latestStorybookVersion = await packageManager.latestVersion('storybook'); + + if (storybookVersion !== latestStorybookVersion) { + return null; + } + const analyzedPackages = await getIncompatibleStorybookPackages({ currentStorybookVersion: storybookVersion, packageManager, diff --git a/code/lib/cli/src/automigrate/index.ts b/code/lib/cli/src/automigrate/index.ts index 20cbf98a4166..8ae73c57102a 100644 --- a/code/lib/cli/src/automigrate/index.ts +++ b/code/lib/cli/src/automigrate/index.ts @@ -29,7 +29,6 @@ import { getMigrationSummary } from './helpers/getMigrationSummary'; import { getStorybookData } from './helpers/mainConfigFile'; import { doctor } from '../doctor'; -import { upgradeStorybookRelatedDependencies } from './fixes/upgrade-storybook-related-dependencies'; import dedent from 'ts-dedent'; const logger = console; @@ -134,20 +133,7 @@ export const automigrate = async ({ return null; } - const selectedFixes: Fix[] = - inputFixes || - allFixes.filter((fix) => { - // we only allow this automigration when the user explicitly asks for it, or they are upgrading to the latest version of storybook - if ( - fix.id === upgradeStorybookRelatedDependencies.id && - isUpgrade !== 'latest' && - fixId !== upgradeStorybookRelatedDependencies.id - ) { - return false; - } - - return true; - }); + const selectedFixes: Fix[] = inputFixes || allFixes; const fixes: Fix[] = fixId ? selectedFixes.filter((f) => f.id === fixId) : selectedFixes; if (fixId && fixes.length === 0) { From b1978746c568716ade7d26dc5bffd95ecee3d3c8 Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Fri, 8 Mar 2024 15:58:59 +0100 Subject: [PATCH 15/16] Revert "remove hard-coded login in inner command" This reverts commit 909cb23f3876abc7f642c40f7f365fbee4745458. --- .../upgrade-storybook-related-dependencies.ts | 6 ------ code/lib/cli/src/automigrate/index.ts | 16 +++++++++++++++- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts b/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts index 7a57e38c7d8d..c780d5eff59e 100644 --- a/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts +++ b/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts @@ -55,12 +55,6 @@ export const upgradeStorybookRelatedDependencies = { promptDefaultValue: false, async check({ packageManager, storybookVersion }) { - const latestStorybookVersion = await packageManager.latestVersion('storybook'); - - if (storybookVersion !== latestStorybookVersion) { - return null; - } - const analyzedPackages = await getIncompatibleStorybookPackages({ currentStorybookVersion: storybookVersion, packageManager, diff --git a/code/lib/cli/src/automigrate/index.ts b/code/lib/cli/src/automigrate/index.ts index 8ae73c57102a..20cbf98a4166 100644 --- a/code/lib/cli/src/automigrate/index.ts +++ b/code/lib/cli/src/automigrate/index.ts @@ -29,6 +29,7 @@ import { getMigrationSummary } from './helpers/getMigrationSummary'; import { getStorybookData } from './helpers/mainConfigFile'; import { doctor } from '../doctor'; +import { upgradeStorybookRelatedDependencies } from './fixes/upgrade-storybook-related-dependencies'; import dedent from 'ts-dedent'; const logger = console; @@ -133,7 +134,20 @@ export const automigrate = async ({ return null; } - const selectedFixes: Fix[] = inputFixes || allFixes; + const selectedFixes: Fix[] = + inputFixes || + allFixes.filter((fix) => { + // we only allow this automigration when the user explicitly asks for it, or they are upgrading to the latest version of storybook + if ( + fix.id === upgradeStorybookRelatedDependencies.id && + isUpgrade !== 'latest' && + fixId !== upgradeStorybookRelatedDependencies.id + ) { + return false; + } + + return true; + }); const fixes: Fix[] = fixId ? selectedFixes.filter((f) => f.id === fixId) : selectedFixes; if (fixId && fixes.length === 0) { From b74ca127bc2eff8ffd9b70b2d61f8327f54c3c40 Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Fri, 8 Mar 2024 16:07:10 +0100 Subject: [PATCH 16/16] add tests --- ...ade-storybook-related-dependencies.test.ts | 95 +++++++++++++++++++ .../upgrade-storybook-related-dependencies.ts | 10 +- 2 files changed, 99 insertions(+), 6 deletions(-) create mode 100644 code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.test.ts diff --git a/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.test.ts b/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.test.ts new file mode 100644 index 000000000000..0c16309647bd --- /dev/null +++ b/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.test.ts @@ -0,0 +1,95 @@ +import { describe, afterEach, it, expect, vi } from 'vitest'; +import type { StorybookConfig } from '@storybook/types'; +import type { JsPackageManager } from '@storybook/core-common'; +import * as docsUtils from '../../doctor/getIncompatibleStorybookPackages'; + +import { upgradeStorybookRelatedDependencies } from './upgrade-storybook-related-dependencies'; + +vi.mock('../../doctor/getIncompatibleStorybookPackages'); + +const check = async ({ + packageManager, + main: mainConfig = {}, + storybookVersion = '8.0.0', +}: { + packageManager: Partial; + main?: Partial & Record; + storybookVersion?: string; +}) => { + return upgradeStorybookRelatedDependencies.check({ + packageManager: packageManager as any, + configDir: '', + mainConfig: mainConfig as any, + storybookVersion, + }); +}; + +describe('upgrade-storybook-related-dependencies fix', () => { + afterEach(() => { + vi.restoreAllMocks(); + }); + + it('should detect storyshots registered in main.js', async () => { + const analyzedPackages = [ + { + packageName: '@chromatic-com/storybook', + packageVersion: '1.2.9', + availableUpgrade: '2.0.0', + hasIncompatibleDependencies: false, + }, + { + packageName: '@storybook/jest', + packageVersion: '0.2.3', + availableUpgrade: '1.0.0', + hasIncompatibleDependencies: false, + }, + { + packageName: '@storybook/preset-create-react-app', + packageVersion: '3.2.0', + availableUpgrade: '8.0.0', + hasIncompatibleDependencies: true, + }, + { + packageName: 'storybook', + packageVersion: '8.0.0', + availableUpgrade: undefined, + hasIncompatibleDependencies: true, + }, + ]; + vi.mocked(docsUtils.getIncompatibleStorybookPackages).mockResolvedValue(analyzedPackages); + await expect( + check({ + packageManager: { + getAllDependencies: async () => ({ + '@chromatic-com/storybook': '1.2.9', + '@storybook/jest': '0.2.3', + '@storybook/preset-create-react-app': '3.2.0', + storybook: '8.0.0', + }), + latestVersion: async (pkgName) => + analyzedPackages.find((pkg) => pkg.packageName === pkgName)?.availableUpgrade || '', + }, + }) + ).resolves.toMatchInlineSnapshot(` + { + "upgradable": [ + { + "afterVersion": "2.0.0", + "beforeVersion": "1.2.9", + "packageName": "@chromatic-com/storybook", + }, + { + "afterVersion": "1.0.0", + "beforeVersion": "0.2.3", + "packageName": "@storybook/jest", + }, + { + "afterVersion": "8.0.0", + "beforeVersion": "3.2.0", + "packageName": "@storybook/preset-create-react-app", + }, + ], + } + `); + }); +}); diff --git a/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts b/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts index c780d5eff59e..5614b7e35ad0 100644 --- a/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts +++ b/code/lib/cli/src/automigrate/fixes/upgrade-storybook-related-dependencies.ts @@ -1,10 +1,10 @@ import { dedent } from 'ts-dedent'; -import type { Fix } from '../types'; import { cyan, yellow } from 'chalk'; -import { getIncompatibleStorybookPackages } from '../../doctor/getIncompatibleStorybookPackages'; import { valid, coerce } from 'semver'; import type { JsPackageManager } from '@storybook/core-common'; import { isCorePackage } from '@storybook/core-common'; +import type { Fix } from '../types'; +import { getIncompatibleStorybookPackages } from '../../doctor/getIncompatibleStorybookPackages'; type PackageMetadata = { packageName: string; @@ -74,12 +74,10 @@ export const upgradeStorybookRelatedDependencies = { ).map((packageName) => [packageName, allDependencies[packageName]]) as [string, string][]; const packageVersions = await getLatestVersions(packageManager, uniquePackages); + const upgradablePackages = packageVersions.filter( ({ packageName, afterVersion, beforeVersion }) => { - if (beforeVersion === null) { - return false; - } - if (afterVersion === null) { + if (beforeVersion === null || afterVersion === null) { return false; }