diff --git a/packages/backend/package.json b/packages/backend/package.json index 54dbe640df..d91428ac9e 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -40,6 +40,7 @@ "@backstage/plugin-azure-sites-backend": "workspace:^", "@backstage/plugin-badges-backend": "workspace:^", "@backstage/plugin-catalog-backend": "workspace:^", + "@backstage/plugin-catalog-backend-module-github": "workspace:^", "@backstage/plugin-catalog-node": "workspace:^", "@backstage/plugin-code-coverage-backend": "workspace:^", "@backstage/plugin-entity-feedback-backend": "workspace:^", diff --git a/packages/backend/src/index.ts b/packages/backend/src/index.ts index 011be941cf..cfd18f243a 100644 --- a/packages/backend/src/index.ts +++ b/packages/backend/src/index.ts @@ -38,11 +38,10 @@ import { import { TaskScheduler } from '@backstage/backend-tasks'; import { Config } from '@backstage/config'; import healthcheck from './plugins/healthcheck'; -import { metricsInit, metricsHandler } from './metrics'; +import { metricsHandler, metricsInit } from './metrics'; import auth from './plugins/auth'; import azureDevOps from './plugins/azure-devops'; import catalog from './plugins/catalog'; -import catalogEventBasedProviders from './plugins/catalogEventBasedProviders'; import codeCoverage from './plugins/codecoverage'; import entityFeedback from './plugins/entityFeedback'; import events from './plugins/events'; @@ -68,6 +67,7 @@ import linguist from './plugins/linguist'; import { PluginEnvironment } from './types'; import { ServerPermissionClient } from '@backstage/plugin-permission-node'; import { DefaultIdentityClient } from '@backstage/plugin-auth-node'; +import createCatalogEventBasedProviders from './plugins/catalogEventBasedProviders'; function makeCreateEnv(config: Config) { const root = getRootLogger(); @@ -156,7 +156,7 @@ async function main() { const exploreEnv = useHotMemoize(module, () => createEnv('explore')); const lighthouseEnv = useHotMemoize(module, () => createEnv('lighthouse')); - const eventBasedEntityProviders = await catalogEventBasedProviders( + const eventBasedEntityProviders = await createCatalogEventBasedProviders( catalogEnv, ); const linguistEnv = useHotMemoize(module, () => createEnv('linguist')); diff --git a/packages/backend/src/plugins/catalog.ts b/packages/backend/src/plugins/catalog.ts index 53204d6957..a70e56d301 100644 --- a/packages/backend/src/plugins/catalog.ts +++ b/packages/backend/src/plugins/catalog.ts @@ -21,6 +21,7 @@ import { Router } from 'express'; import { PluginEnvironment } from '../types'; import { InMemoryEventBroker } from '@backstage/plugin-events-backend'; import { GithubEntityProvider } from '@backstage/plugin-catalog-backend-module-github'; +import { ConflictEventSubscriber } from './conflictEventSubscriber'; export default async function createPlugin( env: PluginEnvironment, @@ -40,6 +41,9 @@ export default async function createPlugin( builder.addProcessor(new ScaffolderEntitiesProcessor()); builder.addEntityProvider(providers ?? []); const conflictBroker = new InMemoryEventBroker(env.logger); + conflictBroker.subscribe( + new ConflictEventSubscriber(env.logger, ['conflicts']), + ); builder.setConflictEventBroker(conflictBroker); const { processingEngine, router } = await builder.build(); await processingEngine.start(); diff --git a/packages/backend/src/plugins/conflictEventSubscriber.ts b/packages/backend/src/plugins/conflictEventSubscriber.ts new file mode 100644 index 0000000000..746d01cca6 --- /dev/null +++ b/packages/backend/src/plugins/conflictEventSubscriber.ts @@ -0,0 +1,50 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { + EntityProvider, + EntityProviderConnection, +} from '@backstage/plugin-catalog-node'; +import { EventParams, EventSubscriber } from '@backstage/plugin-events-node'; +import { Logger } from 'winston'; + +export class ConflictEventSubscriber + implements EntityProvider, EventSubscriber +{ + constructor( + private readonly logger: Logger, + private readonly topics: string[], + ) {} + + async onEvent(params: EventParams): Promise { + this.logger.info( + `onEvent: topic=${params.topic}, metadata=${JSON.stringify( + params.metadata, + )}, payload=${JSON.stringify(params.eventPayload)}`, + ); + } + + supportsEventTopics(): string[] { + return this.topics; + } + + async connect(_: EntityProviderConnection): Promise { + // not doing anything here + } + + getProviderName(): string { + return ConflictEventSubscriber.name; + } +} diff --git a/plugins/catalog-backend/src/database/DefaultProcessingDatabase.ts b/plugins/catalog-backend/src/database/DefaultProcessingDatabase.ts index 4fe24eab97..f7e9a0c81c 100644 --- a/plugins/catalog-backend/src/database/DefaultProcessingDatabase.ts +++ b/plugins/catalog-backend/src/database/DefaultProcessingDatabase.ts @@ -359,8 +359,8 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { `Detected conflicting entityRef ${entityRef} already referenced by ${conflictingKey} and now also ${locationKey}`, ); if (this.options.conflictEventBroker) { - this.options.conflictEventBroker?.publish({ - topic: 'conflicting-entities', + await this.options.conflictEventBroker?.publish({ + topic: 'conflicts', eventPayload: { ...entity, entityRef,