Removed CatalogBuilder Usages

Signed-off-by: Andre Wanlin <awanlin@spotify.com>
This commit is contained in:
Andre Wanlin
2025-04-17 18:11:47 -05:00
parent 51105a038c
commit 10f693c3ad
10 changed files with 13 additions and 362 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/backend-dynamic-feature-service': minor
---
**BREAKING** Removed support for the legacy backend, please migrate to the new backend system
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-catalog-backend-module-incremental-ingestion': minor
---
**BREAKING** Removed support for the legacy backend, please [migrate to the new backend system](https://github.com/backstage/backstage/tree/v1.38.0/plugins/catalog-backend-module-incremental-ingestion#installation).
@@ -5,31 +5,15 @@
```ts
import { BackendFeature } from '@backstage/backend-plugin-api';
import { BackstagePackageJson } from '@backstage/cli-node';
import { CatalogBuilder } from '@backstage/plugin-catalog-backend';
import { Config } from '@backstage/config';
import { ConfigSchema } from '@backstage/config-loader';
import { DatabaseService } from '@backstage/backend-plugin-api';
import { DiscoveryService } from '@backstage/backend-plugin-api';
import { EventBroker } from '@backstage/plugin-events-node';
import { EventsService } from '@backstage/plugin-events-node';
import { HttpPostIngressOptions } from '@backstage/plugin-events-node';
import { IdentityApi } from '@backstage/plugin-auth-node';
import { IndexBuilder } from '@backstage/plugin-search-backend-node';
import { JsonObject } from '@backstage/types';
import { Logger } from 'winston';
import { LoggerService } from '@backstage/backend-plugin-api';
import { PackagePlatform } from '@backstage/cli-node';
import { PackageRole } from '@backstage/cli-node';
import { PermissionEvaluator } from '@backstage/plugin-permission-common';
import { PermissionPolicy } from '@backstage/plugin-permission-node';
import { RootLoggerService } from '@backstage/backend-plugin-api';
import { Router } from 'express';
import { SchedulerService } from '@backstage/backend-plugin-api';
import { SchedulerServiceTaskRunner } from '@backstage/backend-plugin-api';
import { ServiceFactory } from '@backstage/backend-plugin-api';
import { ServiceRef } from '@backstage/backend-plugin-api';
import { TemplateAction } from '@backstage/plugin-scaffolder-node';
import { UrlReaderService } from '@backstage/backend-plugin-api';
import { WinstonLoggerOptions } from '@backstage/backend-defaults/rootLogger';
// @public (undocumented)
@@ -44,9 +28,7 @@ export interface BackendDynamicPlugin extends BaseDynamicPlugin {
}
// @public (undocumented)
export type BackendDynamicPluginInstaller =
| LegacyBackendPluginInstaller
| NewBackendPluginInstaller;
export type BackendDynamicPluginInstaller = NewBackendPluginInstaller;
// @public (undocumented)
export interface BackendPluginProvider {
@@ -271,48 +253,6 @@ export function isBackendDynamicPluginInstaller(
obj: any,
): obj is BackendDynamicPluginInstaller;
// @public @deprecated (undocumented)
export interface LegacyBackendPluginInstaller {
// (undocumented)
catalog?(builder: CatalogBuilder, env: LegacyPluginEnvironment): void;
// (undocumented)
events?(env: LegacyPluginEnvironment): HttpPostIngressOptions[];
// (undocumented)
kind: 'legacy';
// (undocumented)
permissions?: {
policy?: PermissionPolicy;
};
// (undocumented)
router?: {
pluginID: string;
createPlugin(env: LegacyPluginEnvironment): Promise<Router>;
};
// (undocumented)
scaffolder?(env: LegacyPluginEnvironment): TemplateAction<any>[];
// (undocumented)
search?(
indexBuilder: IndexBuilder,
schedule: SchedulerServiceTaskRunner,
env: LegacyPluginEnvironment,
): void;
}
// @public @deprecated (undocumented)
export type LegacyPluginEnvironment = {
logger: Logger;
database: DatabaseService;
config: Config;
reader: UrlReaderService;
discovery: DiscoveryService;
permissions: PermissionEvaluator;
scheduler: SchedulerService;
identity: IdentityApi;
eventBroker: EventBroker;
events: EventsService;
pluginProvider: BackendPluginProvider;
};
// @public (undocumented)
export interface ModuleLoader {
// (undocumented)
@@ -23,8 +23,6 @@ export type {
BackendDynamicPlugin,
BackendDynamicPluginInstaller,
NewBackendPluginInstaller,
LegacyBackendPluginInstaller,
LegacyPluginEnvironment,
DynamicPluginProvider,
FrontendPluginProvider,
BackendPluginProvider,
@@ -30,13 +30,10 @@ import {
BackendDynamicPlugin,
BaseDynamicPlugin,
DynamicPlugin,
LegacyBackendPluginInstaller,
NewBackendPluginInstaller,
LegacyPluginEnvironment,
} from './types';
import { ScannedPluginManifest, ScannedPluginPackage } from '../scanner/types';
import { randomUUID } from 'crypto';
import { TemplateAction } from '@backstage/plugin-scaffolder-node';
import { createSpecializedBackend } from '@backstage/backend-app-api';
import { ConfigSources } from '@backstage/config-loader';
import { Logs, MockedLogger, LogContent } from '../__testUtils__/testUtils';
@@ -552,49 +549,6 @@ describe('backend-dynamic-feature-service', () => {
]);
},
},
{
name: 'should successfully load a legacy backend plugin',
packageManifest: {
name: 'backend-dynamic-plugin-test',
version: '0.0.0',
backstage: {
role: 'backend-plugin',
},
main: 'dist/index.cjs.js',
},
indexFile: {
relativePath: ['dist', 'index.cjs.js'],
content:
'exports.dynamicPluginInstaller={ kind: "legacy", scaffolder: (env)=>[] }',
},
expectedLogs(location) {
return {
infos: [
{
message: `loaded dynamic backend plugin 'backend-dynamic-plugin-test' from '${location}'`,
},
],
};
},
checkLoadedPlugins(plugins) {
expect(plugins).toMatchObject([
{
name: 'backend-dynamic-plugin-test',
version: '0.0.0',
role: 'backend-plugin',
platform: 'node',
installer: {
kind: 'legacy',
},
},
]);
const installer = (plugins[0] as BackendDynamicPlugin)
.installer as LegacyBackendPluginInstaller;
expect(installer.scaffolder!({} as LegacyPluginEnvironment)).toEqual<
TemplateAction<any>[]
>([]);
},
},
{
name: 'should successfully load a frontend plugin',
packageManifest: {
@@ -14,58 +14,10 @@
* limitations under the License.
*/
import { Logger } from 'winston';
import { Config } from '@backstage/config';
import { Router } from 'express';
import { IdentityApi } from '@backstage/plugin-auth-node';
import { PermissionEvaluator } from '@backstage/plugin-permission-common';
import {
EventBroker,
EventsService,
HttpPostIngressOptions,
} from '@backstage/plugin-events-node';
import {
BackendFeature,
UrlReaderService,
SchedulerService,
SchedulerServiceTaskRunner,
DatabaseService,
DiscoveryService,
} from '@backstage/backend-plugin-api';
import { BackendFeature } from '@backstage/backend-plugin-api';
import { PackagePlatform, PackageRole } from '@backstage/cli-node';
import { CatalogBuilder } from '@backstage/plugin-catalog-backend';
import { TemplateAction } from '@backstage/plugin-scaffolder-node';
import { IndexBuilder } from '@backstage/plugin-search-backend-node';
import { PermissionPolicy } from '@backstage/plugin-permission-node';
import { ScannedPluginPackage } from '../scanner';
/**
* @public
*
* @deprecated
*
* Support for the legacy backend system will be removed in the future.
*
* When adding a legacy plugin installer entrypoint in your plugin,
* you should always take the opportunity to also implement support
* for the new backend system if not already done.
*
*/
export type LegacyPluginEnvironment = {
logger: Logger;
database: DatabaseService;
config: Config;
reader: UrlReaderService;
discovery: DiscoveryService;
permissions: PermissionEvaluator;
scheduler: SchedulerService;
identity: IdentityApi;
eventBroker: EventBroker;
events: EventsService;
pluginProvider: BackendPluginProvider;
};
/**
* @public
*/
@@ -126,9 +78,7 @@ export interface BackendDynamicPlugin extends BaseDynamicPlugin {
/**
* @public
*/
export type BackendDynamicPluginInstaller =
| LegacyBackendPluginInstaller
| NewBackendPluginInstaller;
export type BackendDynamicPluginInstaller = NewBackendPluginInstaller;
/**
* @public
@@ -139,38 +89,6 @@ export interface NewBackendPluginInstaller {
install(): BackendFeature | BackendFeature[];
}
/**
* @public
* @deprecated
*
* Support for the legacy backend system will be removed in the future.
*
* When adding a legacy plugin installer entrypoint in your plugin,
* you should always take the opportunity to also implement support
* for the new backend system if not already done.
*
*/
export interface LegacyBackendPluginInstaller {
kind: 'legacy';
router?: {
pluginID: string;
createPlugin(env: LegacyPluginEnvironment): Promise<Router>;
};
catalog?(builder: CatalogBuilder, env: LegacyPluginEnvironment): void;
scaffolder?(env: LegacyPluginEnvironment): TemplateAction<any>[];
search?(
indexBuilder: IndexBuilder,
schedule: SchedulerServiceTaskRunner,
env: LegacyPluginEnvironment,
): void;
events?(env: LegacyPluginEnvironment): HttpPostIngressOptions[];
permissions?: {
policy?: PermissionPolicy;
};
}
/**
* @public
*/
@@ -4,11 +4,9 @@
```ts
import { BackendFeature } from '@backstage/backend-plugin-api';
import { CatalogBuilder } from '@backstage/plugin-catalog-backend';
import { DatabaseService } from '@backstage/backend-plugin-api';
import type { DeferredEntity } from '@backstage/plugin-catalog-node';
import { EventParams } from '@backstage/plugin-events-node';
import { EventSubscriber } from '@backstage/plugin-events-node';
import { ExtensionPoint } from '@backstage/backend-plugin-api';
import { HumanDuration } from '@backstage/types';
import { IncrementalEntityProvider as IncrementalEntityProvider_2 } from '@backstage/plugin-catalog-backend-module-incremental-ingestion';
@@ -16,7 +14,6 @@ import { IncrementalEntityProviderOptions as IncrementalEntityProviderOptions_2
import { PermissionsService } from '@backstage/backend-plugin-api';
import { RootConfigService } from '@backstage/backend-plugin-api';
import { RootLoggerService } from '@backstage/backend-plugin-api';
import { Router } from 'express';
import { SchedulerService } from '@backstage/backend-plugin-api';
import { UrlReaderService } from '@backstage/backend-plugin-api';
@@ -37,23 +34,6 @@ export type EntityIteratorResult<T> =
cursor?: T;
};
// @public @deprecated (undocumented)
export class IncrementalCatalogBuilder {
// (undocumented)
addIncrementalEntityProvider<TCursor, TContext>(
provider: IncrementalEntityProvider<TCursor, TContext>,
options: IncrementalEntityProviderOptions,
): EventSubscriber;
// (undocumented)
build(): Promise<{
incrementalAdminRouter: Router;
}>;
static create(
env: PluginEnvironment,
builder: CatalogBuilder,
): Promise<IncrementalCatalogBuilder>;
}
// @public
export type IncrementalEntityEventResult =
| {
@@ -22,7 +22,6 @@
export { default } from './module';
export * from './module';
export * from './service';
export {
type EntityIteratorResult,
type IncrementalEntityEventResult,
@@ -1,131 +0,0 @@
/*
* Copyright 2022 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 {
IncrementalEntityProvider,
IncrementalEntityProviderOptions,
PluginEnvironment,
} from '../types';
import { CatalogBuilder as CoreCatalogBuilder } from '@backstage/plugin-catalog-backend';
import { createDeferred } from '@backstage/types';
import { Duration } from 'luxon';
import { Knex } from 'knex';
import { IncrementalIngestionEngine } from '../engine/IncrementalIngestionEngine';
import { applyDatabaseMigrations } from '../database/migrations';
import { IncrementalIngestionDatabaseManager } from '../database/IncrementalIngestionDatabaseManager';
import { IncrementalProviderRouter } from '../router/routes';
import { EventParams, EventSubscriber } from '@backstage/plugin-events-node';
/**
* @public
* @deprecated Please migrate to the new backend system and import `@backstage/plugin-catalog-backend-module-incremental-ingestion` as a module, and add providers to the `incrementalIngestionProvidersExtensionPoint` instead
*/
export class IncrementalCatalogBuilder {
/**
* Creates the incremental catalog builder, which extends the regular catalog builder.
* @param env - PluginEnvironment
* @param builder - CatalogBuilder
* @returns IncrementalCatalogBuilder
*/
static async create(env: PluginEnvironment, builder: CoreCatalogBuilder) {
const client = await env.database.getClient();
const manager = new IncrementalIngestionDatabaseManager({ client });
return new IncrementalCatalogBuilder(env, builder, client, manager);
}
private ready = createDeferred();
private constructor(
private env: PluginEnvironment,
private builder: CoreCatalogBuilder,
private client: Knex,
private manager: IncrementalIngestionDatabaseManager,
) {}
async build() {
await applyDatabaseMigrations(this.client);
this.ready.resolve();
const routerLogger = this.env.logger.child({
router: 'IncrementalProviderAdmin',
});
const incrementalAdminRouter = await new IncrementalProviderRouter(
this.manager,
routerLogger,
).createRouter();
return { incrementalAdminRouter };
}
addIncrementalEntityProvider<TCursor, TContext>(
provider: IncrementalEntityProvider<TCursor, TContext>,
options: IncrementalEntityProviderOptions,
): EventSubscriber {
const { burstInterval, burstLength, restLength } = options;
const { logger: catalogLogger, scheduler } = this.env;
const ready = this.ready;
const manager = this.manager;
let engine: IncrementalIngestionEngine;
this.builder.addEntityProvider({
getProviderName: provider.getProviderName.bind(provider),
async connect(connection) {
const logger = catalogLogger.child({
entityProvider: provider.getProviderName(),
});
engine = new IncrementalIngestionEngine({
...options,
ready,
manager,
logger,
provider,
restLength,
connection,
});
let frequency = Duration.isDuration(burstInterval)
? burstInterval
: Duration.fromObject(burstInterval);
if (frequency.as('milliseconds') < 5000) {
frequency = Duration.fromObject({ seconds: 5 }); // don't let it be silly low, to not overload the scheduler
}
let length = Duration.isDuration(burstLength)
? burstLength
: Duration.fromObject(burstLength);
length = length.plus(Duration.fromObject({ minutes: 1 })); // some margin from the actual completion
await scheduler.scheduleTask({
id: provider.getProviderName(),
fn: engine.taskFn.bind(engine),
frequency,
timeout: length,
});
},
});
return {
onEvent: (params: EventParams) => engine.onEvent(params),
supportsEventTopics() {
return engine.supportsEventTopics();
},
};
}
}
@@ -1,17 +0,0 @@
/*
* Copyright 2022 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.
*/
export { IncrementalCatalogBuilder } from './IncrementalCatalogBuilder';