From 841a38741773494f12b65adc4e18464871c48af2 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 1 Apr 2020 01:10:43 +0200 Subject: [PATCH] cli/commands/create-plugin: move templating to tasks helper and fix it + separate out sections --- .../commands/create-plugin/createPlugin.ts | 101 +++++------------- packages/cli/src/helpers/tasks.ts | 48 +++++++++ 2 files changed, 73 insertions(+), 76 deletions(-) diff --git a/packages/cli/src/commands/create-plugin/createPlugin.ts b/packages/cli/src/commands/create-plugin/createPlugin.ts index e4b67ef3ce..1b35d99a59 100644 --- a/packages/cli/src/commands/create-plugin/createPlugin.ts +++ b/packages/cli/src/commands/create-plugin/createPlugin.ts @@ -17,10 +17,8 @@ import fs from 'fs-extra'; import path from 'path'; import { promisify } from 'util'; -import handlebars from 'handlebars'; import chalk from 'chalk'; import inquirer, { Answers, Question } from 'inquirer'; -import recursive from 'recursive-readdir'; import { exec as execCb } from 'child_process'; import { resolve as resolvePath } from 'path'; import os from 'os'; @@ -29,12 +27,10 @@ import { addCodeownersEntry, getCodeownersFilePath, } from './lib/codeowners'; -import { Task } from '../../helpers/tasks'; +import { Task, templatingTask } from '../../helpers/tasks'; const exec = promisify(execCb); async function checkExists(rootDir: string, id: string) { - Task.section('Checking if the plugin ID is available'); - await Task.forItem('checking', id, async () => { const destination = path.join(rootDir, 'plugins', id); @@ -48,8 +44,6 @@ async function checkExists(rootDir: string, id: string) { } export async function createTemporaryPluginFolder(tempDir: string) { - Task.section('Creating a temporary plugin directory'); - await Task.forItem('creating', 'temporary directory', async () => { try { await fs.mkdir(tempDir); @@ -91,8 +85,6 @@ export async function addPluginDependencyToApp( pluginName: string, version: string, ) { - Task.section('Adding plugin as dependency in app'); - const pluginPackage = `@backstage/plugin-${pluginName}`; const packageFilePath = 'packages/app/package.json'; const packageFile = path.join(rootDir, packageFilePath); @@ -121,8 +113,6 @@ export async function addPluginDependencyToApp( } export async function addPluginToApp(rootDir: string, pluginName: string) { - Task.section('Import plugin in app'); - const pluginPackage = `@backstage/plugin-${pluginName}`; const pluginNameCapitalized = pluginName .split('-') @@ -141,65 +131,13 @@ export async function addPluginToApp(rootDir: string, pluginName: string) { }); } -export const createFromTemplateDir = async ( - templateFolder: string, - destinationFolder: string, - answers: Answers, - version: string, -) => { - Task.section('Setting up plugin files'); - const files = await recursive(templateFolder).catch(error => { - throw new Error(`Failed to read template directory: ${error.message}`); - }); - - for (const file of files) { - const destinationFile = file.replace(templateFolder, destinationFolder); - path.dirname(file); - await fs.ensureDir(path.dirname(file)); - - if (file.endsWith('.hbs')) { - await Task.forItem('templating', file, async () => { - const destination = destinationFile.replace(/\.hbs$/, ''); - - const template = await fs.readFile(path.basename(file)); - const compiled = handlebars.compile(template.toString()); - const contents = compiled({ - name: path.basename(destination), - version, - ...answers, - }); - - await fs.writeFile(destination, contents).catch(error => { - throw new Error( - `Failed to create file: ${destination}: ${error.message}`, - ); - }); - }); - } else { - await Task.forItem('copying', file, async () => { - await fs.copyFile(file, destinationFile).catch(error => { - const destination = destinationFile; - throw new Error( - `Failed to copy file to ${destination} : ${error.message}`, - ); - }); - }); - } - } -}; - -async function cleanUp(tempDir: string, id: string) { - Task.log('It seems that something went wrong when creating the plugin 🤔'); - Task.log('We are going to clean up, and then you can try again.'); - - await Task.forItem('Cleaning up', id, async () => { +async function cleanUp(tempDir: string) { + await Task.forItem('remove', 'temporary directory', async () => { await fs.remove(tempDir); }); } async function buildPlugin(pluginFolder: string) { - Task.section('Building the plugin'); - const commands = ['yarn install', 'yarn build']; for (const command of commands) { await Task.forItem('executing', command, async () => { @@ -219,8 +157,6 @@ export async function movePlugin( destination: string, id: string, ) { - Task.section('Moving the plugin to final location'); - await Task.forItem('moving', id, async () => { await fs.move(tempDir, destination).catch(error => { throw new Error( @@ -280,7 +216,7 @@ export default async () => { const appPackage = resolvePath(rootDir, 'packages', 'app'); const cliPackage = resolvePath(__dirname, '..', '..', '..'); - const templateFolder = resolvePath(cliPackage, 'templates', 'default-plugin'); + const templateDir = resolvePath(cliPackage, 'templates', 'default-plugin'); const tempDir = path.join(os.tmpdir(), answers.id); const pluginDir = path.join(rootDir, 'plugins', answers.id); const version = require(resolvePath(cliPackage, 'package.json')).version; @@ -290,14 +226,26 @@ export default async () => { Task.log('Creating the plugin...'); try { + Task.section('Checking if the plugin ID is available'); await checkExists(rootDir, answers.id); + + Task.section('Creating a temporary plugin directory'); await createTemporaryPluginFolder(tempDir); - await createFromTemplateDir(templateFolder, tempDir, answers, version); + + Task.section('Preparing files'); + await templatingTask(templateDir, tempDir, { ...answers, version }); + + Task.section('Moving to final location'); await movePlugin(tempDir, pluginDir, answers.id); + + Task.section('Building the plugin'); await buildPlugin(pluginDir); if (await fs.pathExists(appPackage)) { + Task.section('Adding plugin as dependency in app'); await addPluginDependencyToApp(rootDir, answers.id, version); + + Task.section('Import plugin in app'); await addPluginToApp(rootDir, answers.id); } @@ -317,12 +265,13 @@ export default async () => { ); Task.log(); } catch (error) { - console.log(); - console.log(`${chalk.red(error.message)}`); - console.log(); - await cleanUp(tempDir, answers.id); - console.log(); - console.log(`🔥 ${chalk.red('Failed to create plugin!')}`); - console.log(); + Task.error(error.message); + + Task.log('It seems that something went wrong when creating the plugin 🤔'); + Task.log('We are going to clean up, and then you can try again.'); + + Task.section('Cleanup'); + await cleanUp(tempDir); + Task.error('🔥 Failed to create plugin!'); } }; diff --git a/packages/cli/src/helpers/tasks.ts b/packages/cli/src/helpers/tasks.ts index 65ef169d18..3cba4d262f 100644 --- a/packages/cli/src/helpers/tasks.ts +++ b/packages/cli/src/helpers/tasks.ts @@ -15,7 +15,11 @@ */ import chalk from 'chalk'; +import fs from 'fs-extra'; +import handlebars from 'handlebars'; import ora from 'ora'; +import { basename, dirname } from 'path'; +import recursive from 'recursive-readdir'; const TASK_NAME_MAX_LENGTH = 14; @@ -24,6 +28,10 @@ export class Task { process.stdout.write(`${chalk.green(name)}\n`); } + static error(message: string = '') { + process.stdout.write(`\n${chalk.red(message)}\n\n`); + } + static section(name: string) { const title = chalk.green(`${name}:`); process.stdout.write(`\n ${title}\n`); @@ -51,3 +59,43 @@ export class Task { } } } + +export async function templatingTask( + templateDir: string, + destinationDir: string, + context: any, +) { + const files = await recursive(templateDir).catch(error => { + throw new Error(`Failed to read template directory: ${error.message}`); + }); + + for (const file of files) { + const destinationFile = file.replace(templateDir, destinationDir); + await fs.ensureDir(dirname(destinationFile)); + + if (file.endsWith('.hbs')) { + await Task.forItem('templating', basename(file), async () => { + const destination = destinationFile.replace(/\.hbs$/, ''); + + const template = await fs.readFile(file); + const compiled = handlebars.compile(template.toString()); + const contents = compiled({ name: basename(destination), ...context }); + + await fs.writeFile(destination, contents).catch(error => { + throw new Error( + `Failed to create file: ${destination}: ${error.message}`, + ); + }); + }); + } else { + await Task.forItem('copying', basename(file), async () => { + await fs.copyFile(file, destinationFile).catch(error => { + const destination = destinationFile; + throw new Error( + `Failed to copy file to ${destination} : ${error.message}`, + ); + }); + }); + } + } +}