mirror of
https://github.com/storybookjs/storybook.git
synced 2025-03-16 05:03:11 +08:00
rename repro -> sandbox
This commit is contained in:
parent
ac5c1d22a7
commit
fca8f01de9
2
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
2
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@ -19,7 +19,7 @@ body:
|
||||
attributes:
|
||||
label: To Reproduce
|
||||
description: >-
|
||||
Please create a reproduction by running `npx sb@next repro` and
|
||||
Please create a reproduction by running `npx sb@next sandbox` and
|
||||
following the instructions. Read our
|
||||
[documentation](https://storybook.js.org/docs/react/contribute/how-to-reproduce)
|
||||
to learn more about creating reproductions.
|
||||
|
8
.github/workflows/generate-repros.yml
vendored
8
.github/workflows/generate-repros.yml
vendored
@ -14,7 +14,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
YARN_ENABLE_IMMUTABLE_INSTALLS: false
|
||||
CLEANUP_REPRO_NODE_MODULES: true
|
||||
CLEANUP_SANDBOX_NODE_MODULES: true
|
||||
steps:
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
@ -35,8 +35,8 @@ jobs:
|
||||
run: yarn wait-on http://localhost:6001
|
||||
working-directory: ./code
|
||||
- name: Generate repros
|
||||
run: yarn generate-repros --local-registry
|
||||
run: yarn generate-sandboxes --local-registry
|
||||
working-directory: ./code
|
||||
- name: Publish repros to GitHub
|
||||
run: yarn publish-repros --remote=https://storybook-bot:${{ secrets.PAT_STORYBOOK_BOT}}@github.com/storybookjs/repro-sandboxes.git --push
|
||||
- name: Publish sandboxes to GitHub
|
||||
run: yarn publish-sandboxes --remote=https://storybook-bot:${{ secrets.PAT_STORYBOOK_BOT}}@github.com/storybookjs/sandboxes.git --push
|
||||
working-directory: ./code
|
||||
|
@ -13,7 +13,7 @@ import { add } from './add';
|
||||
import { migrate } from './migrate';
|
||||
import { extract } from './extract';
|
||||
import { upgrade, type UpgradeOptions } from './upgrade';
|
||||
import { repro } from './repro';
|
||||
import { sandbox } from './sandbox';
|
||||
import { link } from './link';
|
||||
import { automigrate } from './automigrate';
|
||||
import { generateStorybookBabelConfigInCWD } from './babel-config';
|
||||
@ -141,13 +141,14 @@ program
|
||||
);
|
||||
|
||||
program
|
||||
.command('repro [filterValue]')
|
||||
.description('Create a reproduction from a set of possible templates')
|
||||
.command('sandbox [filterValue]')
|
||||
.alias('repro') // for retrocompatibility purposes
|
||||
.description('Create a sandbox from a set of possible templates')
|
||||
.option('-o --output <outDir>', 'Define an output directory')
|
||||
.option('-b --branch <branch>', 'Define the branch to download from', 'next')
|
||||
.option('--no-init', 'Whether to download a template without an initialized Storybook', false)
|
||||
.action((filterValue, options) =>
|
||||
repro({ filterValue, ...options }).catch((e) => {
|
||||
sandbox({ filterValue, ...options }).catch((e) => {
|
||||
logger.error(e);
|
||||
process.exit(1);
|
||||
})
|
||||
|
@ -2,7 +2,9 @@ import fse from 'fs-extra';
|
||||
import path from 'path';
|
||||
import { sync as spawnSync } from 'cross-spawn';
|
||||
import { logger } from '@storybook/node-logger';
|
||||
import { exec } from './repro-generators/scripts';
|
||||
import shell from 'shelljs';
|
||||
import chalk from 'chalk';
|
||||
import type { ExecOptions } from 'shelljs';
|
||||
|
||||
interface LinkOptions {
|
||||
target: string;
|
||||
@ -10,6 +12,49 @@ interface LinkOptions {
|
||||
start: boolean;
|
||||
}
|
||||
|
||||
// TODO: Extract this to somewhere else, or use `exec` from a different file that might already have it
|
||||
export const exec = async (
|
||||
command: string,
|
||||
options: ExecOptions = {},
|
||||
{
|
||||
startMessage,
|
||||
errorMessage,
|
||||
dryRun,
|
||||
}: { startMessage?: string; errorMessage?: string; dryRun?: boolean } = {}
|
||||
) => {
|
||||
if (startMessage) logger.info(startMessage);
|
||||
|
||||
if (dryRun) {
|
||||
logger.info(`\n> ${command}\n`);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
logger.info(command);
|
||||
return new Promise((resolve, reject) => {
|
||||
const defaultOptions: ExecOptions = {
|
||||
silent: false,
|
||||
};
|
||||
const child = shell.exec(command, {
|
||||
...defaultOptions,
|
||||
...options,
|
||||
async: true,
|
||||
silent: false,
|
||||
});
|
||||
|
||||
child.stderr.pipe(process.stderr);
|
||||
|
||||
child.on('exit', (code) => {
|
||||
if (code === 0) {
|
||||
resolve(undefined);
|
||||
} else {
|
||||
logger.error(chalk.red(`An error occurred while executing: \`${command}\``));
|
||||
logger.info(errorMessage);
|
||||
reject(new Error(`command exited with code: ${code}: `));
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export const link = async ({ target, local, start }: LinkOptions) => {
|
||||
const storybookDir = process.cwd();
|
||||
try {
|
||||
@ -58,12 +103,12 @@ export const link = async ({ target, local, start }: LinkOptions) => {
|
||||
logger.info(`Installing ${reproName}`);
|
||||
await exec(`yarn install`, { cwd: reproDir });
|
||||
|
||||
// ⚠️ TODO: Fix peer deps in `@storybook/preset-create-react-app`
|
||||
logger.info(
|
||||
`Magic stuff related to @storybook/preset-create-react-app, we need to fix peerDependencies`
|
||||
);
|
||||
|
||||
if (!reproPackageJson.devDependencies?.vite) {
|
||||
// ⚠️ TODO: Fix peer deps in `@storybook/preset-create-react-app`
|
||||
logger.info(
|
||||
`Magic stuff related to @storybook/preset-create-react-app, we need to fix peerDependencies`
|
||||
);
|
||||
|
||||
await exec(`yarn add -D webpack-hot-middleware`, { cwd: reproDir });
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,7 @@ export type Template = {
|
||||
/**
|
||||
* Script used to generate the base project of a template.
|
||||
* The Storybook CLI will then initialize Storybook on top of that template.
|
||||
* This is used to generate projects which are pushed to https://github.com/storybookjs/repro-sandboxes
|
||||
* This is used to generate projects which are pushed to https://github.com/storybookjs/sandboxes
|
||||
*/
|
||||
script: string;
|
||||
/**
|
||||
|
@ -11,7 +11,7 @@ import { allTemplates as TEMPLATES } from './sandbox-templates';
|
||||
|
||||
const logger = console;
|
||||
|
||||
interface ReproOptions {
|
||||
interface SandboxOptions {
|
||||
filterValue?: string;
|
||||
output?: string;
|
||||
branch?: string;
|
||||
@ -21,12 +21,12 @@ type Choice = keyof typeof TEMPLATES;
|
||||
|
||||
const toChoices = (c: Choice): prompts.Choice => ({ title: TEMPLATES[c].name, value: c });
|
||||
|
||||
export const repro = async ({
|
||||
export const sandbox = async ({
|
||||
output: outputDirectory,
|
||||
filterValue,
|
||||
branch,
|
||||
init,
|
||||
}: ReproOptions) => {
|
||||
}: SandboxOptions) => {
|
||||
// Either get a direct match when users pass a template id, or filter through all templates
|
||||
let selectedConfig: Template | undefined = TEMPLATES[filterValue as TemplateKey];
|
||||
let selectedTemplate: Choice | null = selectedConfig ? (filterValue as TemplateKey) : null;
|
||||
@ -83,7 +83,7 @@ export const repro = async ({
|
||||
logger.info(
|
||||
boxen(
|
||||
dedent`
|
||||
🤗 Welcome to ${chalk.yellow('sb repro NEXT')}! 🤗
|
||||
🤗 Welcome to ${chalk.yellow('sb sandbox')}! 🤗
|
||||
|
||||
Create a ${chalk.green('new project')} to minimally reproduce Storybook issues.
|
||||
|
||||
@ -108,7 +108,7 @@ export const repro = async ({
|
||||
selectedConfig = TEMPLATES[selectedTemplate];
|
||||
|
||||
if (!selectedConfig) {
|
||||
throw new Error('🚨 Repro: please specify a valid template type');
|
||||
throw new Error('🚨 Sandbox: please specify a valid template type');
|
||||
}
|
||||
}
|
||||
|
||||
@ -147,11 +147,11 @@ export const repro = async ({
|
||||
|
||||
logger.info(`🏃 Adding ${selectedConfig.name} into ${templateDestination}`);
|
||||
|
||||
logger.log('📦 Downloading repro template...');
|
||||
logger.log('📦 Downloading sandbox template...');
|
||||
try {
|
||||
const templateType = init ? 'after-storybook' : 'before-storybook';
|
||||
// Download the repro based on subfolder "after-storybook" and selected branch
|
||||
const gitPath = `github:storybookjs/repro-templates-temp/${selectedTemplate}/${templateType}#${branch}`;
|
||||
// Download the sandbox based on subfolder "after-storybook" and selected branch
|
||||
const gitPath = `github:storybookjs/sandboxes/${selectedTemplate}/${templateType}#${branch}`;
|
||||
await downloadTemplate(gitPath, {
|
||||
force: true,
|
||||
dir: templateDestination,
|
||||
@ -166,7 +166,7 @@ export const repro = async ({
|
||||
);
|
||||
}
|
||||
} catch (err) {
|
||||
logger.error(`🚨 Failed to download repro template: ${err.message}`);
|
||||
logger.error(`🚨 Failed to download sandbox template: ${err.message}`);
|
||||
throw err;
|
||||
}
|
||||
|
||||
@ -194,7 +194,7 @@ export const repro = async ({
|
||||
)
|
||||
);
|
||||
} catch (error) {
|
||||
logger.error('🚨 Failed to create repro');
|
||||
logger.error('🚨 Failed to create sandbox');
|
||||
throw error;
|
||||
}
|
||||
};
|
@ -30,7 +30,7 @@
|
||||
"ci-tests": "yarn task --task check --no-link --start-from=install && yarn lint && yarn test && cd ../scripts && yarn test",
|
||||
"coverage": "codecov",
|
||||
"danger": "danger",
|
||||
"generate-repros": "ts-node --swc ../scripts/next-repro-generators/generate-repros.ts",
|
||||
"generate-sandboxes": "ts-node --swc ../scripts/sandbox-generators/generate-repros.ts",
|
||||
"github-release": "github-release-from-changelog",
|
||||
"linear-export": "ts-node --swc --project=../scripts/tsconfig.json ../scripts/linear-export.ts",
|
||||
"lint": "yarn lint:js && yarn lint:md",
|
||||
@ -41,7 +41,7 @@
|
||||
"lint:other": "prettier --write '**/*.{css,html,json,md,yml}'",
|
||||
"lint:package": "sort-package-json",
|
||||
"local-registry": "ts-node --swc --project=../scripts/tsconfig.json ../scripts/run-registry.ts",
|
||||
"publish-repros": "ts-node --swc ../scripts/next-repro-generators/publish.ts",
|
||||
"publish-sandboxes": "ts-node --swc ../scripts/sandbox-generators/publish.ts",
|
||||
"publish:debug": "npm run publish:latest -- --npm-tag=debug --no-push",
|
||||
"publish:latest": "lerna publish --exact --concurrency 1 --force-publish",
|
||||
"publish:next": "npm run publish:latest -- --npm-tag=next",
|
||||
|
@ -188,13 +188,13 @@ npx storybook@next link --local /path/to/local-repro-directory
|
||||
|
||||
<div class="aside">
|
||||
|
||||
💡 The `storybook link` command relies on [Yarn 2 linking](https://yarnpkg.com/cli/link/) under the hood. It requires your local reproduction to be using [Yarn 2](https://yarnpkg.com/) as well, which is the case if you're already enabled it with the [`storybook repro`](./how-to-reproduce.md) command per our contribution guidelines. The process will fail if you're trying to link a non-Yarn 2 project.
|
||||
💡 The `storybook link` command relies on [Yarn 2 linking](https://yarnpkg.com/cli/link/) under the hood. It requires your local reproduction to be using [Yarn 2](https://yarnpkg.com/) as well, which is the case if you're already enabled it with the [`storybook sandbox`](./how-to-reproduce.md) command per our contribution guidelines. The process will fail if you're trying to link a non-Yarn 2 project.
|
||||
|
||||
</div>
|
||||
|
||||
## Developing a template
|
||||
|
||||
The first step is to add an entry to `code/lib/cli/src/repro-templates.ts`, which is the master list of all repro templates:
|
||||
The first step is to add an entry to `code/lib/cli/src/sandbox-templates.ts`, which is the master list of all repro templates:
|
||||
|
||||
```ts
|
||||
'cra/default-js': {
|
||||
@ -209,7 +209,7 @@ The first step is to add an entry to `code/lib/cli/src/repro-templates.ts`, whic
|
||||
},
|
||||
```
|
||||
|
||||
Add the `isDevelopment` flag until the PR is merged (you can fast-follow it with a second PR to remove the flag), as it'll make the development process much easier.
|
||||
Add the `inDevelopment` flag until the PR is merged (you can fast-follow it with a second PR to remove the flag), as it'll make the development process much easier.
|
||||
|
||||
The **`key`** `cra/default-js` consists of two parts:
|
||||
|
||||
|
@ -21,11 +21,11 @@ Make sure you have:
|
||||
First, open a terminal and run the following command:
|
||||
|
||||
```shell
|
||||
npx storybook@next repro
|
||||
npx storybook@next sandbox
|
||||
```
|
||||
|
||||
<div class="aside">
|
||||
💡 You can append a template name in the command to get filtered results e.g. <code>npx storybook@next repro react</code>
|
||||
💡 You can append a template name in the command to get filtered results e.g. <code>npx storybook@next sandbox react</code>
|
||||
</div>
|
||||
|
||||
Next, choose the template you want to work with:
|
||||
|
@ -1,3 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
./scripts/node_modules/.bin/ts-node ./scripts/next-repro-generators/generate-repros.ts
|
3
generate-sandboxes.sh
Executable file
3
generate-sandboxes.sh
Executable file
@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
./scripts/node_modules/.bin/ts-node ./scripts/sandbox-generators/generate-sandboxes.ts
|
@ -10,7 +10,7 @@ import { execaCommand } from '../utils/exec';
|
||||
|
||||
import type { OptionValues } from '../utils/options';
|
||||
import { createOptions } from '../utils/options';
|
||||
import { allTemplates as reproTemplates } from '../../code/lib/cli/src/sandbox-templates';
|
||||
import { allTemplates as sandboxTemplates } from '../../code/lib/cli/src/sandbox-templates';
|
||||
import storybookVersions from '../../code/lib/cli/src/versions';
|
||||
import { JsPackageManagerFactory } from '../../code/lib/cli/src/js-package-manager/JsPackageManagerFactory';
|
||||
|
||||
@ -30,7 +30,7 @@ const SCRIPT_TIMEOUT = 5 * 60 * 1000;
|
||||
const sbInit = async (cwd: string, flags?: string[], debug?: boolean) => {
|
||||
const sbCliBinaryPath = join(__dirname, `../../code/lib/cli/bin/index.js`);
|
||||
console.log(`🎁 Installing storybook`);
|
||||
const env = { STORYBOOK_DISABLE_TELEMETRY: 'true', STORYBOOK_REPRO_GENERATOR: 'true' };
|
||||
const env = { STORYBOOK_DISABLE_TELEMETRY: 'true' };
|
||||
const fullFlags = ['--yes', ...(flags || [])];
|
||||
await runCommand(`${sbCliBinaryPath} init ${fullFlags.join(' ')}`, { cwd, env }, debug);
|
||||
};
|
||||
@ -124,7 +124,7 @@ const runGenerators = async (
|
||||
localRegistry = true,
|
||||
debug = false
|
||||
) => {
|
||||
console.log(`🤹♂️ Generating repros with a concurrency of ${maxConcurrentTasks}`);
|
||||
console.log(`🤹♂️ Generating sandboxes with a concurrency of ${maxConcurrentTasks}`);
|
||||
|
||||
const limit = pLimit(maxConcurrentTasks);
|
||||
|
||||
@ -177,8 +177,8 @@ const runGenerators = async (
|
||||
await addDocumentation(baseDir, { name, dirName });
|
||||
|
||||
// Remove node_modules to save space and avoid GH actions failing
|
||||
// They're not uploaded to the git repros repo anyway
|
||||
if (process.env.CLEANUP_REPRO_NODE_MODULES) {
|
||||
// They're not uploaded to the git sandboxes repo anyway
|
||||
if (process.env.CLEANUP_SANDBOX_NODE_MODULES) {
|
||||
console.log(`🗑️ Removing ${join(beforeDir, 'node_modules')}`);
|
||||
await remove(join(beforeDir, 'node_modules'));
|
||||
console.log(`🗑️ Removing ${join(baseDir, AFTER_DIR_NAME, 'node_modules')}`);
|
||||
@ -200,7 +200,7 @@ export const options = createOptions({
|
||||
template: {
|
||||
type: 'string',
|
||||
description: 'Which template would you like to create?',
|
||||
values: Object.keys(reproTemplates),
|
||||
values: Object.keys(sandboxTemplates),
|
||||
},
|
||||
localRegistry: {
|
||||
type: 'boolean',
|
||||
@ -219,7 +219,7 @@ export const generate = async ({
|
||||
localRegistry,
|
||||
debug,
|
||||
}: OptionValues<typeof options>) => {
|
||||
const generatorConfigs = Object.entries(reproTemplates)
|
||||
const generatorConfigs = Object.entries(sandboxTemplates)
|
||||
.map(([dirName, configuration]) => ({
|
||||
dirName,
|
||||
...configuration,
|
@ -91,7 +91,7 @@ program
|
||||
program.parse(process.argv);
|
||||
|
||||
if (!existsSync(REPROS_DIRECTORY)) {
|
||||
throw Error("Can't find repros directory. Did you forget to run generate-repros?");
|
||||
throw Error("Can't find repros directory. Did you forget to run generate-sandboxes?");
|
||||
}
|
||||
|
||||
const tmpFolder = tempy.directory();
|
@ -2,7 +2,7 @@ import { render } from 'ejs';
|
||||
import { readFile } from 'fs-extra';
|
||||
import { format } from 'prettier';
|
||||
import type { GeneratorConfig } from './types';
|
||||
import { allTemplates as reproTemplates } from '../../../code/lib/cli/src/sandbox-templates';
|
||||
import { allTemplates as sandboxTemplates } from '../../../code/lib/cli/src/sandbox-templates';
|
||||
|
||||
export async function renderTemplate(templatePath: string, templateData: Record<string, any>) {
|
||||
const template = await readFile(templatePath, 'utf8');
|
||||
@ -14,7 +14,7 @@ export async function renderTemplate(templatePath: string, templateData: Record<
|
||||
}
|
||||
|
||||
export const getStackblitzUrl = (path: string, branch = 'next') => {
|
||||
return `https://stackblitz.com/github/storybookjs/repro-sandboxes/tree/${branch}/${path}/after-storybook?preset=node`;
|
||||
return `https://stackblitz.com/github/storybookjs/sandboxes/tree/${branch}/${path}/after-storybook?preset=node`;
|
||||
};
|
||||
|
||||
export async function getTemplatesData() {
|
||||
@ -28,12 +28,12 @@ export async function getTemplatesData() {
|
||||
>
|
||||
>;
|
||||
|
||||
const templatesData = Object.keys(reproTemplates).reduce<TemplatesData>(
|
||||
(acc, curr: keyof typeof reproTemplates) => {
|
||||
const templatesData = Object.keys(sandboxTemplates).reduce<TemplatesData>(
|
||||
(acc, curr: keyof typeof sandboxTemplates) => {
|
||||
const [dirName, templateName] = curr.split('/');
|
||||
const groupName =
|
||||
dirName === 'cra' ? 'CRA' : dirName.slice(0, 1).toUpperCase() + dirName.slice(1);
|
||||
const generatorData = reproTemplates[curr];
|
||||
const generatorData = sandboxTemplates[curr];
|
||||
acc[groupName] = acc[groupName] || {};
|
||||
acc[groupName][templateName] = {
|
||||
...generatorData,
|
@ -1,7 +1,7 @@
|
||||
import { join } from 'path';
|
||||
import { move, remove } from 'fs-extra';
|
||||
// eslint-disable-next-line import/no-cycle
|
||||
import { runCommand } from '../generate-repros';
|
||||
import { runCommand } from '../generate-sandboxes';
|
||||
|
||||
interface SetupYarnOptions {
|
||||
cwd: string;
|
@ -27,7 +27,7 @@ export const generate: Task = {
|
||||
}
|
||||
|
||||
// This uses an async import as it depends on `lib/cli` which requires `code` to be installed.
|
||||
const { generate: generateRepro } = await import('../next-repro-generators/generate-repros');
|
||||
const { generate: generateRepro } = await import('../sandbox-generators/generate-sandboxes');
|
||||
|
||||
await generateRepro({
|
||||
template: details.key,
|
||||
|
Loading…
x
Reference in New Issue
Block a user