diff --git a/package.json b/package.json index afc86f2460..e224d1e58a 100644 --- a/package.json +++ b/package.json @@ -76,6 +76,7 @@ "@backstage/repo-tools": "workspace:*", "@changesets/cli": "^2.14.0", "@octokit/rest": "^19.0.3", + "@playwright/test": "^1.32.3", "@spotify/eslint-plugin": "^14.1.3", "@spotify/prettier-config": "^14.0.0", "@techdocs/cli": "workspace:*", diff --git a/plugins/scaffolder-backend/api-report.md b/plugins/scaffolder-backend/api-report.md index 4f005a0e28..f9a810ebea 100644 --- a/plugins/scaffolder-backend/api-report.md +++ b/plugins/scaffolder-backend/api-report.md @@ -360,17 +360,7 @@ export interface CurrentClaimedTask { createdBy?: string; secrets?: TaskSecrets_2; spec: TaskSpec; - state?: { - [key: string]: - | { - status: 'failed'; - reason: string; - } - | { - status: 'success'; - value: JsonValue; - }; - }; + state?: JsonObject; taskId: string; } @@ -411,15 +401,7 @@ export class DatabaseTaskStore implements TaskStore { // (undocumented) getTaskState({ taskId }: { taskId: string }): Promise< | { - [key: string]: - | { - status: 'failed'; - reason: string; - } - | { - status: 'success'; - value: JsonValue; - }; + state: JsonObject; } | undefined >; @@ -445,22 +427,7 @@ export class DatabaseTaskStore implements TaskStore { ids: string[]; }>; // (undocumented) - saveTaskState(options: { - taskId: string; - state?: - | { - [key: string]: - | { - status: 'failed'; - reason: string; - } - | { - status: 'success'; - value: JsonValue; - }; - } - | undefined; - }): Promise; + saveTaskState(options: { taskId: string; state?: JsonObject }): Promise; // (undocumented) shutdownTask(options: TaskStoreShutDownTaskOptions): Promise; } @@ -565,15 +532,7 @@ export class TaskManager implements TaskContext_2 { // (undocumented) getTaskState?(): Promise< | { - [key: string]: - | { - status: 'failed'; - reason: string; - } - | { - status: 'success'; - value: JsonValue; - }; + state?: JsonObject; } | undefined >; @@ -628,15 +587,7 @@ export interface TaskStore { // (undocumented) getTaskState?({ taskId }: { taskId: string }): Promise< | { - [key: string]: - | { - status: 'failed'; - reason: string; - } - | { - status: 'success'; - value: JsonValue; - }; + state: JsonObject; } | undefined >; @@ -663,17 +614,7 @@ export interface TaskStore { // (undocumented) saveTaskState?(options: { taskId: string; - state?: { - [key: string]: - | { - status: 'failed'; - reason: string; - } - | { - status: 'success'; - value: JsonValue; - }; - }; + state?: JsonObject; }): Promise; // (undocumented) shutdownTask?(options: TaskStoreShutDownTaskOptions): Promise; diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.test.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.test.ts index deb72fb7d2..8fda4b5090 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.test.ts @@ -209,9 +209,11 @@ describe('DatabaseTaskStore', () => { const state = await store.getTaskState({ taskId }); expect(state).toStrictEqual({ - 'repo.create': { - status: 'success', - value: { repoUrl: 'https://github.com/backstage/backstage.git' }, + state: { + 'repo.create': { + status: 'success', + value: { repoUrl: 'https://github.com/backstage/backstage.git' }, + }, }, }); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.ts index 263fe3d435..6422e53ee9 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { JsonObject, JsonValue } from '@backstage/types'; +import { JsonObject } from '@backstage/types'; import { PluginDatabaseManager, resolvePackagePath, @@ -397,42 +397,19 @@ export class DatabaseTaskStore implements TaskStore { async getTaskState({ taskId }: { taskId: string }): Promise< | { - [key: string]: - | { status: 'failed'; reason: string } - | { - status: 'success'; - value: JsonValue; - }; + state: JsonObject; } | undefined > { const [result] = await this.db('tasks') .where({ id: taskId }) .select('state'); - return result.state - ? (JSON.parse(result.state) as unknown as { - [key: string]: - | { status: 'failed'; reason: string } - | { - status: 'success'; - value: JsonValue; - }; - }) - : undefined; + return result.state ? { state: JSON.parse(result.state) } : undefined; } async saveTaskState(options: { taskId: string; - state?: - | { - [key: string]: - | { status: 'failed'; reason: string } - | { - status: 'success'; - value: JsonValue; - }; - } - | undefined; + state?: JsonObject; }): Promise { if (options.state) { const serializedState = JSON.stringify(options.state); diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts index 8018812c07..eaf477f35f 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts @@ -580,23 +580,27 @@ describe('NunjucksWorkflowRunner', () => { }), getTaskState: (): Promise< | { - [key: string]: - | { status: 'failed'; reason: string } - | { - status: 'success'; - value: JsonValue; - }; + state: { + [key: string]: + | { status: 'failed'; reason: string } + | { + status: 'success'; + value: JsonValue; + }; + }; } | undefined > => { return Promise.resolve({ - ['v1.task.checkpoint.key1']: { - status: 'success', - value: 'initial', - }, - ['v1.task.checkpoint.key2']: { - status: 'failed', - reason: 'fatal error', + state: { + ['v1.task.checkpoint.key1']: { + status: 'success', + value: 'initial', + }, + ['v1.task.checkpoint.key2']: { + status: 'failed', + reason: 'fatal error', + }, }, }); }, diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts index 1070972112..e3bf094009 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts @@ -79,6 +79,18 @@ type TemplateContext = { each?: JsonValue; }; +type TaskState = { + [key: string]: + | { + status: 'failed'; + reason: string; + } + | { + status: 'success'; + value: JsonValue; + }; +}; + const isValidTaskSpec = (taskSpec: TaskSpec): taskSpec is TaskSpecV1beta3 => { return taskSpec.apiVersion === 'scaffolder.backstage.io/v1beta3'; }; @@ -356,7 +368,7 @@ export class NunjucksWorkflowRunner implements WorkflowRunner { try { let prevValue: U | undefined; if (prevTaskState) { - const prevState = prevTaskState[key]; + const prevState = (prevTaskState.state as TaskState)?.[key]; if (prevState && prevState.status === 'success') { prevValue = prevState.value as U; } diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts index 2287279ea9..c437795778 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts @@ -93,12 +93,7 @@ export class TaskManager implements TaskContext { async getTaskState?(): Promise< | { - [key: string]: - | { status: 'failed'; reason: string } - | { - status: 'success'; - value: JsonValue; - }; + state?: JsonObject; } | undefined > { @@ -186,14 +181,7 @@ export interface CurrentClaimedTask { /** * The state of checkpoints of the task. */ - state?: { - [key: string]: - | { status: 'failed'; reason: string } - | { - status: 'success'; - value: JsonValue; - }; - }; + state?: JsonObject; /** * The creator of the task. */ diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/types.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/types.ts index d0bb48f4f2..c0854af391 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/types.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/types.ts @@ -196,26 +196,14 @@ export interface TaskStore { getTaskState?({ taskId }: { taskId: string }): Promise< | { - [key: string]: - | { status: 'failed'; reason: string } - | { - status: 'success'; - value: JsonValue; - }; + state: JsonObject; } | undefined >; saveTaskState?(options: { taskId: string; - state?: { - [key: string]: - | { status: 'failed'; reason: string } - | { - status: 'success'; - value: JsonValue; - }; - }; + state?: JsonObject; }): Promise; listEvents( diff --git a/plugins/scaffolder-node/api-report.md b/plugins/scaffolder-node/api-report.md index 7c024a0043..3f2e4e369f 100644 --- a/plugins/scaffolder-node/api-report.md +++ b/plugins/scaffolder-node/api-report.md @@ -351,15 +351,7 @@ export interface TaskContext { // (undocumented) getTaskState?(): Promise< | { - [key: string]: - | { - status: 'failed'; - reason: string; - } - | { - status: 'success'; - value: JsonValue; - }; + state?: JsonObject; } | undefined >; diff --git a/plugins/scaffolder-node/src/tasks/types.ts b/plugins/scaffolder-node/src/tasks/types.ts index 18383dbac3..0cca1a0ba2 100644 --- a/plugins/scaffolder-node/src/tasks/types.ts +++ b/plugins/scaffolder-node/src/tasks/types.ts @@ -128,12 +128,7 @@ export interface TaskContext { getTaskState?(): Promise< | { - [key: string]: - | { status: 'failed'; reason: string } - | { - status: 'success'; - value: JsonValue; - }; + state?: JsonObject; } | undefined >; diff --git a/yarn.lock b/yarn.lock index cd5f483ddc..65a4a0a508 100644 --- a/yarn.lock +++ b/yarn.lock @@ -41210,6 +41210,7 @@ __metadata: "@changesets/cli": ^2.14.0 "@manypkg/get-packages": ^1.1.3 "@octokit/rest": ^19.0.3 + "@playwright/test": ^1.32.3 "@spotify/eslint-plugin": ^14.1.3 "@spotify/prettier-config": ^14.0.0 "@techdocs/cli": "workspace:*"