@backstage/plugin-scaffolder-backend 4.1.0-next.0 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/CHANGELOG.md +23 -11
  2. package/README.md +0 -23
  3. package/config.schema.json +7 -63
  4. package/dist/ScaffolderPlugin.cjs.js +9 -2
  5. package/dist/ScaffolderPlugin.cjs.js.map +1 -1
  6. package/dist/actions/createDryRunTemplateAction.cjs.js +0 -2
  7. package/dist/actions/createDryRunTemplateAction.cjs.js.map +1 -1
  8. package/dist/index.d.ts +4 -0
  9. package/dist/scaffolder/actions/builtin/fetch/assertScmUserCredentials.cjs.js +34 -0
  10. package/dist/scaffolder/actions/builtin/fetch/assertScmUserCredentials.cjs.js.map +1 -0
  11. package/dist/scaffolder/actions/builtin/fetch/plain.cjs.js +9 -1
  12. package/dist/scaffolder/actions/builtin/fetch/plain.cjs.js.map +1 -1
  13. package/dist/scaffolder/actions/builtin/fetch/plainFile.cjs.js +9 -1
  14. package/dist/scaffolder/actions/builtin/fetch/plainFile.cjs.js.map +1 -1
  15. package/dist/scaffolder/actions/builtin/fetch/template.cjs.js +8 -0
  16. package/dist/scaffolder/actions/builtin/fetch/template.cjs.js.map +1 -1
  17. package/dist/scaffolder/actions/builtin/fetch/templateFile.cjs.js +8 -0
  18. package/dist/scaffolder/actions/builtin/fetch/templateFile.cjs.js.map +1 -1
  19. package/dist/scaffolder/tasks/DatabaseTaskStore.cjs.js +53 -78
  20. package/dist/scaffolder/tasks/DatabaseTaskStore.cjs.js.map +1 -1
  21. package/dist/scaffolder/tasks/DatabaseWorkspaceProvider.cjs.js +23 -0
  22. package/dist/scaffolder/tasks/DatabaseWorkspaceProvider.cjs.js.map +1 -0
  23. package/dist/scaffolder/tasks/NunjucksWorkflowRunner.cjs.js +130 -91
  24. package/dist/scaffolder/tasks/NunjucksWorkflowRunner.cjs.js.map +1 -1
  25. package/dist/scaffolder/tasks/StorageTaskBroker.cjs.js +29 -53
  26. package/dist/scaffolder/tasks/StorageTaskBroker.cjs.js.map +1 -1
  27. package/dist/scaffolder/tasks/WorkspaceService.cjs.js +18 -26
  28. package/dist/scaffolder/tasks/WorkspaceService.cjs.js.map +1 -1
  29. package/dist/scaffolder/tasks/logger.cjs.js +101 -7
  30. package/dist/scaffolder/tasks/logger.cjs.js.map +1 -1
  31. package/dist/scaffolder/tasks/taskRecoveryHelper.cjs.js +0 -4
  32. package/dist/scaffolder/tasks/taskRecoveryHelper.cjs.js.map +1 -1
  33. package/dist/schema/openapi/generated/router.cjs.js +6 -6
  34. package/dist/schema/openapi/generated/router.cjs.js.map +1 -1
  35. package/dist/service/router.cjs.js +22 -9
  36. package/dist/service/router.cjs.js.map +1 -1
  37. package/dist/service/rules.cjs.js +12 -0
  38. package/dist/service/rules.cjs.js.map +1 -1
  39. package/dist/util/checkPermissions.cjs.js +3 -0
  40. package/dist/util/checkPermissions.cjs.js.map +1 -1
  41. package/package.json +20 -20
@@ -4,7 +4,6 @@ var types = require('@backstage/types');
4
4
  var ObservableImpl = require('zen-observable');
5
5
  var WorkspaceService = require('./WorkspaceService.cjs.js');
6
6
  var helper = require('./helper.cjs.js');
7
- var taskRecoveryHelper = require('./taskRecoveryHelper.cjs.js');
8
7
 
9
8
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
10
9
 
