From b141003f3d195168194d723186362c2fc986daee Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Tue, 8 Aug 2023 12:59:37 +0200 Subject: [PATCH 01/10] Remove options & use config instead Signed-off-by: Philipp Hugenroth --- packages/backend-next/src/index.ts | 16 +-- packages/backend/src/plugins/linguist.ts | 18 +--- plugins/linguist-backend/config.d.ts | 2 + plugins/linguist-backend/src/index.ts | 1 - plugins/linguist-backend/src/plugin.ts | 98 ++++++++----------- .../src/service/router.test.ts | 27 ++--- .../linguist-backend/src/service/router.ts | 68 ++++++++----- .../src/service/standaloneServer.ts | 25 ++--- 8 files changed, 107 insertions(+), 148 deletions(-) diff --git a/packages/backend-next/src/index.ts b/packages/backend-next/src/index.ts index bbb7290c73..f3b1ea06f8 100644 --- a/packages/backend-next/src/index.ts +++ b/packages/backend-next/src/index.ts @@ -36,7 +36,6 @@ import { badgesPlugin } from '@backstage/plugin-badges-backend'; import { azureDevOpsPlugin } from '@backstage/plugin-azure-devops-backend'; import { linguistPlugin } from '@backstage/plugin-linguist-backend'; import { devtoolsPlugin } from '@backstage/plugin-devtools-backend'; -import { TaskScheduleDefinition } from '@backstage/backend-tasks'; import { adrPlugin } from '@backstage/plugin-adr-backend'; import { lighthousePlugin } from '@backstage/plugin-lighthouse-backend'; import { proxyPlugin } from '@backstage/plugin-proxy-backend'; @@ -58,20 +57,7 @@ backend.add(devtoolsPlugin()); backend.add(entityFeedbackPlugin()); // Linguist -const linguistSchedule: TaskScheduleDefinition = { - frequency: { minutes: 2 }, - timeout: { minutes: 15 }, - initialDelay: { seconds: 15 }, -}; - -backend.add( - linguistPlugin({ - schedule: linguistSchedule, - age: { days: 30 }, - batchSize: 2, - useSourceLocation: false, - }), -); +backend.add(linguistPlugin()); // Todo backend.add(todoPlugin()); diff --git a/packages/backend/src/plugins/linguist.ts b/packages/backend/src/plugins/linguist.ts index 2c8713a7e3..25cb66b270 100644 --- a/packages/backend/src/plugins/linguist.ts +++ b/packages/backend/src/plugins/linguist.ts @@ -14,27 +14,13 @@ * limitations under the License. */ -import { TaskScheduleDefinition } from '@backstage/backend-tasks'; import { createRouter } from '@backstage/plugin-linguist-backend'; import { Router } from 'express'; + import type { PluginEnvironment } from '../types'; export default async function createPlugin( env: PluginEnvironment, ): Promise { - const schedule: TaskScheduleDefinition = { - frequency: { minutes: 2 }, - timeout: { minutes: 15 }, - initialDelay: { seconds: 15 }, - }; - - return createRouter( - { - schedule: schedule, - age: { days: 30 }, - batchSize: 2, - useSourceLocation: false, - }, - { ...env }, - ); + return createRouter({ ...env }); } diff --git a/plugins/linguist-backend/config.d.ts b/plugins/linguist-backend/config.d.ts index e7ad487d12..e927bbc930 100644 --- a/plugins/linguist-backend/config.d.ts +++ b/plugins/linguist-backend/config.d.ts @@ -19,6 +19,8 @@ import { HumanDuration } from '@backstage/types'; export interface Config { /** Configuration options for the linguist plugin */ linguist?: { + // TODO + /** Options for the tags processor */ tagsProcessor?: { /** diff --git a/plugins/linguist-backend/src/index.ts b/plugins/linguist-backend/src/index.ts index 107877551e..64016d0d07 100644 --- a/plugins/linguist-backend/src/index.ts +++ b/plugins/linguist-backend/src/index.ts @@ -24,4 +24,3 @@ export * from './processor'; export * from './service/router'; export type { LinguistBackendApi } from './api'; export { linguistPlugin } from './plugin'; -export type { LinguistPluginOptions } from './plugin'; diff --git a/plugins/linguist-backend/src/plugin.ts b/plugins/linguist-backend/src/plugin.ts index f655d6a1f4..3d33d85e72 100644 --- a/plugins/linguist-backend/src/plugin.ts +++ b/plugins/linguist-backend/src/plugin.ts @@ -20,68 +20,48 @@ import { createBackendPlugin, } from '@backstage/backend-plugin-api'; import { createRouter } from './service/router'; -import { TaskScheduleDefinition } from '@backstage/backend-tasks'; -import { HumanDuration } from '@backstage/types'; - -/** - * Options for Linguist backend plugin - * - * @public - */ -export interface LinguistPluginOptions { - schedule?: TaskScheduleDefinition; - age?: HumanDuration; - batchSize?: number; - useSourceLocation?: boolean; - linguistJsOptions?: Record; - kind?: string[]; -} /** * Linguist backend plugin * * @public */ -export const linguistPlugin = createBackendPlugin( - (options: LinguistPluginOptions) => ({ - pluginId: 'linguist', - register(env) { - env.registerInit({ - deps: { - logger: coreServices.logger, - reader: coreServices.urlReader, - database: coreServices.database, - discovery: coreServices.discovery, - scheduler: coreServices.scheduler, - tokenManager: coreServices.tokenManager, - httpRouter: coreServices.httpRouter, - }, - async init({ - logger, - reader, - database, - discovery, - scheduler, - tokenManager, - httpRouter, - }) { - httpRouter.use( - await createRouter( - { - ...options, - }, - { - logger: loggerToWinstonLogger(logger), - reader, - database, - discovery, - scheduler, - tokenManager, - }, - ), - ); - }, - }); - }, - }), -); +export const linguistPlugin = createBackendPlugin(() => ({ + pluginId: 'linguist', + register(env) { + env.registerInit({ + deps: { + logger: coreServices.logger, + config: coreServices.rootConfig, + reader: coreServices.urlReader, + database: coreServices.database, + discovery: coreServices.discovery, + scheduler: coreServices.scheduler, + tokenManager: coreServices.tokenManager, + httpRouter: coreServices.httpRouter, + }, + async init({ + logger, + config, + reader, + database, + discovery, + scheduler, + tokenManager, + httpRouter, + }) { + httpRouter.use( + await createRouter({ + logger: loggerToWinstonLogger(logger), + config, + reader, + database, + discovery, + scheduler, + tokenManager, + }), + ); + }, + }); + }, +})); diff --git a/plugins/linguist-backend/src/service/router.test.ts b/plugins/linguist-backend/src/service/router.test.ts index 7ab8f1c238..e43325bdaf 100644 --- a/plugins/linguist-backend/src/service/router.test.ts +++ b/plugins/linguist-backend/src/service/router.test.ts @@ -27,7 +27,6 @@ import request from 'supertest'; import { ConfigReader } from '@backstage/config'; import { createRouter } from './router'; import { LinguistBackendApi } from '../api'; -import { TaskScheduleDefinition } from '@backstage/backend-tasks'; function createDatabase(): PluginDatabaseManager { return DatabaseManager.fromConfig( @@ -59,28 +58,20 @@ const mockUrlReader = UrlReaders.default({ config: new ConfigReader({}), }); -const schedule: TaskScheduleDefinition = { - frequency: { minutes: 2 }, - timeout: { minutes: 15 }, - initialDelay: { seconds: 15 }, -}; - describe('createRouter', () => { let linguistBackendApi: jest.Mocked; let app: express.Express; beforeAll(async () => { - const router = await createRouter( - { schedule: schedule, age: { days: 30 }, useSourceLocation: false }, - { - linguistBackendApi: linguistBackendApi, - discovery: testDiscovery, - database: createDatabase(), - reader: mockUrlReader, - logger: getVoidLogger(), - tokenManager: mockedTokenManager, - }, - ); + const router = await createRouter({ + linguistBackendApi: linguistBackendApi, + discovery: testDiscovery, + database: createDatabase(), + config: new ConfigReader({}), + reader: mockUrlReader, + logger: getVoidLogger(), + tokenManager: mockedTokenManager, + }); app = express().use(router); }); diff --git a/plugins/linguist-backend/src/service/router.ts b/plugins/linguist-backend/src/service/router.ts index 9e45438ec8..8fbd19eb1c 100644 --- a/plugins/linguist-backend/src/service/router.ts +++ b/plugins/linguist-backend/src/service/router.ts @@ -21,53 +21,77 @@ import { TokenManager, UrlReader, } from '@backstage/backend-common'; +import { + PluginTaskScheduler, + readTaskScheduleDefinitionFromConfig, + TaskScheduleDefinition, +} from '@backstage/backend-tasks'; +import { CatalogClient } from '@backstage/catalog-client'; +import { Config } from '@backstage/config'; +import { HumanDuration } from '@backstage/types'; import express from 'express'; import Router from 'express-promise-router'; import { Logger } from 'winston'; -import { LinguistBackendApi } from '../api'; -import { LinguistBackendDatabase } from '../db'; -import { - PluginTaskScheduler, - TaskScheduleDefinition, -} from '@backstage/backend-tasks'; -import { HumanDuration } from '@backstage/types'; -import { CatalogClient } from '@backstage/catalog-client'; -import { LinguistBackendClient } from '../api/LinguistBackendClient'; -/** @public */ -export interface PluginOptions { - schedule?: TaskScheduleDefinition; - age?: HumanDuration; - batchSize?: number; - useSourceLocation?: boolean; - linguistJsOptions?: Record; - kind?: string[]; -} +import { LinguistBackendApi } from '../api'; +import { LinguistBackendClient } from '../api/LinguistBackendClient'; +import { LinguistBackendDatabase } from '../db'; /** @public */ export interface RouterOptions { linguistBackendApi?: LinguistBackendApi; logger: Logger; reader: UrlReader; + config: Config; tokenManager: TokenManager; database: PluginDatabaseManager; discovery: PluginEndpointDiscovery; scheduler?: PluginTaskScheduler; } +const DEFAULT_SCHEDULE: TaskScheduleDefinition = { + frequency: { minutes: 2 }, + timeout: { minutes: 15 }, + initialDelay: { seconds: 15 }, +}; +// const DEFAULT_AGE = { days: 30 }; +const DEFAULT_BATCH_SIZE = 20; +const DEFAULT_USE_SOURCE_LOCATION = false; + /** @public */ export async function createRouter( - pluginOptions: PluginOptions, routerOptions: RouterOptions, ): Promise { - const { - schedule, + const { config } = routerOptions; + + const schedule = config.has('linguist.schedule') + ? readTaskScheduleDefinitionFromConfig( + config.getConfig('linguist.schedule'), + ) + : DEFAULT_SCHEDULE; + const batchSize = config.has('linguist.batchSize') + ? config.getNumber('linguist.batchSize') + : DEFAULT_BATCH_SIZE; + const useSourceLocation = config.has('linguist.useSourceLocation') + ? config.getBoolean('linguist.useSourceLocation') + : DEFAULT_USE_SOURCE_LOCATION; + + const age = config.getOptionalConfig('linguist.age') as + | HumanDuration + | undefined; + const kind = config.getOptionalStringArray('linguist.kind'); + const linguistJsOptions = config.getOptionalConfig( + 'linguist.linguistJsOptions', + ); + + console.log( age, batchSize, useSourceLocation, kind, linguistJsOptions, - } = pluginOptions; + schedule, + ); const { logger, reader, database, discovery, scheduler, tokenManager } = routerOptions; diff --git a/plugins/linguist-backend/src/service/standaloneServer.ts b/plugins/linguist-backend/src/service/standaloneServer.ts index 11604cddfb..f391570fb3 100644 --- a/plugins/linguist-backend/src/service/standaloneServer.ts +++ b/plugins/linguist-backend/src/service/standaloneServer.ts @@ -26,7 +26,6 @@ import { Server } from 'http'; import { Logger } from 'winston'; import { createRouter } from './router'; import knexFactory from 'knex'; -import { TaskScheduleDefinition } from '@backstage/backend-tasks'; export interface ServerOptions { port: number; @@ -53,23 +52,15 @@ export async function startStandaloneServer( return knex; }); - const schedule: TaskScheduleDefinition = { - frequency: { minutes: 2 }, - timeout: { minutes: 15 }, - initialDelay: { seconds: 15 }, - }; - logger.debug('Starting application server...'); - const router = await createRouter( - { schedule: schedule, age: { days: 30 }, useSourceLocation: false }, - { - database: { getClient: async () => db }, - discovery: SingleHostDiscovery.fromConfig(config), - reader: UrlReaders.default({ logger, config }), - logger, - tokenManager: ServerTokenManager.noop(), - }, - ); + const router = await createRouter({ + database: { getClient: async () => db }, + discovery: SingleHostDiscovery.fromConfig(config), + reader: UrlReaders.default({ logger, config }), + config, + logger, + tokenManager: ServerTokenManager.noop(), + }); let service = createServiceBuilder(module) .setPort(options.port) From 0af1db0b9eccb07aedf9645e3ea4291921d8e333 Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Tue, 8 Aug 2023 15:29:17 +0200 Subject: [PATCH 02/10] Avoid bigger change to plugin Signed-off-by: Philipp Hugenroth --- packages/backend/src/plugins/linguist.ts | 18 ++++- plugins/linguist-backend/config.d.ts | 23 ++++++- plugins/linguist-backend/src/plugin.ts | 56 +++++++++++++--- .../src/service/router.test.ts | 27 +++++--- .../linguist-backend/src/service/router.ts | 66 ++++++------------- .../src/service/standaloneServer.ts | 25 ++++--- 6 files changed, 141 insertions(+), 74 deletions(-) diff --git a/packages/backend/src/plugins/linguist.ts b/packages/backend/src/plugins/linguist.ts index 25cb66b270..2c8713a7e3 100644 --- a/packages/backend/src/plugins/linguist.ts +++ b/packages/backend/src/plugins/linguist.ts @@ -14,13 +14,27 @@ * limitations under the License. */ +import { TaskScheduleDefinition } from '@backstage/backend-tasks'; import { createRouter } from '@backstage/plugin-linguist-backend'; import { Router } from 'express'; - import type { PluginEnvironment } from '../types'; export default async function createPlugin( env: PluginEnvironment, ): Promise { - return createRouter({ ...env }); + const schedule: TaskScheduleDefinition = { + frequency: { minutes: 2 }, + timeout: { minutes: 15 }, + initialDelay: { seconds: 15 }, + }; + + return createRouter( + { + schedule: schedule, + age: { days: 30 }, + batchSize: 2, + useSourceLocation: false, + }, + { ...env }, + ); } diff --git a/plugins/linguist-backend/config.d.ts b/plugins/linguist-backend/config.d.ts index e927bbc930..b864f01df7 100644 --- a/plugins/linguist-backend/config.d.ts +++ b/plugins/linguist-backend/config.d.ts @@ -14,12 +14,33 @@ * limitations under the License. */ +import { TaskScheduleDefinition } from '@backstage/backend-tasks'; import { HumanDuration } from '@backstage/types'; export interface Config { /** Configuration options for the linguist plugin */ linguist?: { - // TODO + schedule?: TaskScheduleDefinition; + /** + * @default 20 + */ + batchSize?: number; + /** + * @default false + */ + useSourceLocation?: boolean; + /** + * Refresh generated language breakdown + */ + age?: HumanDuration; + /** + * @default ['API', 'Component', 'Template'] + */ + kind?: string[]; + /** + * [linguist-js](https://www.npmjs.com/package/linguist-js) options + */ + linguistJsOptions: Record; /** Options for the tags processor */ tagsProcessor?: { diff --git a/plugins/linguist-backend/src/plugin.ts b/plugins/linguist-backend/src/plugin.ts index 3d33d85e72..cf4a00af43 100644 --- a/plugins/linguist-backend/src/plugin.ts +++ b/plugins/linguist-backend/src/plugin.ts @@ -19,8 +19,20 @@ import { coreServices, createBackendPlugin, } from '@backstage/backend-plugin-api'; +import { + TaskScheduleDefinition, + readTaskScheduleDefinitionFromConfig, +} from '@backstage/backend-tasks'; +import { HumanDuration } from '@backstage/types'; + import { createRouter } from './service/router'; +const DEFAULT_SCHEDULE: TaskScheduleDefinition = { + frequency: { minutes: 2 }, + timeout: { minutes: 15 }, + initialDelay: { seconds: 15 }, +}; + /** * Linguist backend plugin * @@ -50,16 +62,42 @@ export const linguistPlugin = createBackendPlugin(() => ({ tokenManager, httpRouter, }) { + const schedule = config.has('linguist.schedule') + ? readTaskScheduleDefinitionFromConfig( + config.getConfig('linguist.schedule'), + ) + : DEFAULT_SCHEDULE; + const batchSize = config.getOptionalNumber('linguist.batchSize'); + const useSourceLocation = config.getBoolean( + 'linguist.useSourceLocation', + ); + const age = config.getOptionalConfig('linguist.age') as + | HumanDuration + | undefined; + const kind = config.getOptionalStringArray('linguist.kind'); + const linguistJsOptions = config.getOptionalConfig( + 'linguist.linguistJsOptions', + ); + httpRouter.use( - await createRouter({ - logger: loggerToWinstonLogger(logger), - config, - reader, - database, - discovery, - scheduler, - tokenManager, - }), + await createRouter( + { + schedule, + batchSize, + useSourceLocation, + age, + kind, + linguistJsOptions, + }, + { + logger: loggerToWinstonLogger(logger), + reader, + database, + discovery, + scheduler, + tokenManager, + }, + ), ); }, }); diff --git a/plugins/linguist-backend/src/service/router.test.ts b/plugins/linguist-backend/src/service/router.test.ts index e43325bdaf..7ab8f1c238 100644 --- a/plugins/linguist-backend/src/service/router.test.ts +++ b/plugins/linguist-backend/src/service/router.test.ts @@ -27,6 +27,7 @@ import request from 'supertest'; import { ConfigReader } from '@backstage/config'; import { createRouter } from './router'; import { LinguistBackendApi } from '../api'; +import { TaskScheduleDefinition } from '@backstage/backend-tasks'; function createDatabase(): PluginDatabaseManager { return DatabaseManager.fromConfig( @@ -58,20 +59,28 @@ const mockUrlReader = UrlReaders.default({ config: new ConfigReader({}), }); +const schedule: TaskScheduleDefinition = { + frequency: { minutes: 2 }, + timeout: { minutes: 15 }, + initialDelay: { seconds: 15 }, +}; + describe('createRouter', () => { let linguistBackendApi: jest.Mocked; let app: express.Express; beforeAll(async () => { - const router = await createRouter({ - linguistBackendApi: linguistBackendApi, - discovery: testDiscovery, - database: createDatabase(), - config: new ConfigReader({}), - reader: mockUrlReader, - logger: getVoidLogger(), - tokenManager: mockedTokenManager, - }); + const router = await createRouter( + { schedule: schedule, age: { days: 30 }, useSourceLocation: false }, + { + linguistBackendApi: linguistBackendApi, + discovery: testDiscovery, + database: createDatabase(), + reader: mockUrlReader, + logger: getVoidLogger(), + tokenManager: mockedTokenManager, + }, + ); app = express().use(router); }); diff --git a/plugins/linguist-backend/src/service/router.ts b/plugins/linguist-backend/src/service/router.ts index 8fbd19eb1c..9e45438ec8 100644 --- a/plugins/linguist-backend/src/service/router.ts +++ b/plugins/linguist-backend/src/service/router.ts @@ -21,77 +21,53 @@ import { TokenManager, UrlReader, } from '@backstage/backend-common'; -import { - PluginTaskScheduler, - readTaskScheduleDefinitionFromConfig, - TaskScheduleDefinition, -} from '@backstage/backend-tasks'; -import { CatalogClient } from '@backstage/catalog-client'; -import { Config } from '@backstage/config'; -import { HumanDuration } from '@backstage/types'; import express from 'express'; import Router from 'express-promise-router'; import { Logger } from 'winston'; - import { LinguistBackendApi } from '../api'; -import { LinguistBackendClient } from '../api/LinguistBackendClient'; import { LinguistBackendDatabase } from '../db'; +import { + PluginTaskScheduler, + TaskScheduleDefinition, +} from '@backstage/backend-tasks'; +import { HumanDuration } from '@backstage/types'; +import { CatalogClient } from '@backstage/catalog-client'; +import { LinguistBackendClient } from '../api/LinguistBackendClient'; + +/** @public */ +export interface PluginOptions { + schedule?: TaskScheduleDefinition; + age?: HumanDuration; + batchSize?: number; + useSourceLocation?: boolean; + linguistJsOptions?: Record; + kind?: string[]; +} /** @public */ export interface RouterOptions { linguistBackendApi?: LinguistBackendApi; logger: Logger; reader: UrlReader; - config: Config; tokenManager: TokenManager; database: PluginDatabaseManager; discovery: PluginEndpointDiscovery; scheduler?: PluginTaskScheduler; } -const DEFAULT_SCHEDULE: TaskScheduleDefinition = { - frequency: { minutes: 2 }, - timeout: { minutes: 15 }, - initialDelay: { seconds: 15 }, -}; -// const DEFAULT_AGE = { days: 30 }; -const DEFAULT_BATCH_SIZE = 20; -const DEFAULT_USE_SOURCE_LOCATION = false; - /** @public */ export async function createRouter( + pluginOptions: PluginOptions, routerOptions: RouterOptions, ): Promise { - const { config } = routerOptions; - - const schedule = config.has('linguist.schedule') - ? readTaskScheduleDefinitionFromConfig( - config.getConfig('linguist.schedule'), - ) - : DEFAULT_SCHEDULE; - const batchSize = config.has('linguist.batchSize') - ? config.getNumber('linguist.batchSize') - : DEFAULT_BATCH_SIZE; - const useSourceLocation = config.has('linguist.useSourceLocation') - ? config.getBoolean('linguist.useSourceLocation') - : DEFAULT_USE_SOURCE_LOCATION; - - const age = config.getOptionalConfig('linguist.age') as - | HumanDuration - | undefined; - const kind = config.getOptionalStringArray('linguist.kind'); - const linguistJsOptions = config.getOptionalConfig( - 'linguist.linguistJsOptions', - ); - - console.log( + const { + schedule, age, batchSize, useSourceLocation, kind, linguistJsOptions, - schedule, - ); + } = pluginOptions; const { logger, reader, database, discovery, scheduler, tokenManager } = routerOptions; diff --git a/plugins/linguist-backend/src/service/standaloneServer.ts b/plugins/linguist-backend/src/service/standaloneServer.ts index f391570fb3..11604cddfb 100644 --- a/plugins/linguist-backend/src/service/standaloneServer.ts +++ b/plugins/linguist-backend/src/service/standaloneServer.ts @@ -26,6 +26,7 @@ import { Server } from 'http'; import { Logger } from 'winston'; import { createRouter } from './router'; import knexFactory from 'knex'; +import { TaskScheduleDefinition } from '@backstage/backend-tasks'; export interface ServerOptions { port: number; @@ -52,15 +53,23 @@ export async function startStandaloneServer( return knex; }); + const schedule: TaskScheduleDefinition = { + frequency: { minutes: 2 }, + timeout: { minutes: 15 }, + initialDelay: { seconds: 15 }, + }; + logger.debug('Starting application server...'); - const router = await createRouter({ - database: { getClient: async () => db }, - discovery: SingleHostDiscovery.fromConfig(config), - reader: UrlReaders.default({ logger, config }), - config, - logger, - tokenManager: ServerTokenManager.noop(), - }); + const router = await createRouter( + { schedule: schedule, age: { days: 30 }, useSourceLocation: false }, + { + database: { getClient: async () => db }, + discovery: SingleHostDiscovery.fromConfig(config), + reader: UrlReaders.default({ logger, config }), + logger, + tokenManager: ServerTokenManager.noop(), + }, + ); let service = createServiceBuilder(module) .setPort(options.port) From 0896d85d5ab5527b1525406a28c1f04c3ebfc583 Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Tue, 8 Aug 2023 15:57:40 +0200 Subject: [PATCH 03/10] Add changeset & update api-reports Signed-off-by: Philipp Hugenroth --- .changeset/sweet-feet-study.md | 5 +++++ plugins/linguist-backend/api-report.md | 18 +----------------- plugins/linguist-backend/config.d.ts | 2 +- 3 files changed, 7 insertions(+), 18 deletions(-) create mode 100644 .changeset/sweet-feet-study.md diff --git a/.changeset/sweet-feet-study.md b/.changeset/sweet-feet-study.md new file mode 100644 index 0000000000..ccec79678b --- /dev/null +++ b/.changeset/sweet-feet-study.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-linguist-backend': minor +--- + +**BREAKING**: Removing options from exported `linguistPlugin()` in favour of static config diff --git a/plugins/linguist-backend/api-report.md b/plugins/linguist-backend/api-report.md index aac978e426..5cee322a5b 100644 --- a/plugins/linguist-backend/api-report.md +++ b/plugins/linguist-backend/api-report.md @@ -36,23 +36,7 @@ export interface LinguistBackendApi { } // @public -export const linguistPlugin: (options: LinguistPluginOptions) => BackendFeature; - -// @public -export interface LinguistPluginOptions { - // (undocumented) - age?: HumanDuration; - // (undocumented) - batchSize?: number; - // (undocumented) - kind?: string[]; - // (undocumented) - linguistJsOptions?: Record; - // (undocumented) - schedule?: TaskScheduleDefinition; - // (undocumented) - useSourceLocation?: boolean; -} +export const linguistPlugin: () => BackendFeature; // @public export class LinguistTagsProcessor implements CatalogProcessor { diff --git a/plugins/linguist-backend/config.d.ts b/plugins/linguist-backend/config.d.ts index b864f01df7..34d09b28e1 100644 --- a/plugins/linguist-backend/config.d.ts +++ b/plugins/linguist-backend/config.d.ts @@ -40,7 +40,7 @@ export interface Config { /** * [linguist-js](https://www.npmjs.com/package/linguist-js) options */ - linguistJsOptions: Record; + linguistJsOptions: object; /** Options for the tags processor */ tagsProcessor?: { From cc622ab8c4f8835a1f5f0126d3b74e2ed0fc9f29 Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Tue, 8 Aug 2023 16:08:59 +0200 Subject: [PATCH 04/10] and small clean up.. Signed-off-by: Philipp Hugenroth --- plugins/linguist-backend/src/plugin.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/linguist-backend/src/plugin.ts b/plugins/linguist-backend/src/plugin.ts index cf4a00af43..a8c90b4ae9 100644 --- a/plugins/linguist-backend/src/plugin.ts +++ b/plugins/linguist-backend/src/plugin.ts @@ -38,7 +38,7 @@ const DEFAULT_SCHEDULE: TaskScheduleDefinition = { * * @public */ -export const linguistPlugin = createBackendPlugin(() => ({ +export const linguistPlugin = createBackendPlugin({ pluginId: 'linguist', register(env) { env.registerInit({ @@ -102,4 +102,4 @@ export const linguistPlugin = createBackendPlugin(() => ({ }, }); }, -})); +}); From 5c56236eeb735e608db592aebe2fda3b3590e53b Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Wed, 9 Aug 2023 11:33:14 +0200 Subject: [PATCH 05/10] Update plugins/linguist-backend/config.d.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw Signed-off-by: Philipp Hugenroth --- plugins/linguist-backend/config.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/linguist-backend/config.d.ts b/plugins/linguist-backend/config.d.ts index 34d09b28e1..c05bc59fe5 100644 --- a/plugins/linguist-backend/config.d.ts +++ b/plugins/linguist-backend/config.d.ts @@ -40,7 +40,7 @@ export interface Config { /** * [linguist-js](https://www.npmjs.com/package/linguist-js) options */ - linguistJsOptions: object; + linguistJsOptions?: object; /** Options for the tags processor */ tagsProcessor?: { From 1bceb3049b0990b3e753ee24020f1f93962dcfb3 Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Wed, 9 Aug 2023 11:45:44 +0200 Subject: [PATCH 06/10] Adjust to review by making schedule optional Signed-off-by: Philipp Hugenroth --- plugins/linguist-backend/config.d.ts | 4 ++-- plugins/linguist-backend/src/plugin.ts | 22 +++++++--------------- 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/plugins/linguist-backend/config.d.ts b/plugins/linguist-backend/config.d.ts index c05bc59fe5..5f5a3e2656 100644 --- a/plugins/linguist-backend/config.d.ts +++ b/plugins/linguist-backend/config.d.ts @@ -15,7 +15,7 @@ */ import { TaskScheduleDefinition } from '@backstage/backend-tasks'; -import { HumanDuration } from '@backstage/types'; +import { HumanDuration, JsonObject } from '@backstage/types'; export interface Config { /** Configuration options for the linguist plugin */ @@ -40,7 +40,7 @@ export interface Config { /** * [linguist-js](https://www.npmjs.com/package/linguist-js) options */ - linguistJsOptions?: object; + linguistJsOptions?: JsonObject; /** Options for the tags processor */ tagsProcessor?: { diff --git a/plugins/linguist-backend/src/plugin.ts b/plugins/linguist-backend/src/plugin.ts index a8c90b4ae9..0605ee3027 100644 --- a/plugins/linguist-backend/src/plugin.ts +++ b/plugins/linguist-backend/src/plugin.ts @@ -19,20 +19,11 @@ import { coreServices, createBackendPlugin, } from '@backstage/backend-plugin-api'; -import { - TaskScheduleDefinition, - readTaskScheduleDefinitionFromConfig, -} from '@backstage/backend-tasks'; +import { readTaskScheduleDefinitionFromConfig } from '@backstage/backend-tasks'; import { HumanDuration } from '@backstage/types'; import { createRouter } from './service/router'; -const DEFAULT_SCHEDULE: TaskScheduleDefinition = { - frequency: { minutes: 2 }, - timeout: { minutes: 15 }, - initialDelay: { seconds: 15 }, -}; - /** * Linguist backend plugin * @@ -62,11 +53,12 @@ export const linguistPlugin = createBackendPlugin({ tokenManager, httpRouter, }) { - const schedule = config.has('linguist.schedule') - ? readTaskScheduleDefinitionFromConfig( - config.getConfig('linguist.schedule'), - ) - : DEFAULT_SCHEDULE; + let schedule; + if (config.has('linguist.schedule')) { + schedule = readTaskScheduleDefinitionFromConfig( + config.getConfig('linguist.schedule'), + ); + } const batchSize = config.getOptionalNumber('linguist.batchSize'); const useSourceLocation = config.getBoolean( 'linguist.useSourceLocation', From 53c52953e4935586bb65503ad97e0183a14d9e5a Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Mon, 14 Aug 2023 16:41:16 +0200 Subject: [PATCH 07/10] Adjust to review Signed-off-by: Philipp Hugenroth --- .changeset/sweet-feet-study.md | 4 +- plugins/linguist-backend/api-report.md | 7 +++ plugins/linguist-backend/config.d.ts | 5 +- plugins/linguist-backend/src/plugin.ts | 49 +++------------ .../src/service/router.test.ts | 63 ++++++++++++++----- .../linguist-backend/src/service/router.ts | 34 +++++++++- 6 files changed, 100 insertions(+), 62 deletions(-) diff --git a/.changeset/sweet-feet-study.md b/.changeset/sweet-feet-study.md index ccec79678b..d27b05e848 100644 --- a/.changeset/sweet-feet-study.md +++ b/.changeset/sweet-feet-study.md @@ -1,5 +1,5 @@ --- -'@backstage/plugin-linguist-backend': minor +'@backstage/plugin-linguist-backend': patch --- -**BREAKING**: Removing options from exported `linguistPlugin()` in favour of static config +Breaking change for the alpha export plugin options from exported `linguistPlugin()` in favour of static config. diff --git a/plugins/linguist-backend/api-report.md b/plugins/linguist-backend/api-report.md index 5cee322a5b..4edd939058 100644 --- a/plugins/linguist-backend/api-report.md +++ b/plugins/linguist-backend/api-report.md @@ -27,6 +27,11 @@ export function createRouter( routerOptions: RouterOptions, ): Promise; +// @public (undocumented) +export function createRouterFromConfig( + routerOptions: RouterOptions, +): Promise; + // @public (undocumented) export interface LinguistBackendApi { // (undocumented) @@ -88,6 +93,8 @@ export interface PluginOptions { // @public (undocumented) export interface RouterOptions { + // (undocumented) + config?: Config; // (undocumented) database: PluginDatabaseManager; // (undocumented) diff --git a/plugins/linguist-backend/config.d.ts b/plugins/linguist-backend/config.d.ts index 5f5a3e2656..758210feb7 100644 --- a/plugins/linguist-backend/config.d.ts +++ b/plugins/linguist-backend/config.d.ts @@ -15,7 +15,8 @@ */ import { TaskScheduleDefinition } from '@backstage/backend-tasks'; -import { HumanDuration, JsonObject } from '@backstage/types'; +import { HumanDuration } from '@backstage/types'; +import { Options as LinguistJsOptions } from 'linguist-js/dist/types'; export interface Config { /** Configuration options for the linguist plugin */ @@ -40,7 +41,7 @@ export interface Config { /** * [linguist-js](https://www.npmjs.com/package/linguist-js) options */ - linguistJsOptions?: JsonObject; + linguistJsOptions?: LinguistJsOptions; /** Options for the tags processor */ tagsProcessor?: { diff --git a/plugins/linguist-backend/src/plugin.ts b/plugins/linguist-backend/src/plugin.ts index 0605ee3027..cbf18d9ebe 100644 --- a/plugins/linguist-backend/src/plugin.ts +++ b/plugins/linguist-backend/src/plugin.ts @@ -19,10 +19,8 @@ import { coreServices, createBackendPlugin, } from '@backstage/backend-plugin-api'; -import { readTaskScheduleDefinitionFromConfig } from '@backstage/backend-tasks'; -import { HumanDuration } from '@backstage/types'; -import { createRouter } from './service/router'; +import { createRouterFromConfig } from './service/router'; /** * Linguist backend plugin @@ -53,43 +51,16 @@ export const linguistPlugin = createBackendPlugin({ tokenManager, httpRouter, }) { - let schedule; - if (config.has('linguist.schedule')) { - schedule = readTaskScheduleDefinitionFromConfig( - config.getConfig('linguist.schedule'), - ); - } - const batchSize = config.getOptionalNumber('linguist.batchSize'); - const useSourceLocation = config.getBoolean( - 'linguist.useSourceLocation', - ); - const age = config.getOptionalConfig('linguist.age') as - | HumanDuration - | undefined; - const kind = config.getOptionalStringArray('linguist.kind'); - const linguistJsOptions = config.getOptionalConfig( - 'linguist.linguistJsOptions', - ); - httpRouter.use( - await createRouter( - { - schedule, - batchSize, - useSourceLocation, - age, - kind, - linguistJsOptions, - }, - { - logger: loggerToWinstonLogger(logger), - reader, - database, - discovery, - scheduler, - tokenManager, - }, - ), + await createRouterFromConfig({ + logger: loggerToWinstonLogger(logger), + config, + reader, + database, + discovery, + scheduler, + tokenManager, + }), ); }, }); diff --git a/plugins/linguist-backend/src/service/router.test.ts b/plugins/linguist-backend/src/service/router.test.ts index 7ab8f1c238..4048e1213b 100644 --- a/plugins/linguist-backend/src/service/router.test.ts +++ b/plugins/linguist-backend/src/service/router.test.ts @@ -25,7 +25,7 @@ import { import express from 'express'; import request from 'supertest'; import { ConfigReader } from '@backstage/config'; -import { createRouter } from './router'; +import { createRouter, createRouterFromConfig } from './router'; import { LinguistBackendApi } from '../api'; import { TaskScheduleDefinition } from '@backstage/backend-tasks'; @@ -69,26 +69,57 @@ describe('createRouter', () => { let linguistBackendApi: jest.Mocked; let app: express.Express; - beforeAll(async () => { - const router = await createRouter( - { schedule: schedule, age: { days: 30 }, useSourceLocation: false }, - { - linguistBackendApi: linguistBackendApi, - discovery: testDiscovery, - database: createDatabase(), - reader: mockUrlReader, - logger: getVoidLogger(), - tokenManager: mockedTokenManager, - }, - ); - app = express().use(router); - }); - beforeEach(() => { jest.resetAllMocks(); }); describe('GET /health', () => { + beforeAll(async () => { + const router = await createRouter( + { schedule: schedule, age: { days: 30 }, useSourceLocation: false }, + { + linguistBackendApi: linguistBackendApi, + discovery: testDiscovery, + database: createDatabase(), + reader: mockUrlReader, + logger: getVoidLogger(), + tokenManager: mockedTokenManager, + }, + ); + app = express().use(router); + }); + it('returns ok', async () => { + const response = await request(app).get('/health'); + + expect(response.status).toEqual(200); + expect(response.body).toEqual({ status: 'ok' }); + }); + }); + + describe('GET /health from config', () => { + beforeAll(async () => { + const config = new ConfigReader({ + linguist: { + schedule: { + frequency: { minutes: 2 }, + timeout: { minutes: 15 }, + initialDelay: { seconds: 15 }, + }, + age: { days: 30 }, + useSourceLocation: false, + }, + }); + const router = await createRouterFromConfig({ + linguistBackendApi: linguistBackendApi, + discovery: testDiscovery, + database: createDatabase(), + reader: mockUrlReader, + logger: getVoidLogger(), + config, + tokenManager: mockedTokenManager, + }); + app = express().use(router); + }); it('returns ok', async () => { const response = await request(app).get('/health'); diff --git a/plugins/linguist-backend/src/service/router.ts b/plugins/linguist-backend/src/service/router.ts index 9e45438ec8..02ff05f398 100644 --- a/plugins/linguist-backend/src/service/router.ts +++ b/plugins/linguist-backend/src/service/router.ts @@ -28,11 +28,13 @@ import { LinguistBackendApi } from '../api'; import { LinguistBackendDatabase } from '../db'; import { PluginTaskScheduler, + readTaskScheduleDefinitionFromConfig, TaskScheduleDefinition, } from '@backstage/backend-tasks'; import { HumanDuration } from '@backstage/types'; import { CatalogClient } from '@backstage/catalog-client'; import { LinguistBackendClient } from '../api/LinguistBackendClient'; +import { Config } from '@backstage/config'; /** @public */ export interface PluginOptions { @@ -53,6 +55,7 @@ export interface RouterOptions { database: PluginDatabaseManager; discovery: PluginEndpointDiscovery; scheduler?: PluginTaskScheduler; + config?: Config; } /** @public */ @@ -60,6 +63,9 @@ export async function createRouter( pluginOptions: PluginOptions, routerOptions: RouterOptions, ): Promise { + const { logger, reader, database, discovery, scheduler, tokenManager } = + routerOptions; + const { schedule, age, @@ -69,9 +75,6 @@ export async function createRouter( linguistJsOptions, } = pluginOptions; - const { logger, reader, database, discovery, scheduler, tokenManager } = - routerOptions; - const linguistBackendStore = await LinguistBackendDatabase.create( await database.getClient(), ); @@ -135,3 +138,28 @@ export async function createRouter( router.use(errorHandler()); return router; } + +/** @public */ +export async function createRouterFromConfig(routerOptions: RouterOptions) { + const { config } = routerOptions; + const pluginOptions: PluginOptions = {}; + if (config) { + if (config.has('linguist.schedule')) { + pluginOptions.schedule = readTaskScheduleDefinitionFromConfig( + config.getConfig('linguist.schedule'), + ); + } + pluginOptions.batchSize = config.getOptionalNumber('linguist.batchSize'); + pluginOptions.useSourceLocation = config.getBoolean( + 'linguist.useSourceLocation', + ); + pluginOptions.age = config.getOptionalConfig('linguist.age') as + | HumanDuration + | undefined; + pluginOptions.kind = config.getOptionalStringArray('linguist.kind'); + pluginOptions.linguistJsOptions = config.getOptionalConfig( + 'linguist.linguistJsOptions', + ); + } + return createRouter(pluginOptions, routerOptions); +} From c823d2b02d01d23a774719f4dfeec58ad0bd070e Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Mon, 14 Aug 2023 17:31:46 +0200 Subject: [PATCH 08/10] Update README Signed-off-by: Philipp Hugenroth --- plugins/linguist-backend/README.md | 36 ++++++++++++++++++------------ 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/plugins/linguist-backend/README.md b/plugins/linguist-backend/README.md index 7bca98191b..d2ed7f5f03 100644 --- a/plugins/linguist-backend/README.md +++ b/plugins/linguist-backend/README.md @@ -70,24 +70,32 @@ In your `packages/backend/src/index.ts` make the following changes: // ... other feature additions -+ const linguistSchedule: TaskScheduleDefinition = { -+ frequency: { minutes: 2 }, -+ timeout: { minutes: 15 }, -+ initialDelay: { seconds: 15 }, -+ }; - -+ backend.add( -+ linguistPlugin({ -+ schedule: linguistSchedule, -+ age: { days: 30 }, -+ batchSize: 2, -+ useSourceLocation: false, -+ }), -+ ); ++ backend.add(linguistPlugin()); backend.start(); ``` +The plugin options can be set through the `app-config.yaml`: + +```yaml +// ... + +linguist: + schedule: + frequency: + minutes: 2 + timeout: + minutes: 2 + initialDelay: + seconds: 15 + age: + days: 30 + batchSize: 2 + useSourceLocation: false + +// ... +``` + ## Plugin Option The Linguist backend has various plugin options that you can provide to the `createRouter` function in your `packages/backend/src/plugins/linguist.ts` file that will allow you to configure various aspects of how it works. The following sections go into the details of these options From a391c31d79c29067581c3273ff00f691fa9c4e8b Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Mon, 14 Aug 2023 17:32:23 +0200 Subject: [PATCH 09/10] Update .changeset/sweet-feet-study.md Co-authored-by: Andre Wanlin <67169551+awanlin@users.noreply.github.com> Signed-off-by: Philipp Hugenroth --- .changeset/sweet-feet-study.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/sweet-feet-study.md b/.changeset/sweet-feet-study.md index d27b05e848..9fd954cbbb 100644 --- a/.changeset/sweet-feet-study.md +++ b/.changeset/sweet-feet-study.md @@ -2,4 +2,4 @@ '@backstage/plugin-linguist-backend': patch --- -Breaking change for the alpha export plugin options from exported `linguistPlugin()` in favour of static config. +**BREAKING**: Removed the alpha export plugin options from exported `linguistPlugin()` (used by the new backend system) in favour of static config. From 5226acf00ba7bb020b993fafa28b930179ac472c Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Mon, 14 Aug 2023 17:40:42 +0200 Subject: [PATCH 10/10] Update sweet-feet-study.md Signed-off-by: Philipp Hugenroth --- .changeset/sweet-feet-study.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/sweet-feet-study.md b/.changeset/sweet-feet-study.md index 9fd954cbbb..4afdb467f6 100644 --- a/.changeset/sweet-feet-study.md +++ b/.changeset/sweet-feet-study.md @@ -1,5 +1,5 @@ --- -'@backstage/plugin-linguist-backend': patch +'@backstage/plugin-linguist-backend': minor --- **BREAKING**: Removed the alpha export plugin options from exported `linguistPlugin()` (used by the new backend system) in favour of static config.