mirror of
https://github.com/storybookjs/storybook.git
synced 2025-04-08 02:11:49 +08:00
122 lines
4.5 KiB
TypeScript
Executable File
122 lines
4.5 KiB
TypeScript
Executable File
import { program } from 'commander';
|
|
// eslint-disable-next-line depend/ban-dependencies
|
|
import { execaCommand } from 'execa';
|
|
import { existsSync } from 'fs';
|
|
// eslint-disable-next-line depend/ban-dependencies
|
|
import { copy, emptyDir, remove, writeFile } from 'fs-extra';
|
|
// eslint-disable-next-line depend/ban-dependencies
|
|
import { glob } from 'glob';
|
|
import { dirname, join, relative } from 'path';
|
|
|
|
import { temporaryDirectory } from '../../code/core/src/common/utils/cli';
|
|
import { REPROS_DIRECTORY } from '../utils/constants';
|
|
import { commitAllToGit } from './utils/git';
|
|
import { getTemplatesData, renderTemplate } from './utils/template';
|
|
|
|
export const logger = console;
|
|
|
|
interface PublishOptions {
|
|
remote?: string;
|
|
push?: boolean;
|
|
branch?: string;
|
|
}
|
|
|
|
const publish = async (options: PublishOptions & { tmpFolder: string }) => {
|
|
const { branch: inputBranch, remote, push, tmpFolder } = options;
|
|
|
|
const scriptPath = __dirname;
|
|
const branch = inputBranch || 'next';
|
|
const templatesData = await getTemplatesData(branch === 'main' ? 'main' : 'next');
|
|
|
|
logger.log(`👯♂️ Cloning the repository ${remote} in branch ${branch}`);
|
|
await execaCommand(`git clone ${remote} .`, { cwd: tmpFolder, cleanup: true });
|
|
await execaCommand(`git checkout ${branch}`, { cwd: tmpFolder, cleanup: true });
|
|
|
|
// otherwise old files will stick around and result inconsistent states
|
|
logger.log(`🗑 Delete existing template dirs from clone`);
|
|
|
|
// empty all existing directories for sandboxes that have a successful after-storybook directory
|
|
await Promise.all(
|
|
// find all successfully generated after-storybook/README.md files
|
|
// eg. /home/repros/react-vite/default-ts/after-storybook/README.md
|
|
// README.md being the last file generated, thus representing a successful generation
|
|
(await glob(join(REPROS_DIRECTORY, '**', 'after-storybook/README.md'))).map((readmePath) => {
|
|
// get the after-storybook path relative to the source 'repros' directory
|
|
// eg. ./react-vite/default-ts/after-storybook
|
|
const pathRelativeToSource = relative(REPROS_DIRECTORY, dirname(readmePath));
|
|
// get the actual path to the corresponding sandbox directory in the clone
|
|
// eg. /home/sandboxes-clone/react-vite/default-ts
|
|
const sandboxDirectoryToEmpty = join(tmpFolder, pathRelativeToSource, '..');
|
|
return emptyDir(sandboxDirectoryToEmpty);
|
|
})
|
|
);
|
|
|
|
logger.log(`🚚 Moving template files into the repository`);
|
|
|
|
const templatePath = join(scriptPath, 'templates', 'root.ejs');
|
|
const templateData = { data: templatesData, version: branch === 'main' ? 'latest' : 'next' };
|
|
|
|
const output = await renderTemplate(templatePath, templateData);
|
|
|
|
await writeFile(join(tmpFolder, 'README.md'), output);
|
|
|
|
logger.log(`🚛 Moving all the repros into the repository`);
|
|
await copy(REPROS_DIRECTORY, tmpFolder);
|
|
|
|
await commitAllToGit({ cwd: tmpFolder, branch });
|
|
|
|
logger.info(`
|
|
🙌 All the examples were bootstrapped:
|
|
- in ${tmpFolder}
|
|
- using the '${branch}' version of Storybook CLI
|
|
- and committed on the '${branch}' branch of a local Git repository
|
|
|
|
Also all the files in the 'templates' folder were copied at the root of the Git repository.
|
|
`);
|
|
|
|
if (push) {
|
|
await execaCommand(`git push --set-upstream origin ${branch}`, {
|
|
cwd: tmpFolder,
|
|
});
|
|
const remoteRepoUrl = `${remote.replace('.git', '')}/tree/${branch}`;
|
|
logger.info(`🚀 Everything was pushed on ${remoteRepoUrl}`);
|
|
} else {
|
|
logger.info(`
|
|
To publish these examples you just need to:
|
|
- push the branch: 'git push --set-upstream origin ${branch}
|
|
`);
|
|
}
|
|
};
|
|
|
|
program
|
|
.description('Create a sandbox from a set of possible templates')
|
|
.option('--remote <remote>', 'Choose the remote to push the contents to')
|
|
.option('--branch <branch>', 'Choose which branch on the remote')
|
|
.option('--push', 'Whether to push the contents to the remote', false)
|
|
.option('--force-push', 'Whether to force push the changes into the repros repository', false);
|
|
|
|
program.parse(process.argv);
|
|
|
|
if (!existsSync(REPROS_DIRECTORY)) {
|
|
throw Error("Couldn't find sandbox directory. Did you forget to run generate-sandboxes?");
|
|
}
|
|
|
|
async function main() {
|
|
const tmpFolder = await temporaryDirectory();
|
|
logger.log(`⏱ Created tmp folder: ${tmpFolder}`);
|
|
|
|
const options = program.opts() as PublishOptions;
|
|
|
|
publish({ ...options, tmpFolder }).catch(async (e) => {
|
|
logger.error(e);
|
|
|
|
if (existsSync(tmpFolder)) {
|
|
logger.log('🚮 Removing the temporary folder..');
|
|
await remove(tmpFolder);
|
|
}
|
|
process.exit(1);
|
|
});
|
|
}
|
|
|
|
main();
|