From e40f2b1f54cf74815aedb52ef5612e444ae4c068 Mon Sep 17 00:00:00 2001 From: Fabian Chong Date: Mon, 7 Sep 2020 22:08:12 +0800 Subject: [PATCH] remove mono repo dependency and private npm registry option --- package.json | 3 +- .../commands/create-plugin/createPlugin.ts | 50 +++++++++++++------ packages/cli/src/commands/index.ts | 3 ++ packages/cli/src/lib/tasks.ts | 7 +++ .../templates/default-plugin/package.json.hbs | 5 +- .../templates/default-plugin/tsconfig.json | 13 +++++ packages/e2e-test/src/e2e-test.ts | 6 ++- 7 files changed, 68 insertions(+), 19 deletions(-) create mode 100644 packages/cli/templates/default-plugin/tsconfig.json diff --git a/package.json b/package.json index 93f8f694a6..1ddfc8bb03 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,8 @@ "docgen": "lerna run docgen", "docker-build:app": "yarn workspace example-app build && docker build . -t spotify/backstage", "docker-build": "yarn tsc && yarn workspace example-backend build-image", - "create-plugin": "backstage-cli create-plugin", + "create-plugin": "backstage-cli create-plugin --scope internal", + "create-oss-plugin": "backstage-cli create-plugin --scope backstage", "remove-plugin": "backstage-cli remove-plugin", "release": "if [ \"$(git symbolic-ref --short HEAD)\" = master ]; then echo \"don't try to release master\"; exit 1; else lerna version --no-push --force-publish; fi", "prettier:check": "prettier --check .", diff --git a/packages/cli/src/commands/create-plugin/createPlugin.ts b/packages/cli/src/commands/create-plugin/createPlugin.ts index 5e6882a4a0..fe23acc924 100644 --- a/packages/cli/src/commands/create-plugin/createPlugin.ts +++ b/packages/cli/src/commands/create-plugin/createPlugin.ts @@ -21,6 +21,7 @@ import inquirer, { Answers, Question } from 'inquirer'; import { exec as execCb } from 'child_process'; import { resolve as resolvePath } from 'path'; import os from 'os'; +import { Command } from 'commander'; import { parseOwnerIds, addCodeownersEntry, @@ -32,12 +33,12 @@ import { version as backstageVersion } from '../../lib/version'; const exec = promisify(execCb); -async function checkExists(rootDir: string, id: string) { - await Task.forItem('checking', id, async () => { - const destination = resolvePath(rootDir, 'plugins', id); - +async function checkExists(destination: string) { + await Task.forItem('checking', destination, async () => { if (await fs.pathExists(destination)) { - const existing = chalk.cyan(destination.replace(`${rootDir}/`, '')); + const existing = chalk.cyan( + destination.replace(`${paths.targetRoot}/`, ''), + ); throw new Error( `A plugin with the same name already exists: ${existing}\nPlease try again with a different plugin ID`, ); @@ -88,8 +89,9 @@ export async function addPluginDependencyToApp( rootDir: string, pluginName: string, versionStr: string, + scopeNameWithSlash: string, ) { - const pluginPackage = `@backstage/plugin-${pluginName}`; + const pluginPackage = `${scopeNameWithSlash}plugin-${pluginName}`; const packageFilePath = 'packages/app/package.json'; const packageFile = resolvePath(rootDir, packageFilePath); @@ -116,8 +118,12 @@ export async function addPluginDependencyToApp( }); } -export async function addPluginToApp(rootDir: string, pluginName: string) { - const pluginPackage = `@backstage/plugin-${pluginName}`; +export async function addPluginToApp( + rootDir: string, + pluginName: string, + scopeNameWithSlash: string, +) { + const pluginPackage = `${scopeNameWithSlash}plugin-${pluginName}`; const pluginNameCapitalized = pluginName .split('-') .map(name => capitalize(name)) @@ -175,8 +181,12 @@ export async function movePlugin( }); } -export default async () => { +export default async (cmd: Command) => { const codeownersPath = await getCodeownersFilePath(paths.targetRoot); + const scopeName = cmd.scope ? `@${cmd.scope.replace(/^@/, '')}` : ''; + const scopeNameWithSlash = cmd.scope ? `${scopeName}/` : ''; + const privatePackage = cmd.private === false ? false : true; + const registryURL = cmd.npmRegistry; const questions: Question[] = [ { @@ -225,16 +235,18 @@ export default async () => { const appPackage = paths.resolveTargetRoot('packages/app'); const templateDir = paths.resolveOwn('templates/default-plugin'); const tempDir = resolvePath(os.tmpdir(), answers.id); - const pluginDir = paths.resolveTargetRoot('plugins', answers.id); + const pluginDir = (await fs.pathExists(paths.resolveTargetRoot('plugins'))) + ? paths.resolveTargetRoot('plugins', answers.id) + : paths.resolveTargetRoot(answers.id); const ownerIds = parseOwnerIds(answers.owner); - const { version } = await fs.readJson(paths.resolveTargetRoot('lerna.json')); + const version = backstageVersion; Task.log(); Task.log('Creating the plugin...'); try { Task.section('Checking if the plugin ID is available'); - await checkExists(paths.targetRoot, answers.id); + await checkExists(pluginDir); Task.section('Creating a temporary plugin directory'); await createTemporaryPluginFolder(tempDir); @@ -244,6 +256,9 @@ export default async () => { ...answers, version, backstageVersion, + scopeName, + privatePackage, + registryURL, }); Task.section('Moving to final location'); @@ -254,10 +269,15 @@ export default async () => { if (await fs.pathExists(appPackage)) { Task.section('Adding plugin as dependency in app'); - await addPluginDependencyToApp(paths.targetRoot, answers.id, version); + await addPluginDependencyToApp( + paths.targetRoot, + answers.id, + version, + scopeNameWithSlash, + ); Task.section('Import plugin in app'); - await addPluginToApp(paths.targetRoot, answers.id); + await addPluginToApp(paths.targetRoot, answers.id, scopeNameWithSlash); } if (ownerIds && ownerIds.length) { @@ -271,7 +291,7 @@ export default async () => { Task.log(); Task.log( `🥇 Successfully created ${chalk.cyan( - `@backstage/plugin-${answers.id}`, + `${scopeNameWithSlash}plugin-${answers.id}`, )}`, ); Task.log(); diff --git a/packages/cli/src/commands/index.ts b/packages/cli/src/commands/index.ts index 4e031cdbc1..f1828cef84 100644 --- a/packages/cli/src/commands/index.ts +++ b/packages/cli/src/commands/index.ts @@ -62,6 +62,9 @@ export function registerCommands(program: CommanderStatic) { program .command('create-plugin') .description('Creates a new plugin in the current repository') + .option('--scope ', 'NPM scope') + .option('--npm-registry ', 'NPM registry URL') + .option('--no-private', 'Public NPM Package') .action( lazy(() => import('./create-plugin/createPlugin').then(m => m.default)), ); diff --git a/packages/cli/src/lib/tasks.ts b/packages/cli/src/lib/tasks.ts index 0753301b78..38f2636b81 100644 --- a/packages/cli/src/lib/tasks.ts +++ b/packages/cli/src/lib/tasks.ts @@ -19,6 +19,7 @@ import fs from 'fs-extra'; import handlebars from 'handlebars'; import ora from 'ora'; import { basename, dirname } from 'path'; +import { paths } from './paths'; import recursive from 'recursive-readdir'; const TASK_NAME_MAX_LENGTH = 14; @@ -73,6 +74,10 @@ export async function templatingTask( throw new Error(`Failed to read template directory: ${error.message}`); }); + const isMonoRepo = (await fs.pathExists(paths.resolveTargetRoot('plugins'))) + ? true + : false; + for (const file of files) { const destinationFile = file.replace(templateDir, destinationDir); await fs.ensureDir(dirname(destinationFile)); @@ -92,6 +97,8 @@ export async function templatingTask( }); }); } else { + if (isMonoRepo && basename(file) === 'tsconfig.json') continue; + await Task.forItem('copying', basename(file), async () => { await fs.copyFile(file, destinationFile).catch(error => { const destination = destinationFile; diff --git a/packages/cli/templates/default-plugin/package.json.hbs b/packages/cli/templates/default-plugin/package.json.hbs index 38d4e41b5b..ad217b0be1 100644 --- a/packages/cli/templates/default-plugin/package.json.hbs +++ b/packages/cli/templates/default-plugin/package.json.hbs @@ -1,11 +1,12 @@ { - "name": "@backstage/plugin-{{id}}", + "name": "{{#if scopeName}}{{scopeName}}/{{/if}}/plugin-{{id}}", "version": "{{version}}", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", - "private": true, + "private": {{privatePackage}}, "publishConfig": { + {{#if registryURL}}"{{scopeName}}:registry":"{{registryURL}}",{{/if}} "access": "public", "main": "dist/index.esm.js", "types": "dist/index.d.ts" diff --git a/packages/cli/templates/default-plugin/tsconfig.json b/packages/cli/templates/default-plugin/tsconfig.json new file mode 100644 index 0000000000..d36fba9e4d --- /dev/null +++ b/packages/cli/templates/default-plugin/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "@backstage/cli/config/tsconfig.json", + "include": [ + "src", + "dev", + "migrations" + ], + "exclude": ["node_modules"], + "compilerOptions": { + "outDir": "dist-types", + "skipLibCheck": true + } +} diff --git a/packages/e2e-test/src/e2e-test.ts b/packages/e2e-test/src/e2e-test.ts index 5dfac68d6a..99ba1426d4 100644 --- a/packages/e2e-test/src/e2e-test.ts +++ b/packages/e2e-test/src/e2e-test.ts @@ -81,7 +81,11 @@ async function buildDistWorkspace(workspaceName: string, rootDir: string) { const path = paths.resolveOwnRoot(pkgJsonPath); const pkgTemplate = await fs.readFile(path, 'utf8'); const { dependencies = {}, devDependencies = {} } = JSON.parse( - handlebars.compile(pkgTemplate)({ version: '0.0.0' }), + handlebars.compile(pkgTemplate)({ + version: '0.0.0', + privatePackage: true, + scopeName: '@backstage', + }), ); Array()