From fbd7c921b9b9e0ab4e514c269af1a3ac5b354719 Mon Sep 17 00:00:00 2001 From: Kurt King Date: Fri, 21 Mar 2025 22:11:08 -0600 Subject: [PATCH 1/8] improve type safety with new type structure Signed-off-by: Kurt King --- .../tasks/NunjucksWorkflowRunner.ts | 15 +-- .../src/scaffolder/tasks/StorageTaskBroker.ts | 106 +++++++++++++----- 2 files changed, 78 insertions(+), 43 deletions(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts index 7802a7ab8d..444d6efe9b 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts @@ -60,6 +60,7 @@ import { scaffolderActionRules } from '../../service/rules'; import { createCounterMetric, createHistogramMetric } from '../../util/metrics'; import { BackstageLoggerTransport, WinstonLogger } from './logger'; import { convertFiltersToRecord } from '../../util/templating'; +import { CheckpointState } from './StorageTaskBroker'; type NunjucksWorkflowRunnerOptions = { workingDirectory: string; @@ -91,16 +92,6 @@ type TemplateContext = { }; }; -type CheckpointState = - | { - status: 'failed'; - reason: string; - } - | { - status: 'success'; - value: JsonValue; - }; - const isValidTaskSpec = (taskSpec: TaskSpec): taskSpec is TaskSpecV1beta3 => { return taskSpec.apiVersion === 'scaffolder.backstage.io/v1beta3'; }; @@ -396,9 +387,7 @@ export class NunjucksWorkflowRunner implements WorkflowRunner { if (prevTaskState) { const prevState = ( - prevTaskState.state?.checkpoints as { - [key: string]: CheckpointState; - } + prevTaskState.state?.checkpoints as CheckpointState )?.[key]; if (prevState && prevState.status === 'success') { diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts index 86f9f7fcf7..a92d4134f5 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts @@ -44,19 +44,30 @@ import { DefaultWorkspaceService, WorkspaceService } from './WorkspaceService'; import { readDuration } from './helper'; import { InternalTaskSecrets, TaskStore } from './types'; -type TaskState = { - checkpoints: { - [key: string]: - | { - status: 'failed'; - reason: string; - } - | { - status: 'success'; - value: JsonValue; - }; - }; +type CheckpointStatus = 'failed' | 'success'; + +export type CheckpointSuccessState = { + status: Extract; + value: JsonValue; }; + +export type CheckpointFailedState = { + status: Extract; + reason: string; +}; + +export type CheckpointState = { + [key: string]: CheckpointSuccessState | CheckpointFailedState; +}; + +export type UpdateCheckpointOptions = { + key: string; +} & CheckpointState[keyof CheckpointState]; + +type TaskState = { + checkpoints: CheckpointState; +}; + /** * TaskManager * @deprecated this type is deprecated, and there will be a new way to create Workers in the next major version. @@ -152,25 +163,57 @@ export class TaskManager implements TaskContext { return this.storage.getTaskState?.({ taskId: this.task.taskId }); } - async updateCheckpoint?( - options: - | { - key: string; - status: 'success'; - value: JsonValue; - } - | { - key: string; - status: 'failed'; - reason: string; - }, - ): Promise { - const { key, ...value } = options; - if (this.task.state) { - (this.task.state as TaskState).checkpoints[key] = value; - } else { - this.task.state = { checkpoints: { [key]: value } }; + /** + * Helper to safely access the checkpoints field from task state + * Ensures type safety when working with task state that might not match our structure + */ + private getCheckpointsFromState(state?: JsonObject): CheckpointState { + if ( + state && + 'checkpoints' in state && + typeof state.checkpoints === 'object' + ) { + return state.checkpoints as CheckpointState; } + return {}; + } + + async updateCheckpoint?(options: UpdateCheckpointOptions): Promise { + const { key, status } = options; + + // Extract appropriate state value based on status + let checkpointValue: CheckpointSuccessState | CheckpointFailedState; + + switch (status) { + case 'success': { + const { value } = options; + checkpointValue = { status, value }; + break; + } + case 'failed': { + const { reason } = options; + checkpointValue = { status, reason }; + break; + } + default: { + // Using status as 'never' gives compile-time guarantee we've handled all cases + const exhaustiveCheck: never = status; + throw new Error(`Unexpected status: ${exhaustiveCheck}`); + } + } + + if (this.task.state) { + const taskState: TaskState = { + checkpoints: this.getCheckpointsFromState(this.task.state), + }; + + // Update with the new checkpoint + taskState.checkpoints[key] = checkpointValue; + this.task.state = taskState; + } else { + this.task.state = { checkpoints: { [key]: checkpointValue } }; + } + await this.storage.saveTaskState?.({ taskId: this.task.taskId, state: this.task.state, @@ -254,6 +297,9 @@ export interface CurrentClaimedTask { secrets?: TaskSecrets; /** * The state of checkpoints of the task. + * This will be a JsonObject that may contain a `checkpoints` field + * with a structure matching the CheckpointState interface. + * @see CheckpointState */ state?: JsonObject; /** From 919a61667310f9d9d9100658742e758e65913fc1 Mon Sep 17 00:00:00 2001 From: Kurt King Date: Fri, 21 Mar 2025 22:22:42 -0600 Subject: [PATCH 2/8] move types to node package Signed-off-by: Kurt King --- .../tasks/NunjucksWorkflowRunner.ts | 2 +- .../src/scaffolder/tasks/StorageTaskBroker.ts | 33 ++------ plugins/scaffolder-node/src/actions/types.ts | 9 ++- .../scaffolder-node/src/checkpoints/index.ts | 17 ++++ .../scaffolder-node/src/checkpoints/types.ts | 78 +++++++++++++++++++ plugins/scaffolder-node/src/index.ts | 1 + plugins/scaffolder-node/src/tasks/types.ts | 17 +--- 7 files changed, 112 insertions(+), 45 deletions(-) create mode 100644 plugins/scaffolder-node/src/checkpoints/index.ts create mode 100644 plugins/scaffolder-node/src/checkpoints/types.ts diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts index 444d6efe9b..d97bf10543 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts @@ -60,7 +60,7 @@ import { scaffolderActionRules } from '../../service/rules'; import { createCounterMetric, createHistogramMetric } from '../../util/metrics'; import { BackstageLoggerTransport, WinstonLogger } from './logger'; import { convertFiltersToRecord } from '../../util/templating'; -import { CheckpointState } from './StorageTaskBroker'; +import { CheckpointState } from '@backstage/plugin-scaffolder-node'; type NunjucksWorkflowRunnerOptions = { workingDirectory: string; diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts index a92d4134f5..9a872e7b3f 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts @@ -33,36 +33,17 @@ import { TaskStatus, } from '@backstage/plugin-scaffolder-node'; import { WorkspaceProvider } from '@backstage/plugin-scaffolder-node/alpha'; -import { - JsonObject, - JsonValue, - Observable, - createDeferred, -} from '@backstage/types'; +import { JsonObject, Observable, createDeferred } from '@backstage/types'; import ObservableImpl from 'zen-observable'; import { DefaultWorkspaceService, WorkspaceService } from './WorkspaceService'; import { readDuration } from './helper'; import { InternalTaskSecrets, TaskStore } from './types'; - -type CheckpointStatus = 'failed' | 'success'; - -export type CheckpointSuccessState = { - status: Extract; - value: JsonValue; -}; - -export type CheckpointFailedState = { - status: Extract; - reason: string; -}; - -export type CheckpointState = { - [key: string]: CheckpointSuccessState | CheckpointFailedState; -}; - -export type UpdateCheckpointOptions = { - key: string; -} & CheckpointState[keyof CheckpointState]; +import { + CheckpointState, + CheckpointSuccessState, + CheckpointFailedState, + UpdateCheckpointOptions, +} from '@backstage/plugin-scaffolder-node'; type TaskState = { checkpoints: CheckpointState; diff --git a/plugins/scaffolder-node/src/actions/types.ts b/plugins/scaffolder-node/src/actions/types.ts index f13d256332..e7e678450d 100644 --- a/plugins/scaffolder-node/src/actions/types.ts +++ b/plugins/scaffolder-node/src/actions/types.ts @@ -23,6 +23,8 @@ import { BackstageCredentials, LoggerService, } from '@backstage/backend-plugin-api'; +import { CheckpointOptions } from '../checkpoints'; + /** * ActionContext is passed into scaffolder actions. * @public @@ -36,10 +38,9 @@ export type ActionContext< secrets?: TaskSecrets; workspacePath: string; input: TActionInput; - checkpoint(opts: { - key: string; - fn: () => Promise | T; - }): Promise; + checkpoint( + opts: CheckpointOptions, + ): Promise; output( name: keyof TActionOutput, value: TActionOutput[keyof TActionOutput], diff --git a/plugins/scaffolder-node/src/checkpoints/index.ts b/plugins/scaffolder-node/src/checkpoints/index.ts new file mode 100644 index 0000000000..5d542de408 --- /dev/null +++ b/plugins/scaffolder-node/src/checkpoints/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2024 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 * from './types'; diff --git a/plugins/scaffolder-node/src/checkpoints/types.ts b/plugins/scaffolder-node/src/checkpoints/types.ts new file mode 100644 index 0000000000..eac3213075 --- /dev/null +++ b/plugins/scaffolder-node/src/checkpoints/types.ts @@ -0,0 +1,78 @@ +/* + * Copyright 2024 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'; + +/** + * The status of a checkpoint, indicating whether it succeeded or failed. + * + * @public + */ +export type CheckpointStatus = 'failed' | 'success'; + +/** + * Represents a successful checkpoint state with a value. + * + * @public + */ +export type CheckpointSuccessState = { + status: Extract; + value: JsonValue; +}; + +/** + * Represents a failed checkpoint state with a reason for failure. + * + * @public + */ +export type CheckpointFailedState = { + status: Extract; + reason: string; +}; + +/** + * A map of checkpoint keys to their states. + * + * @public + */ +export type CheckpointState = { + [key: string]: CheckpointSuccessState | CheckpointFailedState; +}; + +/** + * Options for updating a checkpoint in a task. + * + * @public + */ +export type UpdateCheckpointOptions = { + key: string; +} & CheckpointState[keyof CheckpointState]; + +/** + * Options for checkpoint function invocation. + * + * @public + */ +export type CheckpointOptions = { + /** + * Unique key for the checkpoint + */ + key: string; + /** + * Function to execute for the checkpoint + */ + fn: () => Promise | T; +}; diff --git a/plugins/scaffolder-node/src/index.ts b/plugins/scaffolder-node/src/index.ts index 5d49ee874c..d44f0e9c50 100644 --- a/plugins/scaffolder-node/src/index.ts +++ b/plugins/scaffolder-node/src/index.ts @@ -24,3 +24,4 @@ export * from './actions'; export * from './tasks'; export * from './files'; export * from './types'; +export * from './checkpoints'; diff --git a/plugins/scaffolder-node/src/tasks/types.ts b/plugins/scaffolder-node/src/tasks/types.ts index d8cfd24530..cc9023db8b 100644 --- a/plugins/scaffolder-node/src/tasks/types.ts +++ b/plugins/scaffolder-node/src/tasks/types.ts @@ -16,7 +16,8 @@ import { BackstageCredentials } from '@backstage/backend-plugin-api'; import { TaskSpec } from '@backstage/plugin-scaffolder-common'; -import { JsonObject, JsonValue, Observable } from '@backstage/types'; +import { JsonObject, Observable } from '@backstage/types'; +import { UpdateCheckpointOptions } from '../checkpoints'; /** * TaskSecrets @@ -129,19 +130,7 @@ export interface TaskContext { | undefined >; - updateCheckpoint?( - options: - | { - key: string; - status: 'success'; - value: JsonValue; - } - | { - key: string; - status: 'failed'; - reason: string; - }, - ): Promise; + updateCheckpoint?(options: UpdateCheckpointOptions): Promise; serializeWorkspace?(options: { path: string }): Promise; From 3fb5a07af291645adee0502b4d155784dd934703 Mon Sep 17 00:00:00 2001 From: Kurt King Date: Fri, 21 Mar 2025 22:42:27 -0600 Subject: [PATCH 3/8] use CheckpointOptions where possible Signed-off-by: Kurt King --- .../src/scaffolder/tasks/NunjucksWorkflowRunner.ts | 8 ++++---- .../src/actions/mockActionContext.ts | 12 +++++++----- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts index d97bf10543..d6a420e54a 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts @@ -50,6 +50,7 @@ import { import { createConditionAuthorizer } from '@backstage/plugin-permission-node'; import { actionExecutePermission } from '@backstage/plugin-scaffolder-common/alpha'; import { + CheckpointOptions, TaskContext, TemplateAction, TemplateFilter, @@ -375,10 +376,9 @@ export class NunjucksWorkflowRunner implements WorkflowRunner { secrets: task.secrets ?? {}, logger: taskLogger, workspacePath, - async checkpoint(opts: { - key?: string; - fn: () => Promise | T; - }) { + async checkpoint( + opts: CheckpointOptions, + ) { const { key: checkpointKey, fn } = opts; const key = `v1.task.checkpoint.${step.id}.${checkpointKey}`; diff --git a/plugins/scaffolder-node-test-utils/src/actions/mockActionContext.ts b/plugins/scaffolder-node-test-utils/src/actions/mockActionContext.ts index a6703a12d1..5f8844d13d 100644 --- a/plugins/scaffolder-node-test-utils/src/actions/mockActionContext.ts +++ b/plugins/scaffolder-node-test-utils/src/actions/mockActionContext.ts @@ -21,7 +21,10 @@ import { mockServices, } from '@backstage/backend-test-utils'; import { JsonObject, JsonValue } from '@backstage/types'; -import { ActionContext } from '@backstage/plugin-scaffolder-node'; +import { + ActionContext, + CheckpointOptions, +} from '@backstage/plugin-scaffolder-node'; import { loggerToWinstonLogger } from './loggerToWinstonLogger'; /** @@ -44,10 +47,9 @@ export function createMockActionContext< output: jest.fn(), createTemporaryDirectory: jest.fn(), input: {} as TActionInput, - async checkpoint(opts: { - key: string; - fn: () => Promise | T; - }): Promise { + async checkpoint( + opts: CheckpointOptions, + ): Promise { return opts.fn(); }, getInitiatorCredentials: () => Promise.resolve(credentials), From 70eae7fa1a784950dce885580fc88c0f836c22fd Mon Sep 17 00:00:00 2001 From: Kurt King Date: Fri, 21 Mar 2025 22:47:29 -0600 Subject: [PATCH 4/8] update api reports Signed-off-by: Kurt King --- plugins/scaffolder-backend/report.api.md | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/plugins/scaffolder-backend/report.api.md b/plugins/scaffolder-backend/report.api.md index 1f2a17a384..99be4a27f1 100644 --- a/plugins/scaffolder-backend/report.api.md +++ b/plugins/scaffolder-backend/report.api.md @@ -14,7 +14,6 @@ import { Duration } from 'luxon'; import { EventsService } from '@backstage/plugin-events-node'; import { HumanDuration } from '@backstage/types'; import { JsonObject } from '@backstage/types'; -import { JsonValue } from '@backstage/types'; import { Knex } from 'knex'; import { LoggerService } from '@backstage/backend-plugin-api'; import { PermissionEvaluator } from '@backstage/plugin-permission-common'; @@ -38,6 +37,7 @@ import { TemplateEntityStepV1beta3 } from '@backstage/plugin-scaffolder-common'; import { TemplateFilter } from '@backstage/plugin-scaffolder-node'; import { TemplateGlobal } from '@backstage/plugin-scaffolder-node'; import { TemplateParametersV1beta3 } from '@backstage/plugin-scaffolder-common'; +import { UpdateCheckpointOptions } from '@backstage/plugin-scaffolder-node'; import { UrlReaderService } from '@backstage/backend-plugin-api'; import { WorkspaceProvider } from '@backstage/plugin-scaffolder-node/alpha'; @@ -442,19 +442,7 @@ export class TaskManager implements TaskContext { // (undocumented) get spec(): TaskSpecV1beta3; // (undocumented) - updateCheckpoint?( - options: - | { - key: string; - status: 'success'; - value: JsonValue; - } - | { - key: string; - status: 'failed'; - reason: string; - }, - ): Promise; + updateCheckpoint?(options: UpdateCheckpointOptions): Promise; } // @public @deprecated From dbde1805b60f704955dbdd78ecd128a7c7f71e56 Mon Sep 17 00:00:00 2001 From: Kurt King Date: Mon, 24 Mar 2025 19:41:31 -0600 Subject: [PATCH 5/8] clean up types some Signed-off-by: Kurt King --- .changeset/petite-paths-remain.md | 7 +++ plugins/scaffolder-backend/report.api.md | 4 +- .../tasks/NunjucksWorkflowRunner.ts | 4 +- .../src/scaffolder/tasks/StorageTaskBroker.ts | 63 ++----------------- .../src/actions/mockActionContext.ts | 4 +- plugins/scaffolder-node/src/actions/types.ts | 4 +- .../scaffolder-node/src/checkpoints/types.ts | 35 +++++------ plugins/scaffolder-node/src/tasks/index.ts | 1 + plugins/scaffolder-node/src/tasks/types.ts | 13 +++- 9 files changed, 50 insertions(+), 85 deletions(-) create mode 100644 .changeset/petite-paths-remain.md diff --git a/.changeset/petite-paths-remain.md b/.changeset/petite-paths-remain.md new file mode 100644 index 0000000000..a2bef50c80 --- /dev/null +++ b/.changeset/petite-paths-remain.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-scaffolder-node-test-utils': patch +'@backstage/plugin-scaffolder-backend': patch +'@backstage/plugin-scaffolder-node': patch +--- + +An internal refactor which adds additional types to experimental checkpoints diff --git a/plugins/scaffolder-backend/report.api.md b/plugins/scaffolder-backend/report.api.md index 99be4a27f1..3823db15d6 100644 --- a/plugins/scaffolder-backend/report.api.md +++ b/plugins/scaffolder-backend/report.api.md @@ -37,7 +37,7 @@ import { TemplateEntityStepV1beta3 } from '@backstage/plugin-scaffolder-common'; import { TemplateFilter } from '@backstage/plugin-scaffolder-node'; import { TemplateGlobal } from '@backstage/plugin-scaffolder-node'; import { TemplateParametersV1beta3 } from '@backstage/plugin-scaffolder-common'; -import { UpdateCheckpointOptions } from '@backstage/plugin-scaffolder-node'; +import { UpdateTaskCheckpointOptions } from '@backstage/plugin-scaffolder-node'; import { UrlReaderService } from '@backstage/backend-plugin-api'; import { WorkspaceProvider } from '@backstage/plugin-scaffolder-node/alpha'; @@ -442,7 +442,7 @@ export class TaskManager implements TaskContext { // (undocumented) get spec(): TaskSpecV1beta3; // (undocumented) - updateCheckpoint?(options: UpdateCheckpointOptions): Promise; + updateCheckpoint?(options: UpdateTaskCheckpointOptions): Promise; } // @public @deprecated diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts index d6a420e54a..adc5152e4f 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts @@ -50,7 +50,7 @@ import { import { createConditionAuthorizer } from '@backstage/plugin-permission-node'; import { actionExecutePermission } from '@backstage/plugin-scaffolder-common/alpha'; import { - CheckpointOptions, + CheckpointContext, TaskContext, TemplateAction, TemplateFilter, @@ -377,7 +377,7 @@ export class NunjucksWorkflowRunner implements WorkflowRunner { logger: taskLogger, workspacePath, async checkpoint( - opts: CheckpointOptions, + opts: CheckpointContext, ) { const { key: checkpointKey, fn } = opts; const key = `v1.task.checkpoint.${step.id}.${checkpointKey}`; diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts index 9a872e7b3f..5e90a11d83 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts @@ -23,6 +23,7 @@ import { import { Config } from '@backstage/config'; import { TaskSpec } from '@backstage/plugin-scaffolder-common'; import { + CheckpointState, SerializedTask, SerializedTaskEvent, TaskBroker, @@ -31,6 +32,7 @@ import { TaskContext, TaskSecrets, TaskStatus, + UpdateTaskCheckpointOptions, } from '@backstage/plugin-scaffolder-node'; import { WorkspaceProvider } from '@backstage/plugin-scaffolder-node/alpha'; import { JsonObject, Observable, createDeferred } from '@backstage/types'; @@ -38,17 +40,10 @@ import ObservableImpl from 'zen-observable'; import { DefaultWorkspaceService, WorkspaceService } from './WorkspaceService'; import { readDuration } from './helper'; import { InternalTaskSecrets, TaskStore } from './types'; -import { - CheckpointState, - CheckpointSuccessState, - CheckpointFailedState, - UpdateCheckpointOptions, -} from '@backstage/plugin-scaffolder-node'; type TaskState = { checkpoints: CheckpointState; }; - /** * TaskManager * @deprecated this type is deprecated, and there will be a new way to create Workers in the next major version. @@ -144,57 +139,14 @@ export class TaskManager implements TaskContext { return this.storage.getTaskState?.({ taskId: this.task.taskId }); } - /** - * Helper to safely access the checkpoints field from task state - * Ensures type safety when working with task state that might not match our structure - */ - private getCheckpointsFromState(state?: JsonObject): CheckpointState { - if ( - state && - 'checkpoints' in state && - typeof state.checkpoints === 'object' - ) { - return state.checkpoints as CheckpointState; - } - return {}; - } - - async updateCheckpoint?(options: UpdateCheckpointOptions): Promise { - const { key, status } = options; - - // Extract appropriate state value based on status - let checkpointValue: CheckpointSuccessState | CheckpointFailedState; - - switch (status) { - case 'success': { - const { value } = options; - checkpointValue = { status, value }; - break; - } - case 'failed': { - const { reason } = options; - checkpointValue = { status, reason }; - break; - } - default: { - // Using status as 'never' gives compile-time guarantee we've handled all cases - const exhaustiveCheck: never = status; - throw new Error(`Unexpected status: ${exhaustiveCheck}`); - } - } + async updateCheckpoint?(options: UpdateTaskCheckpointOptions): Promise { + const { key, ...value } = options; if (this.task.state) { - const taskState: TaskState = { - checkpoints: this.getCheckpointsFromState(this.task.state), - }; - - // Update with the new checkpoint - taskState.checkpoints[key] = checkpointValue; - this.task.state = taskState; + (this.task.state as TaskState).checkpoints[key] = value; } else { - this.task.state = { checkpoints: { [key]: checkpointValue } }; + this.task.state = { checkpoints: { [key]: value } }; } - await this.storage.saveTaskState?.({ taskId: this.task.taskId, state: this.task.state, @@ -278,9 +230,6 @@ export interface CurrentClaimedTask { secrets?: TaskSecrets; /** * The state of checkpoints of the task. - * This will be a JsonObject that may contain a `checkpoints` field - * with a structure matching the CheckpointState interface. - * @see CheckpointState */ state?: JsonObject; /** diff --git a/plugins/scaffolder-node-test-utils/src/actions/mockActionContext.ts b/plugins/scaffolder-node-test-utils/src/actions/mockActionContext.ts index 5f8844d13d..d364d4dc1e 100644 --- a/plugins/scaffolder-node-test-utils/src/actions/mockActionContext.ts +++ b/plugins/scaffolder-node-test-utils/src/actions/mockActionContext.ts @@ -23,7 +23,7 @@ import { import { JsonObject, JsonValue } from '@backstage/types'; import { ActionContext, - CheckpointOptions, + CheckpointContext, } from '@backstage/plugin-scaffolder-node'; import { loggerToWinstonLogger } from './loggerToWinstonLogger'; @@ -48,7 +48,7 @@ export function createMockActionContext< createTemporaryDirectory: jest.fn(), input: {} as TActionInput, async checkpoint( - opts: CheckpointOptions, + opts: CheckpointContext, ): Promise { return opts.fn(); }, diff --git a/plugins/scaffolder-node/src/actions/types.ts b/plugins/scaffolder-node/src/actions/types.ts index e7e678450d..8104470dd8 100644 --- a/plugins/scaffolder-node/src/actions/types.ts +++ b/plugins/scaffolder-node/src/actions/types.ts @@ -23,7 +23,7 @@ import { BackstageCredentials, LoggerService, } from '@backstage/backend-plugin-api'; -import { CheckpointOptions } from '../checkpoints'; +import { CheckpointContext } from '../checkpoints'; /** * ActionContext is passed into scaffolder actions. @@ -39,7 +39,7 @@ export type ActionContext< workspacePath: string; input: TActionInput; checkpoint( - opts: CheckpointOptions, + opts: CheckpointContext, ): Promise; output( name: keyof TActionOutput, diff --git a/plugins/scaffolder-node/src/checkpoints/types.ts b/plugins/scaffolder-node/src/checkpoints/types.ts index eac3213075..eecf769f5a 100644 --- a/plugins/scaffolder-node/src/checkpoints/types.ts +++ b/plugins/scaffolder-node/src/checkpoints/types.ts @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Backstage Authors + * Copyright 2025 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. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - import { JsonValue } from '@backstage/types'; /** @@ -28,9 +27,9 @@ export type CheckpointStatus = 'failed' | 'success'; * * @public */ -export type CheckpointSuccessState = { - status: Extract; - value: JsonValue; +export type CheckpointSuccessState = { + status: 'success'; + value: T; }; /** @@ -39,34 +38,34 @@ export type CheckpointSuccessState = { * @public */ export type CheckpointFailedState = { - status: Extract; + status: 'failed'; reason: string; }; +/** + * Represents the union of all possible checkpoint state values. + * + * @public + */ +export type CheckpointStateValue = + | CheckpointSuccessState + | CheckpointFailedState; + /** * A map of checkpoint keys to their states. * * @public */ export type CheckpointState = { - [key: string]: CheckpointSuccessState | CheckpointFailedState; + [key: string]: CheckpointStateValue; }; /** - * Options for updating a checkpoint in a task. + * Context for checkpoint function invocation. * * @public */ -export type UpdateCheckpointOptions = { - key: string; -} & CheckpointState[keyof CheckpointState]; - -/** - * Options for checkpoint function invocation. - * - * @public - */ -export type CheckpointOptions = { +export type CheckpointContext = { /** * Unique key for the checkpoint */ diff --git a/plugins/scaffolder-node/src/tasks/index.ts b/plugins/scaffolder-node/src/tasks/index.ts index 930de95237..e047131d2b 100644 --- a/plugins/scaffolder-node/src/tasks/index.ts +++ b/plugins/scaffolder-node/src/tasks/index.ts @@ -25,4 +25,5 @@ export type { TaskContext, TaskEventType, TaskStatus, + UpdateTaskCheckpointOptions, } from './types'; diff --git a/plugins/scaffolder-node/src/tasks/types.ts b/plugins/scaffolder-node/src/tasks/types.ts index cc9023db8b..e3b64fea15 100644 --- a/plugins/scaffolder-node/src/tasks/types.ts +++ b/plugins/scaffolder-node/src/tasks/types.ts @@ -17,7 +17,7 @@ import { BackstageCredentials } from '@backstage/backend-plugin-api'; import { TaskSpec } from '@backstage/plugin-scaffolder-common'; import { JsonObject, Observable } from '@backstage/types'; -import { UpdateCheckpointOptions } from '../checkpoints'; +import { CheckpointStateValue } from '../checkpoints'; /** * TaskSecrets @@ -105,6 +105,15 @@ export type TaskBrokerDispatchOptions = { createdBy?: string; }; +/** + * Options for updating a checkpoint in a task. + * + * @public + */ +export type UpdateTaskCheckpointOptions = { + key: string; +} & CheckpointStateValue; + /** * Task * @@ -130,7 +139,7 @@ export interface TaskContext { | undefined >; - updateCheckpoint?(options: UpdateCheckpointOptions): Promise; + updateCheckpoint?(options: UpdateTaskCheckpointOptions): Promise; serializeWorkspace?(options: { path: string }): Promise; From 04106ae76e554fe7f4bae047860c260a10ab1540 Mon Sep 17 00:00:00 2001 From: Kurt King Date: Sat, 10 May 2025 12:07:47 -0600 Subject: [PATCH 6/8] refactor to alpha exports Signed-off-by: Kurt King --- .../src/scaffolder/tasks/NunjucksWorkflowRunner.ts | 6 ++++-- .../src/scaffolder/tasks/StorageTaskBroker.ts | 8 +++++--- .../src/actions/mockActionContext.ts | 6 ++---- plugins/scaffolder-node/src/actions/types.ts | 2 +- .../src/{ => alpha}/checkpoints/index.ts | 3 +-- .../src/{ => alpha}/checkpoints/types.ts | 12 ++++++------ plugins/scaffolder-node/src/alpha/index.ts | 1 + plugins/scaffolder-node/src/index.ts | 1 - plugins/scaffolder-node/src/tasks/alpha.ts | 11 +++++++++++ plugins/scaffolder-node/src/tasks/index.ts | 2 +- plugins/scaffolder-node/src/tasks/types.ts | 11 +---------- 11 files changed, 33 insertions(+), 30 deletions(-) rename plugins/scaffolder-node/src/{ => alpha}/checkpoints/index.ts (93%) rename plugins/scaffolder-node/src/{ => alpha}/checkpoints/types.ts (96%) diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts index adc5152e4f..1542db8438 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts @@ -50,7 +50,6 @@ import { import { createConditionAuthorizer } from '@backstage/plugin-permission-node'; import { actionExecutePermission } from '@backstage/plugin-scaffolder-common/alpha'; import { - CheckpointContext, TaskContext, TemplateAction, TemplateFilter, @@ -61,7 +60,10 @@ import { scaffolderActionRules } from '../../service/rules'; import { createCounterMetric, createHistogramMetric } from '../../util/metrics'; import { BackstageLoggerTransport, WinstonLogger } from './logger'; import { convertFiltersToRecord } from '../../util/templating'; -import { CheckpointState } from '@backstage/plugin-scaffolder-node'; +import { + CheckpointState, + CheckpointContext, +} from '@backstage/plugin-scaffolder-node/alpha'; type NunjucksWorkflowRunnerOptions = { workingDirectory: string; diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts index 5e90a11d83..c88a1f687c 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts @@ -23,7 +23,6 @@ import { import { Config } from '@backstage/config'; import { TaskSpec } from '@backstage/plugin-scaffolder-common'; import { - CheckpointState, SerializedTask, SerializedTaskEvent, TaskBroker, @@ -32,9 +31,12 @@ import { TaskContext, TaskSecrets, TaskStatus, - UpdateTaskCheckpointOptions, } from '@backstage/plugin-scaffolder-node'; -import { WorkspaceProvider } from '@backstage/plugin-scaffolder-node/alpha'; +import { + CheckpointState, + WorkspaceProvider, + UpdateTaskCheckpointOptions, +} from '@backstage/plugin-scaffolder-node/alpha'; import { JsonObject, Observable, createDeferred } from '@backstage/types'; import ObservableImpl from 'zen-observable'; import { DefaultWorkspaceService, WorkspaceService } from './WorkspaceService'; diff --git a/plugins/scaffolder-node-test-utils/src/actions/mockActionContext.ts b/plugins/scaffolder-node-test-utils/src/actions/mockActionContext.ts index d364d4dc1e..e2f07f2320 100644 --- a/plugins/scaffolder-node-test-utils/src/actions/mockActionContext.ts +++ b/plugins/scaffolder-node-test-utils/src/actions/mockActionContext.ts @@ -21,10 +21,8 @@ import { mockServices, } from '@backstage/backend-test-utils'; import { JsonObject, JsonValue } from '@backstage/types'; -import { - ActionContext, - CheckpointContext, -} from '@backstage/plugin-scaffolder-node'; +import { ActionContext } from '@backstage/plugin-scaffolder-node'; +import { CheckpointContext } from '@backstage/plugin-scaffolder-node/alpha'; import { loggerToWinstonLogger } from './loggerToWinstonLogger'; /** diff --git a/plugins/scaffolder-node/src/actions/types.ts b/plugins/scaffolder-node/src/actions/types.ts index 8104470dd8..32ab12657c 100644 --- a/plugins/scaffolder-node/src/actions/types.ts +++ b/plugins/scaffolder-node/src/actions/types.ts @@ -23,7 +23,7 @@ import { BackstageCredentials, LoggerService, } from '@backstage/backend-plugin-api'; -import { CheckpointContext } from '../checkpoints'; +import { CheckpointContext } from '../alpha'; /** * ActionContext is passed into scaffolder actions. diff --git a/plugins/scaffolder-node/src/checkpoints/index.ts b/plugins/scaffolder-node/src/alpha/checkpoints/index.ts similarity index 93% rename from plugins/scaffolder-node/src/checkpoints/index.ts rename to plugins/scaffolder-node/src/alpha/checkpoints/index.ts index 5d542de408..16c936b235 100644 --- a/plugins/scaffolder-node/src/checkpoints/index.ts +++ b/plugins/scaffolder-node/src/alpha/checkpoints/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Backstage Authors + * Copyright 2025 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. @@ -13,5 +13,4 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - export * from './types'; diff --git a/plugins/scaffolder-node/src/checkpoints/types.ts b/plugins/scaffolder-node/src/alpha/checkpoints/types.ts similarity index 96% rename from plugins/scaffolder-node/src/checkpoints/types.ts rename to plugins/scaffolder-node/src/alpha/checkpoints/types.ts index eecf769f5a..45f1c03430 100644 --- a/plugins/scaffolder-node/src/checkpoints/types.ts +++ b/plugins/scaffolder-node/src/alpha/checkpoints/types.ts @@ -18,14 +18,14 @@ import { JsonValue } from '@backstage/types'; /** * The status of a checkpoint, indicating whether it succeeded or failed. * - * @public + * @alpha */ export type CheckpointStatus = 'failed' | 'success'; /** * Represents a successful checkpoint state with a value. * - * @public + * @alpha */ export type CheckpointSuccessState = { status: 'success'; @@ -35,7 +35,7 @@ export type CheckpointSuccessState = { /** * Represents a failed checkpoint state with a reason for failure. * - * @public + * @alpha */ export type CheckpointFailedState = { status: 'failed'; @@ -45,7 +45,7 @@ export type CheckpointFailedState = { /** * Represents the union of all possible checkpoint state values. * - * @public + * @alpha */ export type CheckpointStateValue = | CheckpointSuccessState @@ -54,7 +54,7 @@ export type CheckpointStateValue = /** * A map of checkpoint keys to their states. * - * @public + * @alpha */ export type CheckpointState = { [key: string]: CheckpointStateValue; @@ -63,7 +63,7 @@ export type CheckpointState = { /** * Context for checkpoint function invocation. * - * @public + * @alpha */ export type CheckpointContext = { /** diff --git a/plugins/scaffolder-node/src/alpha/index.ts b/plugins/scaffolder-node/src/alpha/index.ts index 9df968a52d..30f95f116a 100644 --- a/plugins/scaffolder-node/src/alpha/index.ts +++ b/plugins/scaffolder-node/src/alpha/index.ts @@ -28,6 +28,7 @@ export * from '../tasks/alpha'; export * from './filters'; export * from './globals'; export * from './types'; +export * from './checkpoints'; /** * Extension point for managing scaffolder actions. diff --git a/plugins/scaffolder-node/src/index.ts b/plugins/scaffolder-node/src/index.ts index d44f0e9c50..5d49ee874c 100644 --- a/plugins/scaffolder-node/src/index.ts +++ b/plugins/scaffolder-node/src/index.ts @@ -24,4 +24,3 @@ export * from './actions'; export * from './tasks'; export * from './files'; export * from './types'; -export * from './checkpoints'; diff --git a/plugins/scaffolder-node/src/tasks/alpha.ts b/plugins/scaffolder-node/src/tasks/alpha.ts index fb6b09026c..4354a798cf 100644 --- a/plugins/scaffolder-node/src/tasks/alpha.ts +++ b/plugins/scaffolder-node/src/tasks/alpha.ts @@ -1,3 +1,5 @@ +import { CheckpointStateValue } from '../alpha'; + /* * Copyright 2024 The Backstage Authors * @@ -14,3 +16,12 @@ * limitations under the License. */ export * from './serializer'; + +/** + * Options for updating a checkpoint in a task. + * + * @alpha + */ +export type UpdateTaskCheckpointOptions = { + key: string; +} & CheckpointStateValue; diff --git a/plugins/scaffolder-node/src/tasks/index.ts b/plugins/scaffolder-node/src/tasks/index.ts index e047131d2b..2ff31857f5 100644 --- a/plugins/scaffolder-node/src/tasks/index.ts +++ b/plugins/scaffolder-node/src/tasks/index.ts @@ -25,5 +25,5 @@ export type { TaskContext, TaskEventType, TaskStatus, - UpdateTaskCheckpointOptions, + // UpdateTaskCheckpointOptions, } from './types'; diff --git a/plugins/scaffolder-node/src/tasks/types.ts b/plugins/scaffolder-node/src/tasks/types.ts index e3b64fea15..5621aa117b 100644 --- a/plugins/scaffolder-node/src/tasks/types.ts +++ b/plugins/scaffolder-node/src/tasks/types.ts @@ -17,7 +17,7 @@ import { BackstageCredentials } from '@backstage/backend-plugin-api'; import { TaskSpec } from '@backstage/plugin-scaffolder-common'; import { JsonObject, Observable } from '@backstage/types'; -import { CheckpointStateValue } from '../checkpoints'; +import { UpdateTaskCheckpointOptions } from '../alpha'; /** * TaskSecrets @@ -105,15 +105,6 @@ export type TaskBrokerDispatchOptions = { createdBy?: string; }; -/** - * Options for updating a checkpoint in a task. - * - * @public - */ -export type UpdateTaskCheckpointOptions = { - key: string; -} & CheckpointStateValue; - /** * Task * From 77f713137e4c70a0a208df1173f9bb366eaf89db Mon Sep 17 00:00:00 2001 From: benjdlambert Date: Mon, 16 Jun 2025 11:41:51 +0200 Subject: [PATCH 7/8] chore: fixing issues with typescript Signed-off-by: benjdlambert --- plugins/scaffolder-backend/report.api.md | 2 +- plugins/scaffolder-node/report-alpha.api.md | 36 ++++++++++++++++++++ plugins/scaffolder-node/report.api.md | 23 ++++--------- plugins/scaffolder-node/src/actions/types.ts | 2 +- plugins/scaffolder-node/src/tasks/types.ts | 2 +- 5 files changed, 45 insertions(+), 20 deletions(-) diff --git a/plugins/scaffolder-backend/report.api.md b/plugins/scaffolder-backend/report.api.md index 3823db15d6..7ece0f84ea 100644 --- a/plugins/scaffolder-backend/report.api.md +++ b/plugins/scaffolder-backend/report.api.md @@ -37,7 +37,7 @@ import { TemplateEntityStepV1beta3 } from '@backstage/plugin-scaffolder-common'; import { TemplateFilter } from '@backstage/plugin-scaffolder-node'; import { TemplateGlobal } from '@backstage/plugin-scaffolder-node'; import { TemplateParametersV1beta3 } from '@backstage/plugin-scaffolder-common'; -import { UpdateTaskCheckpointOptions } from '@backstage/plugin-scaffolder-node'; +import { UpdateTaskCheckpointOptions } from '@backstage/plugin-scaffolder-node/alpha'; import { UrlReaderService } from '@backstage/backend-plugin-api'; import { WorkspaceProvider } from '@backstage/plugin-scaffolder-node/alpha'; diff --git a/plugins/scaffolder-node/report-alpha.api.md b/plugins/scaffolder-node/report-alpha.api.md index a96f312d2d..c3e8c7f71b 100644 --- a/plugins/scaffolder-node/report-alpha.api.md +++ b/plugins/scaffolder-node/report-alpha.api.md @@ -27,6 +27,37 @@ export type AutocompleteHandler = ({ }[]; }>; +// @alpha +export type CheckpointContext = { + key: string; + fn: () => Promise | T; +}; + +// @alpha +export type CheckpointFailedState = { + status: 'failed'; + reason: string; +}; + +// @alpha +export type CheckpointState = { + [key: string]: CheckpointStateValue; +}; + +// @alpha +export type CheckpointStateValue = + | CheckpointSuccessState + | CheckpointFailedState; + +// @alpha +export type CheckpointStatus = 'failed' | 'success'; + +// @alpha +export type CheckpointSuccessState = { + status: 'success'; + value: T; +}; + // @alpha (undocumented) export type CreatedTemplateFilter< TFunctionArgs extends [z.ZodTypeAny, ...z.ZodTypeAny[]], @@ -187,6 +218,11 @@ export type TemplateGlobalFunctionExample = { notes?: string; }; +// @alpha +export type UpdateTaskCheckpointOptions = { + key: string; +} & CheckpointStateValue; + // @alpha export interface WorkspaceProvider { // (undocumented) diff --git a/plugins/scaffolder-node/report.api.md b/plugins/scaffolder-node/report.api.md index a23a9137b1..bceb9980b6 100644 --- a/plugins/scaffolder-node/report.api.md +++ b/plugins/scaffolder-node/report.api.md @@ -4,6 +4,7 @@ ```ts import { BackstageCredentials } from '@backstage/backend-plugin-api'; +import { CheckpointContext } from '@backstage/plugin-scaffolder-node/alpha'; import { Expand } from '@backstage/types'; import { JsonObject } from '@backstage/types'; import { JsonValue } from '@backstage/types'; @@ -15,6 +16,7 @@ import { ScmIntegrations } from '@backstage/integration'; import { SpawnOptionsWithoutStdio } from 'child_process'; import { TaskSpec } from '@backstage/plugin-scaffolder-common'; import { TemplateInfo } from '@backstage/plugin-scaffolder-common'; +import { UpdateTaskCheckpointOptions } from '@backstage/plugin-scaffolder-node/alpha'; import { UrlReaderService } from '@backstage/backend-plugin-api'; import { UserEntity } from '@backstage/catalog-model'; import { Writable } from 'stream'; @@ -30,10 +32,9 @@ export type ActionContext< secrets?: TaskSecrets; workspacePath: string; input: TActionInput; - checkpoint(opts: { - key: string; - fn: () => Promise | T; - }): Promise; + checkpoint( + opts: CheckpointContext, + ): Promise; output( name: keyof TActionOutput, value: TActionOutput[keyof TActionOutput], @@ -446,19 +447,7 @@ export interface TaskContext { // (undocumented) taskId?: string; // (undocumented) - updateCheckpoint?( - options: - | { - key: string; - status: 'success'; - value: JsonValue; - } - | { - key: string; - status: 'failed'; - reason: string; - }, - ): Promise; + updateCheckpoint?(options: UpdateTaskCheckpointOptions): Promise; } // @public diff --git a/plugins/scaffolder-node/src/actions/types.ts b/plugins/scaffolder-node/src/actions/types.ts index 32ab12657c..0162d96d95 100644 --- a/plugins/scaffolder-node/src/actions/types.ts +++ b/plugins/scaffolder-node/src/actions/types.ts @@ -23,7 +23,7 @@ import { BackstageCredentials, LoggerService, } from '@backstage/backend-plugin-api'; -import { CheckpointContext } from '../alpha'; +import { CheckpointContext } from '@backstage/plugin-scaffolder-node/alpha'; /** * ActionContext is passed into scaffolder actions. diff --git a/plugins/scaffolder-node/src/tasks/types.ts b/plugins/scaffolder-node/src/tasks/types.ts index 5621aa117b..d2403f205a 100644 --- a/plugins/scaffolder-node/src/tasks/types.ts +++ b/plugins/scaffolder-node/src/tasks/types.ts @@ -17,7 +17,7 @@ import { BackstageCredentials } from '@backstage/backend-plugin-api'; import { TaskSpec } from '@backstage/plugin-scaffolder-common'; import { JsonObject, Observable } from '@backstage/types'; -import { UpdateTaskCheckpointOptions } from '../alpha'; +import { UpdateTaskCheckpointOptions } from '@backstage/plugin-scaffolder-node/alpha'; /** * TaskSecrets From f63877526a6167acf4cff55f4f26f420720dbe1d Mon Sep 17 00:00:00 2001 From: benjdlambert Date: Mon, 16 Jun 2025 13:35:55 +0200 Subject: [PATCH 8/8] chore: cleanup the types a little bit Signed-off-by: benjdlambert Signed-off-by: benjdlambert --- plugins/scaffolder-node/report-alpha.api.md | 24 +++++++---------- .../src/alpha/checkpoints/types.ts | 26 +++---------------- plugins/scaffolder-node/src/tasks/index.ts | 1 - 3 files changed, 12 insertions(+), 39 deletions(-) diff --git a/plugins/scaffolder-node/report-alpha.api.md b/plugins/scaffolder-node/report-alpha.api.md index c3e8c7f71b..09541fbc56 100644 --- a/plugins/scaffolder-node/report-alpha.api.md +++ b/plugins/scaffolder-node/report-alpha.api.md @@ -33,31 +33,25 @@ export type CheckpointContext = { fn: () => Promise | T; }; -// @alpha -export type CheckpointFailedState = { - status: 'failed'; - reason: string; -}; - // @alpha export type CheckpointState = { [key: string]: CheckpointStateValue; }; // @alpha -export type CheckpointStateValue = - | CheckpointSuccessState - | CheckpointFailedState; +export type CheckpointStateValue = + | { + status: 'failed'; + reason: string; + } + | { + status: 'success'; + value: T; + }; // @alpha export type CheckpointStatus = 'failed' | 'success'; -// @alpha -export type CheckpointSuccessState = { - status: 'success'; - value: T; -}; - // @alpha (undocumented) export type CreatedTemplateFilter< TFunctionArgs extends [z.ZodTypeAny, ...z.ZodTypeAny[]], diff --git a/plugins/scaffolder-node/src/alpha/checkpoints/types.ts b/plugins/scaffolder-node/src/alpha/checkpoints/types.ts index 45f1c03430..5bd1eb5cd3 100644 --- a/plugins/scaffolder-node/src/alpha/checkpoints/types.ts +++ b/plugins/scaffolder-node/src/alpha/checkpoints/types.ts @@ -22,34 +22,14 @@ import { JsonValue } from '@backstage/types'; */ export type CheckpointStatus = 'failed' | 'success'; -/** - * Represents a successful checkpoint state with a value. - * - * @alpha - */ -export type CheckpointSuccessState = { - status: 'success'; - value: T; -}; - -/** - * Represents a failed checkpoint state with a reason for failure. - * - * @alpha - */ -export type CheckpointFailedState = { - status: 'failed'; - reason: string; -}; - /** * Represents the union of all possible checkpoint state values. * * @alpha */ -export type CheckpointStateValue = - | CheckpointSuccessState - | CheckpointFailedState; +export type CheckpointStateValue = + | { status: 'failed'; reason: string } + | { status: 'success'; value: T }; /** * A map of checkpoint keys to their states. diff --git a/plugins/scaffolder-node/src/tasks/index.ts b/plugins/scaffolder-node/src/tasks/index.ts index 2ff31857f5..930de95237 100644 --- a/plugins/scaffolder-node/src/tasks/index.ts +++ b/plugins/scaffolder-node/src/tasks/index.ts @@ -25,5 +25,4 @@ export type { TaskContext, TaskEventType, TaskStatus, - // UpdateTaskCheckpointOptions, } from './types';