From 5ed707f5d18341a14cb27a6b000e4cc848f49ec2 Mon Sep 17 00:00:00 2001 From: Ian VanSchooten Date: Fri, 28 Oct 2022 08:20:37 -0400 Subject: [PATCH 01/20] Remove .prettierrc files --- code/.prettierrc | 8 -------- scripts/.prettierrc | 8 -------- 2 files changed, 16 deletions(-) delete mode 100644 code/.prettierrc delete mode 100644 scripts/.prettierrc diff --git a/code/.prettierrc b/code/.prettierrc deleted file mode 100644 index d033feea7ad..00000000000 --- a/code/.prettierrc +++ /dev/null @@ -1,8 +0,0 @@ -{ - "printWidth": 100, - "tabWidth": 2, - "bracketSpacing": true, - "trailingComma": "es5", - "singleQuote": true, - "arrowParens": "always" -} diff --git a/scripts/.prettierrc b/scripts/.prettierrc deleted file mode 100644 index d033feea7ad..00000000000 --- a/scripts/.prettierrc +++ /dev/null @@ -1,8 +0,0 @@ -{ - "printWidth": 100, - "tabWidth": 2, - "bracketSpacing": true, - "trailingComma": "es5", - "singleQuote": true, - "arrowParens": "always" -} From d99ed8af01c3a7652f1ebf8fe9df6769f49722fc Mon Sep 17 00:00:00 2001 From: Ian VanSchooten Date: Fri, 28 Oct 2022 08:20:58 -0400 Subject: [PATCH 02/20] Remove html parser override --- scripts/prettier.config.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/scripts/prettier.config.js b/scripts/prettier.config.js index c2fbdcbf6ed..b1a30ba19f8 100644 --- a/scripts/prettier.config.js +++ b/scripts/prettier.config.js @@ -3,10 +3,4 @@ const base = require('@storybook/linter-config/prettier.config'); module.exports = { ...base, arrowParens: 'always', - overrides: [ - { - files: '*.html', - options: { parser: 'babel' }, - }, - ], }; From 40381d20024c41d2a4c22f5c0b56279fc8ac5951 Mon Sep 17 00:00:00 2001 From: Ian VanSchooten Date: Fri, 28 Oct 2022 08:29:54 -0400 Subject: [PATCH 03/20] Allow up to prettier 3 --- code/lib/codemod/package.json | 2 +- code/lib/source-loader/package.json | 2 +- code/yarn.lock | 15 +++------------ scripts/package.json | 2 +- scripts/yarn.lock | 10 +++++----- 5 files changed, 11 insertions(+), 20 deletions(-) diff --git a/code/lib/codemod/package.json b/code/lib/codemod/package.json index dec7f71fbde..fc3e6aec334 100644 --- a/code/lib/codemod/package.json +++ b/code/lib/codemod/package.json @@ -46,7 +46,7 @@ "globby": "^11.0.2", "jscodeshift": "^0.13.1", "lodash": "^4.17.21", - "prettier": ">=2.2.1 <=2.3.0", + "prettier": ">=2.2.1 <=3.0.0", "recast": "^0.19.0", "util": "^0.12.4" }, diff --git a/code/lib/source-loader/package.json b/code/lib/source-loader/package.json index f29407d09a0..deb1de5902c 100644 --- a/code/lib/source-loader/package.json +++ b/code/lib/source-loader/package.json @@ -47,7 +47,7 @@ "@storybook/types": "7.0.0-alpha.45", "estraverse": "^5.2.0", "lodash": "^4.17.21", - "prettier": ">=2.2.1 <=2.3.0" + "prettier": ">=2.2.1 <=3.0.0" }, "devDependencies": { "jest-specific-snapshot": "^4.0.0", diff --git a/code/yarn.lock b/code/yarn.lock index 363d89520af..dd01e87ce60 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -6415,7 +6415,7 @@ __metadata: jest-specific-snapshot: ^4.0.0 jscodeshift: ^0.13.1 lodash: ^4.17.21 - prettier: ">=2.2.1 <=2.3.0" + prettier: ">=2.2.1 <=3.0.0" recast: ^0.19.0 typescript: ~4.6.3 util: ^0.12.4 @@ -7699,7 +7699,7 @@ __metadata: estraverse: ^5.2.0 jest-specific-snapshot: ^4.0.0 lodash: ^4.17.21 - prettier: ">=2.2.1 <=2.3.0" + prettier: ">=2.2.1 <=3.0.0" typescript: ~4.6.3 peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 @@ -28639,7 +28639,7 @@ __metadata: languageName: node linkType: hard -"prettier@npm:2.7.1, prettier@npm:>=2.5, prettier@npm:^1.18.2 || ^2.0.0": +"prettier@npm:2.7.1, prettier@npm:>=2.2.1 <=3.0.0, prettier@npm:>=2.5, prettier@npm:^1.18.2 || ^2.0.0": version: 2.7.1 resolution: "prettier@npm:2.7.1" bin: @@ -28648,15 +28648,6 @@ __metadata: languageName: node linkType: hard -"prettier@npm:>=2.2.1 <=2.3.0": - version: 2.3.0 - resolution: "prettier@npm:2.3.0" - bin: - prettier: bin-prettier.js - checksum: b9f434af2f25a37aad0b133894827e980885eb8bf317444c9dde0401ed2c7f463f9996d691f5ee5a0a4450ab46a894cd6557516b561e2522821522ce1f4c6668 - languageName: node - linkType: hard - "pretty-bytes@npm:^5.3.0": version: 5.6.0 resolution: "pretty-bytes@npm:5.6.0" diff --git a/scripts/package.json b/scripts/package.json index 48f8a8646bd..e7190c1c757 100644 --- a/scripts/package.json +++ b/scripts/package.json @@ -147,7 +147,7 @@ "npmlog": "^5.0.1", "nx": "14.6.1", "p-limit": "^3.1.0", - "prettier": ">=2.2.1 <=2.3.0", + "prettier": ">=2.2.1 <=3.0.0", "pretty-hrtime": "^1.0.0", "process": "^0.11.10", "prompts": "^2.4.0", diff --git a/scripts/yarn.lock b/scripts/yarn.lock index d55dc7d41ec..fb167307ddc 100644 --- a/scripts/yarn.lock +++ b/scripts/yarn.lock @@ -3431,7 +3431,7 @@ __metadata: npmlog: ^5.0.1 nx: 14.6.1 p-limit: ^3.1.0 - prettier: ">=2.2.1 <=2.3.0" + prettier: ">=2.2.1 <=3.0.0" pretty-hrtime: ^1.0.0 process: ^0.11.10 prompts: ^2.4.0 @@ -15669,12 +15669,12 @@ __metadata: languageName: node linkType: hard -"prettier@npm:>=2.2.1 <=2.3.0": - version: 2.3.0 - resolution: "prettier@npm:2.3.0" +"prettier@npm:>=2.2.1 <=3.0.0": + version: 2.7.1 + resolution: "prettier@npm:2.7.1" bin: prettier: bin-prettier.js - checksum: b9f434af2f25a37aad0b133894827e980885eb8bf317444c9dde0401ed2c7f463f9996d691f5ee5a0a4450ab46a894cd6557516b561e2522821522ce1f4c6668 + checksum: 359d2b7ecf36bd52924a48331cae506d335f18637fde6c686212f952b9ce678ce9f554a80571049b36ec2897a8a6c40094b776dea371cc5c04c481cf5b78504b languageName: node linkType: hard From 4368b1569df0f2b296189ad5f3f8add9522d4ddd Mon Sep 17 00:00:00 2001 From: Ian VanSchooten Date: Fri, 28 Oct 2022 09:10:49 -0400 Subject: [PATCH 04/20] Make prettier a dependency of @storybook/components --- code/ui/components/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/ui/components/package.json b/code/ui/components/package.json index 4291f4db779..e75af8645fc 100644 --- a/code/ui/components/package.json +++ b/code/ui/components/package.json @@ -56,6 +56,7 @@ "@storybook/theming": "7.0.0-alpha.45", "@storybook/types": "7.0.0-alpha.45", "memoizerific": "^1.11.3", + "prettier": ">=2.5", "util-deprecate": "^1.0.2" }, "devDependencies": { @@ -67,7 +68,6 @@ "global": "^4.4.0", "overlayscrollbars": "^1.13.1", "polished": "^4.2.2", - "prettier": ">=2.5", "react-popper-tooltip": "^3.1.1", "react-syntax-highlighter": "^15.4.5", "react-textarea-autosize": "^8.3.0", From 3488284643af536095be2b9c72080c74e3bf5aac Mon Sep 17 00:00:00 2001 From: Ian VanSchooten Date: Mon, 31 Oct 2022 11:50:22 -0400 Subject: [PATCH 05/20] Restore prettier to devDependencies, so it is bundled --- code/ui/components/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/ui/components/package.json b/code/ui/components/package.json index e75af8645fc..4291f4db779 100644 --- a/code/ui/components/package.json +++ b/code/ui/components/package.json @@ -56,7 +56,6 @@ "@storybook/theming": "7.0.0-alpha.45", "@storybook/types": "7.0.0-alpha.45", "memoizerific": "^1.11.3", - "prettier": ">=2.5", "util-deprecate": "^1.0.2" }, "devDependencies": { @@ -68,6 +67,7 @@ "global": "^4.4.0", "overlayscrollbars": "^1.13.1", "polished": "^4.2.2", + "prettier": ">=2.5", "react-popper-tooltip": "^3.1.1", "react-syntax-highlighter": "^15.4.5", "react-textarea-autosize": "^8.3.0", From 6e256cd2ab9d53c630786ae2b4a064be2eadf4f2 Mon Sep 17 00:00:00 2001 From: Tom Coleman Date: Wed, 2 Nov 2022 16:19:51 +1100 Subject: [PATCH 06/20] Allow setting `docsPage = automatic` to set docs entries for all components --- code/lib/client-api/src/StoryStoreFacade.ts | 8 ++-- code/lib/core-client/src/start.test.ts | 44 +++++++++++++++++++ .../src/utils/StoryIndexGenerator.test.ts | 33 ++++++++++++++ .../src/utils/StoryIndexGenerator.ts | 8 ++-- code/lib/types/src/modules/core-common.ts | 5 ++- 5 files changed, 88 insertions(+), 10 deletions(-) diff --git a/code/lib/client-api/src/StoryStoreFacade.ts b/code/lib/client-api/src/StoryStoreFacade.ts index 3bbef76dc2e..afb1a758369 100644 --- a/code/lib/client-api/src/StoryStoreFacade.ts +++ b/code/lib/client-api/src/StoryStoreFacade.ts @@ -191,12 +191,12 @@ export class StoryStoreFacade { // NOTE: this logic is equivalent to the `extractStories` function of `StoryIndexGenerator` const docsOptions = (global.DOCS_OPTIONS || {}) as DocsOptions; + const docsPageOptedIn = + docsOptions.docsPage === 'automatic' || + (docsOptions.docsPage && componentTags.includes('docsPage')); if (docsOptions.enabled && storyExports.length) { // We will use tags soon and this crappy filename test will go away - if ( - fileName.match(/\.mdx$/) || - (docsOptions.docsPage && componentTags.includes('docsPage')) - ) { + if (fileName.match(/\.mdx$/) || docsPageOptedIn) { const name = docsOptions.defaultName; const docsId = toId(componentId || title, name); this.entries[docsId] = { diff --git a/code/lib/core-client/src/start.test.ts b/code/lib/core-client/src/start.test.ts index 8c3092d147e..c6cd4fb57af 100644 --- a/code/lib/core-client/src/start.test.ts +++ b/code/lib/core-client/src/start.test.ts @@ -1295,6 +1295,50 @@ describe('start', () => { `); }); }); + describe('when docsOptions.docsPage = automatic', () => { + beforeEach(() => { + global.DOCS_OPTIONS = { enabled: true, docsPage: 'automatic', defaultName: 'Docs' }; + }); + + it('adds stories for each component with docsPage tag', async () => { + const renderToDOM = jest.fn(); + + const { configure, clientApi } = start(renderToDOM); + configure('test', () => { + (clientApi as any).addParameters({ + docs: { renderer: () => ({ render: jest.fn((_, _2, _3, d) => d()) }) }, + }); + clientApi + .storiesOf('Component A', { id: 'file1' } as NodeModule) + .add('Story One', jest.fn()) + .add('Story Two', jest.fn()); + + clientApi + .storiesOf('Component B', { id: 'file2' } as NodeModule) + .addParameters({ tags: ['docsPage'] }) + .add('Story Three', jest.fn()); + + return [componentCExports]; + }); + + await waitForRender(); + const setIndexData = mockChannel.emit.mock.calls.find( + (call: [string, any]) => call[0] === SET_INDEX + )[1]; + expect(Object.keys(setIndexData.entries)).toMatchInlineSnapshot(` + Array [ + "component-a--docs", + "component-a--story-one", + "component-a--story-two", + "component-b--docs", + "component-b--story-three", + "component-c--docs", + "component-c--story-one", + "component-c--story-two", + ] + `); + }); + }); }); describe('auto-title', () => { diff --git a/code/lib/core-server/src/utils/StoryIndexGenerator.test.ts b/code/lib/core-server/src/utils/StoryIndexGenerator.test.ts index 49482300b58..bc267e26755 100644 --- a/code/lib/core-server/src/utils/StoryIndexGenerator.test.ts +++ b/code/lib/core-server/src/utils/StoryIndexGenerator.test.ts @@ -441,6 +441,39 @@ describe('StoryIndexGenerator', () => { `); }); + it('generates an entry for every CSF file when docsOptions.docsPage = automatic', async () => { + const specifier: CoreCommon_NormalizedStoriesSpecifier = normalizeStoriesEntry( + './src/**/*.stories.(ts|js|jsx)', + options + ); + + const generator = new StoryIndexGenerator([specifier], { + ...docsPageOptions, + docs: { + ...docsPageOptions.docs, + docsPage: 'automatic', + }, + }); + await generator.initialize(); + + expect(Object.keys((await generator.getIndex()).entries)).toMatchInlineSnapshot(` + Array [ + "a--docs", + "a--story-one", + "b--docs", + "b--story-one", + "d--docs", + "d--story-one", + "first-nested-deeply-f--docs", + "first-nested-deeply-f--story-one", + "nested-button--docs", + "nested-button--story-one", + "second-nested-g--docs", + "second-nested-g--story-one", + ] + `); + }); + it('does not generate a docs page entry if there is a standalone entry with the same name', async () => { const csfSpecifier: CoreCommon_NormalizedStoriesSpecifier = normalizeStoriesEntry( './src/A.stories.js', diff --git a/code/lib/core-server/src/utils/StoryIndexGenerator.ts b/code/lib/core-server/src/utils/StoryIndexGenerator.ts index 2fd5658b68c..14f2a8f9629 100644 --- a/code/lib/core-server/src/utils/StoryIndexGenerator.ts +++ b/code/lib/core-server/src/utils/StoryIndexGenerator.ts @@ -224,12 +224,12 @@ export class StoryIndexGenerator { }); if (this.options.docs.enabled && csf.stories.length) { + const { docsPage } = this.options.docs; + const docsPageOptedIn = + docsPage === 'automatic' || (docsPage && componentTags.includes('docsPage')); // We always add a template for *.stories.mdx, but only if docs page is enabled for // regular CSF files - if ( - storyIndexer.addDocsTemplate || - (this.options.docs.docsPage && componentTags.includes('docsPage')) - ) { + if (storyIndexer.addDocsTemplate || docsPageOptedIn) { const name = this.options.docs.defaultName; const id = toId(csf.meta.title, name); entries.unshift({ diff --git a/code/lib/types/src/modules/core-common.ts b/code/lib/types/src/modules/core-common.ts index 1732dcc749d..c362c026661 100644 --- a/code/lib/types/src/modules/core-common.ts +++ b/code/lib/types/src/modules/core-common.ts @@ -296,9 +296,10 @@ export type DocsOptions = { */ defaultName?: string; /** - * Should we generate a docs entry per CSF file? + * Should we generate a docs entry per CSF file with the `docsPage` tag? + * Set to 'automatic' to generate an entry irrespective of tag. */ - docsPage?: boolean; + docsPage?: boolean | 'automatic'; /** * Only show doc entries in the side bar (usually set with the `--docs` CLI flag) */ From 18d1070f7ba2da38eb98665d619c3577acea4701 Mon Sep 17 00:00:00 2001 From: Tom Coleman Date: Wed, 2 Nov 2022 17:36:55 +1100 Subject: [PATCH 07/20] Create a migration to add `docs.docsPage: 'automatic'` if unset --- .../automigrate/fixes/docsPage-automatic.ts | 61 +++++++++++++++++++ code/lib/cli/src/automigrate/fixes/index.ts | 2 + 2 files changed, 63 insertions(+) create mode 100644 code/lib/cli/src/automigrate/fixes/docsPage-automatic.ts diff --git a/code/lib/cli/src/automigrate/fixes/docsPage-automatic.ts b/code/lib/cli/src/automigrate/fixes/docsPage-automatic.ts new file mode 100644 index 00000000000..6674931246e --- /dev/null +++ b/code/lib/cli/src/automigrate/fixes/docsPage-automatic.ts @@ -0,0 +1,61 @@ +import chalk from 'chalk'; +import { dedent } from 'ts-dedent'; + +import type { ConfigFile } from '@storybook/csf-tools'; +import { readConfig, writeConfig } from '@storybook/csf-tools'; +import { getStorybookInfo } from '@storybook/core-common'; + +import type { Fix } from '../types'; + +const logger = console; + +interface DocsPageAutomaticFrameworkRunOptions { + main: ConfigFile; +} + +/** + * Set the docs.docsPage option to automatic if it isn't already set + */ +export const docsPageAutomatic: Fix = { + id: 'docsPageAutomatic', + + async check({ packageManager }) { + const packageJson = packageManager.retrievePackageJson(); + + const { mainConfig } = getStorybookInfo(packageJson); + + if (!mainConfig) { + logger.warn('Unable to find storybook main.js config, skipping'); + return null; + } + + const main = await readConfig(mainConfig); + const docs = main.getFieldValue(['docs']); + + return docs?.docsPage === undefined ? { main } : null; + }, + + prompt() { + const docsPageAutomaticFormatted = chalk.cyan(`docs: { docsPage: 'automatic' }`); + + return dedent` + We've detected that your main.js configuration file has not configured docsPage. In 6.x we + we defaulted to having a docsPage for every story, in 7.x you need to opt in per-component. + However, we can set the \`docs.docsPage\` to 'automatic' to approximate the old behaviour: + + ${docsPageAutomaticFormatted} + + More info: ${chalk.yellow( + 'https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#docs-page' + )} + `; + }, + + async run({ result: { main }, dryRun }) { + logger.info(`✅ Setting 'docs.docsPage' to 'automatic' in main.js`); + if (!dryRun) { + main.setFieldValue(['docsPage', 'docs'], 'automatic'); + await writeConfig(main); + } + }, +}; diff --git a/code/lib/cli/src/automigrate/fixes/index.ts b/code/lib/cli/src/automigrate/fixes/index.ts index c268e75a316..ba60564eb49 100644 --- a/code/lib/cli/src/automigrate/fixes/index.ts +++ b/code/lib/cli/src/automigrate/fixes/index.ts @@ -12,6 +12,7 @@ import { sbScripts } from './sb-scripts'; import { newFrameworks } from './new-frameworks'; import { removedGlobalClientAPIs } from './remove-global-client-apis'; import { mdx1to2 } from './mdx-1-to-2'; +import { docsPageAutomatic } from './docsPage-automatic'; export * from '../types'; @@ -28,4 +29,5 @@ export const fixes: Fix[] = [ newFrameworks, removedGlobalClientAPIs, mdx1to2, + docsPageAutomatic, ]; From 8012b1122acc2628666e0dbe9a34a4443b298e25 Mon Sep 17 00:00:00 2001 From: Tom Coleman Date: Wed, 2 Nov 2022 22:00:26 +1100 Subject: [PATCH 08/20] Pull renderer+builder from framework's package.json + a known list --- code/lib/telemetry/src/get-framework-info.ts | 50 ++++++++++++++++++++ code/lib/telemetry/src/storybook-metadata.ts | 44 ++--------------- code/lib/telemetry/src/types.ts | 8 ++-- 3 files changed, 56 insertions(+), 46 deletions(-) create mode 100644 code/lib/telemetry/src/get-framework-info.ts diff --git a/code/lib/telemetry/src/get-framework-info.ts b/code/lib/telemetry/src/get-framework-info.ts new file mode 100644 index 00000000000..9dc597b62fa --- /dev/null +++ b/code/lib/telemetry/src/get-framework-info.ts @@ -0,0 +1,50 @@ +import type { PackageJson, StorybookConfig } from '@storybook/types'; + +const knownRenderers = [ + 'html', + 'react', + 'svelte', + 'vue3', + 'preact', + 'server', + 'vue', + 'web-components', + 'angular', + 'ember', +]; + +const knownBuilders = ['builder-webpack5', 'builder-vite']; + +function findMatchingPackage(packageJson: PackageJson, suffixes: string[]) { + const { name = '', version, dependencies, devDependencies, peerDependencies } = packageJson; + + const allDependencies = { + // We include the framework itself because it may be a renderer too (e.g. angular) + [name]: version, + ...dependencies, + ...devDependencies, + ...peerDependencies, + }; + + return suffixes.map((suffix) => `@storybook/${suffix}`).find((pkg) => allDependencies[pkg]); +} + +export async function getFrameworkInfo(mainConfig: StorybookConfig) { + const { framework: frameworkInput } = mainConfig; + + if (!frameworkInput) return {}; + + const framework = typeof frameworkInput === 'string' ? { name: frameworkInput } : frameworkInput; + + // eslint-disable-next-line import/no-dynamic-require, global-require + const frameworkPackageJson = require(`${framework.name}/package.json`); + + const builder = findMatchingPackage(frameworkPackageJson, knownBuilders); + const renderer = findMatchingPackage(frameworkPackageJson, knownRenderers); + + return { + framework, + builder, + renderer, + }; +} diff --git a/code/lib/telemetry/src/storybook-metadata.ts b/code/lib/telemetry/src/storybook-metadata.ts index d185fd41fa8..7250e411fee 100644 --- a/code/lib/telemetry/src/storybook-metadata.ts +++ b/code/lib/telemetry/src/storybook-metadata.ts @@ -12,6 +12,7 @@ import type { StorybookMetadata, Dependency, StorybookAddon } from './types'; import { getActualPackageVersion, getActualPackageVersions } from './package-versions'; import { getMonorepoType } from './get-monorepo-type'; import { cleanPaths } from './sanitize'; +import { getFrameworkInfo } from './get-framework-info'; export const metaFrameworks = { next: 'Next', @@ -23,31 +24,6 @@ export const metaFrameworks = { '@sveltejs/kit': 'svelte-kit', } as Record; -// @TODO: This should be removed in 7.0 as the framework.options field in main.js will replace this -const getFrameworkOptions = (mainConfig: any) => { - const possibleOptions = [ - 'angular', - 'ember', - 'html', - 'preact', - 'react', - 'server', - 'svelte', - 'vue', - 'vue3', - 'webComponents', - ].map((opt) => `${opt}Options`); - - // eslint-disable-next-line no-restricted-syntax - for (const opt of possibleOptions) { - if (opt in mainConfig) { - return mainConfig[opt] as any; - } - } - - return undefined; -}; - export const sanitizeAddonName = (name: string) => { return cleanPaths(name) .replace(/\/dist\/.*/, '') @@ -68,7 +44,6 @@ export const computeStorybookMetadata = async ({ }): Promise => { const metadata: Partial = { generatedAt: new Date().getTime(), - builder: { name: 'webpack5' }, hasCustomBabel: false, hasCustomWebpack: false, hasStaticDirs: false, @@ -118,14 +93,7 @@ export const computeStorybookMetadata = async ({ metadata.typescriptOptions = mainConfig.typescript; } - if (mainConfig.core?.builder) { - const { builder } = mainConfig.core; - - metadata.builder = { - name: typeof builder === 'string' ? builder : builder.name, - options: typeof builder === 'string' ? undefined : builder?.options ?? undefined, - }; - } + const frameworkInfo = await getFrameworkInfo(mainConfig); if (mainConfig.refs) { metadata.refCount = Object.keys(mainConfig.refs).length; @@ -181,22 +149,16 @@ export const computeStorybookMetadata = async ({ const hasStorybookEslint = !!allDependencies['eslint-plugin-storybook']; - // FIXME: resolve framework/renderer split in 7.0 - // OR should be getting this from mainConfig instead? const storybookInfo = getStorybookInfo(packageJson); - const storybookVersion = storybookPackages[storybookInfo.frameworkPackage]?.version || storybookInfo.version; return { ...metadata, + ...frameworkInfo, storybookVersion, language, storybookPackages, - framework: { - name: storybookInfo.framework, - options: getFrameworkOptions(mainConfig), - }, addons, hasStorybookEslint, }; diff --git a/code/lib/telemetry/src/types.ts b/code/lib/telemetry/src/types.ts index 6e8f9c76deb..591ca3de2ec 100644 --- a/code/lib/telemetry/src/types.ts +++ b/code/lib/telemetry/src/types.ts @@ -17,14 +17,12 @@ export type StorybookMetadata = { storybookVersion: string; generatedAt?: number; language: 'typescript' | 'javascript'; - framework: { + framework?: { name: string; options?: any; }; - builder?: { - name: string; - options?: Record; - }; + builder?: string; + renderer?: string; monorepo?: MonorepoType; packageManager?: { type: PM; From 14933094233dcbb304fb1ee520ceb4a08f28be6d Mon Sep 17 00:00:00 2001 From: Tom Coleman Date: Wed, 2 Nov 2022 22:12:48 +1100 Subject: [PATCH 09/20] Fix tests --- code/lib/telemetry/src/get-framework-info.ts | 4 +- .../{package-versions.ts => package-json.ts} | 9 +- .../telemetry/src/storybook-metadata.test.ts | 92 ++++++++----------- code/lib/telemetry/src/storybook-metadata.ts | 2 +- 4 files changed, 49 insertions(+), 58 deletions(-) rename code/lib/telemetry/src/{package-versions.ts => package-json.ts} (63%) diff --git a/code/lib/telemetry/src/get-framework-info.ts b/code/lib/telemetry/src/get-framework-info.ts index 9dc597b62fa..4f465c7f0b2 100644 --- a/code/lib/telemetry/src/get-framework-info.ts +++ b/code/lib/telemetry/src/get-framework-info.ts @@ -1,4 +1,5 @@ import type { PackageJson, StorybookConfig } from '@storybook/types'; +import { getActualPackageJson } from './package-json'; const knownRenderers = [ 'html', @@ -36,8 +37,7 @@ export async function getFrameworkInfo(mainConfig: StorybookConfig) { const framework = typeof frameworkInput === 'string' ? { name: frameworkInput } : frameworkInput; - // eslint-disable-next-line import/no-dynamic-require, global-require - const frameworkPackageJson = require(`${framework.name}/package.json`); + const frameworkPackageJson = await getActualPackageJson(framework.name); const builder = findMatchingPackage(frameworkPackageJson, knownBuilders); const renderer = findMatchingPackage(frameworkPackageJson, knownRenderers); diff --git a/code/lib/telemetry/src/package-versions.ts b/code/lib/telemetry/src/package-json.ts similarity index 63% rename from code/lib/telemetry/src/package-versions.ts rename to code/lib/telemetry/src/package-json.ts index bd31f5c0941..409c519d2f1 100644 --- a/code/lib/telemetry/src/package-versions.ts +++ b/code/lib/telemetry/src/package-json.ts @@ -9,8 +9,7 @@ export const getActualPackageVersions = async (packages: Record { try { - // eslint-disable-next-line import/no-dynamic-require,global-require - const packageJson = require(path.join(packageName, 'package.json')); + const packageJson = await getActualPackageJson(packageName); return { name: packageName, version: packageJson.version, @@ -19,3 +18,9 @@ export const getActualPackageVersion = async (packageName: string) => { return { name: packageName, version: null }; } }; + +export const getActualPackageJson = async (packageName: string) => { + // eslint-disable-next-line import/no-dynamic-require,global-require + const packageJson = require(path.join(packageName, 'package.json')); + return packageJson; +}; diff --git a/code/lib/telemetry/src/storybook-metadata.test.ts b/code/lib/telemetry/src/storybook-metadata.test.ts index f23a78a418b..92a40010609 100644 --- a/code/lib/telemetry/src/storybook-metadata.test.ts +++ b/code/lib/telemetry/src/storybook-metadata.test.ts @@ -12,7 +12,7 @@ const mainJsMock: StorybookConfig = { stories: [], }; -jest.mock('./package-versions', () => { +jest.mock('./package-json', () => { const getActualPackageVersion = jest.fn((name) => Promise.resolve({ name, @@ -24,9 +24,17 @@ jest.mock('./package-versions', () => { Promise.all(Object.keys(packages).map(getActualPackageVersion)) ); + const getActualPackageJson = jest.fn((name) => ({ + dependencies: { + '@storybook/react': 'x.x.x', + '@storybook/builder-vite': 'x.x.x', + }, + })); + return { getActualPackageVersions, getActualPackageVersion, + getActualPackageJson, }; }); @@ -96,40 +104,39 @@ describe('sanitizeAddonName', () => { describe('await computeStorybookMetadata', () => { test('should return frameworkOptions from mainjs', async () => { const reactResult = await computeStorybookMetadata({ - packageJson: { - ...packageJsonMock, - devDependencies: { - '@storybook/react': 'x.x.x', - }, - }, + packageJson: packageJsonMock, mainConfig: { ...mainJsMock, - reactOptions: { - fastRefresh: false, + framework: { + name: '@storybook/react-vite', + options: { + fastRefresh: false, + }, }, }, }); - expect(reactResult.framework).toEqual({ name: 'react', options: { fastRefresh: false } }); + expect(reactResult.framework).toEqual({ + name: '@storybook/react-vite', + options: { fastRefresh: false }, + }); const angularResult = await computeStorybookMetadata({ - packageJson: { - ...packageJsonMock, - devDependencies: { - '@storybook/angular': 'x.x.x', - }, - }, + packageJson: packageJsonMock, mainConfig: { ...mainJsMock, - angularOptions: { - enableIvy: true, - enableNgcc: true, + framework: { + name: '@storybook/angular', + options: { + enableIvy: true, + enableNgcc: true, + }, }, }, }); expect(angularResult.framework).toEqual({ - name: 'angular', + name: '@storybook/angular', options: { enableIvy: true, enableNgcc: true }, }); }); @@ -196,40 +203,19 @@ describe('await computeStorybookMetadata', () => { expect(result.features).toEqual(features); }); - test('should handle different types of builders', async () => { - const simpleBuilder = 'webpack4'; - const complexBuilder = { - name: 'webpack5', - options: { - lazyCompilation: true, - }, - }; + test('should infer builder and renderer from framework package.json', async () => { expect( - ( - await computeStorybookMetadata({ - packageJson: packageJsonMock, - mainConfig: { - ...mainJsMock, - core: { - builder: complexBuilder, - }, - }, - }) - ).builder - ).toEqual(complexBuilder); - expect( - ( - await computeStorybookMetadata({ - packageJson: packageJsonMock, - mainConfig: { - ...mainJsMock, - core: { - builder: simpleBuilder, - }, - }, - }) - ).builder - ).toEqual({ name: simpleBuilder }); + await computeStorybookMetadata({ + packageJson: packageJsonMock, + mainConfig: { + ...mainJsMock, + framework: '@storybook/react-vite', + }, + }) + ).toMatchObject({ + renderer: '@storybook/react', + builder: '@storybook/builder-vite', + }); }); test('should return the number of refs', async () => { diff --git a/code/lib/telemetry/src/storybook-metadata.ts b/code/lib/telemetry/src/storybook-metadata.ts index 7250e411fee..d590f7af408 100644 --- a/code/lib/telemetry/src/storybook-metadata.ts +++ b/code/lib/telemetry/src/storybook-metadata.ts @@ -9,7 +9,7 @@ import { import type { StorybookConfig, PackageJson } from '@storybook/types'; import type { StorybookMetadata, Dependency, StorybookAddon } from './types'; -import { getActualPackageVersion, getActualPackageVersions } from './package-versions'; +import { getActualPackageVersion, getActualPackageVersions } from './package-json'; import { getMonorepoType } from './get-monorepo-type'; import { cleanPaths } from './sanitize'; import { getFrameworkInfo } from './get-framework-info'; From 2ebaa53687238e5e222d3a8cec106b1b760fbd45 Mon Sep 17 00:00:00 2001 From: Tom Coleman Date: Wed, 2 Nov 2022 22:13:19 +1100 Subject: [PATCH 10/20] Small tweak --- code/lib/telemetry/src/storybook-metadata.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/code/lib/telemetry/src/storybook-metadata.test.ts b/code/lib/telemetry/src/storybook-metadata.test.ts index 92a40010609..8b9b57e17a0 100644 --- a/code/lib/telemetry/src/storybook-metadata.test.ts +++ b/code/lib/telemetry/src/storybook-metadata.test.ts @@ -213,6 +213,7 @@ describe('await computeStorybookMetadata', () => { }, }) ).toMatchObject({ + framework: { name: '@storybook/react-vite' }, renderer: '@storybook/react', builder: '@storybook/builder-vite', }); From e789ca6fa9c056bca4d4dafd48b3da79c469bfeb Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Wed, 2 Nov 2022 14:30:21 +0100 Subject: [PATCH 11/20] add re-export back that I removed in https://github.com/storybookjs/storybook/pull/19580 --- code/lib/client-api/src/index.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/lib/client-api/src/index.ts b/code/lib/client-api/src/index.ts index 976a34dec77..47018f594e7 100644 --- a/code/lib/client-api/src/index.ts +++ b/code/lib/client-api/src/index.ts @@ -11,4 +11,6 @@ export { setGlobalRender, } from './ClientApi'; +export * from '@storybook/store'; + export * from './queryparams'; From 2c5079a602fdb8089ce40271e83b2e1355a3ab40 Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Wed, 2 Nov 2022 14:33:42 +0100 Subject: [PATCH 12/20] add them back here too --- code/lib/store/src/hooks.ts | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/code/lib/store/src/hooks.ts b/code/lib/store/src/hooks.ts index cfff7934ec3..69ad8b95e69 100644 --- a/code/lib/store/src/hooks.ts +++ b/code/lib/store/src/hooks.ts @@ -1,6 +1,37 @@ import { SHARED_STATE_CHANGED, SHARED_STATE_SET } from '@storybook/core-events'; -import { addons, useMemo, useState, useEffect, useChannel } from '@storybook/addons'; +import { + addons, + HooksContext, + applyHooks, + useMemo, + useCallback, + useRef, + useState, + useReducer, + useEffect, + useChannel, + useStoryContext, + useParameter, + useArgs, + useGlobals, +} from '@storybook/addons'; + +export { + HooksContext, + applyHooks, + useMemo, + useCallback, + useRef, + useState, + useReducer, + useEffect, + useChannel, + useStoryContext, + useParameter, + useArgs, + useGlobals, +}; export function useSharedState(sharedId: string, defaultState?: S): [S, (s: S) => void] { const channel = addons.getChannel(); From aa16f23dcfef156a3b7501b4bf965d31c3298fb6 Mon Sep 17 00:00:00 2001 From: Ian VanSchooten Date: Wed, 2 Nov 2022 12:14:30 -0400 Subject: [PATCH 13/20] Point to correct .d.ts files from export maps --- code/addons/links/package.json | 2 +- code/addons/outline/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/addons/links/package.json b/code/addons/links/package.json index 45d083b1e68..2f4d0776912 100644 --- a/code/addons/links/package.json +++ b/code/addons/links/package.json @@ -40,7 +40,7 @@ "./react": { "require": "./dist/react/index.js", "import": "./dist/react/index.mjs", - "types": "./dist/react.d.ts" + "types": "./dist/react/index.d.ts" }, "./register": { "require": "./dist/manager.js", diff --git a/code/addons/outline/package.json b/code/addons/outline/package.json index ca64da59d95..eaec64e91f6 100644 --- a/code/addons/outline/package.json +++ b/code/addons/outline/package.json @@ -41,7 +41,7 @@ "./preview": { "require": "./dist/preset/preview.js", "import": "./dist/preset/preview.mjs", - "types": "./dist/preview.d.ts" + "types": "./dist/preset/preview.d.ts" }, "./register": { "require": "./dist/manager.js", From 2f676a2528a2baf1fdf9063642b9621a2fe3d566 Mon Sep 17 00:00:00 2001 From: Gavin Mogan Date: Wed, 2 Nov 2022 15:20:09 -0700 Subject: [PATCH 14/20] Use import.meta.webpackHot instead of module.hot for check --- .../templates/virtualModuleModernEntry.js.handlebars | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/lib/builder-webpack5/templates/virtualModuleModernEntry.js.handlebars b/code/lib/builder-webpack5/templates/virtualModuleModernEntry.js.handlebars index fddbe23fd1f..9f13e58b6e8 100644 --- a/code/lib/builder-webpack5/templates/virtualModuleModernEntry.js.handlebars +++ b/code/lib/builder-webpack5/templates/virtualModuleModernEntry.js.handlebars @@ -32,7 +32,7 @@ window.__STORYBOOK_CLIENT_API__ = new ClientApi({ storyStore: preview.storyStore preview.initialize({ importFn, getProjectAnnotations }); -if (module.hot) { +if (import.meta.webpackHot) { import.meta.webpackHot.accept('./{{storiesFilename}}', () => { // importFn has changed so we need to patch the new one in preview.onStoriesChanged({ importFn }); From 59a5550530e506349015d4ed74484776e051748b Mon Sep 17 00:00:00 2001 From: Michael Shilman Date: Thu, 3 Nov 2022 10:39:04 +0800 Subject: [PATCH 15/20] CSF-tools: Support default exports for SB7 --- code/lib/csf-tools/src/ConfigFile.test.ts | 121 ++++++++++++++++++++++ code/lib/csf-tools/src/ConfigFile.ts | 24 +++++ 2 files changed, 145 insertions(+) diff --git a/code/lib/csf-tools/src/ConfigFile.test.ts b/code/lib/csf-tools/src/ConfigFile.test.ts index 04851d32a91..757ed1b0567 100644 --- a/code/lib/csf-tools/src/ConfigFile.test.ts +++ b/code/lib/csf-tools/src/ConfigFile.test.ts @@ -1,3 +1,5 @@ +/// ; + import { dedent } from 'ts-dedent'; import { formatConfig, loadConfig } from './ConfigFile'; @@ -83,6 +85,7 @@ describe('ConfigFile', () => { ).toEqual('webpack5'); }); }); + describe('module exports', () => { it('missing export', () => { expect( @@ -142,6 +145,66 @@ describe('ConfigFile', () => { ).toEqual([{ directory: '../src', titlePrefix: 'Demo' }]); }); }); + + describe('default export', () => { + it('missing export', () => { + expect( + getField( + ['core', 'builder'], + dedent` + export default { foo: { builder: 'webpack5' } } + ` + ) + ).toBeUndefined(); + }); + it('found scalar', () => { + expect( + getField( + ['core', 'builder'], + dedent` + export default { core: { builder: 'webpack5' } } + ` + ) + ).toEqual('webpack5'); + }); + it('variable ref export', () => { + expect( + getField( + ['core', 'builder'], + dedent` + const core = { builder: 'webpack5' }; + export default { core }; + ` + ) + ).toEqual('webpack5'); + }); + it('variable rename', () => { + expect( + getField( + ['core', 'builder'], + dedent` + const coreVar = { builder: 'webpack5' }; + export default { core: coreVar }; + ` + ) + ).toEqual('webpack5'); + }); + it('variable exports', () => { + expect( + getField( + ['stories'], + dedent` + import type { StorybookConfig } from '@storybook/react-webpack5'; + + const config: StorybookConfig = { + stories: [{ directory: '../src', titlePrefix: 'Demo' }], + } + export default config; + ` + ) + ).toEqual([{ directory: '../src', titlePrefix: 'Demo' }]); + }); + }); }); describe('setField', () => { @@ -228,6 +291,7 @@ describe('ConfigFile', () => { `); }); }); + describe('module exports', () => { it('missing export', () => { expect( @@ -283,6 +347,63 @@ describe('ConfigFile', () => { `); }); }); + + describe('default export', () => { + it('missing export', () => { + expect( + setField( + ['core', 'builder'], + 'webpack5', + dedent` + export default { addons: [] }; + ` + ) + ).toMatchInlineSnapshot(` + export default { + addons: [], + core: { + builder: "webpack5" + } + }; + `); + }); + it('missing field', () => { + expect( + setField( + ['core', 'builder'], + 'webpack5', + dedent` + export default { core: { foo: 'bar' }}; + ` + ) + ).toMatchInlineSnapshot(` + export default { + core: { + foo: 'bar', + builder: 'webpack5' + } + }; + `); + }); + it('found scalar', () => { + expect( + setField( + ['core', 'builder'], + 'webpack5', + dedent` + export default { core: { builder: 'webpack4' } }; + ` + ) + ).toMatchInlineSnapshot(` + export default { + core: { + builder: 'webpack5' + } + }; + `); + }); + }); + describe('quotes', () => { it('no quotes', () => { expect(setField(['foo', 'bar'], 'baz', '')).toMatchInlineSnapshot(` diff --git a/code/lib/csf-tools/src/ConfigFile.ts b/code/lib/csf-tools/src/ConfigFile.ts index bba4f3c2647..e9fde5c61b1 100644 --- a/code/lib/csf-tools/src/ConfigFile.ts +++ b/code/lib/csf-tools/src/ConfigFile.ts @@ -108,6 +108,30 @@ export class ConfigFile { // eslint-disable-next-line @typescript-eslint/no-this-alias const self = this; traverse.default(this._ast, { + ExportDefaultDeclaration: { + enter({ node, parent }) { + const decl = + t.isIdentifier(node.declaration) && t.isProgram(parent) + ? _findVarInitialization(node.declaration.name, parent) + : node.declaration; + + if (t.isObjectExpression(decl)) { + self._exportsObject = decl; + decl.properties.forEach((p: t.ObjectProperty) => { + const exportName = propKey(p); + if (exportName) { + let exportVal = p.value; + if (t.isIdentifier(exportVal)) { + exportVal = _findVarInitialization(exportVal.name, parent as t.Program); + } + self._exports[exportName] = exportVal as t.Expression; + } + }); + } else { + logger.warn(`Unexpected ${JSON.stringify(node)}`); + } + }, + }, ExportNamedDeclaration: { enter({ node, parent }) { if (t.isVariableDeclaration(node.declaration)) { From 36515e65b843b32706116f4b84ad9bf939bfcd31 Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Thu, 3 Nov 2022 13:35:12 +0100 Subject: [PATCH 16/20] docs.inlineStories to true for preact as well --- code/renderers/preact/src/config.ts | 4 +++- code/renderers/preact/src/docs/config.ts | 5 +++++ 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 code/renderers/preact/src/docs/config.ts diff --git a/code/renderers/preact/src/config.ts b/code/renderers/preact/src/config.ts index 73bae9076ba..b2cfe017c00 100644 --- a/code/renderers/preact/src/config.ts +++ b/code/renderers/preact/src/config.ts @@ -1,3 +1,5 @@ +import { parameters as docsParams } from './docs/config'; + export { renderToDOM, render } from './render'; -export const parameters = { framework: 'preact' as const }; +export const parameters = { framework: 'preact' as const, ...docsParams }; diff --git a/code/renderers/preact/src/docs/config.ts b/code/renderers/preact/src/docs/config.ts new file mode 100644 index 00000000000..bd8f5b4bdda --- /dev/null +++ b/code/renderers/preact/src/docs/config.ts @@ -0,0 +1,5 @@ +export const parameters = { + docs: { + inlineStories: true, + }, +}; From 718092494677e10b31ea8a215f1fc4e9bc6c5e71 Mon Sep 17 00:00:00 2001 From: Tom Coleman Date: Thu, 3 Nov 2022 23:35:13 +1100 Subject: [PATCH 17/20] Add loader/decorator to wrap stories in a docs context And a very simple story for the `` block --- .../.storybook/{preview.jsx => preview.tsx} | 50 ++++++++++++++++++- code/ui/blocks/src/blocks/Story.stories.tsx | 20 ++++++++ 2 files changed, 68 insertions(+), 2 deletions(-) rename code/ui/.storybook/{preview.jsx => preview.tsx} (81%) create mode 100644 code/ui/blocks/src/blocks/Story.stories.tsx diff --git a/code/ui/.storybook/preview.jsx b/code/ui/.storybook/preview.tsx similarity index 81% rename from code/ui/.storybook/preview.jsx rename to code/ui/.storybook/preview.tsx index 1b3ce4cdc6d..82542d07241 100644 --- a/code/ui/.storybook/preview.jsx +++ b/code/ui/.storybook/preview.tsx @@ -11,6 +11,12 @@ import { useTheme, } from '@storybook/theming'; import { Symbols } from '@storybook/components'; +import type { PreviewWeb } from '@storybook/preview-web'; +import { DocsContext } from '@storybook/preview-web'; +import type { ReactFramework } from '@storybook/react'; +import type { Channel } from '@storybook/channels'; + +import { DocsContainer } from '../blocks/src/blocks/DocsContainer'; const { document } = global; @@ -86,7 +92,49 @@ const ThemedSetRoot = () => { return null; }; +// eslint-disable-next-line no-underscore-dangle +const preview = (window as any).__STORYBOOK_PREVIEW__ as PreviewWeb; +const channel = (window as any).__STORYBOOK_ADDONS_CHANNEL__ as Channel; +export const loaders = [ + async () => ({ globalValue: 1 }), + + async ({ parameters: { relativeCsfPaths } }) => { + if (!relativeCsfPaths) return {}; + + const csfFiles = await Promise.all( + (relativeCsfPaths as string[]).map(async (relativePath) => { + const webpackPath = `./ui/blocks/src/${relativePath.replace(/^..\//, '')}.tsx`; + const entry = preview.storyStore.storyIndex!.importPathToEntry(webpackPath); + + if (!entry) { + throw new Error(`Couldn't find story file at ${webpackPath} (passed as ${relativePath})`); + } + + return preview.storyStore.loadCSFFileByStoryId(entry.id); + }) + ); + + return { + docsContext: new DocsContext( + channel, + preview.storyStore, + preview.renderStoryToElement.bind(preview), + csfFiles, + false + ), + }; + }, +]; + export const decorators = [ + (Story, { loaded: { docsContext } }) => + docsContext ? ( + + + + ) : ( + + ), (StoryFn, { globals, parameters, playFunction }) => { const defaultTheme = isChromatic() && !playFunction ? 'stacked' : 'light'; const theme = globals.theme || parameters.theme || defaultTheme; @@ -242,7 +290,5 @@ export const globalTypes = { }, }; -export const loaders = [async () => ({ globalValue: 1 })]; - export const argTypes = { color: { control: 'color' } }; export const args = { color: 'red' }; diff --git a/code/ui/blocks/src/blocks/Story.stories.tsx b/code/ui/blocks/src/blocks/Story.stories.tsx new file mode 100644 index 00000000000..bb09d8c635d --- /dev/null +++ b/code/ui/blocks/src/blocks/Story.stories.tsx @@ -0,0 +1,20 @@ +import type { Meta, StoryObj } from '@storybook/react'; + +import { Story as StoryComponent } from './Story'; +import * as BooleanStories from '../controls/Boolean.stories'; + +const meta: Meta = { + component: StoryComponent, + parameters: { + relativeCsfPaths: ['../controls/Boolean.stories'], + }, +}; +export default meta; + +type Story = StoryObj; + +export const BasicOf: Story = { + args: { + of: BooleanStories.Undefined, + }, +}; From 58a373085bcab607befe74b2966aba06ef2cf4c3 Mon Sep 17 00:00:00 2001 From: Tom Coleman Date: Thu, 3 Nov 2022 23:35:38 +1100 Subject: [PATCH 18/20] Turn on optimize deps --- code/ui/.storybook/main.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/code/ui/.storybook/main.ts b/code/ui/.storybook/main.ts index 5c14d08f20e..074a25de112 100644 --- a/code/ui/.storybook/main.ts +++ b/code/ui/.storybook/main.ts @@ -36,6 +36,7 @@ const config: StorybookConfig = { viteFinal: (vite) => ({ ...vite, plugins: [...(vite.plugins || []), csfPlugin({})], + optimizeDeps: { ...vite.optimizeDeps, force: true }, }), }; From 45ec54cd056022369d92d806d2f3ea5ce9c52fd5 Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Tue, 1 Nov 2022 12:12:58 +0100 Subject: [PATCH 19/20] Implement a daily job --- .circleci/config.yml | 126 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 109 insertions(+), 17 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 31ed1d0aec8..6ada5587e67 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,5 +1,12 @@ version: 2.1 +parameters: + workflow: + description: Which workflow to run + type: enum + enum: ['tests', 'daily-tests'] + default: 'tests' + executors: sb_node_16_classic: parameters: @@ -246,12 +253,12 @@ jobs: name: Test command: | cd scripts - yarn test --coverage --runInBand --ci + yarn test --coverage --ci - store_test_results: path: scripts/junit.xml unit-tests: executor: - class: medium+ + class: xlarge name: sb_node_16_browsers steps: - git-shallow-clone/checkout_advanced: @@ -262,7 +269,7 @@ jobs: name: Test command: | cd code - yarn test --coverage --runInBand --ci + yarn test --coverage --ci - store_test_results: path: code/junit.xml - persist_to_workspace: @@ -302,10 +309,18 @@ jobs: path: test-results ## new workflow create-sandboxes: + parameters: + parallelism: + type: integer + default: 9 + cadence: + type: enum + enum: [ "ci", "daily", "weekly" ] + default: "ci" executor: class: medium name: sb_node_16_browsers - parallelism: 9 + parallelism: << parameters.parallelism >> steps: - git-shallow-clone/checkout_advanced: clone_options: '--depth 1 --verbose' @@ -313,7 +328,7 @@ jobs: at: . - run: name: Creating Sandboxes - command: yarn task --task sandbox --template $(yarn get-template ci create) --no-link --start-from=never --junit + command: yarn task --task sandbox --template $(yarn get-template << parameters.cadence >> create) --no-link --start-from=never --junit - persist_to_workspace: root: . paths: @@ -321,10 +336,18 @@ jobs: - store_test_results: path: test-results smoke-test-sandboxes: + parameters: + parallelism: + type: integer + default: 9 + cadence: + type: enum + enum: [ "ci", "daily", "weekly" ] + default: "ci" executor: class: medium name: sb_node_16_browsers - parallelism: 9 + parallelism: << parameters.parallelism >> steps: - git-shallow-clone/checkout_advanced: clone_options: '--depth 1 --verbose' @@ -332,14 +355,22 @@ jobs: at: . - run: name: Smoke Testing Sandboxes - command: yarn task --task smoke-test --template $(yarn get-template ci smoke-test) --no-link --start-from=never --junit + command: yarn task --task smoke-test --template $(yarn get-template << parameters.cadence >> smoke-test) --no-link --start-from=never --junit - store_test_results: path: test-results build-sandboxes: + parameters: + parallelism: + type: integer + default: 9 + cadence: + type: enum + enum: [ "ci", "daily", "weekly" ] + default: "ci" executor: class: medium+ name: sb_node_16_browsers - parallelism: 9 + parallelism: << parameters.parallelism >> steps: - git-shallow-clone/checkout_advanced: clone_options: '--depth 1 --verbose' @@ -347,7 +378,7 @@ jobs: at: . - run: name: Building Sandboxes - command: yarn task --task build --template $(yarn get-template ci build) --no-link --start-from=never --junit + command: yarn task --task build --template $(yarn get-template << parameters.cadence >> build) --no-link --start-from=never --junit - store_test_results: path: test-results - persist_to_workspace: @@ -355,10 +386,18 @@ jobs: paths: - sandbox/*/storybook-static test-runner-sandboxes: + parameters: + parallelism: + type: integer + default: 9 + cadence: + type: enum + enum: [ "ci", "daily", "weekly" ] + default: "ci" executor: class: medium name: sb_playwright - parallelism: 9 + parallelism: << parameters.parallelism >> steps: - git-shallow-clone/checkout_advanced: clone_options: '--depth 1 --verbose' @@ -366,29 +405,44 @@ jobs: at: . - run: name: Running Test Runner - command: yarn task --task test-runner --template $(yarn get-template ci test-runner) --no-link --start-from=never --junit + command: yarn task --task test-runner --template $(yarn get-template << parameters.cadence >> test-runner) --no-link --start-from=never --junit - store_test_results: path: test-results chromatic-sandboxes: + parameters: + parallelism: + type: integer + default: 9 + cadence: + type: enum + enum: ["ci", "daily", "weekly"] + default: "ci" executor: class: medium name: sb_node_16_browsers - parallelism: 9 + parallelism: << parameters.parallelism >> steps: - - git-shallow-clone/checkout_advanced: - clone_options: '--depth 1 --verbose' + - checkout - attach_workspace: at: . - run: name: Running Chromatic - command: yarn task --task chromatic --template $(yarn get-template ci chromatic) --no-link --start-from=never --junit + command: yarn task --task chromatic --template $(yarn get-template << parameters.cadence >> chromatic) --no-link --start-from=never --junit - store_test_results: path: test-results e2e-sandboxes: + parameters: + parallelism: + type: integer + default: 9 + cadence: + type: enum + enum: ["ci", "daily", "weekly"] + default: "ci" executor: class: medium name: sb_playwright - parallelism: 9 + parallelism: << parameters.parallelism >> steps: - git-shallow-clone/checkout_advanced: clone_options: '--depth 1 --verbose' @@ -396,7 +450,7 @@ jobs: at: . - run: name: Running E2E Tests - command: yarn task --task e2e-tests --template $(yarn get-template ci e2e-tests) --no-link --start-from=never --junit + command: yarn task --task e2e-tests --template $(yarn get-template << parameters.cadence >> e2e-tests) --no-link --start-from=never --junit - store_test_results: path: test-results - store_artifacts: # this is where playwright puts more complex stuff @@ -404,7 +458,45 @@ jobs: destination: playwright workflows: + daily-tests: + when: + equal: [ daily-tests, << pipeline.parameters.workflow >> ] + jobs: + - build + - publish: + requires: + - build + - create-sandboxes: + parallelism: 24 + cadence: "daily" + requires: + - publish + # - smoke-test-sandboxes: # disabled for now + # requires: + # - create-sandboxes + - build-sandboxes: + parallelism: 24 + cadence: "daily" + requires: + - create-sandboxes + - test-runner-sandboxes: + parallelism: 24 + cadence: "daily" + requires: + - build-sandboxes + - chromatic-sandboxes: + parallelism: 24 + cadence: "daily" + requires: + - build-sandboxes + - e2e-sandboxes: + parallelism: 24 + cadence: "daily" + requires: + - build-sandboxes test: + when: + equal: [ tests, << pipeline.parameters.workflow >> ] jobs: - build - lint: From 2164a85129b7e2e1d09c337a74b2d30cd8ead7ce Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Thu, 3 Nov 2022 15:45:42 +0100 Subject: [PATCH 20/20] Increase vite-bench to large as it is very flaky --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 6ada5587e67..6f29ac9ebae 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -176,7 +176,7 @@ jobs: destination: sb-bench.tar.gz react-vite-bench: executor: - class: medium + class: large name: sb_playwright working_directory: /tmp/storybook steps: