diff --git a/.changeset/silent-lobsters-tease.md b/.changeset/silent-lobsters-tease.md new file mode 100644 index 0000000000..2dea26d8ff --- /dev/null +++ b/.changeset/silent-lobsters-tease.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +The `backendPlugin` and `backendModule` factory now includes a step for automatically adding the new backend plugin/module to the `index.ts` file of the backend. diff --git a/packages/cli/src/lib/new/factories/backendModule.test.ts b/packages/cli/src/lib/new/factories/backendModule.test.ts index 78ef5f96bb..2d6a4c9c83 100644 --- a/packages/cli/src/lib/new/factories/backendModule.test.ts +++ b/packages/cli/src/lib/new/factories/backendModule.test.ts @@ -26,6 +26,14 @@ import { import { backendModule } from './backendModule'; import { createMockDirectory } from '@backstage/backend-test-utils'; +const backendIndexTsContent = ` +import { createBackend } from '@backstage/backend-defaults'; + +const backend = createBackend(); + +backend.start(); +`; + describe('backendModule factory', () => { const mockDir = createMockDirectory(); @@ -44,6 +52,9 @@ describe('backendModule factory', () => { packages: { backend: { 'package.json': JSON.stringify({}), + src: { + 'index.ts': backendIndexTsContent, + }, }, }, plugins: {}, @@ -86,8 +97,20 @@ describe('backendModule factory', () => { 'Installing:', `moving plugins${sep}test-backend-module-tester-two`, 'backend adding dependency', + 'backend adding module', ]); + await expect( + fs.readFile(mockDir.resolve('packages/backend/src/index.ts'), 'utf8'), + ).resolves.toBe(` +import { createBackend } from '@backstage/backend-defaults'; + +const backend = createBackend(); + +backend.add(import('backstage-plugin-test-backend-module-tester-two')); +backend.start(); +`); + await expect( fs.readJson(mockDir.resolve('packages/backend/package.json')), ).resolves.toEqual({ diff --git a/packages/cli/src/lib/new/factories/backendModule.ts b/packages/cli/src/lib/new/factories/backendModule.ts index 698146a229..67860b812e 100644 --- a/packages/cli/src/lib/new/factories/backendModule.ts +++ b/packages/cli/src/lib/new/factories/backendModule.ts @@ -20,7 +20,7 @@ import camelCase from 'lodash/camelCase'; import { paths } from '../../paths'; import { addCodeownersEntry, getCodeownersFilePath } from '../../codeowners'; import { CreateContext, createFactory } from '../types'; -import { addPackageDependency, Task } from '../../tasks'; +import { addPackageDependency, addToBackend, Task } from '../../tasks'; import { moduleIdIdPrompt, ownerPrompt, @@ -91,6 +91,10 @@ export const backendModule = createFactory({ }); } + await addToBackend(name, { + type: 'module', + }); + if (options.owner) { await addCodeownersEntry(`/plugins/${dirName}`, options.owner); } diff --git a/packages/cli/src/lib/new/factories/backendPlugin.test.ts b/packages/cli/src/lib/new/factories/backendPlugin.test.ts index c5930592a3..f6eeb8cf33 100644 --- a/packages/cli/src/lib/new/factories/backendPlugin.test.ts +++ b/packages/cli/src/lib/new/factories/backendPlugin.test.ts @@ -26,6 +26,14 @@ import { import { backendPlugin } from './backendPlugin'; import { createMockDirectory } from '@backstage/backend-test-utils'; +const backendIndexTsContent = ` +import { createBackend } from '@backstage/backend-defaults'; + +const backend = createBackend(); + +backend.start(); +`; + describe('backendPlugin factory', () => { const mockDir = createMockDirectory(); @@ -44,6 +52,9 @@ describe('backendPlugin factory', () => { packages: { backend: { 'package.json': JSON.stringify({}), + src: { + 'index.ts': backendIndexTsContent, + }, }, }, plugins: {}, @@ -89,6 +100,7 @@ describe('backendPlugin factory', () => { 'Installing:', `moving plugins${sep}test-backend`, 'backend adding dependency', + 'backend adding plugin', ]); await expect( @@ -99,6 +111,17 @@ describe('backendPlugin factory', () => { }, }); + await expect( + fs.readFile(mockDir.resolve('packages/backend/src/index.ts'), 'utf8'), + ).resolves.toBe(` +import { createBackend } from '@backstage/backend-defaults'; + +const backend = createBackend(); + +backend.add(import('backstage-plugin-test-backend')); +backend.start(); +`); + expect(Task.forCommand).toHaveBeenCalledTimes(2); expect(Task.forCommand).toHaveBeenCalledWith('yarn install', { cwd: mockDir.resolve('plugins/test-backend'), diff --git a/packages/cli/src/lib/new/factories/backendPlugin.ts b/packages/cli/src/lib/new/factories/backendPlugin.ts index 09ea98fbe7..fc77896461 100644 --- a/packages/cli/src/lib/new/factories/backendPlugin.ts +++ b/packages/cli/src/lib/new/factories/backendPlugin.ts @@ -20,7 +20,7 @@ import camelCase from 'lodash/camelCase'; import { paths } from '../../paths'; import { addCodeownersEntry, getCodeownersFilePath } from '../../codeowners'; import { CreateContext, createFactory } from '../types'; -import { addPackageDependency, Task } from '../../tasks'; +import { addPackageDependency, addToBackend, Task } from '../../tasks'; import { ownerPrompt, pluginIdPrompt } from './common/prompts'; import { executePluginPackageTemplate } from './common/tasks'; import { resolvePackageName } from './common/util'; @@ -78,6 +78,10 @@ export const backendPlugin = createFactory({ }, ); }); + + await addToBackend(name, { + type: 'plugin', + }); } if (options.owner) { diff --git a/packages/cli/src/lib/tasks.ts b/packages/cli/src/lib/tasks.ts index 851f962c62..ffff2892fb 100644 --- a/packages/cli/src/lib/tasks.ts +++ b/packages/cli/src/lib/tasks.ts @@ -23,6 +23,7 @@ import { basename, dirname } from 'path'; import recursive from 'recursive-readdir'; import { exec as execCb } from 'child_process'; import { assertError } from '@backstage/errors'; +import { paths } from './paths'; const exec = promisify(execCb); @@ -196,3 +197,37 @@ export async function addPackageDependency( throw new Error(`Failed to add package dependencies, ${error}`); } } + +export async function addToBackend( + name: string, + options: { + type: 'plugin' | 'module'; + }, +) { + if (await fs.pathExists(paths.resolveTargetRoot('packages/backend'))) { + await Task.forItem('backend', `adding ${options.type}`, async () => { + const backendFilePath = paths.resolveTargetRoot( + 'packages/backend/src/index.ts', + ); + if (!(await fs.pathExists(backendFilePath))) { + return; + } + + const content = await fs.readFile(backendFilePath, 'utf8'); + const lines = content.split('\n'); + const backendAddLine = `backend.add(import('${name}'));`; + + const backendStartIndex = lines.findIndex(line => + line.match(/backend.start/), + ); + + if (backendStartIndex !== -1) { + const [indentation] = lines[backendStartIndex].match(/^\s*/)!; + lines.splice(backendStartIndex, 0, `${indentation}${backendAddLine}`); + + const newContent = lines.join('\n'); + await fs.writeFile(backendFilePath, newContent, 'utf8'); + } + }); + } +}