@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.
- package/CHANGELOG.md +23 -11
- package/README.md +0 -23
- package/config.schema.json +7 -63
- package/dist/ScaffolderPlugin.cjs.js +9 -2
- package/dist/ScaffolderPlugin.cjs.js.map +1 -1
- package/dist/actions/createDryRunTemplateAction.cjs.js +0 -2
- package/dist/actions/createDryRunTemplateAction.cjs.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/scaffolder/actions/builtin/fetch/assertScmUserCredentials.cjs.js +34 -0
- package/dist/scaffolder/actions/builtin/fetch/assertScmUserCredentials.cjs.js.map +1 -0
- package/dist/scaffolder/actions/builtin/fetch/plain.cjs.js +9 -1
- package/dist/scaffolder/actions/builtin/fetch/plain.cjs.js.map +1 -1
- package/dist/scaffolder/actions/builtin/fetch/plainFile.cjs.js +9 -1
- package/dist/scaffolder/actions/builtin/fetch/plainFile.cjs.js.map +1 -1
- package/dist/scaffolder/actions/builtin/fetch/template.cjs.js +8 -0
- package/dist/scaffolder/actions/builtin/fetch/template.cjs.js.map +1 -1
- package/dist/scaffolder/actions/builtin/fetch/templateFile.cjs.js +8 -0
- package/dist/scaffolder/actions/builtin/fetch/templateFile.cjs.js.map +1 -1
- package/dist/scaffolder/tasks/DatabaseTaskStore.cjs.js +53 -78
- package/dist/scaffolder/tasks/DatabaseTaskStore.cjs.js.map +1 -1
- package/dist/scaffolder/tasks/DatabaseWorkspaceProvider.cjs.js +23 -0
- package/dist/scaffolder/tasks/DatabaseWorkspaceProvider.cjs.js.map +1 -0
- package/dist/scaffolder/tasks/NunjucksWorkflowRunner.cjs.js +130 -91
- package/dist/scaffolder/tasks/NunjucksWorkflowRunner.cjs.js.map +1 -1
- package/dist/scaffolder/tasks/StorageTaskBroker.cjs.js +29 -53
- package/dist/scaffolder/tasks/StorageTaskBroker.cjs.js.map +1 -1
- package/dist/scaffolder/tasks/WorkspaceService.cjs.js +18 -26
- package/dist/scaffolder/tasks/WorkspaceService.cjs.js.map +1 -1
- package/dist/scaffolder/tasks/logger.cjs.js +101 -7
- package/dist/scaffolder/tasks/logger.cjs.js.map +1 -1
- package/dist/scaffolder/tasks/taskRecoveryHelper.cjs.js +0 -4
- package/dist/scaffolder/tasks/taskRecoveryHelper.cjs.js.map +1 -1
- package/dist/schema/openapi/generated/router.cjs.js +6 -6
- package/dist/schema/openapi/generated/router.cjs.js.map +1 -1
- package/dist/service/router.cjs.js +22 -9
- package/dist/service/router.cjs.js.map +1 -1
- package/dist/service/rules.cjs.js +12 -0
- package/dist/service/rules.cjs.js.map +1 -1
- package/dist/util/checkPermissions.cjs.js +3 -0
- package/dist/util/checkPermissions.cjs.js.map +1 -1
- 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,
|
|
15
|
+
static create(task, storage, abortSignal, logger, auth, config, additionalWorkspaceProviders) {
|
|
17
16
|
const workspaceService = WorkspaceService.DefaultWorkspaceService.create(
|
|
18
17
|
task,
|
|
19
|
-
|
|
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
|
|
83
|
-
|
|
84
|
-
|
|
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
|
-
|
|
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.
|
|
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 =
|
|
208
|
-
if (
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
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.
|
|
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,
|
|
30
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
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(
|
|
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]
|
|
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(
|
|
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":"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"}
|
|
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 {
|
|
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;;;;"}
|