From f0ee50cfabd467c357ed955dc1ce19684a9abcb2 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 22 Jan 2022 16:39:48 +0100 Subject: [PATCH] cli: add utility for passing explicit role option Signed-off-by: Patrik Oldsberg --- packages/cli/src/commands/bundle/command.ts | 10 +---- packages/cli/src/commands/index.ts | 3 +- packages/cli/src/lib/role/index.ts | 3 +- .../cli/src/lib/role/packageRoles.test.ts | 44 +++++++++++++++++++ packages/cli/src/lib/role/packageRoles.ts | 18 ++++++++ 5 files changed, 68 insertions(+), 10 deletions(-) diff --git a/packages/cli/src/commands/bundle/command.ts b/packages/cli/src/commands/bundle/command.ts index a13faeee62..44b39e6797 100644 --- a/packages/cli/src/commands/bundle/command.ts +++ b/packages/cli/src/commands/bundle/command.ts @@ -14,19 +14,13 @@ * limitations under the License. */ -import fs from 'fs-extra'; import { Command } from 'commander'; -import { paths } from '../../lib/paths'; -import { readPackageRole } from '../../lib/role/packageRoles'; import { bundleApp } from './bundleApp'; import { bundleBackend } from './bundleBackend'; +import { readRoleForCommand } from '../../lib/role'; export async function command(cmd: Command): Promise { - const pkg = await fs.readJson(paths.resolveTarget('package.json')); - const roleInfo = readPackageRole(pkg); - if (!roleInfo) { - throw new Error(`Target package must have 'backstage.role' set`); - } + const roleInfo = await readRoleForCommand(cmd); const options = { configPaths: cmd.config as string[], diff --git a/packages/cli/src/commands/index.ts b/packages/cli/src/commands/index.ts index e834e0e494..860cd0fd62 100644 --- a/packages/cli/src/commands/index.ts +++ b/packages/cli/src/commands/index.ts @@ -136,6 +136,8 @@ export function registerCommands(program: CommanderStatic) { program .command('bundle') .description('Bundle a package for deployment') + .option(...configOption) + .option('--role ', 'Run the command with an explicit package role') .option( '--skip-build-dependencies', 'Skip the automatic building of local dependencies', @@ -144,7 +146,6 @@ export function registerCommands(program: CommanderStatic) { '--stats', 'If bundle stats are available, write them to the output directory', ) - .option(...configOption) .action(lazy(() => import('./bundle').then(m => m.command))); program diff --git a/packages/cli/src/lib/role/index.ts b/packages/cli/src/lib/role/index.ts index 5a1f836036..9becfa367b 100644 --- a/packages/cli/src/lib/role/index.ts +++ b/packages/cli/src/lib/role/index.ts @@ -21,6 +21,7 @@ export type { } from './types'; export { getRoleInfo, - detectPackageRole, readPackageRole, + readRoleForCommand, + detectPackageRole, } from './packageRoles'; diff --git a/packages/cli/src/lib/role/packageRoles.test.ts b/packages/cli/src/lib/role/packageRoles.test.ts index d41cd08488..f3302d3256 100644 --- a/packages/cli/src/lib/role/packageRoles.test.ts +++ b/packages/cli/src/lib/role/packageRoles.test.ts @@ -14,9 +14,12 @@ * limitations under the License. */ +import mockFs from 'mock-fs'; +import { Command } from 'commander'; import { getRoleInfo, readPackageRole, + readRoleForCommand, detectPackageRole, } from './packageRoles'; @@ -78,6 +81,47 @@ describe('readPackageRole', () => { }); }); +describe('readRoleForCommand', () => { + function mkCommand(args: string) { + return new Command() + .option('--role ', 'test role') + .parse(['node', 'entry.js', ...args.split(' ')]) as Command; + } + + beforeEach(() => { + mockFs({ + 'package.json': JSON.stringify({ + name: 'test', + backstage: { + role: 'web-library', + }, + }), + }); + }); + + afterEach(() => { + mockFs.restore(); + }); + + it('provides role info by role', async () => { + await expect(readRoleForCommand(mkCommand(''))).resolves.toEqual({ + role: 'web-library', + platform: 'web', + }); + + await expect( + readRoleForCommand(mkCommand('--role node-library')), + ).resolves.toEqual({ + role: 'node-library', + platform: 'node', + }); + + await expect( + readRoleForCommand(mkCommand('--role invalid')), + ).rejects.toThrow(`Unknown package role 'invalid'`); + }); +}); + describe('detectPackageRole', () => { it('detects the role of example-app', () => { expect( diff --git a/packages/cli/src/lib/role/packageRoles.ts b/packages/cli/src/lib/role/packageRoles.ts index 9d0ec501c6..67bee0e64f 100644 --- a/packages/cli/src/lib/role/packageRoles.ts +++ b/packages/cli/src/lib/role/packageRoles.ts @@ -15,6 +15,9 @@ */ import { z } from 'zod'; +import fs from 'fs-extra'; +import { Command } from 'commander'; +import { paths } from '../paths'; import { PackageRoleInfo } from './types'; const packageRoles: PackageRoleInfo[] = [ @@ -66,6 +69,21 @@ export function readPackageRole(pkgJson: unknown): PackageRoleInfo | undefined { return undefined; } +export async function readRoleForCommand( + cmd: Command, +): Promise { + if (cmd.role) { + return getRoleInfo(cmd.role); + } + + const pkg = await fs.readJson(paths.resolveTarget('package.json')); + const info = readPackageRole(pkg); + if (!info) { + throw new Error(`Target package must have 'backstage.role' set`); + } + return info; +} + const detectionSchema = z.object({ name: z.string().optional(), scripts: z