diff --git a/packages/cli/src/lib/create/factories/backendPlugin.ts b/packages/cli/src/lib/create/factories/backendPlugin.ts index d7855d5d68..68c684f6ab 100644 --- a/packages/cli/src/lib/create/factories/backendPlugin.ts +++ b/packages/cli/src/lib/create/factories/backendPlugin.ts @@ -16,8 +16,6 @@ import fs from 'fs-extra'; import camelCase from 'lodash/camelCase'; -import upperFirst from 'lodash/upperFirst'; -import chalk from 'chalk'; import { paths } from '../../paths'; import { addCodeownersEntry, @@ -25,10 +23,9 @@ import { parseOwnerIds, } from '../../codeowners'; import { createFactory, CreateContext } from '../types'; -import { Lockfile } from '../../versioning'; -import { addPackageDependency, Task, templatingTask } from '../../tasks'; -import { createPackageVersionProvider } from '../../version'; +import { addPackageDependency, Task } from '../../tasks'; import { ownerPrompt, pluginIdPrompt } from './common/prompts'; +import { executePluginPackageTemplate } from './common/tasks'; type Options = { id: string; @@ -47,38 +44,14 @@ export const backendPlugin = createFactory({ const id = `${options.id}-backend`; const name = ctx.scope ? `@${ctx.scope}/plugin-${id}` : `plugin-${id}`; - const pluginDir = ctx.isMonoRepo + const targetDir = ctx.isMonoRepo ? paths.resolveTargetRoot('plugins', id) : paths.resolveTargetRoot(`backstage-plugin-${id}`); - let lockfile: Lockfile | undefined; - try { - lockfile = await Lockfile.load(paths.resolveTargetRoot('yarn.lock')); - } catch (error) { - console.warn(`No yarn.lock available, ${error}`); - } - - Task.section('Validating prerequisites'); - const shortPluginDir = pluginDir.replace(`${paths.targetRoot}/`, ''); - await Task.forItem('availability', shortPluginDir, async () => { - if (await fs.pathExists(pluginDir)) { - throw new Error( - `A backend plugin with the same ID already exists at ${chalk.cyan( - shortPluginDir, - )}. Please try again with a different ID.`, - ); - } - }); - - const tempDir = await Task.forItem('creating', 'temp dir', async () => { - return await ctx.createTemporaryDirectory(`backstage-plugin-${id}`); - }); - - Task.section('Executing plugin template'); - await templatingTask( - paths.resolveOwn('templates/default-backend-plugin'), - tempDir, - { + await executePluginPackageTemplate(ctx, { + targetDir, + templateName: 'default-backend-plugin', + values: { id, name, pluginVar: `${camelCase(id)}Plugin`, @@ -86,20 +59,8 @@ export const backendPlugin = createFactory({ privatePackage: ctx.private, npmRegistry: ctx.npmRegistry, }, - createPackageVersionProvider(lockfile), - ); - - Task.section('Installing plugin'); - await Task.forItem('moving', shortPluginDir, async () => { - await fs.move(tempDir, pluginDir).catch(error => { - throw new Error( - `Failed to move plugin from ${tempDir} to ${pluginDir}, ${error.message}`, - ); - }); }); - ctx.markAsModified(); - if (await fs.pathExists(paths.resolveTargetRoot('packages/backend'))) { await Task.forItem('backend', 'adding dependency', async () => { await addPackageDependency( @@ -124,9 +85,9 @@ export const backendPlugin = createFactory({ } } - await Task.forCommand('yarn install', { cwd: pluginDir, optional: true }); + await Task.forCommand('yarn install', { cwd: targetDir, optional: true }); await Task.forCommand('yarn lint --fix', { - cwd: pluginDir, + cwd: targetDir, optional: true, }); }, diff --git a/packages/cli/src/lib/create/factories/common/tasks.ts b/packages/cli/src/lib/create/factories/common/tasks.ts new file mode 100644 index 0000000000..b644110a9f --- /dev/null +++ b/packages/cli/src/lib/create/factories/common/tasks.ts @@ -0,0 +1,76 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import fs from 'fs-extra'; +import chalk from 'chalk'; +import { paths } from '../../../paths'; +import { Task, templatingTask } from '../../../tasks'; +import { Lockfile } from '../../../versioning'; +import { createPackageVersionProvider } from '../../../version'; +import { CreateContext } from '../../types'; + +export async function executePluginPackageTemplate( + ctx: CreateContext, + options: { + templateName: string; + targetDir: string; + values: Record; + }, +) { + const { targetDir } = options; + + let lockfile: Lockfile | undefined; + try { + lockfile = await Lockfile.load(paths.resolveTargetRoot('yarn.lock')); + } catch { + /* ignored */ + } + + Task.section('Checking Prerequisites'); + const shortPluginDir = targetDir.replace(`${paths.targetRoot}/`, ''); + await Task.forItem('availability', shortPluginDir, async () => { + if (await fs.pathExists(targetDir)) { + throw new Error( + `A package with the same plugin ID already exists at ${chalk.cyan( + shortPluginDir, + )}. Please try again with a different ID.`, + ); + } + }); + + const tempDir = await Task.forItem('creating', 'temp dir', async () => { + return await ctx.createTemporaryDirectory('backstage-create'); + }); + + Task.section('Executing Template'); + await templatingTask( + paths.resolveOwn('templates', options.templateName), + tempDir, + options.values, + createPackageVersionProvider(lockfile), + ); + + Task.section('Installing'); + await Task.forItem('moving', shortPluginDir, async () => { + await fs.move(tempDir, targetDir).catch(error => { + throw new Error( + `Failed to move package from ${tempDir} to ${targetDir}, ${error.message}`, + ); + }); + }); + + ctx.markAsModified(); +} diff --git a/packages/cli/src/lib/create/factories/frontendPlugin.ts b/packages/cli/src/lib/create/factories/frontendPlugin.ts index 3fe01b7325..bb93bd311c 100644 --- a/packages/cli/src/lib/create/factories/frontendPlugin.ts +++ b/packages/cli/src/lib/create/factories/frontendPlugin.ts @@ -17,7 +17,6 @@ import fs from 'fs-extra'; import camelCase from 'lodash/camelCase'; import upperFirst from 'lodash/upperFirst'; -import chalk from 'chalk'; import { paths } from '../../paths'; import { addCodeownersEntry, @@ -25,10 +24,9 @@ import { parseOwnerIds, } from '../../codeowners'; import { createFactory, CreateContext } from '../types'; -import { Lockfile } from '../../versioning'; -import { addPackageDependency, Task, templatingTask } from '../../tasks'; -import { createPackageVersionProvider } from '../../version'; +import { addPackageDependency, Task } from '../../tasks'; import { ownerPrompt, pluginIdPrompt } from './common/prompts'; +import { executePluginPackageTemplate } from './common/tasks'; type Options = { id: string; @@ -49,60 +47,24 @@ export const frontendPlugin = createFactory({ const name = ctx.scope ? `@${ctx.scope}/plugin-${id}` : `plugin-${id}`; const extensionName = `${upperFirst(camelCase(id))}Page`; - const pluginDir = ctx.isMonoRepo + const targetDir = ctx.isMonoRepo ? paths.resolveTargetRoot('plugins', id) : paths.resolveTargetRoot(`backstage-plugin-${id}`); - let lockfile: Lockfile | undefined; - try { - lockfile = await Lockfile.load(paths.resolveTargetRoot('yarn.lock')); - } catch (error) { - console.warn(`No yarn.lock available, ${error}`); - } - - Task.section('Validating prerequisites'); - const shortPluginDir = pluginDir.replace(`${paths.targetRoot}/`, ''); - await Task.forItem('availability', shortPluginDir, async () => { - if (await fs.pathExists(pluginDir)) { - throw new Error( - `A plugin with the same ID already exists at ${chalk.cyan( - shortPluginDir, - )}. Please try again with a different ID.`, - ); - } - }); - - const tempDir = await Task.forItem('creating', 'temp dir', async () => { - return await ctx.createTemporaryDirectory(`backstage-plugin-${id}`); - }); - - Task.section('Executing plugin template'); - await templatingTask( - paths.resolveOwn('templates/default-plugin'), - tempDir, - { + await executePluginPackageTemplate(ctx, { + targetDir, + templateName: 'default-plugin', + values: { id, + name, + extensionName, pluginVar: `${camelCase(id)}Plugin`, pluginVersion: ctx.defaultVersion, - extensionName, - name, privatePackage: ctx.private, npmRegistry: ctx.npmRegistry, }, - createPackageVersionProvider(lockfile), - ); - - Task.section('Installing plugin'); - await Task.forItem('moving', shortPluginDir, async () => { - await fs.move(tempDir, pluginDir).catch(error => { - throw new Error( - `Failed to move plugin from ${tempDir} to ${pluginDir}, ${error.message}`, - ); - }); }); - ctx.markAsModified(); - if (await fs.pathExists(paths.resolveTargetRoot('packages/app'))) { await Task.forItem('app', 'adding dependency', async () => { await addPackageDependency( @@ -163,9 +125,9 @@ export const frontendPlugin = createFactory({ } } - await Task.forCommand('yarn install', { cwd: pluginDir, optional: true }); + await Task.forCommand('yarn install', { cwd: targetDir, optional: true }); await Task.forCommand('yarn lint --fix', { - cwd: pluginDir, + cwd: targetDir, optional: true, }); },