From fb716988088c94042751eab37e12876d1e1a7e8a Mon Sep 17 00:00:00 2001 From: Min Kim Date: Tue, 21 Nov 2023 23:20:43 -0500 Subject: [PATCH] Refactor create-app template to use the new backend Signed-off-by: Min Kim --- packages/create-app/src/lib/tasks.test.ts | 4 + packages/create-app/src/lib/versions.ts | 10 ++ .../packages/backend/package.json.hbs | 9 +- .../default-app/packages/backend/src/index.ts | 124 +++--------------- .../packages/backend/src/plugins/app.ts | 14 -- .../packages/backend/src/plugins/auth.ts | 54 -------- .../packages/backend/src/plugins/catalog.ts | 14 -- .../packages/backend/src/plugins/proxy.ts | 13 -- .../backend/src/plugins/scaffolder.ts | 22 ---- .../backend/src/plugins/search.ts.hbs | 66 ---------- .../packages/backend/src/plugins/techdocs.ts | 51 ------- 11 files changed, 38 insertions(+), 343 deletions(-) delete mode 100644 packages/create-app/templates/default-app/packages/backend/src/plugins/app.ts delete mode 100644 packages/create-app/templates/default-app/packages/backend/src/plugins/auth.ts delete mode 100644 packages/create-app/templates/default-app/packages/backend/src/plugins/catalog.ts delete mode 100644 packages/create-app/templates/default-app/packages/backend/src/plugins/proxy.ts delete mode 100644 packages/create-app/templates/default-app/packages/backend/src/plugins/scaffolder.ts delete mode 100644 packages/create-app/templates/default-app/packages/backend/src/plugins/search.ts.hbs delete mode 100644 packages/create-app/templates/default-app/packages/backend/src/plugins/techdocs.ts diff --git a/packages/create-app/src/lib/tasks.test.ts b/packages/create-app/src/lib/tasks.test.ts index b1f5e17ba0..34a239ca48 100644 --- a/packages/create-app/src/lib/tasks.test.ts +++ b/packages/create-app/src/lib/tasks.test.ts @@ -51,6 +51,7 @@ jest.mock('./versions', () => ({ root: '1.2.3', '@backstage/cli': '1.0.0', '@backstage/backend-common': '1.0.0', + '@backstage/backend-defaults': '1.0.0', '@backstage/backend-tasks': '1.0.0', '@backstage/catalog-model': '1.0.0', '@backstage/catalog-client': '1.0.0', @@ -58,10 +59,13 @@ jest.mock('./versions', () => ({ '@backstage/plugin-app-backend': '1.0.0', '@backstage/plugin-auth-backend': '1.0.0', '@backstage/plugin-auth-node': '1.0.0', + '@backstage/plugin-auth-backend-module-github-provider': '1.0.0', '@backstage/plugin-catalog-backend': '1.0.0', '@backstage/plugin-catalog-backend-module-scaffolder-entity-model': '1.0.0', '@backstage/plugin-permission-common': '1.0.0', '@backstage/plugin-permission-node': '1.0.0', + '@backstage/plugin-permission-backend': '1.0.0', + '@backstage/plugin-permission-backend-module-allow-all-policy': '1.0.0', '@backstage/plugin-proxy-backend': '1.0.0', '@backstage/plugin-scaffolder-backend': '1.0.0', '@backstage/plugin-search-backend': '1.0.0', diff --git a/packages/create-app/src/lib/versions.ts b/packages/create-app/src/lib/versions.ts index 03ef32d921..ec96bafc1f 100644 --- a/packages/create-app/src/lib/versions.ts +++ b/packages/create-app/src/lib/versions.ts @@ -33,6 +33,7 @@ import { version as root } from '../../../../package.json'; import { version as appDefaults } from '../../../app-defaults/package.json'; import { version as backendCommon } from '../../../backend-common/package.json'; +import { version as backendDefaults } from '../../../backend-defaults/package.json'; import { version as backendTasks } from '../../../backend-tasks/package.json'; import { version as catalogClient } from '../../../catalog-client/package.json'; import { version as catalogModel } from '../../../catalog-model/package.json'; @@ -50,6 +51,7 @@ import { version as theme } from '../../../theme/package.json'; import { version as pluginApiDocs } from '../../../../plugins/api-docs/package.json'; import { version as pluginAppBackend } from '../../../../plugins/app-backend/package.json'; import { version as pluginAuthBackend } from '../../../../plugins/auth-backend/package.json'; +import { version as pluginAuthBackendModuleGithubProvider } from '../../../../plugins/auth-backend-module-github-provider/package.json'; import { version as pluginAuthNode } from '../../../../plugins/auth-node/package.json'; import { version as pluginCatalog } from '../../../../plugins/catalog/package.json'; import { version as pluginCatalogCommon } from '../../../../plugins/catalog-common/package.json'; @@ -62,6 +64,8 @@ import { version as pluginExplore } from '../../../../plugins/explore/package.js import { version as pluginGithubActions } from '../../../../plugins/github-actions/package.json'; import { version as pluginLighthouse } from '../../../../plugins/lighthouse/package.json'; import { version as pluginOrg } from '../../../../plugins/org/package.json'; +import { version as pluginPermissionBackend } from '../../../../plugins/permission-backend/package.json'; +import { version as pluginPermissionBackendModulePolicyAllowAll } from '../../../../plugins/permission-backend-module-policy-allow-all/package.json'; import { version as pluginPermissionCommon } from '../../../../plugins/permission-common/package.json'; import { version as pluginPermissionReact } from '../../../../plugins/permission-react/package.json'; import { version as pluginPermissionNode } from '../../../../plugins/permission-node/package.json'; @@ -87,6 +91,7 @@ export const packageVersions = { root, '@backstage/app-defaults': appDefaults, '@backstage/backend-common': backendCommon, + '@backstage/backend-defaults': backendDefaults, '@backstage/backend-tasks': backendTasks, '@backstage/catalog-client': catalogClient, '@backstage/catalog-model': catalogModel, @@ -101,6 +106,8 @@ export const packageVersions = { '@backstage/plugin-api-docs': pluginApiDocs, '@backstage/plugin-app-backend': pluginAppBackend, '@backstage/plugin-auth-backend': pluginAuthBackend, + '@backstage/plugin-auth-backend-module-github-provider': + pluginAuthBackendModuleGithubProvider, '@backstage/plugin-auth-node': pluginAuthNode, '@backstage/plugin-catalog': pluginCatalog, '@backstage/plugin-catalog-common': pluginCatalogCommon, @@ -114,6 +121,9 @@ export const packageVersions = { '@backstage/plugin-github-actions': pluginGithubActions, '@backstage/plugin-lighthouse': pluginLighthouse, '@backstage/plugin-org': pluginOrg, + '@backstage/plugin-permission-backend': pluginPermissionBackend, + '@backstage/plugin-permission-backend-module-allow-all-policy': + pluginPermissionBackendModulePolicyAllowAll, '@backstage/plugin-permission-common': pluginPermissionCommon, '@backstage/plugin-permission-node': pluginPermissionNode, '@backstage/plugin-permission-react': pluginPermissionReact, diff --git a/packages/create-app/templates/default-app/packages/backend/package.json.hbs b/packages/create-app/templates/default-app/packages/backend/package.json.hbs index f3ed808afe..b9c0c75a77 100644 --- a/packages/create-app/templates/default-app/packages/backend/package.json.hbs +++ b/packages/create-app/templates/default-app/packages/backend/package.json.hbs @@ -17,30 +17,29 @@ }, "dependencies": { "@backstage/backend-common": "^{{version '@backstage/backend-common'}}", + "@backstage/backend-defaults": "^{{version '@backstage/backend-defaults'}}", "@backstage/backend-tasks": "^{{version '@backstage/backend-tasks'}}", - "@backstage/catalog-client": "^{{version '@backstage/catalog-client'}}", - "@backstage/catalog-model": "^{{version '@backstage/catalog-model'}}", "@backstage/config": "^{{version '@backstage/config'}}", "@backstage/plugin-app-backend": "^{{version '@backstage/plugin-app-backend'}}", "@backstage/plugin-auth-backend": "^{{version '@backstage/plugin-auth-backend'}}", + "@backstage/plugin-auth-backend-module-github-provider": "^{{version '@backstage/plugin-auth-backend-module-github-provider'}}", "@backstage/plugin-auth-node": "^{{version '@backstage/plugin-auth-node'}}", "@backstage/plugin-catalog-backend": "^{{version '@backstage/plugin-catalog-backend'}}", "@backstage/plugin-catalog-backend-module-scaffolder-entity-model": "^{{version '@backstage/plugin-catalog-backend-module-scaffolder-entity-model'}}", + "@backstage/plugin-permission-backend": "^{{version '@backstage/plugin-permission-backend'}}", + "@backstage/plugin-permission-backend-module-allow-all-policy": "^{{version '@backstage/plugin-permission-backend-module-allow-all-policy'}}", "@backstage/plugin-permission-common": "^{{version '@backstage/plugin-permission-common'}}", "@backstage/plugin-permission-node": "^{{version '@backstage/plugin-permission-node'}}", "@backstage/plugin-proxy-backend": "^{{version '@backstage/plugin-proxy-backend'}}", "@backstage/plugin-scaffolder-backend": "^{{version '@backstage/plugin-scaffolder-backend'}}", "@backstage/plugin-search-backend": "^{{version '@backstage/plugin-search-backend'}}", "@backstage/plugin-search-backend-module-catalog": "^{{version '@backstage/plugin-search-backend-module-catalog'}}", - "@backstage/plugin-search-backend-module-pg": "^{{version '@backstage/plugin-search-backend-module-pg'}}", "@backstage/plugin-search-backend-module-techdocs": "^{{version '@backstage/plugin-search-backend-module-techdocs'}}", "@backstage/plugin-search-backend-node": "^{{version '@backstage/plugin-search-backend-node'}}", "@backstage/plugin-techdocs-backend": "^{{version '@backstage/plugin-techdocs-backend'}}", "app": "link:../app", "better-sqlite3": "^9.0.0", "dockerode": "^3.3.1", - "express": "^4.17.1", - "express-promise-router": "^4.1.0", "node-gyp": "^9.0.0", "pg": "^8.11.3", "winston": "^3.2.1" diff --git a/packages/create-app/templates/default-app/packages/backend/src/index.ts b/packages/create-app/templates/default-app/packages/backend/src/index.ts index 04c4ff9392..f10c5a9aab 100644 --- a/packages/create-app/templates/default-app/packages/backend/src/index.ts +++ b/packages/create-app/templates/default-app/packages/backend/src/index.ts @@ -6,110 +6,26 @@ * Happy hacking! */ -import Router from 'express-promise-router'; -import { - createServiceBuilder, - loadBackendConfig, - getRootLogger, - useHotMemoize, - notFoundHandler, - CacheManager, - DatabaseManager, - HostDiscovery, - UrlReaders, - ServerTokenManager, -} from '@backstage/backend-common'; -import { TaskScheduler } from '@backstage/backend-tasks'; -import { Config } from '@backstage/config'; -import app from './plugins/app'; -import auth from './plugins/auth'; -import catalog from './plugins/catalog'; -import scaffolder from './plugins/scaffolder'; -import proxy from './plugins/proxy'; -import techdocs from './plugins/techdocs'; -import search from './plugins/search'; -import { PluginEnvironment } from './types'; -import { ServerPermissionClient } from '@backstage/plugin-permission-node'; -import { DefaultIdentityClient } from '@backstage/plugin-auth-node'; +import { createBackend } from '@backstage/backend-defaults'; -function makeCreateEnv(config: Config) { - const root = getRootLogger(); - const reader = UrlReaders.default({ logger: root, config }); - const discovery = HostDiscovery.fromConfig(config); - const cacheManager = CacheManager.fromConfig(config); - const databaseManager = DatabaseManager.fromConfig(config, { logger: root }); - const tokenManager = ServerTokenManager.noop(); - const taskScheduler = TaskScheduler.fromConfig(config, { databaseManager }); +const backend = createBackend(); - const identity = DefaultIdentityClient.create({ - discovery, - }); - const permissions = ServerPermissionClient.fromConfig(config, { - discovery, - tokenManager, - }); +backend.add(import('@backstage/plugin-app-backend/alpha')); +backend.add(import('@backstage/plugin-auth-backend')); +backend.add(import('@backstage/plugin-auth-backend-module-github-provider')); +backend.add(import('@backstage/plugin-catalog-backend/alpha')); +backend.add( + import('@backstage/plugin-catalog-backend-module-scaffolder-entity-model'), +); +backend.add(import('@backstage/plugin-permission-backend/alpha')); +backend.add( + import('@backstage/plugin-permission-backend-module-allow-all-policy'), +); +backend.add(import('@backstage/plugin-proxy-backend/alpha')); +backend.add(import('@backstage/plugin-scaffolder-backend/alpha')); +backend.add(import('@backstage/plugin-search-backend/alpha')); +backend.add(import('@backstage/plugin-search-backend-module-catalog/alpha')); +backend.add(import('@backstage/plugin-search-backend-module-techdocs/alpha')); +backend.add(import('@backstage/plugin-techdocs-backend/alpha')); - root.info(`Created UrlReader ${reader}`); - - return (plugin: string): PluginEnvironment => { - const logger = root.child({ type: 'plugin', plugin }); - const database = databaseManager.forPlugin(plugin); - const cache = cacheManager.forPlugin(plugin); - const scheduler = taskScheduler.forPlugin(plugin); - return { - logger, - database, - cache, - config, - reader, - discovery, - tokenManager, - scheduler, - permissions, - identity, - }; - }; -} - -async function main() { - const config = await loadBackendConfig({ - argv: process.argv, - logger: getRootLogger(), - }); - const createEnv = makeCreateEnv(config); - - const catalogEnv = useHotMemoize(module, () => createEnv('catalog')); - const scaffolderEnv = useHotMemoize(module, () => createEnv('scaffolder')); - const authEnv = useHotMemoize(module, () => createEnv('auth')); - const proxyEnv = useHotMemoize(module, () => createEnv('proxy')); - const techdocsEnv = useHotMemoize(module, () => createEnv('techdocs')); - const searchEnv = useHotMemoize(module, () => createEnv('search')); - const appEnv = useHotMemoize(module, () => createEnv('app')); - - const apiRouter = Router(); - apiRouter.use('/catalog', await catalog(catalogEnv)); - apiRouter.use('/scaffolder', await scaffolder(scaffolderEnv)); - apiRouter.use('/auth', await auth(authEnv)); - apiRouter.use('/techdocs', await techdocs(techdocsEnv)); - apiRouter.use('/proxy', await proxy(proxyEnv)); - apiRouter.use('/search', await search(searchEnv)); - - // Add backends ABOVE this line; this 404 handler is the catch-all fallback - apiRouter.use(notFoundHandler()); - - const service = createServiceBuilder(module) - .loadConfig(config) - .addRouter('/api', apiRouter) - .addRouter('', await app(appEnv)); - - await service.start().catch(err => { - console.log(err); - process.exit(1); - }); -} - -module.hot?.accept(); -main().catch(error => { - console.error('Backend failed to start up', error); - process.exit(1); -}); +backend.start(); diff --git a/packages/create-app/templates/default-app/packages/backend/src/plugins/app.ts b/packages/create-app/templates/default-app/packages/backend/src/plugins/app.ts deleted file mode 100644 index 7c37f68467..0000000000 --- a/packages/create-app/templates/default-app/packages/backend/src/plugins/app.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { createRouter } from '@backstage/plugin-app-backend'; -import { Router } from 'express'; -import { PluginEnvironment } from '../types'; - -export default async function createPlugin( - env: PluginEnvironment, -): Promise { - return await createRouter({ - logger: env.logger, - config: env.config, - database: env.database, - appPackageName: 'app', - }); -} diff --git a/packages/create-app/templates/default-app/packages/backend/src/plugins/auth.ts b/packages/create-app/templates/default-app/packages/backend/src/plugins/auth.ts deleted file mode 100644 index 77eb6aae21..0000000000 --- a/packages/create-app/templates/default-app/packages/backend/src/plugins/auth.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { - createRouter, - providers, - defaultAuthProviderFactories, -} from '@backstage/plugin-auth-backend'; -import { Router } from 'express'; -import { PluginEnvironment } from '../types'; - -export default async function createPlugin( - env: PluginEnvironment, -): Promise { - return await createRouter({ - logger: env.logger, - config: env.config, - database: env.database, - discovery: env.discovery, - tokenManager: env.tokenManager, - providerFactories: { - ...defaultAuthProviderFactories, - - // This replaces the default GitHub auth provider with a customized one. - // The `signIn` option enables sign-in for this provider, using the - // identity resolution logic that's provided in the `resolver` callback. - // - // This particular resolver makes all users share a single "guest" identity. - // It should only be used for testing and trying out Backstage. - // - // If you want to use a production ready resolver you can switch to - // the one that is commented out below, it looks up a user entity in the - // catalog using the GitHub username of the authenticated user. - // That resolver requires you to have user entities populated in the catalog, - // for example using https://backstage.io/docs/integrations/github/org - // - // There are other resolvers to choose from, and you can also create - // your own, see the auth documentation for more details: - // - // https://backstage.io/docs/auth/identity-resolver - github: providers.github.create({ - signIn: { - resolver(_, ctx) { - const userRef = 'user:default/guest'; // Must be a full entity reference - return ctx.issueToken({ - claims: { - sub: userRef, // The user's own identity - ent: [userRef], // A list of identities that the user claims ownership through - }, - }); - }, - // resolver: providers.github.resolvers.usernameMatchingUserEntityName(), - }, - }), - }, - }); -} diff --git a/packages/create-app/templates/default-app/packages/backend/src/plugins/catalog.ts b/packages/create-app/templates/default-app/packages/backend/src/plugins/catalog.ts deleted file mode 100644 index 4decdca1c4..0000000000 --- a/packages/create-app/templates/default-app/packages/backend/src/plugins/catalog.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { CatalogBuilder } from '@backstage/plugin-catalog-backend'; -import { ScaffolderEntitiesProcessor } from '@backstage/plugin-catalog-backend-module-scaffolder-entity-model'; -import { Router } from 'express'; -import { PluginEnvironment } from '../types'; - -export default async function createPlugin( - env: PluginEnvironment, -): Promise { - const builder = await CatalogBuilder.create(env); - builder.addProcessor(new ScaffolderEntitiesProcessor()); - const { processingEngine, router } = await builder.build(); - await processingEngine.start(); - return router; -} diff --git a/packages/create-app/templates/default-app/packages/backend/src/plugins/proxy.ts b/packages/create-app/templates/default-app/packages/backend/src/plugins/proxy.ts deleted file mode 100644 index 54ec3937e9..0000000000 --- a/packages/create-app/templates/default-app/packages/backend/src/plugins/proxy.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { createRouter } from '@backstage/plugin-proxy-backend'; -import { Router } from 'express'; -import { PluginEnvironment } from '../types'; - -export default async function createPlugin( - env: PluginEnvironment, -): Promise { - return await createRouter({ - logger: env.logger, - config: env.config, - discovery: env.discovery, - }); -} diff --git a/packages/create-app/templates/default-app/packages/backend/src/plugins/scaffolder.ts b/packages/create-app/templates/default-app/packages/backend/src/plugins/scaffolder.ts deleted file mode 100644 index a12fee2295..0000000000 --- a/packages/create-app/templates/default-app/packages/backend/src/plugins/scaffolder.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { CatalogClient } from '@backstage/catalog-client'; -import { createRouter } from '@backstage/plugin-scaffolder-backend'; -import { Router } from 'express'; -import type { PluginEnvironment } from '../types'; - -export default async function createPlugin( - env: PluginEnvironment, -): Promise { - const catalogClient = new CatalogClient({ - discoveryApi: env.discovery, - }); - - return await createRouter({ - logger: env.logger, - config: env.config, - database: env.database, - reader: env.reader, - catalogClient, - identity: env.identity, - permissions: env.permissions, - }); -} diff --git a/packages/create-app/templates/default-app/packages/backend/src/plugins/search.ts.hbs b/packages/create-app/templates/default-app/packages/backend/src/plugins/search.ts.hbs deleted file mode 100644 index 467ac60a5a..0000000000 --- a/packages/create-app/templates/default-app/packages/backend/src/plugins/search.ts.hbs +++ /dev/null @@ -1,66 +0,0 @@ -import { useHotCleanup } from '@backstage/backend-common'; -import { createRouter } from '@backstage/plugin-search-backend'; -import { - IndexBuilder, - LunrSearchEngine, -} from '@backstage/plugin-search-backend-node'; -import { PluginEnvironment } from '../types'; -import { DefaultCatalogCollatorFactory } from '@backstage/plugin-search-backend-module-catalog'; -import { DefaultTechDocsCollatorFactory } from '@backstage/plugin-search-backend-module-techdocs'; -import { Router } from 'express'; - -export default async function createPlugin( - env: PluginEnvironment, -): Promise { - // Initialize a connection to a search engine. - const searchEngine = new LunrSearchEngine({ - logger: env.logger, - }); - const indexBuilder = new IndexBuilder({ - logger: env.logger, - searchEngine, - }); - - const schedule = env.scheduler.createScheduledTaskRunner({ - frequency: { minutes: 10 }, - timeout: { minutes: 15 }, - // A 3 second delay gives the backend server a chance to initialize before - // any collators are executed, which may attempt requests against the API. - initialDelay: { seconds: 3 }, - }); - - // Collators are responsible for gathering documents known to plugins. This - // collator gathers entities from the software catalog. - indexBuilder.addCollator({ - schedule, - factory: DefaultCatalogCollatorFactory.fromConfig(env.config, { - discovery: env.discovery, - tokenManager: env.tokenManager, - }), - }); - - // collator gathers entities from techdocs. - indexBuilder.addCollator({ - schedule, - factory: DefaultTechDocsCollatorFactory.fromConfig(env.config, { - discovery: env.discovery, - logger: env.logger, - tokenManager: env.tokenManager, - }), - }); - - // The scheduler controls when documents are gathered from collators and sent - // to the search engine for indexing. - const { scheduler } = await indexBuilder.build(); - scheduler.start(); - - useHotCleanup(module, () => scheduler.stop()); - - return await createRouter({ - engine: indexBuilder.getSearchEngine(), - types: indexBuilder.getDocumentTypes(), - permissions: env.permissions, - config: env.config, - logger: env.logger, - }); -} diff --git a/packages/create-app/templates/default-app/packages/backend/src/plugins/techdocs.ts b/packages/create-app/templates/default-app/packages/backend/src/plugins/techdocs.ts deleted file mode 100644 index be8bb0c06f..0000000000 --- a/packages/create-app/templates/default-app/packages/backend/src/plugins/techdocs.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { DockerContainerRunner } from '@backstage/backend-common'; -import { - createRouter, - Generators, - Preparers, - Publisher, -} from '@backstage/plugin-techdocs-backend'; -import Docker from 'dockerode'; -import { Router } from 'express'; -import { PluginEnvironment } from '../types'; - -export default async function createPlugin( - env: PluginEnvironment, -): Promise { - // Preparers are responsible for fetching source files for documentation. - const preparers = await Preparers.fromConfig(env.config, { - logger: env.logger, - reader: env.reader, - }); - - // Docker client (conditionally) used by the generators, based on techdocs.generators config. - const dockerClient = new Docker(); - const containerRunner = new DockerContainerRunner({ dockerClient }); - - // Generators are used for generating documentation sites. - const generators = await Generators.fromConfig(env.config, { - logger: env.logger, - containerRunner, - }); - - // Publisher is used for - // 1. Publishing generated files to storage - // 2. Fetching files from storage and passing them to TechDocs frontend. - const publisher = await Publisher.fromConfig(env.config, { - logger: env.logger, - discovery: env.discovery, - }); - - // checks if the publisher is working and logs the result - await publisher.getReadiness(); - - return await createRouter({ - preparers, - generators, - publisher, - logger: env.logger, - config: env.config, - discovery: env.discovery, - cache: env.cache, - }); -}