incorporated some of feedback

Signed-off-by: bnechyporenko <bnechyporenko@bol.com>
This commit is contained in:
bnechyporenko
2024-01-20 15:49:32 +01:00
parent 49268c38da
commit e5a3599819
11 changed files with 42 additions and 44 deletions
@@ -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:
-1
View File
@@ -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:^",
@@ -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<Knex> {
@@ -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<void> {
@@ -480,7 +491,9 @@ export class DatabaseTaskStore implements TaskStore {
});
}
async recoverTasks(options: TaskStoreRecoverTaskOptions): Promise<string[]> {
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 }));
}
}
@@ -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,
};
@@ -205,7 +205,7 @@ export class StorageTaskBroker implements TaskBroker {
});
}
public async recoverTasks(): Promise<boolean> {
public async recoverTasks(): Promise<void> {
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;
}
/**
@@ -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
}
}
@@ -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: [] });
});
});
});
@@ -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
@@ -170,7 +170,9 @@ export interface TaskStore {
options: TaskStoreCreateTaskOptions,
): Promise<TaskStoreCreateTaskResult>;
recoverTasks?(options: TaskStoreRecoverTaskOptions): Promise<string[]>;
recoverTasks?(
options: TaskStoreRecoverTaskOptions,
): Promise<{ id: string }[]>;
getTask(taskId: string): Promise<SerializedTask>;
+1 -1
View File
@@ -131,7 +131,7 @@ export interface TaskBroker {
claim(): Promise<TaskContext>;
recoverTasks?(): Promise<boolean>;
recoverTasks?(): Promise<void>;
dispatch(
options: TaskBrokerDispatchOptions,
-1
View File
@@ -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:^"