Skip to content

Commit

Permalink
feat: add next-repro CLI command
Browse files Browse the repository at this point in the history
  • Loading branch information
yannbf committed Jul 26, 2022
1 parent 3044e4a commit d282324
Show file tree
Hide file tree
Showing 7 changed files with 152 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ dist
*.DS_Store
.cache
junit.xml
/repros

# Yarn stuff
/**/.yarn/*
Expand Down
1 change: 1 addition & 0 deletions code/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
"lint:other": "prettier --write '**/*.{css,html,json,md,yml}'",
"lint:package": "sort-package-json",
"local-registry": "ts-node --project=../scripts/tsconfig.json ../scripts/run-registry.ts --port 6000",
"next-repro": "ts-node ../scripts/next-repro-generators/index.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",
Expand Down
126 changes: 126 additions & 0 deletions scripts/next-repro-generators/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/* eslint-disable no-console */
import path, { join, relative } from 'path';
import program from 'commander';
import { command } from 'execa';
import type { Options as ExecaOptions } from 'execa';
import yaml from 'js-yaml';
import pLimit from 'p-limit';
import prettyTime from 'pretty-hrtime';
import { copy, emptyDir, ensureDir, readFile, remove, rename } from 'fs-extra';

const maxConcurrentTasks = 3;

type GeneratorConfig = {
name: string;
script: string;
// expected?: {
// framework?: string;
// renderer?: string;
// builder?: string;
// };
};

type DataEntry = {
script: string;
};

const OUTPUT_DIRECTORY = join(__dirname, '..', '..', 'repros');

const addStorybook = async (baseDir: string) => {
const beforeDir = join(baseDir, 'before');
const afterDir = join(baseDir, 'after');
const tmpDir = join(baseDir, '.tmp');

await ensureDir(tmpDir);
await emptyDir(tmpDir);

await copy(beforeDir, tmpDir);

const sbCliBinaryPath = join(__dirname, `../../code/lib/cli/bin/index.js`);
await runCommand(`${sbCliBinaryPath} init`, {
cwd: tmpDir,
});

await rename(tmpDir, afterDir);
};

const runCommand = async (commandString: string, options: ExecaOptions) => {
// TODO: remove true
const shouldDebug = true || !!process.env.DEBUG;

const out = await command('which yarn', {
...options,
});
commandString = commandString.replace('yarn', out.stdout.trim());

if (shouldDebug) {
console.log(`Running command: ${commandString}`);
}

return command(commandString, { stdout: shouldDebug ? 'inherit' : 'ignore', ...options });
};

const runGenerators = async (generators: GeneratorConfig[]) => {
console.log(`🤹‍♂️ Generating repros with a concurrency of ${maxConcurrentTasks}`);

const limit = pLimit(maxConcurrentTasks);

return Promise.all(
generators.map(({ name, script }) =>
limit(async () => {
const time = process.hrtime();
console.log(`🧬 generating ${name}`);

const baseDir = join(OUTPUT_DIRECTORY, name);
const beforeDir = join(baseDir, 'before');
const afterDir = join(baseDir, 'after');
const tmpDir = join(baseDir, '.tmp');

await Promise.all([
ensureDir(beforeDir).then(() => emptyDir(beforeDir)),
remove(afterDir),
remove(tmpDir),
]);

await runCommand(script, { cwd: beforeDir });

await addStorybook(baseDir);

console.log(
`✅ Created ${name} in ./${relative(process.cwd(), baseDir)} successfully in ${prettyTime(
process.hrtime(time)
)}`
);
})
)
);
};

const generate = async ({ config }: { config: string }) => {
const configContents = await readFile(config, 'utf8');
const data: Record<string, DataEntry> = yaml.load(configContents);

runGenerators(
Object.entries(data).map(([name, configuration]) => ({
name,
script: configuration.script,
}))
);
};

program
.description('Create a reproduction from a set of possible templates')
.option(
'-c --config <config>',
'Choose a custom configuration file (.yml format)',
path.join(__dirname, 'repro-config.yml')
);

program.parse(process.argv);

const options = program.opts() as { config: string };

generate(options).catch((e) => {
console.error(e);
process.exit(1);
});
14 changes: 14 additions & 0 deletions scripts/next-repro-generators/repro-config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# group-name/instance-name. Should always be two levels deep.
cra/default-js:
script: "yarn -v"
expected:
framework: "@storybook/cra"
renderer: "@storybook/react"
builder: "@storybook/builder-webpack5"

# cra/default-ts:
# script: "yarn create react-app . --template typescript"
# expected:
# framework: "@storybook/cra"
# renderer: "@storybook/react"
# builder: "@storybook/builder-webpack5"
1 change: 1 addition & 0 deletions scripts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@
"npmlog": "^5.0.1",
"p-limit": "^3.1.0",
"prettier": ">=2.2.1 <=2.3.0",
"pretty-hrtime": "^1.0.0",
"prompts": "^2.4.0",
"react": "16.14.0",
"react-dom": "16.14.0",
Expand Down
1 change: 1 addition & 0 deletions scripts/typings.d.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
declare module 'verdaccio';
declare module 'pretty-hrtime';
8 changes: 8 additions & 0 deletions scripts/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3334,6 +3334,7 @@ __metadata:
npmlog: ^5.0.1
p-limit: ^3.1.0
prettier: ">=2.2.1 <=2.3.0"
pretty-hrtime: ^1.0.0
prompts: ^2.4.0
puppeteer: ^2.1.1
react: 16.14.0
Expand Down Expand Up @@ -15639,6 +15640,13 @@ __metadata:
languageName: node
linkType: hard

"pretty-hrtime@npm:^1.0.0":
version: 1.0.3
resolution: "pretty-hrtime@npm:1.0.3"
checksum: 67cb3fc283a72252b49ac488647e6a01b78b7aa1b8f2061834aa1650691229081518ef3ca940f77f41cc8a8f02ba9eeb74b843481596670209e493062f2e89e0
languageName: node
linkType: hard

"prettyjson@npm:^1.2.1":
version: 1.2.5
resolution: "prettyjson@npm:1.2.5"
Expand Down

0 comments on commit d282324

Please sign in to comment.