From 51987dbdaf876cd90222311f89c15ca527ab6be7 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 15 Aug 2023 10:40:11 +0200 Subject: [PATCH 1/7] backend-plugin-api: remove plugin and module options Signed-off-by: Patrik Oldsberg --- .changeset/red-ghosts-train.md | 5 + packages/backend-plugin-api/api-report.md | 12 +- .../src/wiring/factories.test.ts | 151 ++---------------- .../src/wiring/factories.ts | 37 ++--- .../backend-plugin-api/src/wiring/types.ts | 6 +- 5 files changed, 37 insertions(+), 174 deletions(-) create mode 100644 .changeset/red-ghosts-train.md diff --git a/.changeset/red-ghosts-train.md b/.changeset/red-ghosts-train.md new file mode 100644 index 0000000000..daa6692820 --- /dev/null +++ b/.changeset/red-ghosts-train.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-plugin-api': minor +--- + +**BREAKING**: Removed the ability to define options for plugins and modules. Existing options should be migrated to instead use either static configuration or extension points. diff --git a/packages/backend-plugin-api/api-report.md b/packages/backend-plugin-api/api-report.md index 9fa2149e43..0789168926 100644 --- a/packages/backend-plugin-api/api-report.md +++ b/packages/backend-plugin-api/api-report.md @@ -119,14 +119,14 @@ export namespace coreServices { } // @public -export function createBackendModule( - config: BackendModuleConfig | ((...params: TOptions) => BackendModuleConfig), -): (...params: TOptions) => BackendFeature; +export function createBackendModule( + config: BackendModuleConfig, +): () => BackendFeature; // @public -export function createBackendPlugin( - config: BackendPluginConfig | ((...params: TOptions) => BackendPluginConfig), -): (...params: TOptions) => BackendFeature; +export function createBackendPlugin( + config: BackendPluginConfig, +): () => BackendFeature; // @public export function createExtensionPoint( diff --git a/packages/backend-plugin-api/src/wiring/factories.test.ts b/packages/backend-plugin-api/src/wiring/factories.test.ts index 17b0eed55f..1fd05a1605 100644 --- a/packages/backend-plugin-api/src/wiring/factories.test.ts +++ b/packages/backend-plugin-api/src/wiring/factories.test.ts @@ -33,22 +33,19 @@ describe('createExtensionPoint', () => { describe('createBackendPlugin', () => { it('should create a BackendPlugin', () => { - const plugin = createBackendPlugin((_options: { a: string }) => ({ + const plugin = createBackendPlugin({ pluginId: 'x', register(r) { r.registerInit({ deps: {}, async init() {} }); }, - })); + }); expect(plugin).toBeDefined(); - expect(plugin({ a: 'a' })).toBeDefined(); - expect(plugin({ a: 'a' })).toEqual({ + expect(plugin()).toEqual({ $$type: '@backstage/BackendFeature', version: 'v1', getRegistrations: expect.any(Function), }); - expect( - (plugin({ a: 'a' }) as InternalBackendFeature).getRegistrations(), - ).toEqual([ + expect((plugin() as InternalBackendFeature).getRegistrations()).toEqual([ { type: 'plugin', pluginId: 'x', @@ -60,91 +57,27 @@ describe('createBackendPlugin', () => { }, ]); // @ts-expect-error - expect(plugin()).toBeDefined(); - // @ts-expect-error - expect(plugin({ b: 'b' })).toBeDefined(); - }); - - it('should create plugins with optional options', () => { - const plugin = createBackendPlugin((_options?: { a: string }) => ({ - pluginId: 'x', - register() {}, - })); - expect(plugin).toBeDefined(); expect(plugin({ a: 'a' })).toBeDefined(); - expect(plugin()).toBeDefined(); - // @ts-expect-error - expect(plugin({ b: 'b' })).toBeDefined(); - }); - - it('should create plugins without options', () => { - const plugin = createBackendPlugin({ - pluginId: 'x', - register() {}, - }); - expect(plugin).toBeDefined(); - // @ts-expect-error - expect(plugin({ a: 'a' })).toBeDefined(); - // @ts-expect-error - expect(plugin({})).toBeDefined(); - }); - - it('should create a BackendPlugin with options as interface', () => { - interface TestOptions { - a: string; - } - const plugin = createBackendPlugin((_options: TestOptions) => ({ - pluginId: 'x', - register() {}, - })); - expect(plugin).toBeDefined(); - expect(plugin({ a: 'a' })).toBeDefined(); - expect(plugin({ a: 'a' })).toEqual({ - $$type: '@backstage/BackendFeature', - version: 'v1', - getRegistrations: expect.any(Function), - }); - // @ts-expect-error - expect(plugin()).toBeDefined(); - // @ts-expect-error - expect(plugin({ b: 'b' })).toBeDefined(); - }); - - it('should create plugins with optional options as interface', () => { - interface TestOptions { - a: string; - } - const plugin = createBackendPlugin((_options?: TestOptions) => ({ - pluginId: 'x', - register() {}, - })); - expect(plugin).toBeDefined(); - expect(plugin({ a: 'a' })).toBeDefined(); - expect(plugin()).toBeDefined(); - // @ts-expect-error - expect(plugin({ b: 'b' })).toBeDefined(); }); }); describe('createBackendModule', () => { it('should create a BackendModule', () => { - const mod = createBackendModule((_options: { a: string }) => ({ + const mod = createBackendModule({ pluginId: 'x', moduleId: 'y', register(r) { r.registerInit({ deps: {}, async init() {} }); }, - })); + }); expect(mod).toBeDefined(); - expect(mod({ a: 'a' })).toBeDefined(); - expect(mod({ a: 'a' })).toEqual({ + expect(mod()).toBeDefined(); + expect(mod()).toEqual({ $$type: '@backstage/BackendFeature', version: 'v1', getRegistrations: expect.any(Function), }); - expect( - (mod({ a: 'a' }) as InternalBackendFeature).getRegistrations(), - ).toEqual([ + expect((mod() as InternalBackendFeature).getRegistrations()).toEqual([ { type: 'module', pluginId: 'x', @@ -157,72 +90,6 @@ describe('createBackendModule', () => { }, ]); // @ts-expect-error - expect(mod()).toBeDefined(); - // @ts-expect-error - expect(mod({ b: 'b' })).toBeDefined(); - }); - - it('should create modules with optional options', () => { - const mod = createBackendModule((_options?: { a: string }) => ({ - pluginId: 'x', - moduleId: 'y', - register() {}, - })); - expect(mod).toBeDefined(); expect(mod({ a: 'a' })).toBeDefined(); - expect(mod()).toBeDefined(); - // @ts-expect-error - expect(mod({ b: 'b' })).toBeDefined(); - }); - - it('should create modules without options', () => { - const mod = createBackendModule({ - pluginId: 'x', - moduleId: 'y', - register() {}, - }); - expect(mod).toBeDefined(); - // @ts-expect-error - expect(mod({ a: 'a' })).toBeDefined(); - // @ts-expect-error - expect(mod({})).toBeDefined(); - }); - - it('should create a BackendModule as interface', () => { - interface TestOptions { - a: string; - } - const mod = createBackendModule((_options: TestOptions) => ({ - pluginId: 'x', - moduleId: 'y', - register() {}, - })); - expect(mod).toBeDefined(); - expect(mod({ a: 'a' })).toBeDefined(); - expect(mod({ a: 'a' })).toEqual({ - $$type: '@backstage/BackendFeature', - version: 'v1', - getRegistrations: expect.any(Function), - }); - // @ts-expect-error - expect(mod()).toBeDefined(); - // @ts-expect-error - expect(mod({ b: 'b' })).toBeDefined(); - }); - - it('should create modules with optional options as interface', () => { - interface TestOptions { - a: string; - } - const mod = createBackendModule((_options?: TestOptions) => ({ - pluginId: 'x', - moduleId: 'y', - register() {}, - })); - expect(mod).toBeDefined(); - expect(mod({ a: 'a' })).toBeDefined(); - expect(mod()).toBeDefined(); - // @ts-expect-error - expect(mod({ b: 'b' })).toBeDefined(); }); }); diff --git a/packages/backend-plugin-api/src/wiring/factories.ts b/packages/backend-plugin-api/src/wiring/factories.ts index c2ff1f84b9..af40256411 100644 --- a/packages/backend-plugin-api/src/wiring/factories.ts +++ b/packages/backend-plugin-api/src/wiring/factories.ts @@ -85,14 +85,10 @@ export interface BackendPluginConfig { * @see {@link https://backstage.io/docs/backend-system/architecture/plugins | The architecture of plugins} * @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns} */ -export function createBackendPlugin( - config: BackendPluginConfig | ((...params: TOptions) => BackendPluginConfig), -): (...params: TOptions) => BackendFeature { - const configCallback = typeof config === 'function' ? config : () => config; - - const factory: BackendFeatureFactory = (...options) => { - const c = configCallback(...options); - +export function createBackendPlugin( + config: BackendPluginConfig, +): () => BackendFeature { + const factory: BackendFeatureFactory = () => { let registrations: InternalBackendPluginRegistration[]; return { @@ -107,7 +103,7 @@ export function createBackendPlugin( let init: InternalBackendPluginRegistration['init'] | undefined = undefined; - c.register({ + config.register({ registerExtensionPoint(ext, impl) { if (init) { throw new Error( @@ -129,14 +125,14 @@ export function createBackendPlugin( if (!init) { throw new Error( - `registerInit was not called by register in ${c.pluginId}`, + `registerInit was not called by register in ${config.pluginId}`, ); } registrations = [ { type: 'plugin', - pluginId: c.pluginId, + pluginId: config.pluginId, extensionPoints, init, }, @@ -179,13 +175,10 @@ export interface BackendModuleConfig { * @see {@link https://backstage.io/docs/backend-system/architecture/modules | The architecture of modules} * @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns} */ -export function createBackendModule( - config: BackendModuleConfig | ((...params: TOptions) => BackendModuleConfig), -): (...params: TOptions) => BackendFeature { - const configCallback = typeof config === 'function' ? config : () => config; - const factory: BackendFeatureFactory = (...options: TOptions) => { - const c = configCallback(...options); - +export function createBackendModule( + config: BackendModuleConfig, +): () => BackendFeature { + const factory: BackendFeatureFactory = () => { let registrations: InternalBackendModuleRegistration[]; return { @@ -200,7 +193,7 @@ export function createBackendModule( let init: InternalBackendModuleRegistration['init'] | undefined = undefined; - c.register({ + config.register({ registerExtensionPoint(ext, impl) { if (init) { throw new Error( @@ -222,15 +215,15 @@ export function createBackendModule( if (!init) { throw new Error( - `registerInit was not called by register in ${c.moduleId} module for ${c.pluginId}`, + `registerInit was not called by register in ${config.moduleId} module for ${config.pluginId}`, ); } registrations = [ { type: 'module', - pluginId: c.pluginId, - moduleId: c.moduleId, + pluginId: config.pluginId, + moduleId: config.moduleId, extensionPoints, init, }, diff --git a/packages/backend-plugin-api/src/wiring/types.ts b/packages/backend-plugin-api/src/wiring/types.ts index e2ed6ce387..d416ce7f9a 100644 --- a/packages/backend-plugin-api/src/wiring/types.ts +++ b/packages/backend-plugin-api/src/wiring/types.ts @@ -72,10 +72,8 @@ export interface BackendModuleRegistrationPoints { } /** @internal */ -export interface BackendFeatureFactory< - TOptions extends [options?: object] = [], -> { - (...options: TOptions): BackendFeature; +export interface BackendFeatureFactory { + (): BackendFeature; $$type: '@backstage/BackendFeatureFactory'; } From a6d816c9cce171bb480993ddcdf79579e9eee9ed Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 15 Aug 2023 10:48:28 +0200 Subject: [PATCH 2/7] permission-backend: fix backend plugin declaration Signed-off-by: Patrik Oldsberg --- .changeset/weak-apes-flow.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/weak-apes-flow.md diff --git a/.changeset/weak-apes-flow.md b/.changeset/weak-apes-flow.md new file mode 100644 index 0000000000..c5673d381a --- /dev/null +++ b/.changeset/weak-apes-flow.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-permission-backend': patch +--- + +Minor internal fix. From e07a4914f62186afbbb8a87bae6c0ad5eaf2a4d0 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 15 Aug 2023 16:05:13 +0200 Subject: [PATCH 3/7] scaffolder-backend: move more types to -node Signed-off-by: Patrik Oldsberg --- .changeset/honest-fireants-applaud.md | 17 +++ .changeset/little-peas-decide.md | 5 + .../src/lib/templating/SecureTemplater.ts | 20 ++- .../src/scaffolder/tasks/types.ts | 99 +++++--------- plugins/scaffolder-node/src/index.ts | 1 + plugins/scaffolder-node/src/tasks/index.ts | 13 +- plugins/scaffolder-node/src/tasks/types.ts | 124 ++++++++++++++++++ plugins/scaffolder-node/src/types.ts | 25 ++++ 8 files changed, 229 insertions(+), 75 deletions(-) create mode 100644 .changeset/honest-fireants-applaud.md create mode 100644 .changeset/little-peas-decide.md create mode 100644 plugins/scaffolder-node/src/types.ts diff --git a/.changeset/honest-fireants-applaud.md b/.changeset/honest-fireants-applaud.md new file mode 100644 index 0000000000..2fd29e493a --- /dev/null +++ b/.changeset/honest-fireants-applaud.md @@ -0,0 +1,17 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +Deprecated the following type exports, which have been moved to `@backstage/plugin-scaffolder-node` instead: + +- `TemplateFilter` +- `TemplateGlobal` +- `TaskStatus` +- `TaskCompletionState` +- `SerializedTask` +- `TaskEventType` +- `SerializedTaskEvent` +- `TaskBrokerDispatchResult` +- `TaskBrokerDispatchOptions` +- `TaskContext` +- `TaskBroker` diff --git a/.changeset/little-peas-decide.md b/.changeset/little-peas-decide.md new file mode 100644 index 0000000000..3eb3d0cf9d --- /dev/null +++ b/.changeset/little-peas-decide.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-node': patch +--- + +Added several new types that were moved from `@backstage/plugin-scaffolder-backend`. diff --git a/plugins/scaffolder-backend/src/lib/templating/SecureTemplater.ts b/plugins/scaffolder-backend/src/lib/templating/SecureTemplater.ts index 488604e981..701863c7f6 100644 --- a/plugins/scaffolder-backend/src/lib/templating/SecureTemplater.ts +++ b/plugins/scaffolder-backend/src/lib/templating/SecureTemplater.ts @@ -16,6 +16,10 @@ import { Isolate } from 'isolated-vm'; import { resolvePackagePath } from '@backstage/backend-common'; +import { + TemplateFilter as _TemplateFilter, + TemplateGlobal as _TemplateGlobal, +} from '@backstage/plugin-scaffolder-node'; import fs from 'fs-extra'; import { JsonValue } from '@backstage/types'; @@ -86,13 +90,17 @@ const { render, renderCompat } = (() => { })(); `; -/** @public */ -export type TemplateFilter = (...args: JsonValue[]) => JsonValue | undefined; +/** + * @public + * @deprecated Import from `@backstage/plugin-scaffolder-node` instead. + */ +export type TemplateFilter = _TemplateFilter; -/** @public */ -export type TemplateGlobal = - | ((...args: JsonValue[]) => JsonValue | undefined) - | JsonValue; +/** + * @public + * @deprecated Import from `@backstage/plugin-scaffolder-node` instead. + */ +export type TemplateGlobal = _TemplateGlobal; export interface SecureTemplaterOptions { /* Enables jinja compatibility and the "jsonify" filter */ diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/types.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/types.ts index 112276b9dd..1d925e5610 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/types.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/types.ts @@ -14,131 +14,94 @@ * limitations under the License. */ -import { JsonValue, JsonObject, Observable } from '@backstage/types'; +import { JsonValue, JsonObject } from '@backstage/types'; import { TaskSpec, TaskStep } from '@backstage/plugin-scaffolder-common'; import { TaskSecrets } from '@backstage/plugin-scaffolder-node'; -import { TemplateAction } from '@backstage/plugin-scaffolder-node'; +import { + TemplateAction, + TaskStatus as _TaskStatus, + TaskCompletionState as _TaskCompletionState, + SerializedTask as _SerializedTask, + TaskEventType as _TaskEventType, + SerializedTaskEvent as _SerializedTaskEvent, + TaskBrokerDispatchResult as _TaskBrokerDispatchResult, + TaskBrokerDispatchOptions as _TaskBrokerDispatchOptions, + TaskContext as _TaskContext, + TaskBroker as _TaskBroker, +} from '@backstage/plugin-scaffolder-node'; /** * The status of each step of the Task * * @public + * @deprecated Import from `@backstage/plugin-scaffolder-node` instead. */ -export type TaskStatus = - | 'cancelled' - | 'completed' - | 'failed' - | 'open' - | 'processing'; +export type TaskStatus = _TaskStatus; /** * The state of a completed task. * * @public + * @deprecated Import from `@backstage/plugin-scaffolder-node` instead. */ -export type TaskCompletionState = 'failed' | 'completed'; +export type TaskCompletionState = _TaskCompletionState; /** * SerializedTask * * @public + * @deprecated Import from `@backstage/plugin-scaffolder-node` instead. */ -export type SerializedTask = { - id: string; - spec: TaskSpec; - status: TaskStatus; - createdAt: string; - lastHeartbeatAt?: string; - createdBy?: string; - secrets?: TaskSecrets; -}; +export type SerializedTask = _SerializedTask; /** * TaskEventType * * @public + * @deprecated Import from `@backstage/plugin-scaffolder-node` instead. */ -export type TaskEventType = 'completion' | 'log' | 'cancelled'; +export type TaskEventType = _TaskEventType; /** * SerializedTaskEvent * * @public + * @deprecated Import from `@backstage/plugin-scaffolder-node` instead. */ -export type SerializedTaskEvent = { - id: number; - taskId: string; - body: JsonObject; - type: TaskEventType; - createdAt: string; -}; +export type SerializedTaskEvent = _SerializedTaskEvent; /** * The result of {@link TaskBroker.dispatch} * * @public + * @deprecated Import from `@backstage/plugin-scaffolder-node` instead. */ -export type TaskBrokerDispatchResult = { - taskId: string; -}; +export type TaskBrokerDispatchResult = _TaskBrokerDispatchResult; /** * The options passed to {@link TaskBroker.dispatch} * Currently a spec and optional secrets * * @public + * @deprecated Import from `@backstage/plugin-scaffolder-node` instead. */ -export type TaskBrokerDispatchOptions = { - spec: TaskSpec; - secrets?: TaskSecrets; - createdBy?: string; -}; +export type TaskBrokerDispatchOptions = _TaskBrokerDispatchOptions; /** * Task * * @public + * @deprecated Import from `@backstage/plugin-scaffolder-node` instead. */ -export interface TaskContext { - cancelSignal: AbortSignal; - spec: TaskSpec; - secrets?: TaskSecrets; - createdBy?: string; - done: boolean; - isDryRun?: boolean; - - complete(result: TaskCompletionState, metadata?: JsonObject): Promise; - - emitLog(message: string, logMetadata?: JsonObject): Promise; - - getWorkspaceName(): Promise; -} +export type TaskContext = _TaskContext; /** * TaskBroker * * @public + * @deprecated Import from `@backstage/plugin-scaffolder-node` instead. */ -export interface TaskBroker { - cancel?(taskId: string): Promise; - - claim(): Promise; - - dispatch( - options: TaskBrokerDispatchOptions, - ): Promise; - - vacuumTasks(options: { timeoutS: number }): Promise; - - event$(options: { - taskId: string; - after: number | undefined; - }): Observable<{ events: SerializedTaskEvent[] }>; - - get(taskId: string): Promise; - - list?(options?: { createdBy?: string }): Promise<{ tasks: SerializedTask[] }>; -} +export type TaskBroker = _TaskBroker; /** * TaskStoreEmitOptions diff --git a/plugins/scaffolder-node/src/index.ts b/plugins/scaffolder-node/src/index.ts index 2a7c06234e..5bf556232e 100644 --- a/plugins/scaffolder-node/src/index.ts +++ b/plugins/scaffolder-node/src/index.ts @@ -22,6 +22,7 @@ export * from './actions'; export * from './tasks'; +export type { TemplateFilter, TemplateGlobal } from './types'; export { scaffolderActionsExtensionPoint, type ScaffolderActionsExtensionPoint, diff --git a/plugins/scaffolder-node/src/tasks/index.ts b/plugins/scaffolder-node/src/tasks/index.ts index 0c1d0d813e..930de95237 100644 --- a/plugins/scaffolder-node/src/tasks/index.ts +++ b/plugins/scaffolder-node/src/tasks/index.ts @@ -14,4 +14,15 @@ * limitations under the License. */ -export { type TaskSecrets } from './types'; +export type { + TaskSecrets, + SerializedTask, + SerializedTaskEvent, + TaskBroker, + TaskBrokerDispatchOptions, + TaskBrokerDispatchResult, + TaskCompletionState, + TaskContext, + TaskEventType, + TaskStatus, +} from './types'; diff --git a/plugins/scaffolder-node/src/tasks/types.ts b/plugins/scaffolder-node/src/tasks/types.ts index c17b3cbde3..8c9cc29e31 100644 --- a/plugins/scaffolder-node/src/tasks/types.ts +++ b/plugins/scaffolder-node/src/tasks/types.ts @@ -14,6 +14,9 @@ * limitations under the License. */ +import { TaskSpec } from '@backstage/plugin-scaffolder-common'; +import { JsonObject, Observable } from '@backstage/types'; + /** * TaskSecrets * @@ -22,3 +25,124 @@ export type TaskSecrets = Record & { backstageToken?: string; }; + +/** + * The status of each step of the Task + * + * @public + */ +export type TaskStatus = + | 'cancelled' + | 'completed' + | 'failed' + | 'open' + | 'processing'; + +/** + * The state of a completed task. + * + * @public + */ +export type TaskCompletionState = 'failed' | 'completed'; + +/** + * SerializedTask + * + * @public + */ +export type SerializedTask = { + id: string; + spec: TaskSpec; + status: TaskStatus; + createdAt: string; + lastHeartbeatAt?: string; + createdBy?: string; + secrets?: TaskSecrets; +}; + +/** + * TaskEventType + * + * @public + */ +export type TaskEventType = 'completion' | 'log' | 'cancelled'; + +/** + * SerializedTaskEvent + * + * @public + */ +export type SerializedTaskEvent = { + id: number; + taskId: string; + body: JsonObject; + type: TaskEventType; + createdAt: string; +}; + +/** + * The result of {@link TaskBroker.dispatch} + * + * @public + */ +export type TaskBrokerDispatchResult = { + taskId: string; +}; + +/** + * The options passed to {@link TaskBroker.dispatch} + * Currently a spec and optional secrets + * + * @public + */ +export type TaskBrokerDispatchOptions = { + spec: TaskSpec; + secrets?: TaskSecrets; + createdBy?: string; +}; + +/** + * Task + * + * @public + */ +export interface TaskContext { + cancelSignal: AbortSignal; + spec: TaskSpec; + secrets?: TaskSecrets; + createdBy?: string; + done: boolean; + isDryRun?: boolean; + + complete(result: TaskCompletionState, metadata?: JsonObject): Promise; + + emitLog(message: string, logMetadata?: JsonObject): Promise; + + getWorkspaceName(): Promise; +} + +/** + * TaskBroker + * + * @public + */ +export interface TaskBroker { + cancel?(taskId: string): Promise; + + claim(): Promise; + + dispatch( + options: TaskBrokerDispatchOptions, + ): Promise; + + vacuumTasks(options: { timeoutS: number }): Promise; + + event$(options: { + taskId: string; + after: number | undefined; + }): Observable<{ events: SerializedTaskEvent[] }>; + + get(taskId: string): Promise; + + list?(options?: { createdBy?: string }): Promise<{ tasks: SerializedTask[] }>; +} diff --git a/plugins/scaffolder-node/src/types.ts b/plugins/scaffolder-node/src/types.ts new file mode 100644 index 0000000000..bae106c84e --- /dev/null +++ b/plugins/scaffolder-node/src/types.ts @@ -0,0 +1,25 @@ +/* + * 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 { JsonValue } from '@backstage/types'; + +/** @public */ +export type TemplateFilter = (...args: JsonValue[]) => JsonValue | undefined; + +/** @public */ +export type TemplateGlobal = + | ((...args: JsonValue[]) => JsonValue | undefined) + | JsonValue; From 88bc6e27a213fd8ecb24d91ad809864ac6dfb29e Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 15 Aug 2023 16:11:05 +0200 Subject: [PATCH 4/7] scaffolder-backend: make concurrentTasksLimit configurable via static config Signed-off-by: Patrik Oldsberg --- .changeset/metal-eagles-invite.md | 5 +++ plugins/scaffolder-backend/config.d.ts | 9 ++++++ .../scaffolder-backend/src/service/router.ts | 32 +++++++++++-------- 3 files changed, 32 insertions(+), 14 deletions(-) create mode 100644 .changeset/metal-eagles-invite.md diff --git a/.changeset/metal-eagles-invite.md b/.changeset/metal-eagles-invite.md new file mode 100644 index 0000000000..6c41c6017d --- /dev/null +++ b/.changeset/metal-eagles-invite.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +The `concurrentTasksLimit` option can now be configured via static configuration as well. Setting it to 0 will now also disable the task worker. diff --git a/plugins/scaffolder-backend/config.d.ts b/plugins/scaffolder-backend/config.d.ts index 7883284165..60ccd52257 100644 --- a/plugins/scaffolder-backend/config.d.ts +++ b/plugins/scaffolder-backend/config.d.ts @@ -28,5 +28,14 @@ export interface Config { * The commit message used when new components are created. */ defaultCommitMessage?: string; + + /** + * Sets the number of concurrent tasks that can be run at any given time on the TaskWorker. + * + * Defaults to 10. + * + * Set to 0 to disable task workers altogether. + */ + concurrentTasksLimit?: number; }; } diff --git a/plugins/scaffolder-backend/src/service/router.ts b/plugins/scaffolder-backend/src/service/router.ts index 1771067367..15f7c11eba 100644 --- a/plugins/scaffolder-backend/src/service/router.ts +++ b/plugins/scaffolder-backend/src/service/router.ts @@ -231,13 +231,15 @@ export async function createRouter( catalogClient, actions, taskWorkers, - concurrentTasksLimit, scheduler, additionalTemplateFilters, additionalTemplateGlobals, permissions, permissionRules, } = options; + const concurrentTasksLimit = + options.concurrentTasksLimit ?? + options.config.getOptionalNumber('scaffolder.concurrentTasksLimit'); const logger = parentLogger.child({ plugin: 'scaffolder' }); @@ -275,19 +277,21 @@ export async function createRouter( const actionRegistry = new TemplateActionRegistry(); const workers = []; - for (let i = 0; i < (taskWorkers || 1); i++) { - const worker = await TaskWorker.create({ - taskBroker, - actionRegistry, - integrations, - logger, - workingDirectory, - additionalTemplateFilters, - additionalTemplateGlobals, - concurrentTasksLimit, - permissions, - }); - workers.push(worker); + if (concurrentTasksLimit !== 0) { + for (let i = 0; i < (taskWorkers || 1); i++) { + const worker = await TaskWorker.create({ + taskBroker, + actionRegistry, + integrations, + logger, + workingDirectory, + additionalTemplateFilters, + additionalTemplateGlobals, + concurrentTasksLimit, + permissions, + }); + workers.push(worker); + } } const actionsToRegister = Array.isArray(actions) From 349611126ae2efe5ea6b4be05ae9b8bf3a7a41c3 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 15 Aug 2023 16:14:20 +0200 Subject: [PATCH 5/7] scaffolder-backend: removed alpha options Signed-off-by: Patrik Oldsberg --- .changeset/cold-carpets-invent.md | 5 + .changeset/mean-shoes-return.md | 5 + .../src/ScaffolderPlugin.ts | 182 ++++++++---------- plugins/scaffolder-backend/src/alpha.ts | 1 - plugins/scaffolder-node/src/extensions.ts | 46 ++++- plugins/scaffolder-node/src/index.ts | 4 + 6 files changed, 142 insertions(+), 101 deletions(-) create mode 100644 .changeset/cold-carpets-invent.md create mode 100644 .changeset/mean-shoes-return.md diff --git a/.changeset/cold-carpets-invent.md b/.changeset/cold-carpets-invent.md new file mode 100644 index 0000000000..f30c60131d --- /dev/null +++ b/.changeset/cold-carpets-invent.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +Removed the options from the alpha `scaffolderPlugin` export. To extend the scaffolder plugin you instead now use the available extension points, `scaffolderActionsExtensionPoint`, `scaffolderTaskBrokerExtensionPoint`, and `scaffolderTemplatingExtensionPoint`. diff --git a/.changeset/mean-shoes-return.md b/.changeset/mean-shoes-return.md new file mode 100644 index 0000000000..29973a6cbd --- /dev/null +++ b/.changeset/mean-shoes-return.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-node': patch +--- + +Added two new alpha extension points, `scaffolderTaskBrokerExtensionPoint` and `scaffolderTemplatingExtensionPoint`. diff --git a/plugins/scaffolder-backend/src/ScaffolderPlugin.ts b/plugins/scaffolder-backend/src/ScaffolderPlugin.ts index f361bfcdf9..98bd4a1d66 100644 --- a/plugins/scaffolder-backend/src/ScaffolderPlugin.ts +++ b/plugins/scaffolder-backend/src/ScaffolderPlugin.ts @@ -23,120 +23,104 @@ import { ScmIntegrations } from '@backstage/integration'; import { catalogServiceRef } from '@backstage/plugin-catalog-node/alpha'; import { scaffolderActionsExtensionPoint, - ScaffolderActionsExtensionPoint, + scaffolderTaskBrokerExtensionPoint, + scaffolderTemplatingExtensionPoint, + TaskBroker, TemplateAction, -} from '@backstage/plugin-scaffolder-node'; -import { TemplateFilter, TemplateGlobal, - TaskBroker, -} from '@backstage/plugin-scaffolder-backend'; +} from '@backstage/plugin-scaffolder-node'; import { createBuiltinActions } from './scaffolder'; import { createRouter } from './service/router'; /** - * Catalog plugin options + * Scaffolder plugin * * @alpha */ -export type ScaffolderPluginOptions = { - actions?: TemplateAction[]; - taskWorkers?: number; - taskBroker?: TaskBroker; - additionalTemplateFilters?: Record; - additionalTemplateGlobals?: Record; -}; +export const scaffolderPlugin = createBackendPlugin({ + pluginId: 'scaffolder', + register(env) { + const addedActions = new Array>(); + env.registerExtensionPoint(scaffolderActionsExtensionPoint, { + addActions(...newActions: TemplateAction[]) { + addedActions.push(...newActions); + }, + }); -class ScaffolderActionsExtensionPointImpl - implements ScaffolderActionsExtensionPoint -{ - #actions = new Array>(); + let taskBroker: TaskBroker | undefined; + env.registerExtensionPoint(scaffolderTaskBrokerExtensionPoint, { + setTaskBroker(newTaskBroker) { + if (taskBroker) { + throw new Error('Task broker may only be set once'); + } + taskBroker = newTaskBroker; + }, + }); - addActions(...actions: TemplateAction[]): void { - this.#actions.push(...actions); - } + const additionalTemplateFilters: Record = {}; + const additionalTemplateGlobals: Record = {}; + env.registerExtensionPoint(scaffolderTemplatingExtensionPoint, { + addTemplateFilters(newFilters) { + Object.assign(additionalTemplateFilters, newFilters); + }, + addTemplateGlobals(newGlobals) { + Object.assign(additionalTemplateGlobals, newGlobals); + }, + }); - get actions() { - return this.#actions; - } -} + env.registerInit({ + deps: { + logger: coreServices.logger, + config: coreServices.rootConfig, + reader: coreServices.urlReader, + permissions: coreServices.permissions, + database: coreServices.database, + httpRouter: coreServices.httpRouter, + catalogClient: catalogServiceRef, + }, + async init({ + logger, + config, + reader, + database, + httpRouter, + catalogClient, + permissions, + }) { + const log = loggerToWinstonLogger(logger); -/** - * Catalog plugin - * - * @alpha - */ -export const scaffolderPlugin = createBackendPlugin( - (options?: ScaffolderPluginOptions) => ({ - pluginId: 'scaffolder', - register(env) { - const actionsExtensions = new ScaffolderActionsExtensionPointImpl(); - - env.registerExtensionPoint( - scaffolderActionsExtensionPoint, - actionsExtensions, - ); - - env.registerInit({ - deps: { - logger: coreServices.logger, - config: coreServices.rootConfig, - reader: coreServices.urlReader, - permissions: coreServices.permissions, - database: coreServices.database, - httpRouter: coreServices.httpRouter, - catalogClient: catalogServiceRef, - }, - async init({ - logger, - config, - reader, - database, - httpRouter, - catalogClient, - permissions, - }) { - const { - additionalTemplateFilters, - taskBroker, - taskWorkers, - additionalTemplateGlobals, - } = options ?? {}; - const log = loggerToWinstonLogger(logger); - - const actions = options?.actions || [ - ...actionsExtensions.actions, - ...createBuiltinActions({ - integrations: ScmIntegrations.fromConfig(config), - catalogClient, - reader, - config, - additionalTemplateFilters, - additionalTemplateGlobals, - }), - ]; - - const actionIds = actions.map(action => action.id).join(', '); - log.info( - `Starting scaffolder with the following actions enabled ${actionIds}`, - ); - - const router = await createRouter({ - logger: log, - config, - database, + const actions = [ + ...addedActions, + ...createBuiltinActions({ + integrations: ScmIntegrations.fromConfig(config), catalogClient, reader, - actions, - taskBroker, - taskWorkers, + config, additionalTemplateFilters, additionalTemplateGlobals, - permissions, - }); - httpRouter.use(router); - }, - }); - }, - }), -); + }), + ]; + + const actionIds = actions.map(action => action.id).join(', '); + log.info( + `Starting scaffolder with the following actions enabled ${actionIds}`, + ); + + const router = await createRouter({ + logger: log, + config, + database, + catalogClient, + reader, + actions, + taskBroker, + additionalTemplateFilters, + additionalTemplateGlobals, + permissions, + }); + httpRouter.use(router); + }, + }); + }, +}); diff --git a/plugins/scaffolder-backend/src/alpha.ts b/plugins/scaffolder-backend/src/alpha.ts index 713f2569aa..e1b4bc1067 100644 --- a/plugins/scaffolder-backend/src/alpha.ts +++ b/plugins/scaffolder-backend/src/alpha.ts @@ -17,4 +17,3 @@ export * from './modules'; export * from './service'; export { scaffolderPlugin } from './ScaffolderPlugin'; -export type { ScaffolderPluginOptions } from './ScaffolderPlugin'; diff --git a/plugins/scaffolder-node/src/extensions.ts b/plugins/scaffolder-node/src/extensions.ts index 1ae51ce2e6..b85da5b590 100644 --- a/plugins/scaffolder-node/src/extensions.ts +++ b/plugins/scaffolder-node/src/extensions.ts @@ -15,7 +15,12 @@ */ import { createExtensionPoint } from '@backstage/backend-plugin-api'; -import { TemplateAction } from './actions'; +import { + TemplateAction, + TemplateFilter, + TemplateGlobal, + TaskBroker, +} from '@backstage/plugin-scaffolder-node'; /** * Extension point for managing scaffolder actions. @@ -35,3 +40,42 @@ export const scaffolderActionsExtensionPoint = createExtensionPoint({ id: 'scaffolder.actions', }); + +/** + * Extension point for replacing the scaffolder task broker. + * + * @alpha + */ +export interface ScaffolderTaskBrokerExtensionPoint { + setTaskBroker(taskBroker: TaskBroker): void; +} + +/** + * Extension point for replacing the scaffolder task broker. + * + * @alpha + */ +export const scaffolderTaskBrokerExtensionPoint = + createExtensionPoint({ + id: 'scaffolder.taskBroker', + }); + +/** + * Extension point for adding template filters and globals. + * + * @alpha + */ +export interface ScaffolderTemplatingExtensionPoint { + addTemplateFilters(filters: Record): void; + addTemplateGlobals(filters: Record): void; +} + +/** + * Extension point for adding template filters and globals. + * + * @alpha + */ +export const scaffolderTemplatingExtensionPoint = + createExtensionPoint({ + id: 'scaffolder.templating', + }); diff --git a/plugins/scaffolder-node/src/index.ts b/plugins/scaffolder-node/src/index.ts index 5bf556232e..dcce065108 100644 --- a/plugins/scaffolder-node/src/index.ts +++ b/plugins/scaffolder-node/src/index.ts @@ -26,4 +26,8 @@ export type { TemplateFilter, TemplateGlobal } from './types'; export { scaffolderActionsExtensionPoint, type ScaffolderActionsExtensionPoint, + scaffolderTaskBrokerExtensionPoint, + type ScaffolderTaskBrokerExtensionPoint, + scaffolderTemplatingExtensionPoint, + type ScaffolderTemplatingExtensionPoint, } from './extensions'; From 6565eeb2d4904093fefc2ada0672d1b99a1ee9c9 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 15 Aug 2023 16:39:13 +0200 Subject: [PATCH 6/7] scaffolder-{backend,node}: update API reports + fixes Signed-off-by: Patrik Oldsberg --- .../scaffolder-backend/alpha-api-report.md | 17 +-- plugins/scaffolder-backend/api-report.md | 124 +++++------------ .../src/scaffolder/tasks/types.ts | 4 +- plugins/scaffolder-node/api-report.md | 129 +++++++++++++++++- 4 files changed, 164 insertions(+), 110 deletions(-) diff --git a/plugins/scaffolder-backend/alpha-api-report.md b/plugins/scaffolder-backend/alpha-api-report.md index 363fcafd17..c1758f9b17 100644 --- a/plugins/scaffolder-backend/alpha-api-report.md +++ b/plugins/scaffolder-backend/alpha-api-report.md @@ -12,11 +12,7 @@ import { PermissionCriteria } from '@backstage/plugin-permission-common'; import { PermissionRule } from '@backstage/plugin-permission-node'; import { PermissionRuleParams } from '@backstage/plugin-permission-common'; import { ResourcePermission } from '@backstage/plugin-permission-common'; -import { TaskBroker } from '@backstage/plugin-scaffolder-backend'; -import { TemplateAction } from '@backstage/plugin-scaffolder-node'; import { TemplateEntityStepV1beta3 } from '@backstage/plugin-scaffolder-common'; -import { TemplateFilter } from '@backstage/plugin-scaffolder-backend'; -import { TemplateGlobal } from '@backstage/plugin-scaffolder-backend'; import { TemplateParametersV1beta3 } from '@backstage/plugin-scaffolder-common'; // @alpha @@ -90,18 +86,7 @@ export const scaffolderActionConditions: Conditions<{ }>; // @alpha -export const scaffolderPlugin: ( - options?: ScaffolderPluginOptions | undefined, -) => BackendFeature; - -// @alpha -export type ScaffolderPluginOptions = { - actions?: TemplateAction[]; - taskWorkers?: number; - taskBroker?: TaskBroker; - additionalTemplateFilters?: Record; - additionalTemplateGlobals?: Record; -}; +export const scaffolderPlugin: () => BackendFeature; // @alpha export const scaffolderTemplateConditions: Conditions<{ diff --git a/plugins/scaffolder-backend/api-report.md b/plugins/scaffolder-backend/api-report.md index 4fe961056f..7fe4964827 100644 --- a/plugins/scaffolder-backend/api-report.md +++ b/plugins/scaffolder-backend/api-report.md @@ -19,11 +19,9 @@ import { GithubCredentialsProvider } from '@backstage/integration'; import { HumanDuration } from '@backstage/types'; import { IdentityApi } from '@backstage/plugin-auth-node'; import { JsonObject } from '@backstage/types'; -import { JsonValue } from '@backstage/types'; import { Knex } from 'knex'; import { LocationSpec } from '@backstage/plugin-catalog-common'; import { Logger } from 'winston'; -import { Observable } from '@backstage/types'; import { Octokit } from 'octokit'; import { PermissionEvaluator } from '@backstage/plugin-permission-common'; import { PermissionRule } from '@backstage/plugin-permission-node'; @@ -35,12 +33,23 @@ import { RESOURCE_TYPE_SCAFFOLDER_TEMPLATE } from '@backstage/plugin-scaffolder- import { Schema } from 'jsonschema'; import { ScmIntegrationRegistry } from '@backstage/integration'; import { ScmIntegrations } from '@backstage/integration'; +import { SerializedTask as SerializedTask_2 } from '@backstage/plugin-scaffolder-node'; +import { SerializedTaskEvent as SerializedTaskEvent_2 } from '@backstage/plugin-scaffolder-node'; +import { TaskBroker as TaskBroker_2 } from '@backstage/plugin-scaffolder-node'; +import { TaskBrokerDispatchOptions as TaskBrokerDispatchOptions_2 } from '@backstage/plugin-scaffolder-node'; +import { TaskBrokerDispatchResult as TaskBrokerDispatchResult_2 } from '@backstage/plugin-scaffolder-node'; +import { TaskCompletionState as TaskCompletionState_2 } from '@backstage/plugin-scaffolder-node'; +import { TaskContext as TaskContext_2 } from '@backstage/plugin-scaffolder-node'; +import { TaskEventType as TaskEventType_2 } from '@backstage/plugin-scaffolder-node'; import { TaskSecrets as TaskSecrets_2 } from '@backstage/plugin-scaffolder-node'; import { TaskSpec } from '@backstage/plugin-scaffolder-common'; import { TaskSpecV1beta3 } from '@backstage/plugin-scaffolder-common'; +import { TaskStatus as TaskStatus_2 } from '@backstage/plugin-scaffolder-node'; import { TemplateAction as TemplateAction_2 } from '@backstage/plugin-scaffolder-node'; import { TemplateActionOptions } from '@backstage/plugin-scaffolder-node'; import { TemplateEntityStepV1beta3 } from '@backstage/plugin-scaffolder-common'; +import { TemplateFilter as TemplateFilter_2 } from '@backstage/plugin-scaffolder-node'; +import { TemplateGlobal as TemplateGlobal_2 } from '@backstage/plugin-scaffolder-node'; import { TemplateParametersV1beta3 } from '@backstage/plugin-scaffolder-common'; import { UrlReader } from '@backstage/backend-common'; import { ZodType } from 'zod'; @@ -886,89 +895,29 @@ export class ScaffolderEntitiesProcessor implements CatalogProcessor { validateEntityKind(entity: Entity): Promise; } -// @public -export type SerializedTask = { - id: string; - spec: TaskSpec; - status: TaskStatus; - createdAt: string; - lastHeartbeatAt?: string; - createdBy?: string; - secrets?: TaskSecrets_2; -}; +// @public @deprecated +export type SerializedTask = SerializedTask_2; -// @public -export type SerializedTaskEvent = { - id: number; - taskId: string; - body: JsonObject; - type: TaskEventType; - createdAt: string; -}; +// @public @deprecated +export type SerializedTaskEvent = SerializedTaskEvent_2; -// @public -export interface TaskBroker { - // (undocumented) - cancel?(taskId: string): Promise; - // (undocumented) - claim(): Promise; - // (undocumented) - dispatch( - options: TaskBrokerDispatchOptions, - ): Promise; - // (undocumented) - event$(options: { taskId: string; after: number | undefined }): Observable<{ - events: SerializedTaskEvent[]; - }>; - // (undocumented) - get(taskId: string): Promise; - // (undocumented) - list?(options?: { createdBy?: string }): Promise<{ - tasks: SerializedTask[]; - }>; - // (undocumented) - vacuumTasks(options: { timeoutS: number }): Promise; -} +// @public @deprecated +export type TaskBroker = TaskBroker_2; -// @public -export type TaskBrokerDispatchOptions = { - spec: TaskSpec; - secrets?: TaskSecrets_2; - createdBy?: string; -}; +// @public @deprecated +export type TaskBrokerDispatchOptions = TaskBrokerDispatchOptions_2; -// @public -export type TaskBrokerDispatchResult = { - taskId: string; -}; +// @public @deprecated +export type TaskBrokerDispatchResult = TaskBrokerDispatchResult_2; -// @public -export type TaskCompletionState = 'failed' | 'completed'; +// @public @deprecated +export type TaskCompletionState = TaskCompletionState_2; -// @public -export interface TaskContext { - // (undocumented) - cancelSignal: AbortSignal; - // (undocumented) - complete(result: TaskCompletionState, metadata?: JsonObject): Promise; - // (undocumented) - createdBy?: string; - // (undocumented) - done: boolean; - // (undocumented) - emitLog(message: string, logMetadata?: JsonObject): Promise; - // (undocumented) - getWorkspaceName(): Promise; - // (undocumented) - isDryRun?: boolean; - // (undocumented) - secrets?: TaskSecrets_2; - // (undocumented) - spec: TaskSpec; -} +// @public @deprecated +export type TaskContext = TaskContext_2; -// @public -export type TaskEventType = 'completion' | 'log' | 'cancelled'; +// @public @deprecated +export type TaskEventType = TaskEventType_2; // @public export class TaskManager implements TaskContext { @@ -1000,13 +949,8 @@ export class TaskManager implements TaskContext { // @public @deprecated (undocumented) export type TaskSecrets = TaskSecrets_2; -// @public -export type TaskStatus = - | 'cancelled' - | 'completed' - | 'failed' - | 'open' - | 'processing'; +// @public @deprecated +export type TaskStatus = TaskStatus_2; // @public export interface TaskStore { @@ -1103,13 +1047,11 @@ export class TemplateActionRegistry { register(action: TemplateAction_2): void; } -// @public (undocumented) -export type TemplateFilter = (...args: JsonValue[]) => JsonValue | undefined; +// @public @deprecated (undocumented) +export type TemplateFilter = TemplateFilter_2; -// @public (undocumented) -export type TemplateGlobal = - | ((...args: JsonValue[]) => JsonValue | undefined) - | JsonValue; +// @public @deprecated (undocumented) +export type TemplateGlobal = TemplateGlobal_2; // @public (undocumented) export type TemplatePermissionRuleInput< diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/types.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/types.ts index 1d925e5610..4560f27c0b 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/types.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/types.ts @@ -71,7 +71,7 @@ export type TaskEventType = _TaskEventType; export type SerializedTaskEvent = _SerializedTaskEvent; /** - * The result of {@link TaskBroker.dispatch} + * The result of `TaskBroker.dispatch`. * * @public * @deprecated Import from `@backstage/plugin-scaffolder-node` instead. @@ -79,7 +79,7 @@ export type SerializedTaskEvent = _SerializedTaskEvent; export type TaskBrokerDispatchResult = _TaskBrokerDispatchResult; /** - * The options passed to {@link TaskBroker.dispatch} + * The options passed to `TaskBroker.dispatch`. * Currently a spec and optional secrets * * @public diff --git a/plugins/scaffolder-node/api-report.md b/plugins/scaffolder-node/api-report.md index ec1b2df2fa..52ce3c8d13 100644 --- a/plugins/scaffolder-node/api-report.md +++ b/plugins/scaffolder-node/api-report.md @@ -7,10 +7,17 @@ import { ExtensionPoint } from '@backstage/backend-plugin-api'; import { JsonObject } from '@backstage/types'; +import { JsonValue } from '@backstage/types'; import { Logger } from 'winston'; +import { Observable } from '@backstage/types'; import { Schema } from 'jsonschema'; import { ScmIntegrations } from '@backstage/integration'; import { SpawnOptionsWithoutStdio } from 'child_process'; +import { TaskBroker as TaskBroker_2 } from '@backstage/plugin-scaffolder-node'; +import { TaskSpec } from '@backstage/plugin-scaffolder-common'; +import { TemplateAction as TemplateAction_2 } from '@backstage/plugin-scaffolder-node'; +import { TemplateFilter as TemplateFilter_2 } from '@backstage/plugin-scaffolder-node'; +import { TemplateGlobal as TemplateGlobal_2 } from '@backstage/plugin-scaffolder-node'; import { TemplateInfo } from '@backstage/plugin-scaffolder-common'; import { UrlReader } from '@backstage/backend-common'; import { UserEntity } from '@backstage/catalog-model'; @@ -105,17 +112,129 @@ export function fetchFile(options: { // @alpha export interface ScaffolderActionsExtensionPoint { // (undocumented) - addActions(...actions: TemplateAction[]): void; + addActions(...actions: TemplateAction_2[]): void; } // @alpha export const scaffolderActionsExtensionPoint: ExtensionPoint; +// @alpha +export interface ScaffolderTaskBrokerExtensionPoint { + // (undocumented) + setTaskBroker(taskBroker: TaskBroker_2): void; +} + +// @alpha +export const scaffolderTaskBrokerExtensionPoint: ExtensionPoint; + +// @alpha +export interface ScaffolderTemplatingExtensionPoint { + // (undocumented) + addTemplateFilters(filters: Record): void; + // (undocumented) + addTemplateGlobals(filters: Record): void; +} + +// @alpha +export const scaffolderTemplatingExtensionPoint: ExtensionPoint; + +// @public +export type SerializedTask = { + id: string; + spec: TaskSpec; + status: TaskStatus; + createdAt: string; + lastHeartbeatAt?: string; + createdBy?: string; + secrets?: TaskSecrets; +}; + +// @public +export type SerializedTaskEvent = { + id: number; + taskId: string; + body: JsonObject; + type: TaskEventType; + createdAt: string; +}; + +// @public +export interface TaskBroker { + // (undocumented) + cancel?(taskId: string): Promise; + // (undocumented) + claim(): Promise; + // (undocumented) + dispatch( + options: TaskBrokerDispatchOptions, + ): Promise; + // (undocumented) + event$(options: { taskId: string; after: number | undefined }): Observable<{ + events: SerializedTaskEvent[]; + }>; + // (undocumented) + get(taskId: string): Promise; + // (undocumented) + list?(options?: { createdBy?: string }): Promise<{ + tasks: SerializedTask[]; + }>; + // (undocumented) + vacuumTasks(options: { timeoutS: number }): Promise; +} + +// @public +export type TaskBrokerDispatchOptions = { + spec: TaskSpec; + secrets?: TaskSecrets; + createdBy?: string; +}; + +// @public +export type TaskBrokerDispatchResult = { + taskId: string; +}; + +// @public +export type TaskCompletionState = 'failed' | 'completed'; + +// @public +export interface TaskContext { + // (undocumented) + cancelSignal: AbortSignal; + // (undocumented) + complete(result: TaskCompletionState, metadata?: JsonObject): Promise; + // (undocumented) + createdBy?: string; + // (undocumented) + done: boolean; + // (undocumented) + emitLog(message: string, logMetadata?: JsonObject): Promise; + // (undocumented) + getWorkspaceName(): Promise; + // (undocumented) + isDryRun?: boolean; + // (undocumented) + secrets?: TaskSecrets; + // (undocumented) + spec: TaskSpec; +} + +// @public +export type TaskEventType = 'completion' | 'log' | 'cancelled'; + // @public export type TaskSecrets = Record & { backstageToken?: string; }; +// @public +export type TaskStatus = + | 'cancelled' + | 'completed' + | 'failed' + | 'open' + | 'processing'; + // @public (undocumented) export type TemplateAction< TActionInput extends JsonObject = JsonObject, @@ -158,4 +277,12 @@ export type TemplateExample = { description: string; example: string; }; + +// @public (undocumented) +export type TemplateFilter = (...args: JsonValue[]) => JsonValue | undefined; + +// @public (undocumented) +export type TemplateGlobal = + | ((...args: JsonValue[]) => JsonValue | undefined) + | JsonValue; ``` From 239fff427f6ecb830f100de69321c14be5704f7d Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 15 Aug 2023 17:10:10 +0200 Subject: [PATCH 7/7] removed unnecessary changeset Signed-off-by: Patrik Oldsberg --- .changeset/weak-apes-flow.md | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 .changeset/weak-apes-flow.md diff --git a/.changeset/weak-apes-flow.md b/.changeset/weak-apes-flow.md deleted file mode 100644 index c5673d381a..0000000000 --- a/.changeset/weak-apes-flow.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-permission-backend': patch ---- - -Minor internal fix.