@@ -13,10 +12,12 @@ var ObservableImpl__default = /*#__PURE__*/_interopDefaultCompat(ObservableImpl)
13
12
  class TaskManager {
14
13
  isDone = false;
15
14
  heartbeatTimeoutId;
16
- static create(task, storage, abortSignal, logger, auth, workspaceProvider) {
15
+ static create(task, storage, abortSignal, logger, auth, config, additionalWorkspaceProviders) {
17
16
  const workspaceService = WorkspaceService.DefaultWorkspaceService.create(
18
17
  task,
19
- workspaceProvider
18
+ storage,
19
+ additionalWorkspaceProviders,
20
+ config
20
21
  );
21
22
  const agent = new TaskManager(
22
23
  task,
@@ -79,24 +80,16 @@ class TaskManager {
79
80
  }
80
81
  async updateCheckpoint(options) {
81
82
  const { key, ...value } = options;
82
- this.task.state ??= { checkpoints: {}, steps: {} };
83
- this.task.state.checkpoints ??= {};
84
- this.task.state.checkpoints[key] = value;
83
+ if (this.task.state) {
84
+ this.task.state.checkpoints[key] = value;
85
+ } else {
86
+ this.task.state = { checkpoints: { [key]: value } };
87
+ }
85
88
  await this.storage.saveTaskState?.({
86
89
  taskId: this.task.taskId,
87
90
  state: this.task.state
88
91
  });
89
92
  }
90
- async updateStepState(options) {
91
- const { stepId, status, output } = options;
92
- this.task.state ??= { checkpoints: {}, steps: {} };
93
- this.task.state.steps ??= {};
94
- this.task.state.steps[stepId] = { status, output };
95
- await this.storage.saveTaskState({
96
- taskId: this.task.taskId,
97
- state: this.task.state
98
- });
99
- }
100
93
  async serializeWorkspace(options) {
101
94
  await this.workspaceService.serializeWorkspace(options);
102
95
  }
@@ -116,16 +109,6 @@ class TaskManager {
116
109
  if (this.heartbeatTimeoutId) {
117
110
  clearTimeout(this.heartbeatTimeoutId);
118
111
  }
119
- if (result === "completed") {
120
- try {
121
- await this.workspaceService.cleanWorkspace();
122
- } catch (error) {
123
- this.logger.warn(
124
- `Failed to clean workspace for task ${this.task.taskId}`,
125
- error
126
- );
127
- }
128
- }
129
112
  }
130
113
  startTimeout() {
131
114
  this.heartbeatTimeoutId = setTimeout(async () => {
@@ -159,17 +142,14 @@ class StorageTaskBroker {
159
142
  logger;
160
143
  config;
161
144
  auth;
162
- workspaceProvider;
145
+ additionalWorkspaceProviders;
163
146
  auditor;
164
147
  constructor(storage, logger, config, auth, additionalWorkspaceProviders, auditor) {
165
148
  this.storage = storage;
166
149
  this.logger = logger;
167
150
  this.config = config;
168
151
  this.auth = auth;
169
- this.workspaceProvider = WorkspaceService.resolveWorkspaceProvider(
170
- additionalWorkspaceProviders,
171
- config
172
- );
152
+ this.additionalWorkspaceProviders = additionalWorkspaceProviders;
173
153
  this.auditor = auditor;
174
154
  }
175
155
  async list(options) {
@@ -204,25 +184,20 @@ class StorageTaskBroker {
204
184
  });
205
185
  }
206
186
  async recoverTasks() {
207
- const enabled = taskRecoveryHelper.isTaskRecoveryEnabled(this.config);
208
- if (!enabled) {
209
- return;
210
- }
211
- const defaultTimeout = { seconds: 30 };
212
- const timeout = this.config?.has("scaffolder.taskRecovery.staleTimeout") ? helper.readDuration(
213
- this.config,
214
- "scaffolder.taskRecovery.staleTimeout",
215
- defaultTimeout
216
- ) : helper.readDuration(
217
- this.config,
218
- "scaffolder.EXPERIMENTAL_recoverTasksTimeout",
219
- defaultTimeout
220
- );
221
- const { ids: recoveredTaskIds } = await this.storage.recoverTasks?.({
222
- timeout
223
- }) ?? { ids: [] };
224
- if (recoveredTaskIds.length > 0) {
225
- this.signalDispatch();
187
+ const enabled = this.config?.getOptionalBoolean("scaffolder.EXPERIMENTAL_recoverTasks") ?? false;
188
+ if (enabled) {
189
+ const defaultTimeout = { seconds: 30 };
190
+ const timeout = helper.readDuration(
191
+ this.config,
192
+ "scaffolder.EXPERIMENTAL_recoverTasksTimeout",
193
+ defaultTimeout
194
+ );
195
+ const { ids: recoveredTaskIds } = await this.storage.recoverTasks?.({
196
+ timeout
197
+ }) ?? { ids: [] };
198
+ if (recoveredTaskIds.length > 0) {
199
+ this.signalDispatch();
200
+ }
226
201
  }
227
202
  }
228
203
  /**
@@ -246,7 +221,8 @@ class StorageTaskBroker {
246
221
  abortController.signal,
247
222
  this.logger,
248
223
  this.auth,
249
- this.workspaceProvider
224
+ this.config,
225
+ this.additionalWorkspaceProviders
250
226
  );
251
227
  }
252
228
  await this.waitForDispatch();
@@ -281,9 +257,9 @@ class StorageTaskBroker {
281
257
  const isTaskRecoverable = task.spec.EXPERIMENTAL_recovery?.EXPERIMENTAL_strategy === "startOver";
282
258
  while (!cancelled) {
283
259
  const result = await this.storage.listEvents({
260
+ isTaskRecoverable,
284
261
  taskId,
285
- after,
286
- isTaskRecoverable
262
+ after
287
263
  });
288
264
  const { events } = result;
289
265
  if (events.length) {
@@ -1 +1 @@
1
- {"version":3,"file":"StorageTaskBroker.cjs.js","sources":["../../../src/scaffolder/tasks/StorageTaskBroker.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n AuditorService,\n AuthService,\n BackstageCredentials,\n LoggerService,\n} from '@backstage/backend-plugin-api';\nimport { Config } from '@backstage/config';\nimport { TaskSpec } from '@backstage/plugin-scaffolder-common';\nimport {\n SerializedTask,\n SerializedTaskEvent,\n TaskBroker,\n TaskBrokerDispatchOptions,\n TaskCompletionState,\n TaskContext,\n TaskFilters,\n TaskSecrets,\n TaskStatus,\n} from '@backstage/plugin-scaffolder-node';\nimport {\n WorkspaceProvider,\n UpdateTaskCheckpointOptions,\n} from '@backstage/plugin-scaffolder-node/alpha';\nimport {\n HumanDuration,\n JsonObject,\n Observable,\n createDeferred,\n} from '@backstage/types';\nimport ObservableImpl from 'zen-observable';\nimport {\n DefaultWorkspaceService,\n resolveWorkspaceProvider,\n WorkspaceService,\n} from './WorkspaceService';\nimport { readDuration } from './helper';\nimport { isTaskRecoveryEnabled } from './taskRecoveryHelper';\nimport {\n InternalTaskSecrets,\n TaskStore,\n UpdateStepStateOptions,\n TaskState,\n} from './types';\nimport { PermissionCriteria } from '@backstage/plugin-permission-common';\n/**\n * TaskManager\n */\nexport class TaskManager implements TaskContext {\n private isDone = false;\n\n private heartbeatTimeoutId?: ReturnType<typeof setInterval>;\n\n static create(\n task: CurrentClaimedTask,\n storage: TaskStore,\n abortSignal: AbortSignal,\n logger: LoggerService,\n auth?: AuthService,\n workspaceProvider?: WorkspaceProvider,\n ) {\n const workspaceService = DefaultWorkspaceService.create(\n task,\n workspaceProvider,\n );\n\n const agent = new TaskManager(\n task,\n storage,\n abortSignal,\n logger,\n workspaceService,\n auth,\n );\n agent.startTimeout();\n return agent;\n }\n\n private readonly task: CurrentClaimedTask;\n private readonly storage: TaskStore;\n private readonly signal: AbortSignal;\n private readonly logger: LoggerService;\n private readonly workspaceService: WorkspaceService;\n private readonly auth?: AuthService;\n\n // Runs heartbeat internally\n private constructor(\n task: CurrentClaimedTask,\n storage: TaskStore,\n signal: AbortSignal,\n logger: LoggerService,\n workspaceService: WorkspaceService,\n auth?: AuthService,\n ) {\n this.task = task;\n this.storage = storage;\n this.signal = signal;\n this.logger = logger;\n this.workspaceService = workspaceService;\n this.auth = auth;\n }\n\n get taskId() {\n return this.task.taskId;\n }\n\n get spec() {\n return this.task.spec;\n }\n\n get cancelSignal() {\n return this.signal;\n }\n\n get secrets() {\n return this.task.secrets;\n }\n\n get createdBy() {\n return this.task.createdBy;\n }\n\n async getWorkspaceName() {\n return this.task.taskId;\n }\n\n async rehydrateWorkspace?(options: {\n taskId: string;\n targetPath: string;\n }): Promise<void> {\n await this.workspaceService.rehydrateWorkspace(options);\n }\n\n get done() {\n return this.isDone;\n }\n\n async emitLog(message: string, logMetadata?: JsonObject): Promise<void> {\n await this.storage.emitLogEvent({\n taskId: this.task.taskId,\n body: { message, ...logMetadata },\n });\n }\n\n async getTaskState?(): Promise<\n | {\n state?: JsonObject;\n }\n | undefined\n > {\n return this.storage.getTaskState?.({ taskId: this.task.taskId });\n }\n\n async updateCheckpoint?(options: UpdateTaskCheckpointOptions): Promise<void> {\n const { key, ...value } = options;\n\n // Initialize state structure if needed\n this.task.state ??= { checkpoints: {}, steps: {} };\n this.task.state.checkpoints ??= {};\n this.task.state.checkpoints[key] = value;\n\n await this.storage.saveTaskState?.({\n taskId: this.task.taskId,\n state: this.task.state,\n });\n }\n\n async updateStepState?(options: UpdateStepStateOptions): Promise<void> {\n const { stepId, status, output } = options;\n\n // Initialize state structure if needed\n this.task.state ??= { checkpoints: {}, steps: {} };\n this.task.state.steps ??= {};\n this.task.state.steps[stepId] = { status, output };\n\n await this.storage.saveTaskState({\n taskId: this.task.taskId,\n state: this.task.state,\n });\n }\n\n async serializeWorkspace?(options: { path: string }): Promise<void> {\n await this.workspaceService.serializeWorkspace(options);\n }\n\n async cleanWorkspace?(): Promise<void> {\n await this.workspaceService.cleanWorkspace();\n }\n\n async complete(\n result: TaskCompletionState,\n metadata?: JsonObject,\n ): Promise<void> {\n await this.storage.completeTask({\n taskId: this.task.taskId,\n status: result === 'failed' ? 'failed' : 'completed',\n eventBody: {\n message: `Run completed with status: ${result}`,\n ...metadata,\n },\n });\n this.isDone = true;\n if (this.heartbeatTimeoutId) {\n clearTimeout(this.heartbeatTimeoutId);\n }\n\n // Clean up serialized workspace on success only\n // Failed tasks may be retried later, so keep their workspace\n if (result === 'completed') {\n try {\n await this.workspaceService.cleanWorkspace();\n } catch (error) {\n this.logger.warn(\n `Failed to clean workspace for task ${this.task.taskId}`,\n error,\n );\n }\n }\n }\n\n private startTimeout() {\n this.heartbeatTimeoutId = setTimeout(async () => {\n try {\n await this.storage.heartbeatTask(this.task.taskId);\n this.startTimeout();\n } catch (error) {\n this.isDone = true;\n\n this.logger.error(\n `Heartbeat for task ${this.task.taskId} failed`,\n error,\n );\n }\n }, 1000);\n }\n\n async getInitiatorCredentials(): Promise<BackstageCredentials> {\n const secrets = this.task.secrets as InternalTaskSecrets;\n\n if (secrets && secrets.__initiatorCredentials) {\n return JSON.parse(secrets.__initiatorCredentials);\n }\n if (!this.auth) {\n throw new Error(\n 'Failed to create none credentials in scaffolder task. The TaskManager has not been initialized with an auth service implementation',\n );\n }\n return this.auth.getNoneCredentials();\n }\n}\n\n/**\n * Stores the state of the current claimed task passed to the TaskContext\n *\n * @public\n */\nexport interface CurrentClaimedTask {\n /**\n * The TaskSpec of the current claimed task.\n */\n spec: TaskSpec;\n /**\n * The uuid of the current claimed task.\n */\n taskId: string;\n /**\n * The secrets that are stored with the task.\n */\n secrets?: TaskSecrets;\n /**\n * The state of checkpoints of the task.\n */\n state?: TaskState;\n /**\n * The creator of the task.\n */\n createdBy?: string;\n /**\n * The workspace of the task.\n */\n workspace?: Promise<Buffer>;\n}\n\nexport class StorageTaskBroker implements TaskBroker {\n private readonly storage: TaskStore;\n private readonly logger: LoggerService;\n private readonly config?: Config;\n private readonly auth?: AuthService;\n private readonly workspaceProvider?: WorkspaceProvider;\n private readonly auditor?: AuditorService;\n\n constructor(\n storage: TaskStore,\n logger: LoggerService,\n config?: Config,\n auth?: AuthService,\n additionalWorkspaceProviders?: Record<string, WorkspaceProvider>,\n auditor?: AuditorService,\n ) {\n this.storage = storage;\n this.logger = logger;\n this.config = config;\n this.auth = auth;\n this.workspaceProvider = resolveWorkspaceProvider(\n additionalWorkspaceProviders,\n config,\n );\n this.auditor = auditor;\n }\n\n async list(options?: {\n createdBy?: string;\n status?: TaskStatus;\n filters?: {\n createdBy?: string | string[];\n status?: TaskStatus | TaskStatus[];\n };\n pagination?: {\n limit?: number;\n offset?: number;\n };\n order?: { order: 'asc' | 'desc'; field: string }[];\n permissionFilters?: PermissionCriteria<TaskFilters>;\n }): Promise<{ tasks: SerializedTask[]; totalTasks?: number }> {\n if (!this.storage.list) {\n throw new Error(\n 'TaskStore does not implement the list method. Please implement the list method to be able to list tasks',\n );\n }\n return await this.storage.list(options ?? {});\n }\n\n private deferredDispatch = createDeferred();\n\n private async registerCancellable(\n taskId: string,\n abortController: AbortController,\n ) {\n let shouldUnsubscribe = false;\n const subscription = this.event$({ taskId, after: undefined }).subscribe({\n error: _ => {\n subscription.unsubscribe();\n },\n next: ({ events }) => {\n for (const event of events) {\n if (event.type === 'cancelled') {\n abortController.abort();\n shouldUnsubscribe = true;\n }\n\n if (event.type === 'completion' && !event.isTaskRecoverable) {\n shouldUnsubscribe = true;\n }\n }\n if (shouldUnsubscribe) {\n subscription.unsubscribe();\n }\n },\n });\n }\n\n public async recoverTasks(): Promise<void> {\n const enabled = isTaskRecoveryEnabled(this.config);\n\n if (!enabled) {\n return;\n }\n\n const defaultTimeout: HumanDuration = { seconds: 30 };\n const timeout = this.config?.has('scaffolder.taskRecovery.staleTimeout')\n ? readDuration(\n this.config,\n 'scaffolder.taskRecovery.staleTimeout',\n defaultTimeout,\n )\n : readDuration(\n this.config,\n 'scaffolder.EXPERIMENTAL_recoverTasksTimeout',\n defaultTimeout,\n );\n\n const { ids: recoveredTaskIds } = (await this.storage.recoverTasks?.({\n timeout,\n })) ?? { ids: [] };\n\n if (recoveredTaskIds.length > 0) {\n this.signalDispatch();\n }\n }\n\n /**\n * {@inheritdoc TaskBroker.claim}\n */\n async claim(): Promise<TaskContext> {\n for (;;) {\n const pendingTask = await this.storage.claimTask();\n if (pendingTask) {\n const abortController = new AbortController();\n await this.registerCancellable(pendingTask.id, abortController);\n return TaskManager.create(\n {\n taskId: pendingTask.id,\n spec: pendingTask.spec,\n secrets: pendingTask.secrets,\n createdBy: pendingTask.createdBy,\n state: pendingTask.state,\n },\n this.storage,\n abortController.signal,\n this.logger,\n this.auth,\n this.workspaceProvider,\n );\n }\n\n await this.waitForDispatch();\n }\n }\n\n /**\n * {@inheritdoc TaskBroker.dispatch}\n */\n async dispatch(\n options: TaskBrokerDispatchOptions,\n ): Promise<{ taskId: string }> {\n const taskRow = await this.storage.createTask(options);\n this.signalDispatch();\n return {\n taskId: taskRow.taskId,\n };\n }\n\n /**\n * {@inheritdoc TaskBroker.get}\n */\n async get(taskId: string): Promise<SerializedTask> {\n return this.storage.getTask(taskId);\n }\n\n /**\n * {@inheritdoc TaskBroker.event$}\n */\n event$(options: {\n taskId: string;\n after?: number;\n }): Observable<{ events: SerializedTaskEvent[] }> {\n return new ObservableImpl(observer => {\n const { taskId } = options;\n\n let after = options.after;\n let cancelled = false;\n\n (async () => {\n const task = await this.storage.getTask(taskId);\n const isTaskRecoverable =\n task.spec.EXPERIMENTAL_recovery?.EXPERIMENTAL_strategy ===\n 'startOver';\n\n while (!cancelled) {\n const result = await this.storage.listEvents({\n taskId,\n after,\n isTaskRecoverable,\n });\n const { events } = result;\n if (events.length) {\n after = events[events.length - 1].id;\n observer.next(result);\n }\n\n await new Promise(resolve => setTimeout(resolve, 1000));\n }\n })();\n\n return () => {\n cancelled = true;\n };\n });\n }\n\n /**\n * {@inheritdoc TaskBroker.vacuumTasks}\n */\n async vacuumTasks(options: { timeoutS: number }): Promise<void> {\n const { tasks } = await this.storage.listStaleTasks(options);\n await Promise.all(\n tasks.map(async task => {\n const auditorEvent = await this.auditor?.createEvent({\n eventId: 'task',\n severityLevel: 'medium',\n meta: {\n actionType: 'stale-cancel',\n taskId: task.taskId,\n },\n });\n try {\n await this.storage.completeTask({\n taskId: task.taskId,\n status: 'failed',\n eventBody: {\n message:\n 'The task was cancelled because the task worker lost connection to the task broker',\n },\n });\n await auditorEvent?.success();\n } catch (error) {\n this.logger.warn(`Failed to cancel task '${task.taskId}', ${error}`);\n await auditorEvent?.fail({ error: error });\n }\n }),\n );\n }\n\n private waitForDispatch() {\n return this.deferredDispatch;\n }\n\n private signalDispatch() {\n this.deferredDispatch.resolve();\n this.deferredDispatch = createDeferred();\n }\n\n async cancel(taskId: string) {\n const { events } = await this.storage.listEvents({ taskId });\n const currentStepId =\n events.length > 0\n ? events\n .filter(({ body }) => body?.stepId)\n .reduce((prev, curr) => (prev.id > curr.id ? prev : curr)).body\n .stepId\n : 0;\n\n await this.storage.cancelTask?.({\n taskId,\n body: {\n message: `Step ${currentStepId} has been cancelled.`,\n stepId: currentStepId,\n status: 'cancelled',\n },\n });\n }\n\n async retry(options: {\n secrets?: TaskSecrets;\n taskId: string;\n }): Promise<void> {\n await this.storage.retryTask?.(options);\n this.signalDispatch();\n }\n}\n"],"names":["DefaultWorkspaceService","resolveWorkspaceProvider","createDeferred","isTaskRecoveryEnabled","readDuration","ObservableImpl"],"mappings":"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"}
1
+ {"version":3,"file":"StorageTaskBroker.cjs.js","sources":["../../../src/scaffolder/tasks/StorageTaskBroker.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n AuditorService,\n AuthService,\n BackstageCredentials,\n LoggerService,\n} from '@backstage/backend-plugin-api';\nimport { Config } from '@backstage/config';\nimport { TaskSpec } from '@backstage/plugin-scaffolder-common';\nimport {\n SerializedTask,\n SerializedTaskEvent,\n TaskBroker,\n TaskBrokerDispatchOptions,\n TaskCompletionState,\n TaskContext,\n TaskFilters,\n TaskSecrets,\n TaskStatus,\n} from '@backstage/plugin-scaffolder-node';\nimport {\n CheckpointState,\n WorkspaceProvider,\n UpdateTaskCheckpointOptions,\n} from '@backstage/plugin-scaffolder-node/alpha';\nimport { JsonObject, Observable, createDeferred } from '@backstage/types';\nimport ObservableImpl from 'zen-observable';\nimport { DefaultWorkspaceService, WorkspaceService } from './WorkspaceService';\nimport { readDuration } from './helper';\nimport { InternalTaskSecrets, TaskStore } from './types';\nimport { PermissionCriteria } from '@backstage/plugin-permission-common';\n\ntype TaskState = {\n checkpoints: CheckpointState;\n};\n/**\n * TaskManager\n */\nexport class TaskManager implements TaskContext {\n private isDone = false;\n\n private heartbeatTimeoutId?: ReturnType<typeof setInterval>;\n\n static create(\n task: CurrentClaimedTask,\n storage: TaskStore,\n abortSignal: AbortSignal,\n logger: LoggerService,\n auth?: AuthService,\n config?: Config,\n additionalWorkspaceProviders?: Record<string, WorkspaceProvider>,\n ) {\n const workspaceService = DefaultWorkspaceService.create(\n task,\n storage,\n additionalWorkspaceProviders,\n config,\n );\n\n const agent = new TaskManager(\n task,\n storage,\n abortSignal,\n logger,\n workspaceService,\n auth,\n );\n agent.startTimeout();\n return agent;\n }\n\n private readonly task: CurrentClaimedTask;\n private readonly storage: TaskStore;\n private readonly signal: AbortSignal;\n private readonly logger: LoggerService;\n private readonly workspaceService: WorkspaceService;\n private readonly auth?: AuthService;\n\n // Runs heartbeat internally\n private constructor(\n task: CurrentClaimedTask,\n storage: TaskStore,\n signal: AbortSignal,\n logger: LoggerService,\n workspaceService: WorkspaceService,\n auth?: AuthService,\n ) {\n this.task = task;\n this.storage = storage;\n this.signal = signal;\n this.logger = logger;\n this.workspaceService = workspaceService;\n this.auth = auth;\n }\n\n get taskId() {\n return this.task.taskId;\n }\n\n get spec() {\n return this.task.spec;\n }\n\n get cancelSignal() {\n return this.signal;\n }\n\n get secrets() {\n return this.task.secrets;\n }\n\n get createdBy() {\n return this.task.createdBy;\n }\n\n async getWorkspaceName() {\n return this.task.taskId;\n }\n\n async rehydrateWorkspace?(options: {\n taskId: string;\n targetPath: string;\n }): Promise<void> {\n await this.workspaceService.rehydrateWorkspace(options);\n }\n\n get done() {\n return this.isDone;\n }\n\n async emitLog(message: string, logMetadata?: JsonObject): Promise<void> {\n await this.storage.emitLogEvent({\n taskId: this.task.taskId,\n body: { message, ...logMetadata },\n });\n }\n\n async getTaskState?(): Promise<\n | {\n state?: JsonObject;\n }\n | undefined\n > {\n return this.storage.getTaskState?.({ taskId: this.task.taskId });\n }\n\n async updateCheckpoint?(options: UpdateTaskCheckpointOptions): Promise<void> {\n const { key, ...value } = options;\n\n if (this.task.state) {\n (this.task.state as TaskState).checkpoints[key] = value;\n } else {\n this.task.state = { checkpoints: { [key]: value } };\n }\n await this.storage.saveTaskState?.({\n taskId: this.task.taskId,\n state: this.task.state,\n });\n }\n\n async serializeWorkspace?(options: { path: string }): Promise<void> {\n await this.workspaceService.serializeWorkspace(options);\n }\n\n async cleanWorkspace?(): Promise<void> {\n await this.workspaceService.cleanWorkspace();\n }\n\n async complete(\n result: TaskCompletionState,\n metadata?: JsonObject,\n ): Promise<void> {\n await this.storage.completeTask({\n taskId: this.task.taskId,\n status: result === 'failed' ? 'failed' : 'completed',\n eventBody: {\n message: `Run completed with status: ${result}`,\n ...metadata,\n },\n });\n this.isDone = true;\n if (this.heartbeatTimeoutId) {\n clearTimeout(this.heartbeatTimeoutId);\n }\n }\n\n private startTimeout() {\n this.heartbeatTimeoutId = setTimeout(async () => {\n try {\n await this.storage.heartbeatTask(this.task.taskId);\n this.startTimeout();\n } catch (error) {\n this.isDone = true;\n\n this.logger.error(\n `Heartbeat for task ${this.task.taskId} failed`,\n error,\n );\n }\n }, 1000);\n }\n\n async getInitiatorCredentials(): Promise<BackstageCredentials> {\n const secrets = this.task.secrets as InternalTaskSecrets;\n\n if (secrets && secrets.__initiatorCredentials) {\n return JSON.parse(secrets.__initiatorCredentials);\n }\n if (!this.auth) {\n throw new Error(\n 'Failed to create none credentials in scaffolder task. The TaskManager has not been initialized with an auth service implementation',\n );\n }\n return this.auth.getNoneCredentials();\n }\n}\n\n/**\n * Stores the state of the current claimed task passed to the TaskContext\n *\n * @public\n */\nexport interface CurrentClaimedTask {\n /**\n * The TaskSpec of the current claimed task.\n */\n spec: TaskSpec;\n /**\n * The uuid of the current claimed task.\n */\n taskId: string;\n /**\n * The secrets that are stored with the task.\n */\n secrets?: TaskSecrets;\n /**\n * The state of checkpoints of the task.\n */\n state?: JsonObject;\n /**\n * The creator of the task.\n */\n createdBy?: string;\n /**\n * The workspace of the task.\n */\n workspace?: Promise<Buffer>;\n}\n\nexport class StorageTaskBroker implements TaskBroker {\n private readonly storage: TaskStore;\n private readonly logger: LoggerService;\n private readonly config?: Config;\n private readonly auth?: AuthService;\n private readonly additionalWorkspaceProviders?: Record<\n string,\n WorkspaceProvider\n >;\n private readonly auditor?: AuditorService;\n\n constructor(\n storage: TaskStore,\n logger: LoggerService,\n config?: Config,\n auth?: AuthService,\n additionalWorkspaceProviders?: Record<string, WorkspaceProvider>,\n auditor?: AuditorService,\n ) {\n this.storage = storage;\n this.logger = logger;\n this.config = config;\n this.auth = auth;\n this.additionalWorkspaceProviders = additionalWorkspaceProviders;\n this.auditor = auditor;\n }\n\n async list(options?: {\n createdBy?: string;\n status?: TaskStatus;\n filters?: {\n createdBy?: string | string[];\n status?: TaskStatus | TaskStatus[];\n };\n pagination?: {\n limit?: number;\n offset?: number;\n };\n order?: { order: 'asc' | 'desc'; field: string }[];\n permissionFilters?: PermissionCriteria<TaskFilters>;\n }): Promise<{ tasks: SerializedTask[]; totalTasks?: number }> {\n if (!this.storage.list) {\n throw new Error(\n 'TaskStore does not implement the list method. Please implement the list method to be able to list tasks',\n );\n }\n return await this.storage.list(options ?? {});\n }\n\n private deferredDispatch = createDeferred();\n\n private async registerCancellable(\n taskId: string,\n abortController: AbortController,\n ) {\n let shouldUnsubscribe = false;\n const subscription = this.event$({ taskId, after: undefined }).subscribe({\n error: _ => {\n subscription.unsubscribe();\n },\n next: ({ events }) => {\n for (const event of events) {\n if (event.type === 'cancelled') {\n abortController.abort();\n shouldUnsubscribe = true;\n }\n\n if (event.type === 'completion' && !event.isTaskRecoverable) {\n shouldUnsubscribe = true;\n }\n }\n if (shouldUnsubscribe) {\n subscription.unsubscribe();\n }\n },\n });\n }\n\n public async recoverTasks(): Promise<void> {\n const enabled =\n this.config?.getOptionalBoolean('scaffolder.EXPERIMENTAL_recoverTasks') ??\n false;\n\n if (enabled) {\n const defaultTimeout = { seconds: 30 };\n const timeout = readDuration(\n this.config,\n 'scaffolder.EXPERIMENTAL_recoverTasksTimeout',\n defaultTimeout,\n );\n const { ids: recoveredTaskIds } = (await this.storage.recoverTasks?.({\n timeout,\n })) ?? { ids: [] };\n if (recoveredTaskIds.length > 0) {\n this.signalDispatch();\n }\n }\n }\n\n /**\n * {@inheritdoc TaskBroker.claim}\n */\n async claim(): Promise<TaskContext> {\n for (;;) {\n const pendingTask = await this.storage.claimTask();\n if (pendingTask) {\n const abortController = new AbortController();\n await this.registerCancellable(pendingTask.id, abortController);\n return TaskManager.create(\n {\n taskId: pendingTask.id,\n spec: pendingTask.spec,\n secrets: pendingTask.secrets,\n createdBy: pendingTask.createdBy,\n state: pendingTask.state,\n },\n this.storage,\n abortController.signal,\n this.logger,\n this.auth,\n this.config,\n this.additionalWorkspaceProviders,\n );\n }\n\n await this.waitForDispatch();\n }\n }\n\n /**\n * {@inheritdoc TaskBroker.dispatch}\n */\n async dispatch(\n options: TaskBrokerDispatchOptions,\n ): Promise<{ taskId: string }> {\n const taskRow = await this.storage.createTask(options);\n this.signalDispatch();\n return {\n taskId: taskRow.taskId,\n };\n }\n\n /**\n * {@inheritdoc TaskBroker.get}\n */\n async get(taskId: string): Promise<SerializedTask> {\n return this.storage.getTask(taskId);\n }\n\n /**\n * {@inheritdoc TaskBroker.event$}\n */\n event$(options: {\n taskId: string;\n after?: number;\n }): Observable<{ events: SerializedTaskEvent[] }> {\n return new ObservableImpl(observer => {\n const { taskId } = options;\n\n let after = options.after;\n let cancelled = false;\n\n (async () => {\n const task = await this.storage.getTask(taskId);\n const isTaskRecoverable =\n task.spec.EXPERIMENTAL_recovery?.EXPERIMENTAL_strategy ===\n 'startOver';\n\n while (!cancelled) {\n const result = await this.storage.listEvents({\n isTaskRecoverable,\n taskId,\n after,\n });\n const { events } = result;\n if (events.length) {\n after = events[events.length - 1].id;\n observer.next(result);\n }\n\n await new Promise(resolve => setTimeout(resolve, 1000));\n }\n })();\n\n return () => {\n cancelled = true;\n };\n });\n }\n\n /**\n * {@inheritdoc TaskBroker.vacuumTasks}\n */\n async vacuumTasks(options: { timeoutS: number }): Promise<void> {\n const { tasks } = await this.storage.listStaleTasks(options);\n await Promise.all(\n tasks.map(async task => {\n const auditorEvent = await this.auditor?.createEvent({\n eventId: 'task',\n severityLevel: 'medium',\n meta: {\n actionType: 'stale-cancel',\n taskId: task.taskId,\n },\n });\n try {\n await this.storage.completeTask({\n taskId: task.taskId,\n status: 'failed',\n eventBody: {\n message:\n 'The task was cancelled because the task worker lost connection to the task broker',\n },\n });\n await auditorEvent?.success();\n } catch (error) {\n this.logger.warn(`Failed to cancel task '${task.taskId}', ${error}`);\n await auditorEvent?.fail({ error: error });\n }\n }),\n );\n }\n\n private waitForDispatch() {\n return this.deferredDispatch;\n }\n\n private signalDispatch() {\n this.deferredDispatch.resolve();\n this.deferredDispatch = createDeferred();\n }\n\n async cancel(taskId: string) {\n const { events } = await this.storage.listEvents({ taskId });\n const currentStepId =\n events.length > 0\n ? events\n .filter(({ body }) => body?.stepId)\n .reduce((prev, curr) => (prev.id > curr.id ? prev : curr)).body\n .stepId\n : 0;\n\n await this.storage.cancelTask?.({\n taskId,\n body: {\n message: `Step ${currentStepId} has been cancelled.`,\n stepId: currentStepId,\n status: 'cancelled',\n },\n });\n }\n\n async retry(options: {\n secrets?: TaskSecrets;\n taskId: string;\n }): Promise<void> {\n await this.storage.retryTask?.(options);\n this.signalDispatch();\n }\n}\n"],"names":["DefaultWorkspaceService","createDeferred","readDuration","ObservableImpl"],"mappings":"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"}
@@ -1,42 +1,30 @@
1
1
  'use strict';
2
2
 
3
+ var DatabaseWorkspaceProvider = require('./DatabaseWorkspaceProvider.cjs.js');
3
4
  var fs = require('fs-extra');
4
5
 
5
6
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
6
7
 
7
8
  var fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
8
9
 
9
- function resolveWorkspaceProvider(workspaceProviders, config) {
10
- const legacySerializationEnabled = config?.getOptionalBoolean(
11
- "scaffolder.EXPERIMENTAL_workspaceSerialization"
12
- ) ?? false;
13
- const providerName = config?.getOptionalString("scaffolder.taskRecovery.workspaceProvider") ?? (legacySerializationEnabled ? config?.getOptionalString(
14
- "scaffolder.EXPERIMENTAL_workspaceSerializationProvider"
15
- ) ?? "database" : void 0);
16
- if (!providerName) {
17
- return void 0;
18
- }
19
- const workspaceProvider = workspaceProviders && Object.prototype.hasOwnProperty.call(workspaceProviders, providerName) ? workspaceProviders[providerName] : void 0;
20
- if (!workspaceProvider) {
21
- const databaseProviderGuidance = providerName === "database" ? ` For database storage, add '@backstage/plugin-scaffolder-backend-module-workspace-database'. When running in production, also set 'scaffolder.taskRecovery.database.dangerouslyEnableInProduction' to true.` : "";
22
- throw new Error(
23
- `Workspace provider '${providerName}' is configured but not available. Make sure to install and register the corresponding module.${databaseProviderGuidance}`
24
- );
25
- }
26
- return workspaceProvider;
27
- }
28
10
  class DefaultWorkspaceService {
29
- static create(task, workspaceProvider) {
30
- return new DefaultWorkspaceService(task, workspaceProvider);
11
+ static create(task, storage, additionalWorkspaceProviders, config) {
12
+ const workspaceProviderName = config?.getOptionalString(
13
+ "scaffolder.EXPERIMENTAL_workspaceSerializationProvider"
14
+ ) ?? "database";
15
+ const workspaceProvider = additionalWorkspaceProviders?.[workspaceProviderName] ?? DatabaseWorkspaceProvider.DatabaseWorkspaceProvider.create(storage);
16
+ return new DefaultWorkspaceService(task, workspaceProvider, config);
31
17
  }
32
18
  task;
33
19
  workspaceProvider;
34
- constructor(task, workspaceProvider) {
20
+ config;
21
+ constructor(task, workspaceProvider, config) {
35
22
  this.task = task;
36
23
  this.workspaceProvider = workspaceProvider;
24
+ this.config = config;
37
25
  }
38
26
  async serializeWorkspace(options) {
39
- if (this.workspaceProvider) {
27
+ if (this.isWorkspaceSerializationEnabled()) {
40
28
  await this.workspaceProvider.serializeWorkspace({
41
29
  path: options.path,
42
30
  taskId: this.task.taskId
@@ -44,18 +32,22 @@ class DefaultWorkspaceService {
44
32
  }
45
33
  }
46
34
  async cleanWorkspace() {
47
- if (this.workspaceProvider) {
35
+ if (this.isWorkspaceSerializationEnabled()) {
48
36
  await this.workspaceProvider.cleanWorkspace({ taskId: this.task.taskId });
49
37
  }
50
38
  }
51
39
  async rehydrateWorkspace(options) {
52
- if (this.workspaceProvider) {
40
+ if (this.isWorkspaceSerializationEnabled()) {
53
41
  await fs__default.default.mkdirp(options.targetPath);
54
42
  await this.workspaceProvider.rehydrateWorkspace(options);
55
43
  }
56
44
  }
45
+ isWorkspaceSerializationEnabled() {
46
+ return this.config?.getOptionalBoolean(
47
+ "scaffolder.EXPERIMENTAL_workspaceSerialization"
48
+ ) ?? false;
49
+ }
57
50
  }
58
51
 
59
52
  exports.DefaultWorkspaceService = DefaultWorkspaceService;
60
- exports.resolveWorkspaceProvider = resolveWorkspaceProvider;
61
53
  //# sourceMappingURL=WorkspaceService.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"WorkspaceService.cjs.js","sources":["../../../src/scaffolder/tasks/WorkspaceService.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { Config } from '@backstage/config';\nimport type { CurrentClaimedTask } from './StorageTaskBroker';\nimport type { WorkspaceProvider } from '@backstage/plugin-scaffolder-node/alpha';\nimport fs from 'fs-extra';\n\nexport interface WorkspaceService {\n serializeWorkspace(options: { path: string }): Promise<void>;\n\n cleanWorkspace(): Promise<void>;\n\n rehydrateWorkspace(options: {\n taskId: string;\n targetPath: string;\n }): Promise<void>;\n}\n\nexport function resolveWorkspaceProvider(\n workspaceProviders?: Record<string, WorkspaceProvider>,\n config?: Config,\n): WorkspaceProvider | undefined {\n const legacySerializationEnabled =\n config?.getOptionalBoolean(\n 'scaffolder.EXPERIMENTAL_workspaceSerialization',\n ) ?? false;\n const providerName =\n config?.getOptionalString('scaffolder.taskRecovery.workspaceProvider') ??\n (legacySerializationEnabled\n ? config?.getOptionalString(\n 'scaffolder.EXPERIMENTAL_workspaceSerializationProvider',\n ) ?? 'database'\n : undefined);\n\n if (!providerName) {\n return undefined;\n }\n\n const workspaceProvider =\n workspaceProviders &&\n Object.prototype.hasOwnProperty.call(workspaceProviders, providerName)\n ? workspaceProviders[providerName]\n : undefined;\n\n if (!workspaceProvider) {\n const databaseProviderGuidance =\n providerName === 'database'\n ? ` For database storage, add '@backstage/plugin-scaffolder-backend-module-workspace-database'. ` +\n `When running in production, also set ` +\n `'scaffolder.taskRecovery.database.dangerouslyEnableInProduction' to true.`\n : '';\n throw new Error(\n `Workspace provider '${providerName}' is configured but not available. Make sure to install and register the corresponding module.${databaseProviderGuidance}`,\n );\n }\n\n return workspaceProvider;\n}\n\nexport class DefaultWorkspaceService implements WorkspaceService {\n static create(\n task: CurrentClaimedTask,\n workspaceProvider?: WorkspaceProvider,\n ) {\n return new DefaultWorkspaceService(task, workspaceProvider);\n }\n\n private readonly task: CurrentClaimedTask;\n private readonly workspaceProvider?: WorkspaceProvider;\n\n private constructor(\n task: CurrentClaimedTask,\n workspaceProvider: WorkspaceProvider | undefined,\n ) {\n this.task = task;\n this.workspaceProvider = workspaceProvider;\n }\n\n public async serializeWorkspace(options: { path: string }): Promise<void> {\n if (this.workspaceProvider) {\n await this.workspaceProvider.serializeWorkspace({\n path: options.path,\n taskId: this.task.taskId,\n });\n }\n }\n\n public async cleanWorkspace(): Promise<void> {\n if (this.workspaceProvider) {\n await this.workspaceProvider.cleanWorkspace({ taskId: this.task.taskId });\n }\n }\n\n public async rehydrateWorkspace(options: {\n taskId: string;\n targetPath: string;\n }): Promise<void> {\n if (this.workspaceProvider) {\n await fs.mkdirp(options.targetPath);\n await this.workspaceProvider.rehydrateWorkspace(options);\n }\n }\n}\n"],"names":["fs"],"mappings":";;;;;;;;AAgCO,SAAS,wBAAA,CACd,oBACA,MAAA,EAC+B;AAC/B,EAAA,MAAM,6BACJ,MAAA,EAAQ,kBAAA;AAAA,IACN;AAAA,GACF,IAAK,KAAA;AACP,EAAA,MAAM,eACJ,MAAA,EAAQ,iBAAA,CAAkB,2CAA2C,CAAA,KACpE,6BACG,MAAA,EAAQ,iBAAA;AAAA,IACN;AAAA,OACG,UAAA,GACL,MAAA,CAAA;AAEN,EAAA,IAAI,CAAC,YAAA,EAAc;AACjB,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,MAAM,iBAAA,GACJ,kBAAA,IACA,MAAA,CAAO,SAAA,CAAU,cAAA,CAAe,IAAA,CAAK,kBAAA,EAAoB,YAAY,CAAA,GACjE,kBAAA,CAAmB,YAAY,CAAA,GAC/B,MAAA;AAEN,EAAA,IAAI,CAAC,iBAAA,EAAmB;AACtB,IAAA,MAAM,wBAAA,GACJ,YAAA,KAAiB,UAAA,GACb,CAAA,2MAAA,CAAA,GAGA,EAAA;AACN,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,oBAAA,EAAuB,YAAY,CAAA,8FAAA,EAAiG,wBAAwB,CAAA;AAAA,KAC9J;AAAA,EACF;AAEA,EAAA,OAAO,iBAAA;AACT;AAEO,MAAM,uBAAA,CAAoD;AAAA,EAC/D,OAAO,MAAA,CACL,IAAA,EACA,iBAAA,EACA;AACA,IAAA,OAAO,IAAI,uBAAA,CAAwB,IAAA,EAAM,iBAAiB,CAAA;AAAA,EAC5D;AAAA,EAEiB,IAAA;AAAA,EACA,iBAAA;AAAA,EAET,WAAA,CACN,MACA,iBAAA,EACA;AACA,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AACZ,IAAA,IAAA,CAAK,iBAAA,GAAoB,iBAAA;AAAA,EAC3B;AAAA,EAEA,MAAa,mBAAmB,OAAA,EAA0C;AACxE,IAAA,IAAI,KAAK,iBAAA,EAAmB;AAC1B,MAAA,MAAM,IAAA,CAAK,kBAAkB,kBAAA,CAAmB;AAAA,QAC9C,MAAM,OAAA,CAAQ,IAAA;AAAA,QACd,MAAA,EAAQ,KAAK,IAAA,CAAK;AAAA,OACnB,CAAA;AAAA,IACH;AAAA,EACF;AAAA,EAEA,MAAa,cAAA,GAAgC;AAC3C,IAAA,IAAI,KAAK,iBAAA,EAAmB;AAC1B,MAAA,MAAM,IAAA,CAAK,kBAAkB,cAAA,CAAe,EAAE,QAAQ,IAAA,CAAK,IAAA,CAAK,QAAQ,CAAA;AAAA,IAC1E;AAAA,EACF;AAAA,EAEA,MAAa,mBAAmB,OAAA,EAGd;AAChB,IAAA,IAAI,KAAK,iBAAA,EAAmB;AAC1B,MAAA,MAAMA,mBAAA,CAAG,MAAA,CAAO,OAAA,CAAQ,UAAU,CAAA;AAClC,MAAA,MAAM,IAAA,CAAK,iBAAA,CAAkB,kBAAA,CAAmB,OAAO,CAAA;AAAA,IACzD;AAAA,EACF;AACF;;;;;"}
1
+ {"version":3,"file":"WorkspaceService.cjs.js","sources":["../../../src/scaffolder/tasks/WorkspaceService.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport { CurrentClaimedTask } from './StorageTaskBroker';\nimport { WorkspaceProvider } from '@backstage/plugin-scaffolder-node/alpha';\nimport { DatabaseWorkspaceProvider } from './DatabaseWorkspaceProvider';\nimport { TaskStore } from './types';\nimport fs from 'fs-extra';\n\nexport interface WorkspaceService {\n serializeWorkspace(options: { path: string }): Promise<void>;\n\n cleanWorkspace(): Promise<void>;\n\n rehydrateWorkspace(options: {\n taskId: string;\n targetPath: string;\n }): Promise<void>;\n}\n\nexport class DefaultWorkspaceService implements WorkspaceService {\n static create(\n task: CurrentClaimedTask,\n storage: TaskStore,\n additionalWorkspaceProviders?: Record<string, WorkspaceProvider>,\n config?: Config,\n ) {\n const workspaceProviderName =\n config?.getOptionalString(\n 'scaffolder.EXPERIMENTAL_workspaceSerializationProvider',\n ) ?? 'database';\n const workspaceProvider =\n additionalWorkspaceProviders?.[workspaceProviderName] ??\n DatabaseWorkspaceProvider.create(storage);\n return new DefaultWorkspaceService(task, workspaceProvider, config);\n }\n\n private readonly task: CurrentClaimedTask;\n private readonly workspaceProvider: WorkspaceProvider;\n private readonly config?: Config;\n\n private constructor(\n task: CurrentClaimedTask,\n workspaceProvider: WorkspaceProvider,\n config?: Config,\n ) {\n this.task = task;\n this.workspaceProvider = workspaceProvider;\n this.config = config;\n }\n\n public async serializeWorkspace(options: { path: string }): Promise<void> {\n if (this.isWorkspaceSerializationEnabled()) {\n await this.workspaceProvider.serializeWorkspace({\n path: options.path,\n taskId: this.task.taskId,\n });\n }\n }\n\n public async cleanWorkspace(): Promise<void> {\n if (this.isWorkspaceSerializationEnabled()) {\n await this.workspaceProvider.cleanWorkspace({ taskId: this.task.taskId });\n }\n }\n\n public async rehydrateWorkspace(options: {\n taskId: string;\n targetPath: string;\n }): Promise<void> {\n if (this.isWorkspaceSerializationEnabled()) {\n await fs.mkdirp(options.targetPath);\n await this.workspaceProvider.rehydrateWorkspace(options);\n }\n }\n\n private isWorkspaceSerializationEnabled(): boolean {\n return (\n this.config?.getOptionalBoolean(\n 'scaffolder.EXPERIMENTAL_workspaceSerialization',\n ) ?? false\n );\n }\n}\n"],"names":["DatabaseWorkspaceProvider","fs"],"mappings":";;;;;;;;;AAkCO,MAAM,uBAAA,CAAoD;AAAA,EAC/D,OAAO,MAAA,CACL,IAAA,EACA,OAAA,EACA,8BACA,MAAA,EACA;AACA,IAAA,MAAM,wBACJ,MAAA,EAAQ,iBAAA;AAAA,MACN;AAAA,KACF,IAAK,UAAA;AACP,IAAA,MAAM,oBACJ,4BAAA,GAA+B,qBAAqB,CAAA,IACpDA,mDAAA,CAA0B,OAAO,OAAO,CAAA;AAC1C,IAAA,OAAO,IAAI,uBAAA,CAAwB,IAAA,EAAM,iBAAA,EAAmB,MAAM,CAAA;AAAA,EACpE;AAAA,EAEiB,IAAA;AAAA,EACA,iBAAA;AAAA,EACA,MAAA;AAAA,EAET,WAAA,CACN,IAAA,EACA,iBAAA,EACA,MAAA,EACA;AACA,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AACZ,IAAA,IAAA,CAAK,iBAAA,GAAoB,iBAAA;AACzB,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AAAA,EAChB;AAAA,EAEA,MAAa,mBAAmB,OAAA,EAA0C;AACxE,IAAA,IAAI,IAAA,CAAK,iCAAgC,EAAG;AAC1C,MAAA,MAAM,IAAA,CAAK,kBAAkB,kBAAA,CAAmB;AAAA,QAC9C,MAAM,OAAA,CAAQ,IAAA;AAAA,QACd,MAAA,EAAQ,KAAK,IAAA,CAAK;AAAA,OACnB,CAAA;AAAA,IACH;AAAA,EACF;AAAA,EAEA,MAAa,cAAA,GAAgC;AAC3C,IAAA,IAAI,IAAA,CAAK,iCAAgC,EAAG;AAC1C,MAAA,MAAM,IAAA,CAAK,kBAAkB,cAAA,CAAe,EAAE,QAAQ,IAAA,CAAK,IAAA,CAAK,QAAQ,CAAA;AAAA,IAC1E;AAAA,EACF;AAAA,EAEA,MAAa,mBAAmB,OAAA,EAGd;AAChB,IAAA,IAAI,IAAA,CAAK,iCAAgC,EAAG;AAC1C,MAAA,MAAMC,mBAAA,CAAG,MAAA,CAAO,OAAA,CAAQ,UAAU,CAAA;AAClC,MAAA,MAAM,IAAA,CAAK,iBAAA,CAAkB,kBAAA,CAAmB,OAAO,CAAA;AAAA,IACzD;AAAA,EACF;AAAA,EAEQ,+BAAA,GAA2C;AACjD,IAAA,OACE,KAAK,MAAA,EAAQ,kBAAA;AAAA,MACX;AAAA,KACF,IAAK,KAAA;AAAA,EAET;AACF;;;;"}
@@ -52,6 +52,8 @@ class BackstageLoggerTransport extends Transport__default.default {
52
52
  class WinstonLogger {
53
53
  #winston;
54
54
  #addRedactions;
55
+ #redact;
56
+ #redactError;
55
57
  /**
56
58
  * Creates a {@link WinstonLogger} instance.
57
59
  */
@@ -65,7 +67,12 @@ class WinstonLogger {
65
67
  if (options.meta) {
66
68
  logger = logger.child(options.meta);
67
69
  }
68
- return new WinstonLogger(logger, redacter.add);
70
+ return new WinstonLogger(
71
+ logger,
72
+ redacter.add,
73
+ redacter.redact,
74
+ redacter.redactError
75
+ );
69
76
  }
70
77
  /**
71
78
  * Creates a winston log formatter for redacting secrets.
@@ -73,13 +80,85 @@ class WinstonLogger {
73
80
  static redacter() {
74
81
  const redactionSet = /* @__PURE__ */ new Set();
75
82
  let redactionPattern = void 0;
83
+ const redact = (value) => {
84
+ if (!redactionPattern) {
85
+ return value;
86
+ }
87
+ const ranges = Array.from(value.matchAll(redactionPattern), (match) => ({
88
+ start: match.index,
89
+ end: match.index + match[1].length
90
+ }));
91
+ if (ranges.length === 0) {
92
+ return value;
93
+ }
94
+ const mergedRanges = [];
95
+ for (const range of ranges) {
96
+ const previous = mergedRanges.at(-1);
97
+ if (previous && range.start < previous.end) {
98
+ previous.end = Math.max(previous.end, range.end);
99
+ } else {
100
+ mergedRanges.push(range);
101
+ }
102
+ }
103
+ let result = "";
104
+ let cursor = 0;
105
+ for (const range of mergedRanges) {
106
+ result += `${value.slice(cursor, range.start)}***`;
107
+ cursor = range.end;
108
+ }
109
+ return result + value.slice(cursor);
110
+ };
111
+ const createSanitizedError = (name = "Error", message = "Task failed", stack) => {
112
+ const sanitizedError = new Error(message);
113
+ sanitizedError.name = name;
114
+ if (stack !== void 0) {
115
+ sanitizedError.stack = stack;
116
+ }
117
+ return sanitizedError;
118
+ };
119
+ const createUnknownError = (value) => {
120
+ try {
121
+ return createSanitizedError(
122
+ "Error",
123
+ redact(`unknown error '${String(value)}'`)
124
+ );
125
+ } catch {
126
+ return createSanitizedError(
127
+ "Error",
128
+ `unknown error of type '${typeof value}'`
129
+ );
130
+ }
131
+ };
132
+ const redactError = (error) => {
133
+ if ((typeof error !== "object" || error === null) && typeof error !== "function") {
134
+ return typeof error === "string" ? createSanitizedError("Error", redact(error)) : createUnknownError(error);
135
+ }
136
+ const errorLike = error;
137
+ let originalName;
138
+ let originalMessage;
139
+ let originalStack;
140
+ try {
141
+ originalName = errorLike.name;
142
+ originalMessage = errorLike.message;
143
+ originalStack = errorLike.stack;
144
+ } catch {
145
+ return createSanitizedError();
146
+ }
147
+ if (typeof originalName !== "string" || !originalName || typeof originalMessage !== "string") {
148
+ return createUnknownError(error);
149
+ }
150
+ const name = redact(originalName);
151
+ const message = redact(originalMessage);
152
+ const stack = typeof originalStack === "string" ? redact(originalStack) : void 0;
153
+ return createSanitizedError(name, message, stack);
154
+ };
76
155
  return {
77
156
  format: winston.format((obj) => {
78
157
  if (!redactionPattern || !obj) {
79
158
  return obj;
80
159
  }
81
160
  if (typeof obj[tripleBeam.MESSAGE] === "string") {
82
- obj[tripleBeam.MESSAGE] = obj[tripleBeam.MESSAGE].replace(redactionPattern, "***");
161
+ obj[tripleBeam.MESSAGE] = redact(obj[tripleBeam.MESSAGE]);
83
162
  }
84
163
  return obj;
85
164
  })(),
@@ -99,10 +178,12 @@ class WinstonLogger {
99
178
  }
100
179
  }
101
180
  if (added > 0) {
102
- const redactions = Array.from(redactionSet).map((r) => escapeRegExp(r)).join("|");
103
- redactionPattern = new RegExp(`(${redactions})`, "g");
181
+ const redactions = Array.from(redactionSet).sort((a, b) => b.length - a.length).map((r) => escapeRegExp(r)).join("|");
182
+ redactionPattern = new RegExp(`(?=(${redactions}))`, "g");
104
183
  }
105
- }
184
+ },
185
+ redact,
186
+ redactError
106
187
  };
107
188
  }
108
189
  /**
@@ -138,9 +219,11 @@ class WinstonLogger {
138
219
  })
139
220
  );
140
221
  }
141
- constructor(winston, addRedactions) {
222
+ constructor(winston, addRedactions, redact, redactError) {
142
223
  this.#winston = winston;
143
224
  this.#addRedactions = addRedactions;
225
+ this.#redact = redact;
226
+ this.#redactError = redactError;
144
227
  }
145
228
  error(message, meta) {
146
229
  this.#winston.error(message, meta);
@@ -155,11 +238,22 @@ class WinstonLogger {
155
238
  this.#winston.debug(message, meta);
156
239
  }
157
240
  child(meta) {
158
- return new WinstonLogger(this.#winston.child(meta));
241
+ return new WinstonLogger(
242
+ this.#winston.child(meta),
243
+ this.#addRedactions,
244
+ this.#redact,
245
+ this.#redactError
246
+ );
159
247
  }
160
248
  addRedactions(redactions) {
161
249
  this.#addRedactions?.(redactions);
162
250
  }
251
+ redact(value) {
252
+ return this.#redact?.(value) ?? value;
253
+ }
254
+ redactError(error) {
255
+ return this.#redactError?.(error) ?? new Error("Task failed");
256
+ }
163
257
  }
164
258
 
165
259
  exports.BackstageLoggerTransport = BackstageLoggerTransport;
@@ -1 +1 @@
1
- {"version":3,"file":"logger.cjs.js","sources":["../../../src/scaffolder/tasks/logger.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n LoggerService,\n RootLoggerService,\n} from '@backstage/backend-plugin-api';\nimport { JsonObject } from '@backstage/types';\nimport { Format, TransformableInfo } from 'logform';\nimport Transport, { TransportStreamOptions } from 'winston-transport';\nimport { Logger, format, createLogger, transports } from 'winston';\nimport { LEVEL, MESSAGE, SPLAT } from 'triple-beam';\nimport { TaskContext } from '@backstage/plugin-scaffolder-node';\nimport _ from 'lodash';\n\n/**\n * Escapes a given string to be used inside a RegExp.\n *\n * Taken from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions\n */\nconst escapeRegExp = (text: string) => {\n return text.replace(/[.*+?^${}(\\)|[\\]\\\\]/g, '\\\\$&');\n};\n\ninterface WinstonLoggerOptions {\n meta?: JsonObject;\n level: string;\n format: Format;\n transports: Transport[];\n}\n\n// This is a workaround for being able to preserve the log format of the root logger.\n// Will revisit all of this implementation once we can break the router to use only `LoggerService`.\nexport class BackstageLoggerTransport extends Transport {\n private readonly backstageLogger: LoggerService;\n private readonly taskContext: TaskContext;\n private readonly stepId: string;\n\n constructor(\n backstageLogger: LoggerService,\n taskContext: TaskContext,\n stepId: string,\n opts?: TransportStreamOptions,\n ) {\n super(opts);\n this.backstageLogger = backstageLogger;\n this.taskContext = taskContext;\n this.stepId = stepId;\n }\n\n log(info: TransformableInfo, callback: VoidFunction) {\n if (typeof info !== 'object' || info === null) {\n callback();\n return;\n }\n\n const message = info[MESSAGE];\n const level = info[LEVEL];\n\n switch (level) {\n case 'error':\n this.backstageLogger.error(String(message));\n break;\n case 'warn':\n this.backstageLogger.warn(String(message));\n break;\n case 'info':\n this.backstageLogger.info(String(message));\n break;\n case 'debug':\n this.backstageLogger.debug(String(message));\n break;\n default:\n this.backstageLogger.info(String(message));\n break;\n }\n\n this.taskContext.emitLog(String(message), { stepId: this.stepId });\n callback();\n }\n}\n\nexport class WinstonLogger implements RootLoggerService {\n #winston: Logger;\n #addRedactions?: (redactions: Iterable<string>) => void;\n\n /**\n * Creates a {@link WinstonLogger} instance.\n */\n static create(options: WinstonLoggerOptions): WinstonLogger {\n const redacter = WinstonLogger.redacter();\n\n let logger = createLogger({\n level: options.level,\n format: format.combine(options.format, redacter.format),\n transports: options.transports ?? new transports.Console(),\n });\n\n if (options.meta) {\n logger = logger.child(options.meta);\n }\n\n return new WinstonLogger(logger, redacter.add);\n }\n\n /**\n * Creates a winston log formatter for redacting secrets.\n */\n static redacter(): {\n format: Format;\n add: (redactions: Iterable<string>) => void;\n } {\n const redactionSet = new Set<string>();\n\n let redactionPattern: RegExp | undefined = undefined;\n\n return {\n format: format((obj: TransformableInfo) => {\n if (!redactionPattern || !obj) {\n return obj;\n }\n\n if (typeof obj[MESSAGE] === 'string') {\n obj[MESSAGE] = obj[MESSAGE].replace(redactionPattern, '***');\n }\n\n return obj;\n })(),\n add(newRedactions) {\n let added = 0;\n for (const redactionToTrim of newRedactions) {\n // Skip null or undefined values\n if (redactionToTrim === null || redactionToTrim === undefined) {\n continue;\n }\n // Trimming the string ensures that we don't accdentally get extra\n // newlines or other whitespace interfering with the redaction; this\n // can happen for example when using string literals in yaml\n const redaction = redactionToTrim.trim();\n // Exclude secrets that are empty or just one character in length. These\n // typically mean that you are running local dev or tests, or using the\n // --lax flag which sets things to just 'x'.\n if (redaction.length <= 1) {\n continue;\n }\n if (!redactionSet.has(redaction)) {\n redactionSet.add(redaction);\n added += 1;\n }\n }\n if (added > 0) {\n const redactions = Array.from(redactionSet)\n .map(r => escapeRegExp(r))\n .join('|');\n redactionPattern = new RegExp(`(${redactions})`, 'g');\n }\n },\n };\n }\n\n /**\n * Creates a pretty printed winston log formatter.\n */\n static colorFormat(): Format {\n const colorizer = format.colorize();\n\n return format.combine(\n format.timestamp(),\n format.colorize({\n colors: {\n timestamp: 'dim',\n prefix: 'blue',\n field: 'cyan',\n debug: 'grey',\n },\n }),\n format.printf((info: TransformableInfo) => {\n const { timestamp, plugin, service } = info;\n const message = info[MESSAGE];\n const level = info[LEVEL];\n const fields = info[SPLAT];\n const prefix = plugin || service;\n const timestampColor = colorizer.colorize(\n 'timestamp',\n String(timestamp),\n );\n const prefixColor = colorizer.colorize('prefix', String(prefix));\n\n const extraFields = Object.entries(fields as any)\n .map(\n ([key, value]) =>\n `${colorizer.colorize('field', `${key}`)}=${value}`,\n )\n .join(' ');\n\n return `${timestampColor} ${prefixColor} ${level} ${message} ${extraFields}`;\n }),\n );\n }\n\n private constructor(\n winston: Logger,\n addRedactions?: (redactions: Iterable<string>) => void,\n ) {\n this.#winston = winston;\n this.#addRedactions = addRedactions;\n }\n\n error(message: string, meta?: JsonObject): void {\n this.#winston.error(message, meta);\n }\n\n warn(message: string, meta?: JsonObject): void {\n this.#winston.warn(message, meta);\n }\n\n info(message: string, meta?: JsonObject): void {\n this.#winston.info(message, meta);\n }\n\n debug(message: string, meta?: JsonObject): void {\n this.#winston.debug(message, meta);\n }\n\n child(meta: JsonObject): LoggerService {\n return new WinstonLogger(this.#winston.child(meta));\n }\n\n addRedactions(redactions: Iterable<string>) {\n this.#addRedactions?.(redactions);\n }\n}\n"],"names":["Transport","MESSAGE","LEVEL","createLogger","format","transports","SPLAT"],"mappings":";;;;;;;;;;AAgCA,MAAM,YAAA,GAAe,CAAC,IAAA,KAAiB;AACrC,EAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,sBAAA,EAAwB,MAAM,CAAA;AACpD,CAAA;AAWO,MAAM,iCAAiCA,0BAAA,CAAU;AAAA,EACrC,eAAA;AAAA,EACA,WAAA;AAAA,EACA,MAAA;AAAA,EAEjB,WAAA,CACE,eAAA,EACA,WAAA,EACA,MAAA,EACA,IAAA,EACA;AACA,IAAA,KAAA,CAAM,IAAI,CAAA;AACV,IAAA,IAAA,CAAK,eAAA,GAAkB,eAAA;AACvB,IAAA,IAAA,CAAK,WAAA,GAAc,WAAA;AACnB,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AAAA,EAChB;AAAA,EAEA,GAAA,CAAI,MAAyB,QAAA,EAAwB;AACnD,IAAA,IAAI,OAAO,IAAA,KAAS,QAAA,IAAY,IAAA,KAAS,IAAA,EAAM;AAC7C,MAAA,QAAA,EAAS;AACT,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,OAAA,GAAU,KAAKC,kBAAO,CAAA;AAC5B,IAAA,MAAM,KAAA,GAAQ,KAAKC,gBAAK,CAAA;AAExB,IAAA,QAAQ,KAAA;AAAO,MACb,KAAK,OAAA;AACH,QAAA,IAAA,CAAK,eAAA,CAAgB,KAAA,CAAM,MAAA,CAAO,OAAO,CAAC,CAAA;AAC1C,QAAA;AAAA,MACF,KAAK,MAAA;AACH,QAAA,IAAA,CAAK,eAAA,CAAgB,IAAA,CAAK,MAAA,CAAO,OAAO,CAAC,CAAA;AACzC,QAAA;AAAA,MACF,KAAK,MAAA;AACH,QAAA,IAAA,CAAK,eAAA,CAAgB,IAAA,CAAK,MAAA,CAAO,OAAO,CAAC,CAAA;AACzC,QAAA;AAAA,MACF,KAAK,OAAA;AACH,QAAA,IAAA,CAAK,eAAA,CAAgB,KAAA,CAAM,MAAA,CAAO,OAAO,CAAC,CAAA;AAC1C,QAAA;AAAA,MACF;AACE,QAAA,IAAA,CAAK,eAAA,CAAgB,IAAA,CAAK,MAAA,CAAO,OAAO,CAAC,CAAA;AACzC,QAAA;AAAA;AAGJ,IAAA,IAAA,CAAK,WAAA,CAAY,QAAQ,MAAA,CAAO,OAAO,GAAG,EAAE,MAAA,EAAQ,IAAA,CAAK,MAAA,EAAQ,CAAA;AACjE,IAAA,QAAA,EAAS;AAAA,EACX;AACF;AAEO,MAAM,aAAA,CAA2C;AAAA,EACtD,QAAA;AAAA,EACA,cAAA;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,OAAO,OAAA,EAA8C;AAC1D,IAAA,MAAM,QAAA,GAAW,cAAc,QAAA,EAAS;AAExC,IAAA,IAAI,SAASC,oBAAA,CAAa;AAAA,MACxB,OAAO,OAAA,CAAQ,KAAA;AAAA,MACf,QAAQC,cAAA,CAAO,OAAA,CAAQ,OAAA,CAAQ,MAAA,EAAQ,SAAS,MAAM,CAAA;AAAA,MACtD,UAAA,EAAY,OAAA,CAAQ,UAAA,IAAc,IAAIC,mBAAW,OAAA;AAAQ,KAC1D,CAAA;AAED,IAAA,IAAI,QAAQ,IAAA,EAAM;AAChB,MAAA,MAAA,GAAS,MAAA,CAAO,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA;AAAA,IACpC;AAEA,IAAA,OAAO,IAAI,aAAA,CAAc,MAAA,EAAQ,QAAA,CAAS,GAAG,CAAA;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,QAAA,GAGL;AACA,IAAA,MAAM,YAAA,uBAAmB,GAAA,EAAY;AAErC,IAAA,IAAI,gBAAA,GAAuC,MAAA;AAE3C,IAAA,OAAO;AAAA,MACL,MAAA,EAAQD,cAAA,CAAO,CAAC,GAAA,KAA2B;AACzC,QAAA,IAAI,CAAC,gBAAA,IAAoB,CAAC,GAAA,EAAK;AAC7B,UAAA,OAAO,GAAA;AAAA,QACT;AAEA,QAAA,IAAI,OAAO,GAAA,CAAIH,kBAAO,CAAA,KAAM,QAAA,EAAU;AACpC,UAAA,GAAA,CAAIA,kBAAO,CAAA,GAAI,GAAA,CAAIA,kBAAO,CAAA,CAAE,OAAA,CAAQ,kBAAkB,KAAK,CAAA;AAAA,QAC7D;AAEA,QAAA,OAAO,GAAA;AAAA,MACT,CAAC,CAAA,EAAE;AAAA,MACH,IAAI,aAAA,EAAe;AACjB,QAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,QAAA,KAAA,MAAW,mBAAmB,aAAA,EAAe;AAE3C,UAAA,IAAI,eAAA,KAAoB,IAAA,IAAQ,eAAA,KAAoB,MAAA,EAAW;AAC7D,YAAA;AAAA,UACF;AAIA,UAAA,MAAM,SAAA,GAAY,gBAAgB,IAAA,EAAK;AAIvC,UAAA,IAAI,SAAA,CAAU,UAAU,CAAA,EAAG;AACzB,YAAA;AAAA,UACF;AACA,UAAA,IAAI,CAAC,YAAA,CAAa,GAAA,CAAI,SAAS,CAAA,EAAG;AAChC,YAAA,YAAA,CAAa,IAAI,SAAS,CAAA;AAC1B,YAAA,KAAA,IAAS,CAAA;AAAA,UACX;AAAA,QACF;AACA,QAAA,IAAI,QAAQ,CAAA,EAAG;AACb,UAAA,MAAM,UAAA,GAAa,KAAA,CAAM,IAAA,CAAK,YAAY,CAAA,CACvC,GAAA,CAAI,CAAA,CAAA,KAAK,YAAA,CAAa,CAAC,CAAC,CAAA,CACxB,IAAA,CAAK,GAAG,CAAA;AACX,UAAA,gBAAA,GAAmB,IAAI,MAAA,CAAO,CAAA,CAAA,EAAI,UAAU,KAAK,GAAG,CAAA;AAAA,QACtD;AAAA,MACF;AAAA,KACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,WAAA,GAAsB;AAC3B,IAAA,MAAM,SAAA,GAAYG,eAAO,QAAA,EAAS;AAElC,IAAA,OAAOA,cAAA,CAAO,OAAA;AAAA,MACZA,eAAO,SAAA,EAAU;AAAA,MACjBA,eAAO,QAAA,CAAS;AAAA,QACd,MAAA,EAAQ;AAAA,UACN,SAAA,EAAW,KAAA;AAAA,UACX,MAAA,EAAQ,MAAA;AAAA,UACR,KAAA,EAAO,MAAA;AAAA,UACP,KAAA,EAAO;AAAA;AACT,OACD,CAAA;AAAA,MACDA,cAAA,CAAO,MAAA,CAAO,CAAC,IAAA,KAA4B;AACzC,QAAA,MAAM,EAAE,SAAA,EAAW,MAAA,EAAQ,OAAA,EAAQ,GAAI,IAAA;AACvC,QAAA,MAAM,OAAA,GAAU,KAAKH,kBAAO,CAAA;AAC5B,QAAA,MAAM,KAAA,GAAQ,KAAKC,gBAAK,CAAA;AACxB,QAAA,MAAM,MAAA,GAAS,KAAKI,gBAAK,CAAA;AACzB,QAAA,MAAM,SAAS,MAAA,IAAU,OAAA;AACzB,QAAA,MAAM,iBAAiB,SAAA,CAAU,QAAA;AAAA,UAC/B,WAAA;AAAA,UACA,OAAO,SAAS;AAAA,SAClB;AACA,QAAA,MAAM,cAAc,SAAA,CAAU,QAAA,CAAS,QAAA,EAAU,MAAA,CAAO,MAAM,CAAC,CAAA;AAE/D,QAAA,MAAM,WAAA,GAAc,MAAA,CAAO,OAAA,CAAQ,MAAa,CAAA,CAC7C,GAAA;AAAA,UACC,CAAC,CAAC,GAAA,EAAK,KAAK,MACV,CAAA,EAAG,SAAA,CAAU,QAAA,CAAS,OAAA,EAAS,CAAA,EAAG,GAAG,CAAA,CAAE,CAAC,IAAI,KAAK,CAAA;AAAA,SACrD,CACC,KAAK,GAAG,CAAA;AAEX,QAAA,OAAO,CAAA,EAAG,cAAc,CAAA,CAAA,EAAI,WAAW,IAAI,KAAK,CAAA,CAAA,EAAI,OAAO,CAAA,CAAA,EAAI,WAAW,CAAA,CAAA;AAAA,MAC5E,CAAC;AAAA,KACH;AAAA,EACF;AAAA,EAEQ,WAAA,CACN,SACA,aAAA,EACA;AACA,IAAA,IAAA,CAAK,QAAA,GAAW,OAAA;AAChB,IAAA,IAAA,CAAK,cAAA,GAAiB,aAAA;AAAA,EACxB;AAAA,EAEA,KAAA,CAAM,SAAiB,IAAA,EAAyB;AAC9C,IAAA,IAAA,CAAK,QAAA,CAAS,KAAA,CAAM,OAAA,EAAS,IAAI,CAAA;AAAA,EACnC;AAAA,EAEA,IAAA,CAAK,SAAiB,IAAA,EAAyB;AAC7C,IAAA,IAAA,CAAK,QAAA,CAAS,IAAA,CAAK,OAAA,EAAS,IAAI,CAAA;AAAA,EAClC;AAAA,EAEA,IAAA,CAAK,SAAiB,IAAA,EAAyB;AAC7C,IAAA,IAAA,CAAK,QAAA,CAAS,IAAA,CAAK,OAAA,EAAS,IAAI,CAAA;AAAA,EAClC;AAAA,EAEA,KAAA,CAAM,SAAiB,IAAA,EAAyB;AAC9C,IAAA,IAAA,CAAK,QAAA,CAAS,KAAA,CAAM,OAAA,EAAS,IAAI,CAAA;AAAA,EACnC;AAAA,EAEA,MAAM,IAAA,EAAiC;AACrC,IAAA,OAAO,IAAI,aAAA,CAAc,IAAA,CAAK,QAAA,CAAS,KAAA,CAAM,IAAI,CAAC,CAAA;AAAA,EACpD;AAAA,EAEA,cAAc,UAAA,EAA8B;AAC1C,IAAA,IAAA,CAAK,iBAAiB,UAAU,CAAA;AAAA,EAClC;AACF;;;;;"}
1
+ {"version":3,"file":"logger.cjs.js","sources":["../../../src/scaffolder/tasks/logger.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n LoggerService,\n RootLoggerService,\n} from '@backstage/backend-plugin-api';\nimport { JsonObject } from '@backstage/types';\nimport { Format, TransformableInfo } from 'logform';\nimport Transport, { TransportStreamOptions } from 'winston-transport';\nimport { Logger, format, createLogger, transports } from 'winston';\nimport { LEVEL, MESSAGE, SPLAT } from 'triple-beam';\nimport { TaskContext } from '@backstage/plugin-scaffolder-node';\nimport type { ErrorLike } from '@backstage/errors';\nimport _ from 'lodash';\n\n/**\n * Escapes a given string to be used inside a RegExp.\n *\n * Taken from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions\n */\nconst escapeRegExp = (text: string) => {\n return text.replace(/[.*+?^${}(\\)|[\\]\\\\]/g, '\\\\$&');\n};\n\ninterface WinstonLoggerOptions {\n meta?: JsonObject;\n level: string;\n format: Format;\n transports: Transport[];\n}\n\n// This is a workaround for being able to preserve the log format of the root logger.\n// Will revisit all of this implementation once we can break the router to use only `LoggerService`.\nexport class BackstageLoggerTransport extends Transport {\n private readonly backstageLogger: LoggerService;\n private readonly taskContext: TaskContext;\n private readonly stepId: string;\n\n constructor(\n backstageLogger: LoggerService,\n taskContext: TaskContext,\n stepId: string,\n opts?: TransportStreamOptions,\n ) {\n super(opts);\n this.backstageLogger = backstageLogger;\n this.taskContext = taskContext;\n this.stepId = stepId;\n }\n\n log(info: TransformableInfo, callback: VoidFunction) {\n if (typeof info !== 'object' || info === null) {\n callback();\n return;\n }\n\n const message = info[MESSAGE];\n const level = info[LEVEL];\n\n switch (level) {\n case 'error':\n this.backstageLogger.error(String(message));\n break;\n case 'warn':\n this.backstageLogger.warn(String(message));\n break;\n case 'info':\n this.backstageLogger.info(String(message));\n break;\n case 'debug':\n this.backstageLogger.debug(String(message));\n break;\n default:\n this.backstageLogger.info(String(message));\n break;\n }\n\n this.taskContext.emitLog(String(message), { stepId: this.stepId });\n callback();\n }\n}\n\nexport class WinstonLogger implements RootLoggerService {\n #winston: Logger;\n #addRedactions?: (redactions: Iterable<string>) => void;\n #redact?: (value: string) => string;\n #redactError?: (error: unknown) => ErrorLike;\n\n /**\n * Creates a {@link WinstonLogger} instance.\n */\n static create(options: WinstonLoggerOptions): WinstonLogger {\n const redacter = WinstonLogger.redacter();\n\n let logger = createLogger({\n level: options.level,\n format: format.combine(options.format, redacter.format),\n transports: options.transports ?? new transports.Console(),\n });\n\n if (options.meta) {\n logger = logger.child(options.meta);\n }\n\n return new WinstonLogger(\n logger,\n redacter.add,\n redacter.redact,\n redacter.redactError,\n );\n }\n\n /**\n * Creates a winston log formatter for redacting secrets.\n */\n static redacter(): {\n format: Format;\n add: (redactions: Iterable<string>) => void;\n redact: (value: string) => string;\n redactError: (error: unknown) => ErrorLike;\n } {\n const redactionSet = new Set<string>();\n\n let redactionPattern: RegExp | undefined = undefined;\n\n const redact = (value: string) => {\n if (!redactionPattern) {\n return value;\n }\n\n const ranges = Array.from(value.matchAll(redactionPattern), match => ({\n start: match.index,\n end: match.index + match[1].length,\n }));\n if (ranges.length === 0) {\n return value;\n }\n\n const mergedRanges: { start: number; end: number }[] = [];\n for (const range of ranges) {\n const previous = mergedRanges.at(-1);\n if (previous && range.start < previous.end) {\n previous.end = Math.max(previous.end, range.end);\n } else {\n mergedRanges.push(range);\n }\n }\n\n let result = '';\n let cursor = 0;\n for (const range of mergedRanges) {\n result += `${value.slice(cursor, range.start)}***`;\n cursor = range.end;\n }\n return result + value.slice(cursor);\n };\n\n const createSanitizedError = (\n name = 'Error',\n message = 'Task failed',\n stack?: string,\n ): ErrorLike => {\n const sanitizedError = new Error(message) as ErrorLike;\n sanitizedError.name = name;\n if (stack !== undefined) {\n sanitizedError.stack = stack;\n }\n return sanitizedError;\n };\n\n const createUnknownError = (value: unknown): ErrorLike => {\n try {\n return createSanitizedError(\n 'Error',\n redact(`unknown error '${String(value)}'`),\n );\n } catch {\n return createSanitizedError(\n 'Error',\n `unknown error of type '${typeof value}'`,\n );\n }\n };\n\n const redactError = (error: unknown): ErrorLike => {\n if (\n (typeof error !== 'object' || error === null) &&\n typeof error !== 'function'\n ) {\n return typeof error === 'string'\n ? createSanitizedError('Error', redact(error))\n : createUnknownError(error);\n }\n\n const errorLike = error as Partial<ErrorLike>;\n let originalName: unknown;\n let originalMessage: unknown;\n let originalStack: unknown;\n\n try {\n originalName = errorLike.name;\n originalMessage = errorLike.message;\n originalStack = errorLike.stack;\n } catch {\n return createSanitizedError();\n }\n\n if (\n typeof originalName !== 'string' ||\n !originalName ||\n typeof originalMessage !== 'string'\n ) {\n return createUnknownError(error);\n }\n\n const name = redact(originalName);\n const message = redact(originalMessage);\n const stack =\n typeof originalStack === 'string' ? redact(originalStack) : undefined;\n\n return createSanitizedError(name, message, stack);\n };\n\n return {\n format: format((obj: TransformableInfo) => {\n if (!redactionPattern || !obj) {\n return obj;\n }\n\n if (typeof obj[MESSAGE] === 'string') {\n obj[MESSAGE] = redact(obj[MESSAGE]);\n }\n\n return obj;\n })(),\n add(newRedactions) {\n let added = 0;\n for (const redactionToTrim of newRedactions) {\n // Skip null or undefined values\n if (redactionToTrim === null || redactionToTrim === undefined) {\n continue;\n }\n // Trimming the string ensures that we don't accdentally get extra\n // newlines or other whitespace interfering with the redaction; this\n // can happen for example when using string literals in yaml\n const redaction = redactionToTrim.trim();\n // Exclude secrets that are empty or just one character in length. These\n // typically mean that you are running local dev or tests, or using the\n // --lax flag which sets things to just 'x'.\n if (redaction.length <= 1) {\n continue;\n }\n if (!redactionSet.has(redaction)) {\n redactionSet.add(redaction);\n added += 1;\n }\n }\n if (added > 0) {\n const redactions = Array.from(redactionSet)\n .sort((a, b) => b.length - a.length)\n .map(r => escapeRegExp(r))\n .join('|');\n redactionPattern = new RegExp(`(?=(${redactions}))`, 'g');\n }\n },\n redact,\n redactError,\n };\n }\n\n /**\n * Creates a pretty printed winston log formatter.\n */\n static colorFormat(): Format {\n const colorizer = format.colorize();\n\n return format.combine(\n format.timestamp(),\n format.colorize({\n colors: {\n timestamp: 'dim',\n prefix: 'blue',\n field: 'cyan',\n debug: 'grey',\n },\n }),\n format.printf((info: TransformableInfo) => {\n const { timestamp, plugin, service } = info;\n const message = info[MESSAGE];\n const level = info[LEVEL];\n const fields = info[SPLAT];\n const prefix = plugin || service;\n const timestampColor = colorizer.colorize(\n 'timestamp',\n String(timestamp),\n );\n const prefixColor = colorizer.colorize('prefix', String(prefix));\n\n const extraFields = Object.entries(fields as any)\n .map(\n ([key, value]) =>\n `${colorizer.colorize('field', `${key}`)}=${value}`,\n )\n .join(' ');\n\n return `${timestampColor} ${prefixColor} ${level} ${message} ${extraFields}`;\n }),\n );\n }\n\n private constructor(\n winston: Logger,\n addRedactions?: (redactions: Iterable<string>) => void,\n redact?: (value: string) => string,\n redactError?: (error: unknown) => ErrorLike,\n ) {\n this.#winston = winston;\n this.#addRedactions = addRedactions;\n this.#redact = redact;\n this.#redactError = redactError;\n }\n\n error(message: string, meta?: JsonObject): void {\n this.#winston.error(message, meta);\n }\n\n warn(message: string, meta?: JsonObject): void {\n this.#winston.warn(message, meta);\n }\n\n info(message: string, meta?: JsonObject): void {\n this.#winston.info(message, meta);\n }\n\n debug(message: string, meta?: JsonObject): void {\n this.#winston.debug(message, meta);\n }\n\n child(meta: JsonObject): LoggerService {\n return new WinstonLogger(\n this.#winston.child(meta),\n this.#addRedactions,\n this.#redact,\n this.#redactError,\n );\n }\n\n addRedactions(redactions: Iterable<string>) {\n this.#addRedactions?.(redactions);\n }\n\n redact(value: string) {\n return this.#redact?.(value) ?? value;\n }\n\n redactError(error: unknown): ErrorLike {\n return (\n this.#redactError?.(error) ?? (new Error('Task failed') as ErrorLike)\n );\n }\n}\n"],"names":["Transport","MESSAGE","LEVEL","createLogger","format","transports","SPLAT"],"mappings":"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"}
@@ -13,10 +13,6 @@ const trimEventsTillLastRecovery = (events) => {
13
13
  }
14
14
  return { events };
15
15
  };
16
- const isTaskRecoveryEnabled = (config) => {
17
- return config?.getOptionalBoolean("scaffolder.taskRecovery.enabled") ?? config?.getOptionalBoolean("scaffolder.EXPERIMENTAL_recoverTasks") ?? false;
18
- };
19
16
 
20
- exports.isTaskRecoveryEnabled = isTaskRecoveryEnabled;
21
17
  exports.trimEventsTillLastRecovery = trimEventsTillLastRecovery;
22
18
  //# sourceMappingURL=taskRecoveryHelper.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"taskRecoveryHelper.cjs.js","sources":["../../../src/scaffolder/tasks/taskRecoveryHelper.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { SerializedTaskEvent } from '@backstage/plugin-scaffolder-node';\nimport { Config } from '@backstage/config';\nimport { TaskRecoverStrategy } from '@backstage/plugin-scaffolder-common';\n\nexport const trimEventsTillLastRecovery = (\n events: SerializedTaskEvent[],\n): { events: SerializedTaskEvent[] } => {\n const recoveredEventInd = events\n .slice()\n .reverse()\n .findIndex(event => event.type === 'recovered');\n\n if (recoveredEventInd >= 0) {\n const ind = events.length - recoveredEventInd - 1;\n const { recoverStrategy } = events[ind].body as {\n recoverStrategy?: TaskRecoverStrategy;\n };\n if (recoverStrategy === 'startOver') {\n return {\n events: recoveredEventInd === 0 ? [] : events.slice(ind),\n };\n }\n }\n\n return { events };\n};\n\n/**\n * Resolves whether automatic task recovery is enabled, falling back to the\n * legacy `EXPERIMENTAL_recoverTasks` flag for backwards compatibility.\n */\nexport const isTaskRecoveryEnabled = (config?: Config): boolean => {\n return (\n config?.getOptionalBoolean('scaffolder.taskRecovery.enabled') ??\n config?.getOptionalBoolean('scaffolder.EXPERIMENTAL_recoverTasks') ??\n false\n );\n};\n"],"names":[],"mappings":";;AAoBO,MAAM,0BAAA,GAA6B,CACxC,MAAA,KACsC;AACtC,EAAA,MAAM,iBAAA,GAAoB,MAAA,CACvB,KAAA,EAAM,CACN,OAAA,GACA,SAAA,CAAU,CAAA,KAAA,KAAS,KAAA,CAAM,IAAA,KAAS,WAAW,CAAA;AAEhD,EAAA,IAAI,qBAAqB,CAAA,EAAG;AAC1B,IAAA,MAAM,GAAA,GAAM,MAAA,CAAO,MAAA,GAAS,iBAAA,GAAoB,CAAA;AAChD,IAAA,MAAM,EAAE,eAAA,EAAgB,GAAI,MAAA,CAAO,GAAG,CAAA,CAAE,IAAA;AAGxC,IAAA,IAAI,oBAAoB,WAAA,EAAa;AACnC,MAAA,OAAO;AAAA,QACL,QAAQ,iBAAA,KAAsB,CAAA,GAAI,EAAC,GAAI,MAAA,CAAO,MAAM,GAAG;AAAA,OACzD;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAO,EAAE,MAAA,EAAO;AAClB;AAMO,MAAM,qBAAA,GAAwB,CAAC,MAAA,KAA6B;AACjE,EAAA,OACE,QAAQ,kBAAA,CAAmB,iCAAiC,KAC5D,MAAA,EAAQ,kBAAA,CAAmB,sCAAsC,CAAA,IACjE,KAAA;AAEJ;;;;;"}
1
+ {"version":3,"file":"taskRecoveryHelper.cjs.js","sources":["../../../src/scaffolder/tasks/taskRecoveryHelper.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { SerializedTaskEvent } from '@backstage/plugin-scaffolder-node';\nimport { TaskRecoverStrategy } from '@backstage/plugin-scaffolder-common';\n\nexport const trimEventsTillLastRecovery = (\n events: SerializedTaskEvent[],\n): { events: SerializedTaskEvent[] } => {\n const recoveredEventInd = events\n .slice()\n .reverse()\n .findIndex(event => event.type === 'recovered');\n\n if (recoveredEventInd >= 0) {\n const ind = events.length - recoveredEventInd - 1;\n const { recoverStrategy } = events[ind].body as {\n recoverStrategy?: TaskRecoverStrategy;\n };\n if (recoverStrategy === 'startOver') {\n return {\n events: recoveredEventInd === 0 ? [] : events.slice(ind),\n };\n }\n }\n\n return { events };\n};\n"],"names":[],"mappings":";;AAmBO,MAAM,0BAAA,GAA6B,CACxC,MAAA,KACsC;AACtC,EAAA,MAAM,iBAAA,GAAoB,MAAA,CACvB,KAAA,EAAM,CACN,OAAA,GACA,SAAA,CAAU,CAAA,KAAA,KAAS,KAAA,CAAM,IAAA,KAAS,WAAW,CAAA;AAEhD,EAAA,IAAI,qBAAqB,CAAA,EAAG;AAC1B,IAAA,MAAM,GAAA,GAAM,MAAA,CAAO,MAAA,GAAS,iBAAA,GAAoB,CAAA;AAChD,IAAA,MAAM,EAAE,eAAA,EAAgB,GAAI,MAAA,CAAO,GAAG,CAAA,CAAE,IAAA;AAGxC,IAAA,IAAI,oBAAoB,WAAA,EAAa;AACnC,MAAA,OAAO;AAAA,QACL,QAAQ,iBAAA,KAAsB,CAAA,GAAI,EAAC,GAAI,MAAA,CAAO,MAAM,GAAG;AAAA,OACzD;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAO,EAAE,MAAA,EAAO;AAClB;;;;"}