mirror of
https://github.com/storybookjs/storybook.git
synced 2025-04-02 05:03:44 +08:00
Merge branch 'next' of github.com:storybookjs/storybook into next
This commit is contained in:
commit
4628a286e0
5
.github/workflows/generate-repros-next.yml
vendored
5
.github/workflows/generate-repros-next.yml
vendored
@ -3,11 +3,6 @@ name: Generate and push repros to the next branch
|
||||
on:
|
||||
schedule:
|
||||
- cron: '2 2 */1 * *'
|
||||
workflow_dispatch:
|
||||
# To remove when the branch will be merged
|
||||
push:
|
||||
branches:
|
||||
- yann/sb-509-create-github-action
|
||||
|
||||
jobs:
|
||||
generate:
|
||||
|
@ -42,6 +42,7 @@
|
||||
],
|
||||
"scripts": {
|
||||
"check": "tsc --noEmit",
|
||||
"preprepare": "node ./scripts/generate-repro-templates-list.js",
|
||||
"prepare": "node ../../../scripts/prepare.js",
|
||||
"test": "jest test/**/*.test.js"
|
||||
},
|
||||
@ -60,6 +61,7 @@
|
||||
"commander": "^6.2.1",
|
||||
"core-js": "^3.8.2",
|
||||
"cross-spawn": "^7.0.3",
|
||||
"degit": "^2.8.4",
|
||||
"envinfo": "^7.7.3",
|
||||
"execa": "^5.0.0",
|
||||
"express": "^4.17.1",
|
||||
@ -67,6 +69,7 @@
|
||||
"fs-extra": "^9.0.1",
|
||||
"get-port": "^5.1.1",
|
||||
"globby": "^11.0.2",
|
||||
"js-yaml": "^3.14.1",
|
||||
"jscodeshift": "^0.13.1",
|
||||
"json5": "^2.1.3",
|
||||
"leven": "^3.1.0",
|
||||
@ -81,6 +84,7 @@
|
||||
"devDependencies": {
|
||||
"@storybook/client-api": "7.0.0-alpha.17",
|
||||
"@types/cross-spawn": "^6.0.2",
|
||||
"@types/degit": "^2.8.3",
|
||||
"@types/prompts": "^2.0.9",
|
||||
"@types/puppeteer-core": "^2.1.0",
|
||||
"@types/semver": "^7.3.4",
|
||||
|
42
code/lib/cli/scripts/generate-repro-templates-list.js
Executable file
42
code/lib/cli/scripts/generate-repro-templates-list.js
Executable file
@ -0,0 +1,42 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const { writeFile } = require('fs-extra');
|
||||
const { exec } = require('child_process');
|
||||
const path = require('path');
|
||||
const { default: dedent } = require('ts-dedent');
|
||||
const { readFile } = require('fs-extra');
|
||||
const yml = require('js-yaml');
|
||||
|
||||
const logger = console;
|
||||
|
||||
async function getTemplatesData(filePath) {
|
||||
const configContents = await readFile(filePath, 'utf8');
|
||||
return yml.load(configContents);
|
||||
}
|
||||
|
||||
const run = async () => {
|
||||
logger.log('Generating templates list...');
|
||||
const templatesData = await getTemplatesData(
|
||||
path.resolve(__dirname, '../../../../scripts/next-repro-generators/repro-config.yml')
|
||||
);
|
||||
const destination = path.join(__dirname, '..', 'src', 'repro-templates.ts');
|
||||
|
||||
await writeFile(
|
||||
destination,
|
||||
dedent`
|
||||
// This file was auto generated from generate-repro-templates-list.js, please do not edit!
|
||||
export default ${JSON.stringify(templatesData, null, 2)}
|
||||
`
|
||||
);
|
||||
|
||||
exec(`yarn lint:js:cmd --fix ${destination}`, {
|
||||
cwd: path.join(__dirname, '..', '..', '..'),
|
||||
});
|
||||
|
||||
logger.log('Done! generated ', destination);
|
||||
};
|
||||
|
||||
run().catch((e) => {
|
||||
logger.error(e);
|
||||
process.exit(1);
|
||||
});
|
@ -13,6 +13,7 @@ import { migrate } from './migrate';
|
||||
import { extract } from './extract';
|
||||
import { upgrade } from './upgrade';
|
||||
import { repro } from './repro';
|
||||
import { reproNext } from './repro-next';
|
||||
import { link } from './link';
|
||||
import { automigrate } from './automigrate';
|
||||
import { generateStorybookBabelConfigInCWD } from './babel-config';
|
||||
@ -146,6 +147,18 @@ program
|
||||
})
|
||||
);
|
||||
|
||||
program
|
||||
.command('repro-next [filterValue]')
|
||||
.description('Create a reproduction from a set of possible templates')
|
||||
.option('-o --output <outDir>', 'Define an output directory')
|
||||
.option('-b --branch <branch>', 'Define the branch to degit from', 'next')
|
||||
.action((filterValue, options) =>
|
||||
reproNext({ filterValue, ...options }).catch((e) => {
|
||||
logger.error(e);
|
||||
process.exit(1);
|
||||
})
|
||||
);
|
||||
|
||||
program
|
||||
.command('link <repo-url-or-directory>')
|
||||
.description('Pull down a repro from a URL (or a local directory), link it, and run storybook')
|
||||
|
172
code/lib/cli/src/repro-next.ts
Normal file
172
code/lib/cli/src/repro-next.ts
Normal file
@ -0,0 +1,172 @@
|
||||
import prompts from 'prompts';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import chalk from 'chalk';
|
||||
import boxen from 'boxen';
|
||||
import { dedent } from 'ts-dedent';
|
||||
import degit from 'degit';
|
||||
|
||||
import TEMPLATES from './repro-templates';
|
||||
|
||||
const logger = console;
|
||||
|
||||
interface ReproOptions {
|
||||
filterValue?: string;
|
||||
output?: string;
|
||||
branch?: string;
|
||||
}
|
||||
type Choice = keyof typeof TEMPLATES;
|
||||
|
||||
const toChoices = (c: Choice): prompts.Choice => ({ title: TEMPLATES[c].name, value: c });
|
||||
|
||||
export const reproNext = async ({ output: outputDirectory, filterValue, branch }: ReproOptions) => {
|
||||
const keys = Object.keys(TEMPLATES) as Choice[];
|
||||
// get value from template and reduce through TEMPLATES to filter out the correct template
|
||||
const choices = keys.reduce<Choice[]>((acc, group) => {
|
||||
const current = TEMPLATES[group];
|
||||
|
||||
const filterRegex = new RegExp(filterValue, 'i');
|
||||
if (!filterValue) {
|
||||
acc.push(group);
|
||||
return acc;
|
||||
}
|
||||
|
||||
if (
|
||||
current.name.match(filterRegex) ||
|
||||
group.match(filterRegex) ||
|
||||
current.expected.builder.match(filterRegex) ||
|
||||
current.expected.framework.match(filterRegex) ||
|
||||
current.expected.renderer.match(filterRegex)
|
||||
) {
|
||||
acc.push(group);
|
||||
return acc;
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
if (choices.length === 0) {
|
||||
logger.info(
|
||||
boxen(
|
||||
dedent`
|
||||
🔎 You filtered out all templates. 🔍
|
||||
After filtering all the templates with "${chalk.yellow(
|
||||
filterValue
|
||||
)}", we found no templates.
|
||||
|
||||
Available templates:
|
||||
${keys.map((key) => chalk.blue`- ${key}`).join('\n')}
|
||||
`.trim(),
|
||||
{ borderStyle: 'round', padding: 1, borderColor: '#F1618C' } as any
|
||||
)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
let selectedTemplate: Choice | null = null;
|
||||
|
||||
if (choices.length === 1) {
|
||||
[selectedTemplate] = choices;
|
||||
} else {
|
||||
logger.info(
|
||||
boxen(
|
||||
dedent`
|
||||
🤗 Welcome to ${chalk.yellow('sb repro NEXT')}! 🤗
|
||||
|
||||
Create a ${chalk.green('new project')} to minimally reproduce Storybook issues.
|
||||
|
||||
1. select an environment that most closely matches your project setup.
|
||||
2. select a location for the reproduction, outside of your project.
|
||||
|
||||
After the reproduction is ready, we'll guide you through the next steps.
|
||||
`.trim(),
|
||||
{ borderStyle: 'round', padding: 1, borderColor: '#F1618C' } as any
|
||||
)
|
||||
);
|
||||
|
||||
selectedTemplate = await promptSelectedTemplate(choices);
|
||||
}
|
||||
|
||||
const hasSelectedTemplate = !!(selectedTemplate ?? null);
|
||||
if (!hasSelectedTemplate) {
|
||||
logger.error('Somehow we got no templates. Please rerun this command!');
|
||||
return;
|
||||
}
|
||||
|
||||
const selectedConfig = TEMPLATES[selectedTemplate];
|
||||
|
||||
if (!selectedConfig) {
|
||||
throw new Error('🚨 Repro: please specify a valid template type');
|
||||
}
|
||||
|
||||
let selectedDirectory = outputDirectory;
|
||||
if (!selectedDirectory) {
|
||||
const { directory } = await prompts({
|
||||
type: 'text',
|
||||
message: 'Enter the output directory',
|
||||
name: 'directory',
|
||||
initial: selectedTemplate,
|
||||
validate: (directoryName) =>
|
||||
fs.existsSync(directoryName)
|
||||
? `${directoryName} already exists. Please choose another name.`
|
||||
: true,
|
||||
});
|
||||
selectedDirectory = directory;
|
||||
}
|
||||
|
||||
try {
|
||||
const cwd = path.isAbsolute(selectedDirectory)
|
||||
? selectedDirectory
|
||||
: path.join(process.cwd(), selectedDirectory);
|
||||
|
||||
logger.info(`🏃 Adding ${selectedConfig.name} into ${cwd}`);
|
||||
|
||||
logger.log('📦 Downloading repro template...');
|
||||
try {
|
||||
// Download the repro based on subfolder "after-storybook" and selected branch
|
||||
await degit(
|
||||
`storybookjs/repro-templates-temp/${selectedTemplate}/after-storybook#${branch}`,
|
||||
{
|
||||
force: true,
|
||||
}
|
||||
).clone(selectedTemplate.replace('/', '-'));
|
||||
} catch (err) {
|
||||
logger.error(`🚨 Failed to download repro template: ${err.message}`);
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info(
|
||||
boxen(
|
||||
dedent`
|
||||
🎉 Your Storybook reproduction project is ready to use! 🎉
|
||||
|
||||
${chalk.yellow(`cd ${selectedDirectory}`)}
|
||||
${chalk.yellow(`yarn storybook`)}
|
||||
|
||||
Once you've recreated the problem you're experiencing, please:
|
||||
|
||||
1. Document any additional steps in ${chalk.cyan('README.md')}
|
||||
2. Publish the repository to github
|
||||
3. Link to the repro repository in your issue
|
||||
|
||||
Having a clean repro helps us solve your issue faster! 🙏
|
||||
`.trim(),
|
||||
{ borderStyle: 'round', padding: 1, borderColor: '#F1618C' } as any
|
||||
)
|
||||
);
|
||||
} catch (error) {
|
||||
logger.error('🚨 Failed to create repro');
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
async function promptSelectedTemplate(choices: Choice[]): Promise<Choice | null> {
|
||||
const { template } = await prompts({
|
||||
type: 'select',
|
||||
message: '🌈 Select the template',
|
||||
name: 'template',
|
||||
choices: choices.map(toChoices),
|
||||
});
|
||||
|
||||
return template || null;
|
||||
}
|
21
code/lib/cli/src/repro-templates.ts
Normal file
21
code/lib/cli/src/repro-templates.ts
Normal file
@ -0,0 +1,21 @@
|
||||
// auto generated file, do not edit
|
||||
export default {
|
||||
'cra/default-js': {
|
||||
name: 'Create React App (Javascript)',
|
||||
script: 'npx create-react-app .',
|
||||
expected: {
|
||||
framework: '@storybook/cra',
|
||||
renderer: '@storybook/react',
|
||||
builder: '@storybook/builder-webpack5',
|
||||
},
|
||||
},
|
||||
'cra/default-ts': {
|
||||
name: 'Create React App (Typescript)',
|
||||
script: 'npx create-react-app . --template typescript',
|
||||
expected: {
|
||||
framework: '@storybook/cra',
|
||||
renderer: '@storybook/react',
|
||||
builder: '@storybook/builder-webpack5',
|
||||
},
|
||||
},
|
||||
} as const;
|
@ -7691,6 +7691,7 @@ __metadata:
|
||||
"@storybook/semver": ^7.3.2
|
||||
"@storybook/telemetry": 7.0.0-alpha.17
|
||||
"@types/cross-spawn": ^6.0.2
|
||||
"@types/degit": ^2.8.3
|
||||
"@types/prompts": ^2.0.9
|
||||
"@types/puppeteer-core": ^2.1.0
|
||||
"@types/semver": ^7.3.4
|
||||
@ -7701,6 +7702,7 @@ __metadata:
|
||||
commander: ^6.2.1
|
||||
core-js: ^3.8.2
|
||||
cross-spawn: ^7.0.3
|
||||
degit: ^2.8.4
|
||||
envinfo: ^7.7.3
|
||||
execa: ^5.0.0
|
||||
express: ^4.17.1
|
||||
@ -7708,6 +7710,7 @@ __metadata:
|
||||
fs-extra: ^9.0.1
|
||||
get-port: ^5.1.1
|
||||
globby: ^11.0.2
|
||||
js-yaml: ^3.14.1
|
||||
jscodeshift: ^0.13.1
|
||||
json5: ^2.1.3
|
||||
leven: ^3.1.0
|
||||
@ -10110,6 +10113,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/degit@npm:^2.8.3":
|
||||
version: 2.8.3
|
||||
resolution: "@types/degit@npm:2.8.3"
|
||||
checksum: 1693dc0033aa5aa5c339b76d570c462e3e0ff41e22a7cc2d0164276199ddbd6ed18813042868355bc5f60ee257c0b18bce904c193008685b790392454ec9fcbd
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/detect-port@npm:^1.3.2":
|
||||
version: 1.3.2
|
||||
resolution: "@types/detect-port@npm:1.3.2"
|
||||
@ -18446,6 +18456,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"degit@npm:^2.8.4":
|
||||
version: 2.8.4
|
||||
resolution: "degit@npm:2.8.4"
|
||||
bin:
|
||||
degit: degit
|
||||
checksum: 25ae9daf8010b450ffe8307c5ca903fe8bfaa8bb8622da12f81f2b6c3b1bb24e96fe3ab0b4ec4a1a19684f674b2158a8a3a2178c481882cc4991c7a0859ec40a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"del-cli@npm:^4.0.1":
|
||||
version: 4.0.1
|
||||
resolution: "del-cli@npm:4.0.1"
|
||||
|
Loading…
x
Reference in New Issue
Block a user