diff --git a/docs/features/techdocs/creating-and-publishing.md b/docs/features/techdocs/creating-and-publishing.md index 3fca490b6d..1251f67276 100644 --- a/docs/features/techdocs/creating-and-publishing.md +++ b/docs/features/techdocs/creating-and-publishing.md @@ -41,23 +41,6 @@ default, we highly recommend you to set that up. Follow our how-to guide [How to add documentation setup to your software templates](./how-to-guides.md#how-to-add-the-documentation-setup-to-your-software-templates) to get started. -### Use the documentation template - -There could be _some_ situations where you don't want to keep your docs close to -your code, but still want to publish documentation - for example, an onboarding -tutorial. For this use case, we have put together a documentation template. Your -Backstage instance should by default have a documentation template added. If -not, copy the catalog locations from the -[create-app template](https://github.com/backstage/backstage/blob/master/packages/create-app/templates/default-app/app-config.yaml.hbs) -to add the documentation template. The template creates a component with -**only** TechDocs configuration and default markdown files, and is otherwise -empty. - -![Documentation Template](../../assets/techdocs/documentation-template.png) - -Create an entity from the documentation template and you will get the needed -setup for free. - ### Enable documentation for an already existing entity Prerequisites: diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index 3b2029d997..24325449b3 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -57,7 +57,6 @@ "@backstage/plugin-auth-node": "workspace:^", "@backstage/plugin-catalog-backend-module-scaffolder-entity-model": "workspace:^", "@backstage/plugin-catalog-node": "workspace:^", - "@backstage/plugin-events-node": "workspace:^", "@backstage/plugin-permission-common": "workspace:^", "@backstage/plugin-permission-node": "workspace:^", "@backstage/plugin-scaffolder-backend-module-azure": "workspace:^", diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.ts index b7d7517c10..0ce4e38659 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.ts @@ -36,10 +36,11 @@ import { SerializedTask, TaskStatus, TaskEventType, + TaskSecrets, } from '@backstage/plugin-scaffolder-node'; import { DateTime, Duration } from 'luxon'; import { TaskRecovery, TaskSpec } from '@backstage/plugin-scaffolder-common'; -import { compactEvents } from './taskRecoveryHelper'; +import { trimEventsTillLastRecovery } from './taskRecoveryHelper'; const migrationsDir = resolvePackagePath( '@backstage/plugin-scaffolder-backend', @@ -131,6 +132,16 @@ export class DatabaseTaskStore implements TaskStore { } } + private parseTaskSecrets(taskRow: RawDbTaskRow): TaskSecrets | undefined { + try { + return taskRow.secrets ? JSON.parse(taskRow.secrets) : undefined; + } catch (error) { + throw new Error( + `Failed to parse secrets of task '${taskRow.id}', ${error}`, + ); + } + } + private static async getClient( database: PluginDatabaseManager | Knex, ): Promise { @@ -255,7 +266,7 @@ export class DatabaseTaskStore implements TaskStore { return undefined; } - const secrets = task.secrets ? JSON.parse(task.secrets) : undefined; + const secrets = this.parseTaskSecrets(task); return { id: task.id, spec, @@ -264,7 +275,7 @@ export class DatabaseTaskStore implements TaskStore { createdAt: task.created_at, createdBy: task.created_by ?? undefined, secrets, - } as SerializedTask; + }; }); } @@ -426,7 +437,7 @@ export class DatabaseTaskStore implements TaskStore { } }); - return compactEvents(events); + return trimEventsTillLastRecovery(events); } async shutdownTask(options: TaskStoreShutDownTaskOptions): Promise { @@ -480,7 +491,9 @@ export class DatabaseTaskStore implements TaskStore { }); } - async recoverTasks(options: TaskStoreRecoverTaskOptions): Promise { + async recoverTasks( + options: TaskStoreRecoverTaskOptions, + ): Promise<{ id: string }[]> { const taskIdsToRecover: string[] = []; const timeoutS = Duration.fromObject(options.timeout).as('seconds'); @@ -525,6 +538,6 @@ export class DatabaseTaskStore implements TaskStore { } }); - return taskIdsToRecover; + return taskIdsToRecover.map(id => ({ id })); } } diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts index e9c7740357..ce1ad71c33 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts @@ -418,7 +418,6 @@ export class NunjucksWorkflowRunner implements WorkflowRunner { const context: TemplateContext = { parameters: task.spec.parameters, - EXPERIMENTAL_recovery: task.spec.EXPERIMENTAL_recovery, steps: {}, user: task.spec.user, }; diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts index 5bd72d05a2..96300bec58 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts @@ -205,7 +205,7 @@ export class StorageTaskBroker implements TaskBroker { }); } - public async recoverTasks(): Promise { + public async recoverTasks(): Promise { const enabled = (this.config && this.config.getOptionalBoolean( @@ -214,21 +214,20 @@ export class StorageTaskBroker implements TaskBroker { false; if (enabled) { + const defaultTimeout = { seconds: 30 }; + const timeout = readDuration( + this.config, + 'scaffolder.EXPERIMENTAL_recoverTasksTimeout', + defaultTimeout, + ); const recoveredTaskIds = (await this.storage.recoverTasks?.({ - timeout: readDuration( - this.config, - 'scaffolder.EXPERIMENTAL_recoverTasksTimeout', - { - seconds: 30, - }, - ), + timeout, })) ?? []; - recoveredTaskIds.forEach(() => { + if (recoveredTaskIds.length > 0) { this.signalDispatch(); - }); + } } - return enabled; } /** diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/TaskWorker.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/TaskWorker.ts index 8111a28793..5e116922de 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/TaskWorker.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/TaskWorker.ts @@ -20,7 +20,7 @@ import { NunjucksWorkflowRunner } from './NunjucksWorkflowRunner'; import { Logger } from 'winston'; import { TemplateActionRegistry } from '../actions'; import { ScmIntegrations } from '@backstage/integration'; -import { assertError } from '@backstage/errors'; +import { assertError, stringifyError } from '@backstage/errors'; import { TemplateFilter, TemplateGlobal } from '../../lib'; import { PermissionEvaluator } from '@backstage/plugin-permission-common'; @@ -36,6 +36,7 @@ export type TaskWorkerOptions = { }; concurrentTasksLimit: number; permissions?: PermissionEvaluator; + logger?: Logger; }; /** @@ -74,8 +75,10 @@ export type CreateWorkerOptions = { */ export class TaskWorker { private taskQueue: PQueue; + private logger: Logger | undefined; private constructor(private readonly options: TaskWorkerOptions) { + this.logger = options.logger; this.taskQueue = new PQueue({ concurrency: options.concurrentTasksLimit, }); @@ -115,7 +118,8 @@ export class TaskWorker { async recoverTasks() { try { await this.options.taskBroker.recoverTasks?.(); - } catch (_err) { + } catch (err) { + this.logger?.error(stringifyError(err)); // ignore } } diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/taskRecoveryHelper.test.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/taskRecoveryHelper.test.ts index 9a1c012c70..8224feab8e 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/taskRecoveryHelper.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/taskRecoveryHelper.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { compactEvents } from './taskRecoveryHelper'; +import { trimEventsTillLastRecovery } from './taskRecoveryHelper'; import { SerializedTaskEvent } from './types'; const toLogEvent = (stepId: string) => @@ -41,7 +41,7 @@ describe('taskRecoveryHelper', () => { const events = [...logEvents, toRecoveredEvent('startOver')]; - expect(compactEvents(events)).toEqual({ events: [] }); + expect(trimEventsTillLastRecovery(events)).toEqual({ events: [] }); }); }); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/taskRecoveryHelper.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/taskRecoveryHelper.ts index 31b05c6924..f3b8b321fe 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/taskRecoveryHelper.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/taskRecoveryHelper.ts @@ -17,7 +17,7 @@ import { SerializedTaskEvent } from '@backstage/plugin-scaffolder-node'; import { TaskRecoverStrategy } from '@backstage/plugin-scaffolder-common'; -export const compactEvents = ( +export const trimEventsTillLastRecovery = ( events: SerializedTaskEvent[], ): { events: SerializedTaskEvent[] } => { const recoveredEventInd = events diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/types.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/types.ts index d113e23c5b..85c5b6f69e 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/types.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/types.ts @@ -170,7 +170,9 @@ export interface TaskStore { options: TaskStoreCreateTaskOptions, ): Promise; - recoverTasks?(options: TaskStoreRecoverTaskOptions): Promise; + recoverTasks?( + options: TaskStoreRecoverTaskOptions, + ): Promise<{ id: string }[]>; getTask(taskId: string): Promise; diff --git a/plugins/scaffolder-node/src/tasks/types.ts b/plugins/scaffolder-node/src/tasks/types.ts index 12e6416749..7cdc044bdf 100644 --- a/plugins/scaffolder-node/src/tasks/types.ts +++ b/plugins/scaffolder-node/src/tasks/types.ts @@ -131,7 +131,7 @@ export interface TaskBroker { claim(): Promise; - recoverTasks?(): Promise; + recoverTasks?(): Promise; dispatch( options: TaskBrokerDispatchOptions, diff --git a/yarn.lock b/yarn.lock index 2fee1c1d2c..4992eb3807 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8190,7 +8190,6 @@ __metadata: "@backstage/plugin-auth-node": "workspace:^" "@backstage/plugin-catalog-backend-module-scaffolder-entity-model": "workspace:^" "@backstage/plugin-catalog-node": "workspace:^" - "@backstage/plugin-events-node": "workspace:^" "@backstage/plugin-permission-common": "workspace:^" "@backstage/plugin-permission-node": "workspace:^" "@backstage/plugin-scaffolder-backend-module-azure": "workspace:^"