Merge pull request #145 from spotify/eide/cli-build-plugin

[cli] Run required yarn commands when creating a plugin
This commit is contained in:
marcuseide
2020-03-04 11:17:19 +01:00
committed by GitHub
2 changed files with 78 additions and 23 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@spotify-backstage/cli",
"version": "1.2.0",
"version": "1.3.0",
"main": "src/index.ts",
"main:src": "src/index.ts",
"license": "Apache-2.0",
@@ -4,11 +4,21 @@ import handlebars from 'handlebars';
import chalk from 'chalk';
import inquirer, { Answers, Question } from 'inquirer';
import recursive from 'recursive-readdir';
import { promisify } from 'util';
import { exec } from 'child_process';
export const createPluginFolder = (rootDir: string, id: string): string => {
console.log();
console.log(chalk.green(' Creating the plugin directory:'));
const destination = path.join(rootDir, 'packages', 'plugins', id);
if (fs.existsSync(destination)) {
console.log(
chalk.red(
` failed:\t ✗ ${chalk.cyan(destination.replace(rootDir, ''))}`,
),
);
throw new Error(
`A plugin with the same name already exists: ${chalk.cyan(
destination.replace(rootDir, ''),
@@ -16,13 +26,15 @@ export const createPluginFolder = (rootDir: string, id: string): string => {
);
}
process.stdout.write(
chalk.green(` creating\t${chalk.cyan(destination.replace(rootDir, ''))}`),
);
try {
console.log(
chalk.green(`Creating:\t${chalk.cyan(destination.replace(rootDir, ''))}`),
);
fs.mkdirSync(destination, { recursive: true });
process.stdout.write(chalk.green(' ✓\n'));
return destination;
} catch (e) {
process.stdout.write(chalk.red(`\n`));
throw new Error(
`Failed to create plugin directory: ${destination}: ${e.message}`,
);
@@ -41,11 +53,10 @@ export const createFileFromTemplate = (
...answers,
});
try {
console.log(
chalk.green(`Creating:\t${chalk.cyan(path.basename(destination))}`),
);
fs.writeFileSync(destination, contents);
process.stdout.write(chalk.green(`\n`));
} catch (e) {
process.stdout.write(chalk.red(`\n`));
throw new Error(`Failed to create file: ${destination}: ${e.message}`);
}
};
@@ -55,14 +66,28 @@ export const createFromTemplateDir = async (
destinationFolder: string,
answers: Answers,
) => {
console.log();
console.log(chalk.green(' Reading template files:'));
let files = [];
process.stdout.write(chalk.green(` reading\t`));
try {
files = await recursive(templateFolder);
process.stdout.write(
chalk.green(`${chalk.cyan(`${files.length} files`)}\n`),
);
} catch (e) {
console.log(chalk.red(` ✗ 0 files\n`));
throw new Error(`Failed to read files in template directory: ${e.message}`);
}
console.log();
console.log(chalk.green(' Setting up the plugin files:'));
files.forEach(file => {
process.stdout.write(
chalk.green(` processing\t${chalk.cyan(path.basename(file))}`),
);
fs.ensureDirSync(
file
.replace(templateFolder, destinationFolder)
@@ -75,10 +100,11 @@ export const createFromTemplateDir = async (
answers,
);
} else {
console.log(chalk.green(`Copying:\t${chalk.cyan(path.basename(file))}`));
try {
fs.copyFileSync(file, file.replace(templateFolder, destinationFolder));
process.stdout.write(chalk.green(`\n`));
} catch (e) {
process.stdout.write(chalk.red(`\n`));
throw new Error(
`Failed to copy file: ${file.replace(
templateFolder,
@@ -98,7 +124,7 @@ const cleanUp = async (rootDir: string, id: string) => {
type: 'confirm',
name: 'cleanup',
message: chalk.yellow(
`Do you want to remove the created directory and all the files in it?\ndir: ${chalk.cyan(
`It seems that something went wrong when creating the plugin 🤔\nDo you want to remove the following directory and all the files in it:\n${chalk.cyan(
destination,
)}`,
),
@@ -107,18 +133,47 @@ const cleanUp = async (rootDir: string, id: string) => {
const answers: Answers = await inquirer.prompt(questions);
if (answers.cleanup) {
console.log();
console.log(chalk.green(`🧹 Cleaning up...`));
console.log();
console.log(chalk.green(` Removing plugin:`));
process.stdout.write(
chalk.green(
` deleting\t${chalk.cyan(destination.replace(rootDir, ''))}`,
),
);
try {
// Not using recursion here, so only empty directories can be removed
fs.rmdirSync(destination);
console.log();
console.log(
chalk.green(`Removing ${chalk.cyan(destination.replace(rootDir, ''))}`),
);
process.stdout.write(chalk.green(`\n`));
console.log();
} catch (e) {
process.stdout.write(chalk.red(`\n`));
console.log();
console.log(chalk.red(`Failed to cleanup: ${e.message}`));
console.log();
}
}
};
const buildPlugin = async (pluginFolder: string) => {
console.log();
console.log(chalk.green(` Building the plugin:`));
const prom_exec = promisify(exec);
// const commands = ['yarn', 'yarn build'];
const commands = ['yarn'];
for (const command of commands) {
process.stdout.write(chalk.green(` executing\t${chalk.cyan(command)}`));
try {
process.chdir(pluginFolder);
await prom_exec(command, { timeout: 60000 });
process.stdout.write(chalk.cyan(`\n`));
} catch (e) {
process.stdout.write(chalk.red(`\n`));
throw new Error(
`Could not execute command ${chalk.cyan(command)}: ${e.message}`,
);
}
}
};
@@ -148,29 +203,29 @@ const createPlugin = async (): Promise<any> => {
);
try {
console.log();
console.log(chalk.green('🧩 Creating the plugin...'));
const destinationFolder = createPluginFolder(rootDir, answers.id);
await createFromTemplateDir(templateFolder, destinationFolder, answers);
await buildPlugin(destinationFolder);
console.log();
console.log(
chalk.green(
`Successfully created a Backstage Plugin in ${chalk.cyan(
path.join('packages', 'plugins', answers.id),
`🥇 Successfully created ${chalk.cyan(
`@spotify-backstage/plugin-${answers.id}`,
)}`,
),
);
console.log(
chalk.green(
`Run ${chalk.cyan('yarn start')} in the plugin directory to start it.`,
),
);
console.log();
return destinationFolder;
} catch (e) {
console.log();
console.log(chalk.red(e.message));
console.log(`${chalk.red(e.message)}`);
console.log();
console.log(`🔥 ${chalk.red('Failed to create plugin!')}`);
console.log();
await cleanUp(rootDir, answers.id);