@backstage/plugin-scaffolder-backend 1.29.0 → 1.30.0-next.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 +35 -0
- package/README.md +29 -0
- package/dist/ScaffolderPlugin.cjs.js +8 -5
- package/dist/ScaffolderPlugin.cjs.js.map +1 -1
- package/dist/index.d.ts +7 -4
- package/dist/scaffolder/dryrun/createDryRunner.cjs.js +5 -4
- package/dist/scaffolder/dryrun/createDryRunner.cjs.js.map +1 -1
- package/dist/scaffolder/tasks/NunjucksWorkflowRunner.cjs.js +18 -14
- package/dist/scaffolder/tasks/NunjucksWorkflowRunner.cjs.js.map +1 -1
- package/dist/scaffolder/tasks/StorageTaskBroker.cjs.js +14 -5
- package/dist/scaffolder/tasks/StorageTaskBroker.cjs.js.map +1 -1
- package/dist/scaffolder/tasks/TaskWorker.cjs.js +21 -2
- package/dist/scaffolder/tasks/TaskWorker.cjs.js.map +1 -1
- package/dist/service/router.cjs.js +475 -309
- package/dist/service/router.cjs.js.map +1 -1
- package/package.json +31 -31
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,40 @@
|
|
|
1
1
|
# @backstage/plugin-scaffolder-backend
|
|
2
2
|
|
|
3
|
+
## 1.30.0-next.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- a4aa244: This change integrates the `auditor` service into the Scaffolder plugin.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies
|
|
12
|
+
- @backstage/plugin-permission-node@0.8.8-next.0
|
|
13
|
+
- @backstage/backend-defaults@0.8.0-next.0
|
|
14
|
+
- @backstage/plugin-catalog-node@1.15.2-next.0
|
|
15
|
+
- @backstage/backend-plugin-api@1.2.0-next.0
|
|
16
|
+
- @backstage/plugin-scaffolder-node@0.7.0-next.0
|
|
17
|
+
- @backstage/catalog-client@1.9.1
|
|
18
|
+
- @backstage/catalog-model@1.7.3
|
|
19
|
+
- @backstage/config@1.3.2
|
|
20
|
+
- @backstage/errors@1.2.7
|
|
21
|
+
- @backstage/integration@1.16.1
|
|
22
|
+
- @backstage/types@1.2.1
|
|
23
|
+
- @backstage/plugin-auth-node@0.5.7-next.0
|
|
24
|
+
- @backstage/plugin-bitbucket-cloud-common@0.2.27
|
|
25
|
+
- @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.5-next.0
|
|
26
|
+
- @backstage/plugin-events-node@0.4.8-next.0
|
|
27
|
+
- @backstage/plugin-permission-common@0.8.4
|
|
28
|
+
- @backstage/plugin-scaffolder-backend-module-azure@0.2.6-next.0
|
|
29
|
+
- @backstage/plugin-scaffolder-backend-module-bitbucket@0.3.7-next.0
|
|
30
|
+
- @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.6-next.0
|
|
31
|
+
- @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.6-next.0
|
|
32
|
+
- @backstage/plugin-scaffolder-backend-module-gerrit@0.2.6-next.0
|
|
33
|
+
- @backstage/plugin-scaffolder-backend-module-gitea@0.2.6-next.0
|
|
34
|
+
- @backstage/plugin-scaffolder-backend-module-github@0.5.6-next.0
|
|
35
|
+
- @backstage/plugin-scaffolder-backend-module-gitlab@0.7.2-next.0
|
|
36
|
+
- @backstage/plugin-scaffolder-common@1.5.9
|
|
37
|
+
|
|
3
38
|
## 1.29.0
|
|
4
39
|
|
|
5
40
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -63,3 +63,32 @@ you will not have any templates available to use. These need to be [added to the
|
|
|
63
63
|
|
|
64
64
|
To get up and running and try out some templates quickly, you can or copy the
|
|
65
65
|
catalog locations from the [create-app template](https://github.com/backstage/backstage/blob/master/packages/create-app/templates/default-app/app-config.yaml.hbs).
|
|
66
|
+
|
|
67
|
+
## Audit Events
|
|
68
|
+
|
|
69
|
+
The Scaffolder backend emits audit events for various operations. Events are grouped logically by `eventId`, with `subEventId` providing further distinction when needed.
|
|
70
|
+
|
|
71
|
+
**Template Events:**
|
|
72
|
+
|
|
73
|
+
- **`template-parameter-schema`**: Retrieves template parameter schemas. (GET `/v2/templates/:namespace/:kind/:name/parameter-schema`)
|
|
74
|
+
|
|
75
|
+
**Action Events:**
|
|
76
|
+
|
|
77
|
+
- **`action-fetch`**: Retrieves installed actions. (GET `/v2/actions`)
|
|
78
|
+
|
|
79
|
+
**Task Events:**
|
|
80
|
+
|
|
81
|
+
- **`task`**: Operations related to Scaffolder tasks.
|
|
82
|
+
|
|
83
|
+
Filter on `actionType`.
|
|
84
|
+
|
|
85
|
+
- **`create`**: Creates a new task. (POST `/v2/tasks`)
|
|
86
|
+
- **`list`**: Fetches details of all tasks. (GET `/v2/tasks`)
|
|
87
|
+
- **`get`**: Fetches details of a specific task. (GET `/v2/tasks/:taskId`)
|
|
88
|
+
- **`cancel`**: Cancels a running task. (POST `/v2/tasks/:taskId/cancel`)
|
|
89
|
+
- **`retry`**: Retries a failed task. (POST `/v2/tasks/:taskId/retry`)
|
|
90
|
+
- **`stream`**: Retrieves a stream of task logs. (GET `/v2/tasks/:taskId/eventstream`)
|
|
91
|
+
- **`events`**: Retrieves a snapshot of task logs. (GET `/v2/tasks/:taskId/events`)
|
|
92
|
+
- **`dry-run`**: Creates a dry-run task. (POST `/v2/dry-run`) All audit logs for events associated with dry runs have the `meta.isDryLog` flag set to `true`.
|
|
93
|
+
- **`stale-cancel`**: Automated cancellation of stale tasks.
|
|
94
|
+
- **`execute`**: Tracks the initiation and completion of a real scaffolder task execution. This event will not occur during dry runs.
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var backendPluginApi = require('@backstage/backend-plugin-api');
|
|
4
3
|
var backendCommon = require('@backstage/backend-common');
|
|
4
|
+
var backendPluginApi = require('@backstage/backend-plugin-api');
|
|
5
5
|
var integration = require('@backstage/integration');
|
|
6
6
|
var alpha$1 = require('@backstage/plugin-catalog-node/alpha');
|
|
7
|
+
var pluginEventsNode = require('@backstage/plugin-events-node');
|
|
7
8
|
var alpha = require('@backstage/plugin-scaffolder-node/alpha');
|
|
8
9
|
var register = require('./scaffolder/actions/builtin/catalog/register.cjs.js');
|
|
9
10
|
var write = require('./scaffolder/actions/builtin/catalog/write.cjs.js');
|
|
@@ -29,13 +30,12 @@ require('@backstage/errors');
|
|
|
29
30
|
require('./scaffolder/tasks/DatabaseTaskStore.cjs.js');
|
|
30
31
|
require('@backstage/types');
|
|
31
32
|
require('zen-observable');
|
|
33
|
+
require('fs-extra');
|
|
32
34
|
require('@backstage/config');
|
|
33
35
|
require('lodash');
|
|
34
|
-
require('fs-extra');
|
|
35
36
|
require('p-queue');
|
|
36
37
|
require('./scaffolder/tasks/NunjucksWorkflowRunner.cjs.js');
|
|
37
38
|
var router = require('./service/router.cjs.js');
|
|
38
|
-
var pluginEventsNode = require('@backstage/plugin-events-node');
|
|
39
39
|
|
|
40
40
|
const scaffolderPlugin = backendPluginApi.createBackendPlugin({
|
|
41
41
|
pluginId: "scaffolder",
|
|
@@ -89,6 +89,7 @@ const scaffolderPlugin = backendPluginApi.createBackendPlugin({
|
|
|
89
89
|
discovery: backendPluginApi.coreServices.discovery,
|
|
90
90
|
httpRouter: backendPluginApi.coreServices.httpRouter,
|
|
91
91
|
httpAuth: backendPluginApi.coreServices.httpAuth,
|
|
92
|
+
auditor: backendPluginApi.coreServices.auditor,
|
|
92
93
|
catalogClient: alpha$1.catalogServiceRef,
|
|
93
94
|
events: pluginEventsNode.eventsServiceRef
|
|
94
95
|
},
|
|
@@ -104,7 +105,8 @@ const scaffolderPlugin = backendPluginApi.createBackendPlugin({
|
|
|
104
105
|
httpAuth,
|
|
105
106
|
catalogClient,
|
|
106
107
|
permissions,
|
|
107
|
-
events
|
|
108
|
+
events,
|
|
109
|
+
auditor
|
|
108
110
|
}) {
|
|
109
111
|
const log$1 = backendCommon.loggerToWinstonLogger(logger);
|
|
110
112
|
const integrations = integration.ScmIntegrations.fromConfig(config);
|
|
@@ -163,7 +165,8 @@ const scaffolderPlugin = backendPluginApi.createBackendPlugin({
|
|
|
163
165
|
permissions,
|
|
164
166
|
autocompleteHandlers,
|
|
165
167
|
additionalWorkspaceProviders,
|
|
166
|
-
events
|
|
168
|
+
events,
|
|
169
|
+
auditor
|
|
167
170
|
});
|
|
168
171
|
httpRouter.use(router$1);
|
|
169
172
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ScaffolderPlugin.cjs.js","sources":["../src/ScaffolderPlugin.ts"],"sourcesContent":["/*\n * Copyright 2022 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 coreServices,\n createBackendPlugin,\n} from '@backstage/backend-plugin-api';\nimport { loggerToWinstonLogger } from '@backstage/backend-common';\nimport { ScmIntegrations } from '@backstage/integration';\nimport { catalogServiceRef } from '@backstage/plugin-catalog-node/alpha';\nimport {\n TaskBroker,\n TemplateAction,\n TemplateFilter,\n TemplateGlobal,\n} from '@backstage/plugin-scaffolder-node';\nimport {\n AutocompleteHandler,\n scaffolderActionsExtensionPoint,\n scaffolderAutocompleteExtensionPoint,\n scaffolderTaskBrokerExtensionPoint,\n scaffolderTemplatingExtensionPoint,\n scaffolderWorkspaceProviderExtensionPoint,\n WorkspaceProvider,\n} from '@backstage/plugin-scaffolder-node/alpha';\nimport {\n createCatalogRegisterAction,\n createCatalogWriteAction,\n createDebugLogAction,\n createFetchCatalogEntityAction,\n createFetchPlainAction,\n createFetchPlainFileAction,\n createFetchTemplateAction,\n createFetchTemplateFileAction,\n createFilesystemDeleteAction,\n createFilesystemRenameAction,\n createFilesystemReadDirAction,\n createWaitAction,\n} from './scaffolder';\nimport { createRouter } from './service/router';\nimport { eventsServiceRef } from '@backstage/plugin-events-node';\n\n/**\n * Scaffolder plugin\n *\n * @public\n */\nexport const scaffolderPlugin = createBackendPlugin({\n pluginId: 'scaffolder',\n register(env) {\n const addedActions = new Array<TemplateAction<any, any>>();\n env.registerExtensionPoint(scaffolderActionsExtensionPoint, {\n addActions(...newActions: TemplateAction<any>[]) {\n addedActions.push(...newActions);\n },\n });\n\n let taskBroker: TaskBroker | undefined;\n env.registerExtensionPoint(scaffolderTaskBrokerExtensionPoint, {\n setTaskBroker(newTaskBroker) {\n if (taskBroker) {\n throw new Error('Task broker may only be set once');\n }\n taskBroker = newTaskBroker;\n },\n });\n\n const additionalTemplateFilters: Record<string, TemplateFilter> = {};\n const additionalTemplateGlobals: Record<string, TemplateGlobal> = {};\n env.registerExtensionPoint(scaffolderTemplatingExtensionPoint, {\n addTemplateFilters(newFilters) {\n Object.assign(additionalTemplateFilters, newFilters);\n },\n addTemplateGlobals(newGlobals) {\n Object.assign(additionalTemplateGlobals, newGlobals);\n },\n });\n\n const autocompleteHandlers: Record<string, AutocompleteHandler> = {};\n env.registerExtensionPoint(scaffolderAutocompleteExtensionPoint, {\n addAutocompleteProvider(provider) {\n autocompleteHandlers[provider.id] = provider.handler;\n },\n });\n\n const additionalWorkspaceProviders: Record<string, WorkspaceProvider> = {};\n env.registerExtensionPoint(scaffolderWorkspaceProviderExtensionPoint, {\n addProviders(provider) {\n Object.assign(additionalWorkspaceProviders, provider);\n },\n });\n\n env.registerInit({\n deps: {\n logger: coreServices.logger,\n config: coreServices.rootConfig,\n lifecycle: coreServices.rootLifecycle,\n reader: coreServices.urlReader,\n permissions: coreServices.permissions,\n database: coreServices.database,\n auth: coreServices.auth,\n discovery: coreServices.discovery,\n httpRouter: coreServices.httpRouter,\n httpAuth: coreServices.httpAuth,\n catalogClient: catalogServiceRef,\n events: eventsServiceRef,\n },\n async init({\n logger,\n config,\n lifecycle,\n reader,\n database,\n auth,\n discovery,\n httpRouter,\n httpAuth,\n catalogClient,\n permissions,\n events,\n }) {\n const log = loggerToWinstonLogger(logger);\n const integrations = ScmIntegrations.fromConfig(config);\n\n const actions = [\n // actions provided from other modules\n ...addedActions,\n\n // built-in actions for the scaffolder\n createFetchPlainAction({\n reader,\n integrations,\n }),\n createFetchPlainFileAction({\n reader,\n integrations,\n }),\n createFetchTemplateAction({\n integrations,\n reader,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n }),\n createFetchTemplateFileAction({\n integrations,\n reader,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n }),\n createDebugLogAction(),\n createWaitAction(),\n // todo(blam): maybe these should be a -catalog module?\n createCatalogRegisterAction({ catalogClient, integrations, auth }),\n createFetchCatalogEntityAction({ catalogClient, auth }),\n createCatalogWriteAction(),\n createFilesystemDeleteAction(),\n createFilesystemRenameAction(),\n createFilesystemReadDirAction(),\n ];\n\n const actionIds = actions.map(action => action.id).join(', ');\n\n log.info(\n `Starting scaffolder with the following actions enabled ${actionIds}`,\n );\n\n const router = await createRouter({\n logger: log,\n config,\n database,\n catalogClient,\n reader,\n lifecycle,\n actions,\n taskBroker,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n auth,\n httpAuth,\n discovery,\n permissions,\n autocompleteHandlers,\n additionalWorkspaceProviders,\n events,\n });\n httpRouter.use(router);\n },\n });\n },\n});\n"],"names":["createBackendPlugin","scaffolderActionsExtensionPoint","scaffolderTaskBrokerExtensionPoint","scaffolderTemplatingExtensionPoint","scaffolderAutocompleteExtensionPoint","scaffolderWorkspaceProviderExtensionPoint","coreServices","catalogServiceRef","eventsServiceRef","log","loggerToWinstonLogger","ScmIntegrations","createFetchPlainAction","createFetchPlainFileAction","createFetchTemplateAction","createFetchTemplateFileAction","createDebugLogAction","createWaitAction","createCatalogRegisterAction","createFetchCatalogEntityAction","createCatalogWriteAction","createFilesystemDeleteAction","createFilesystemRenameAction","createFilesystemReadDirAction","router","createRouter"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ScaffolderPlugin.cjs.js","sources":["../src/ScaffolderPlugin.ts"],"sourcesContent":["/*\n * Copyright 2022 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 { loggerToWinstonLogger } from '@backstage/backend-common';\nimport {\n coreServices,\n createBackendPlugin,\n} from '@backstage/backend-plugin-api';\nimport { ScmIntegrations } from '@backstage/integration';\nimport { catalogServiceRef } from '@backstage/plugin-catalog-node/alpha';\nimport { eventsServiceRef } from '@backstage/plugin-events-node';\nimport {\n TaskBroker,\n TemplateAction,\n TemplateFilter,\n TemplateGlobal,\n} from '@backstage/plugin-scaffolder-node';\nimport {\n AutocompleteHandler,\n scaffolderActionsExtensionPoint,\n scaffolderAutocompleteExtensionPoint,\n scaffolderTaskBrokerExtensionPoint,\n scaffolderTemplatingExtensionPoint,\n scaffolderWorkspaceProviderExtensionPoint,\n WorkspaceProvider,\n} from '@backstage/plugin-scaffolder-node/alpha';\nimport {\n createCatalogRegisterAction,\n createCatalogWriteAction,\n createDebugLogAction,\n createFetchCatalogEntityAction,\n createFetchPlainAction,\n createFetchPlainFileAction,\n createFetchTemplateAction,\n createFetchTemplateFileAction,\n createFilesystemDeleteAction,\n createFilesystemReadDirAction,\n createFilesystemRenameAction,\n createWaitAction,\n} from './scaffolder';\nimport { createRouter } from './service/router';\n\n/**\n * Scaffolder plugin\n *\n * @public\n */\nexport const scaffolderPlugin = createBackendPlugin({\n pluginId: 'scaffolder',\n register(env) {\n const addedActions = new Array<TemplateAction<any, any>>();\n env.registerExtensionPoint(scaffolderActionsExtensionPoint, {\n addActions(...newActions: TemplateAction<any>[]) {\n addedActions.push(...newActions);\n },\n });\n\n let taskBroker: TaskBroker | undefined;\n env.registerExtensionPoint(scaffolderTaskBrokerExtensionPoint, {\n setTaskBroker(newTaskBroker) {\n if (taskBroker) {\n throw new Error('Task broker may only be set once');\n }\n taskBroker = newTaskBroker;\n },\n });\n\n const additionalTemplateFilters: Record<string, TemplateFilter> = {};\n const additionalTemplateGlobals: Record<string, TemplateGlobal> = {};\n env.registerExtensionPoint(scaffolderTemplatingExtensionPoint, {\n addTemplateFilters(newFilters) {\n Object.assign(additionalTemplateFilters, newFilters);\n },\n addTemplateGlobals(newGlobals) {\n Object.assign(additionalTemplateGlobals, newGlobals);\n },\n });\n\n const autocompleteHandlers: Record<string, AutocompleteHandler> = {};\n env.registerExtensionPoint(scaffolderAutocompleteExtensionPoint, {\n addAutocompleteProvider(provider) {\n autocompleteHandlers[provider.id] = provider.handler;\n },\n });\n\n const additionalWorkspaceProviders: Record<string, WorkspaceProvider> = {};\n env.registerExtensionPoint(scaffolderWorkspaceProviderExtensionPoint, {\n addProviders(provider) {\n Object.assign(additionalWorkspaceProviders, provider);\n },\n });\n\n env.registerInit({\n deps: {\n logger: coreServices.logger,\n config: coreServices.rootConfig,\n lifecycle: coreServices.rootLifecycle,\n reader: coreServices.urlReader,\n permissions: coreServices.permissions,\n database: coreServices.database,\n auth: coreServices.auth,\n discovery: coreServices.discovery,\n httpRouter: coreServices.httpRouter,\n httpAuth: coreServices.httpAuth,\n auditor: coreServices.auditor,\n catalogClient: catalogServiceRef,\n events: eventsServiceRef,\n },\n async init({\n logger,\n config,\n lifecycle,\n reader,\n database,\n auth,\n discovery,\n httpRouter,\n httpAuth,\n catalogClient,\n permissions,\n events,\n auditor,\n }) {\n const log = loggerToWinstonLogger(logger);\n const integrations = ScmIntegrations.fromConfig(config);\n\n const actions = [\n // actions provided from other modules\n ...addedActions,\n\n // built-in actions for the scaffolder\n createFetchPlainAction({\n reader,\n integrations,\n }),\n createFetchPlainFileAction({\n reader,\n integrations,\n }),\n createFetchTemplateAction({\n integrations,\n reader,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n }),\n createFetchTemplateFileAction({\n integrations,\n reader,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n }),\n createDebugLogAction(),\n createWaitAction(),\n // todo(blam): maybe these should be a -catalog module?\n createCatalogRegisterAction({ catalogClient, integrations, auth }),\n createFetchCatalogEntityAction({ catalogClient, auth }),\n createCatalogWriteAction(),\n createFilesystemDeleteAction(),\n createFilesystemRenameAction(),\n createFilesystemReadDirAction(),\n ];\n\n const actionIds = actions.map(action => action.id).join(', ');\n\n log.info(\n `Starting scaffolder with the following actions enabled ${actionIds}`,\n );\n\n const router = await createRouter({\n logger: log,\n config,\n database,\n catalogClient,\n reader,\n lifecycle,\n actions,\n taskBroker,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n auth,\n httpAuth,\n discovery,\n permissions,\n autocompleteHandlers,\n additionalWorkspaceProviders,\n events,\n auditor,\n });\n httpRouter.use(router);\n },\n });\n },\n});\n"],"names":["createBackendPlugin","scaffolderActionsExtensionPoint","scaffolderTaskBrokerExtensionPoint","scaffolderTemplatingExtensionPoint","scaffolderAutocompleteExtensionPoint","scaffolderWorkspaceProviderExtensionPoint","coreServices","catalogServiceRef","eventsServiceRef","log","loggerToWinstonLogger","ScmIntegrations","createFetchPlainAction","createFetchPlainFileAction","createFetchTemplateAction","createFetchTemplateFileAction","createDebugLogAction","createWaitAction","createCatalogRegisterAction","createFetchCatalogEntityAction","createCatalogWriteAction","createFilesystemDeleteAction","createFilesystemRenameAction","createFilesystemReadDirAction","router","createRouter"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import * as _backstage_backend_plugin_api from '@backstage/backend-plugin-api';
|
|
3
|
-
import { AuthService, UrlReaderService, DatabaseService, BackstageCredentials, LifecycleService, SchedulerService, PermissionsService, HttpAuthService, DiscoveryService } from '@backstage/backend-plugin-api';
|
|
3
|
+
import { AuthService, UrlReaderService, DatabaseService, BackstageCredentials, AuditorService, LifecycleService, SchedulerService, PermissionsService, HttpAuthService, DiscoveryService } from '@backstage/backend-plugin-api';
|
|
4
4
|
import * as _backstage_plugin_scaffolder_node from '@backstage/plugin-scaffolder-node';
|
|
5
5
|
import { TemplateFilter as TemplateFilter$1, TemplateGlobal as TemplateGlobal$1, TemplateAction as TemplateAction$1, TaskStatus as TaskStatus$1, TaskCompletionState as TaskCompletionState$1, SerializedTask as SerializedTask$1, TaskEventType as TaskEventType$1, SerializedTaskEvent as SerializedTaskEvent$1, TaskBrokerDispatchResult as TaskBrokerDispatchResult$1, TaskBrokerDispatchOptions as TaskBrokerDispatchOptions$1, TaskContext as TaskContext$1, TaskBroker as TaskBroker$1, TaskSecrets as TaskSecrets$1, ActionContext as ActionContext$1, ExecuteShellCommandOptions, executeShellCommand as executeShellCommand$1, fetchContents as fetchContents$1 } from '@backstage/plugin-scaffolder-node';
|
|
6
6
|
import * as _backstage_types from '@backstage/types';
|
|
@@ -21,13 +21,13 @@ import { Knex } from 'knex';
|
|
|
21
21
|
import * as _backstage_plugin_scaffolder_common from '@backstage/plugin-scaffolder-common';
|
|
22
22
|
import { TaskSpec, TaskRecovery, TemplateEntityStepV1beta3, TemplateParametersV1beta3 } from '@backstage/plugin-scaffolder-common';
|
|
23
23
|
import { EventsService } from '@backstage/plugin-events-node';
|
|
24
|
-
import { Logger } from 'winston';
|
|
25
24
|
import { WorkspaceProvider, AutocompleteHandler } from '@backstage/plugin-scaffolder-node/alpha';
|
|
25
|
+
import { Logger } from 'winston';
|
|
26
26
|
import { PermissionEvaluator, PermissionRuleParams } from '@backstage/plugin-permission-common';
|
|
27
|
+
import { IdentityApi } from '@backstage/plugin-auth-node';
|
|
28
|
+
import { PermissionRule } from '@backstage/plugin-permission-node';
|
|
27
29
|
import { RESOURCE_TYPE_SCAFFOLDER_TEMPLATE, RESOURCE_TYPE_SCAFFOLDER_ACTION } from '@backstage/plugin-scaffolder-common/alpha';
|
|
28
30
|
import express from 'express';
|
|
29
|
-
import { PermissionRule } from '@backstage/plugin-permission-node';
|
|
30
|
-
import { IdentityApi } from '@backstage/plugin-auth-node';
|
|
31
31
|
import * as jsonschema from 'jsonschema';
|
|
32
32
|
import * as zod from 'zod';
|
|
33
33
|
import { ScaffolderEntitiesProcessor as ScaffolderEntitiesProcessor$1 } from '@backstage/plugin-catalog-backend-module-scaffolder-entity-model';
|
|
@@ -814,6 +814,7 @@ type CreateWorkerOptions = {
|
|
|
814
814
|
integrations: ScmIntegrations;
|
|
815
815
|
workingDirectory: string;
|
|
816
816
|
logger: Logger;
|
|
817
|
+
auditor?: AuditorService;
|
|
817
818
|
additionalTemplateFilters?: Record<string, TemplateFilter$1>;
|
|
818
819
|
/**
|
|
819
820
|
* The number of tasks that can be executed at the same time by the worker
|
|
@@ -840,6 +841,7 @@ declare class TaskWorker {
|
|
|
840
841
|
private readonly options;
|
|
841
842
|
private taskQueue;
|
|
842
843
|
private logger;
|
|
844
|
+
private auditor;
|
|
843
845
|
private stopWorkers;
|
|
844
846
|
private constructor();
|
|
845
847
|
static create(options: CreateWorkerOptions): Promise<TaskWorker>;
|
|
@@ -896,6 +898,7 @@ interface RouterOptions {
|
|
|
896
898
|
identity?: IdentityApi;
|
|
897
899
|
discovery?: DiscoveryService;
|
|
898
900
|
events?: EventsService;
|
|
901
|
+
auditor?: AuditorService;
|
|
899
902
|
autocompleteHandlers?: Record<string, AutocompleteHandler>;
|
|
900
903
|
}
|
|
901
904
|
/**
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var url = require('url');
|
|
4
3
|
var pluginScaffolderNode = require('@backstage/plugin-scaffolder-node');
|
|
4
|
+
var fs = require('fs-extra');
|
|
5
5
|
var path = require('path');
|
|
6
|
+
var url = require('url');
|
|
7
|
+
var uuid = require('uuid');
|
|
6
8
|
var NunjucksWorkflowRunner = require('../tasks/NunjucksWorkflowRunner.cjs.js');
|
|
7
9
|
var DecoratedActionsRegistry = require('./DecoratedActionsRegistry.cjs.js');
|
|
8
|
-
var fs = require('fs-extra');
|
|
9
|
-
var uuid = require('uuid');
|
|
10
10
|
|
|
11
11
|
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
|
|
12
12
|
|
|
13
|
-
var path__default = /*#__PURE__*/_interopDefaultCompat(path);
|
|
14
13
|
var fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
|
|
14
|
+
var path__default = /*#__PURE__*/_interopDefaultCompat(path);
|
|
15
15
|
|
|
16
16
|
function createDryRunner(options) {
|
|
17
17
|
return async function dryRun(input) {
|
|
@@ -42,6 +42,7 @@ function createDryRunner(options) {
|
|
|
42
42
|
await pluginScaffolderNode.deserializeDirectoryContents(contentsPath, input.directoryContents);
|
|
43
43
|
const abortSignal = new AbortController().signal;
|
|
44
44
|
const result = await workflowRunner.execute({
|
|
45
|
+
taskId: dryRunId,
|
|
45
46
|
spec: {
|
|
46
47
|
...input.spec,
|
|
47
48
|
steps: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createDryRunner.cjs.js","sources":["../../../src/scaffolder/dryrun/createDryRunner.ts"],"sourcesContent":["/*\n * Copyright 2022 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":"createDryRunner.cjs.js","sources":["../../../src/scaffolder/dryrun/createDryRunner.ts"],"sourcesContent":["/*\n * Copyright 2022 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 BackstageCredentials,\n} from '@backstage/backend-plugin-api';\nimport type { UserEntity } from '@backstage/catalog-model';\nimport { ScmIntegrations } from '@backstage/integration';\nimport { PermissionEvaluator } from '@backstage/plugin-permission-common';\nimport { TaskSpec, TemplateInfo } from '@backstage/plugin-scaffolder-common';\nimport {\n createTemplateAction,\n deserializeDirectoryContents,\n SerializedFile,\n serializeDirectoryContents,\n TaskSecrets,\n TemplateFilter,\n TemplateGlobal,\n} from '@backstage/plugin-scaffolder-node';\nimport { JsonObject } from '@backstage/types';\nimport fs from 'fs-extra';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\nimport { v4 as uuid } from 'uuid';\nimport { Logger } from 'winston';\nimport { TemplateActionRegistry } from '../actions';\nimport { NunjucksWorkflowRunner } from '../tasks/NunjucksWorkflowRunner';\nimport { DecoratedActionsRegistry } from './DecoratedActionsRegistry';\n\ninterface DryRunInput {\n spec: TaskSpec;\n templateInfo: TemplateInfo;\n secrets?: TaskSecrets;\n directoryContents: SerializedFile[];\n credentials: BackstageCredentials;\n user?: {\n entity?: UserEntity;\n ref?: string;\n };\n}\n\ninterface DryRunResult {\n log: Array<{ body: JsonObject }>;\n directoryContents: SerializedFile[];\n output: JsonObject;\n}\n\n/** @internal */\nexport type TemplateTesterCreateOptions = {\n logger: Logger;\n auditor?: AuditorService;\n integrations: ScmIntegrations;\n actionRegistry: TemplateActionRegistry;\n workingDirectory: string;\n additionalTemplateFilters?: Record<string, TemplateFilter>;\n additionalTemplateGlobals?: Record<string, TemplateGlobal>;\n permissions?: PermissionEvaluator;\n};\n\n/**\n * Executes a dry-run of the provided template.\n *\n * The provided content will be extracted into a temporary directory\n * which is then use as the base for any relative file fetch paths.\n *\n * @internal\n */\nexport function createDryRunner(options: TemplateTesterCreateOptions) {\n return async function dryRun(input: DryRunInput): Promise<DryRunResult> {\n let contentPromise;\n\n const workflowRunner = new NunjucksWorkflowRunner({\n ...options,\n actionRegistry: new DecoratedActionsRegistry(options.actionRegistry, [\n createTemplateAction({\n id: 'dry-run:extract',\n supportsDryRun: true,\n async handler(ctx) {\n contentPromise = serializeDirectoryContents(ctx.workspacePath);\n await contentPromise.catch(() => {});\n },\n }),\n ]),\n });\n\n // Extracting contentsPath and dryRunId from the baseUrl\n const baseUrl = input.templateInfo.baseUrl;\n if (!baseUrl) {\n throw new Error('baseUrl is required');\n }\n const basePath = fileURLToPath(new URL(baseUrl));\n const contentsPath = path.dirname(basePath);\n const dryRunId = uuid();\n\n const log = new Array<{ body: JsonObject }>();\n\n try {\n await deserializeDirectoryContents(contentsPath, input.directoryContents);\n\n const abortSignal = new AbortController().signal;\n const result = await workflowRunner.execute({\n taskId: dryRunId,\n spec: {\n ...input.spec,\n steps: [\n ...input.spec.steps,\n {\n id: dryRunId,\n name: 'dry-run:extract',\n action: 'dry-run:extract',\n },\n ],\n templateInfo: input.templateInfo,\n },\n secrets: input.secrets,\n getInitiatorCredentials: () => Promise.resolve(input.credentials),\n // No need to update this at the end of the run, so just hard-code it\n done: false,\n isDryRun: true,\n getWorkspaceName: async () => `dry-run-${dryRunId}`,\n cancelSignal: abortSignal,\n async emitLog(message: string, logMetadata?: JsonObject) {\n if (logMetadata?.stepId === dryRunId) {\n return;\n }\n log.push({\n body: {\n ...logMetadata,\n message,\n },\n });\n },\n complete: async () => {\n throw new Error('Not implemented');\n },\n });\n\n if (!contentPromise) {\n throw new Error('Content extraction step was skipped');\n }\n const directoryContents = await contentPromise;\n\n return {\n log,\n directoryContents,\n output: result.output,\n };\n } finally {\n await fs.remove(contentsPath);\n }\n };\n}\n"],"names":["NunjucksWorkflowRunner","DecoratedActionsRegistry","createTemplateAction","serializeDirectoryContents","fileURLToPath","path","uuid","deserializeDirectoryContents","fs"],"mappings":"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"}
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var errors = require('@backstage/errors');
|
|
4
|
+
var api = require('@opentelemetry/api');
|
|
4
5
|
var fs = require('fs-extra');
|
|
5
|
-
var
|
|
6
|
+
var jsonschema = require('jsonschema');
|
|
6
7
|
var nunjucks = require('nunjucks');
|
|
7
|
-
var
|
|
8
|
+
var path = require('path');
|
|
8
9
|
var stream = require('stream');
|
|
9
|
-
var
|
|
10
|
-
var jsonschema = require('jsonschema');
|
|
11
|
-
var api = require('@opentelemetry/api');
|
|
10
|
+
var winston = require('winston');
|
|
12
11
|
var SecureTemplater = require('../../lib/templating/SecureTemplater.cjs.js');
|
|
12
|
+
var helper = require('./helper.cjs.js');
|
|
13
|
+
var backendCommon = require('@backstage/backend-common');
|
|
14
|
+
var pluginPermissionCommon = require('@backstage/plugin-permission-common');
|
|
13
15
|
var pluginPermissionNode = require('@backstage/plugin-permission-node');
|
|
14
|
-
var
|
|
16
|
+
var alpha = require('@backstage/plugin-scaffolder-common/alpha');
|
|
15
17
|
var filters = require('../../lib/templating/filters.cjs.js');
|
|
16
|
-
var pluginPermissionCommon = require('@backstage/plugin-permission-common');
|
|
17
18
|
var rules = require('../../service/rules.cjs.js');
|
|
18
|
-
var
|
|
19
|
-
var backendCommon = require('@backstage/backend-common');
|
|
19
|
+
var metrics = require('../../util/metrics.cjs.js');
|
|
20
20
|
var logger = require('./logger.cjs.js');
|
|
21
21
|
|
|
22
22
|
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
|
|
@@ -39,10 +39,10 @@ function _interopNamespaceCompat(e) {
|
|
|
39
39
|
return Object.freeze(n);
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
var winston__namespace = /*#__PURE__*/_interopNamespaceCompat(winston);
|
|
43
42
|
var fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
|
|
44
|
-
var path__default = /*#__PURE__*/_interopDefaultCompat(path);
|
|
45
43
|
var nunjucks__default = /*#__PURE__*/_interopDefaultCompat(nunjucks);
|
|
44
|
+
var path__default = /*#__PURE__*/_interopDefaultCompat(path);
|
|
45
|
+
var winston__namespace = /*#__PURE__*/_interopNamespaceCompat(winston);
|
|
46
46
|
|
|
47
47
|
const isValidTaskSpec = (taskSpec) => {
|
|
48
48
|
return taskSpec.apiVersion === "scaffolder.backstage.io/v1beta3";
|
|
@@ -133,7 +133,9 @@ class NunjucksWorkflowRunner {
|
|
|
133
133
|
async executeStep(task, step, context, renderTemplate, taskTrack, workspacePath, decision) {
|
|
134
134
|
const stepTrack = await this.tracker.stepStart(task, step);
|
|
135
135
|
if (task.cancelSignal.aborted) {
|
|
136
|
-
throw new Error(
|
|
136
|
+
throw new Error(
|
|
137
|
+
`Step ${step.id} (${step.name}) of task ${task.taskId} has been cancelled.`
|
|
138
|
+
);
|
|
137
139
|
}
|
|
138
140
|
try {
|
|
139
141
|
if (step.if === false || typeof step.if === "string" && !helper.isTruthy(this.render(step.if, context, renderTemplate))) {
|
|
@@ -299,7 +301,9 @@ class NunjucksWorkflowRunner {
|
|
|
299
301
|
}
|
|
300
302
|
context.steps[step.id] = { output: stepOutput };
|
|
301
303
|
if (task.cancelSignal.aborted) {
|
|
302
|
-
throw new Error(
|
|
304
|
+
throw new Error(
|
|
305
|
+
`Step ${step.id} (${step.name}) of task ${task.taskId} has been cancelled.`
|
|
306
|
+
);
|
|
303
307
|
}
|
|
304
308
|
await stepTrack.markSuccessful();
|
|
305
309
|
} catch (err) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NunjucksWorkflowRunner.cjs.js","sources":["../../../src/scaffolder/tasks/NunjucksWorkflowRunner.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 { ScmIntegrations } from '@backstage/integration';\nimport { TaskTrackType, WorkflowResponse, WorkflowRunner } from './types';\nimport * as winston from 'winston';\nimport fs from 'fs-extra';\nimport path from 'path';\nimport nunjucks from 'nunjucks';\nimport { JsonArray, JsonObject, JsonValue } from '@backstage/types';\nimport { InputError, NotAllowedError, stringifyError } from '@backstage/errors';\nimport { PassThrough } from 'stream';\nimport { generateExampleOutput, isTruthy } from './helper';\nimport { validate as validateJsonSchema } from 'jsonschema';\nimport { TemplateActionRegistry } from '../actions';\nimport { metrics } from '@opentelemetry/api';\nimport {\n SecureTemplater,\n SecureTemplateRenderer,\n} from '../../lib/templating/SecureTemplater';\nimport {\n TaskRecovery,\n TaskSpec,\n TaskSpecV1beta3,\n TaskStep,\n} from '@backstage/plugin-scaffolder-common';\n\nimport {\n TemplateAction,\n TemplateFilter,\n TemplateGlobal,\n TaskContext,\n} from '@backstage/plugin-scaffolder-node';\nimport { createConditionAuthorizer } from '@backstage/plugin-permission-node';\nimport { UserEntity } from '@backstage/catalog-model';\nimport { createCounterMetric, createHistogramMetric } from '../../util/metrics';\nimport { createDefaultFilters } from '../../lib/templating/filters';\nimport {\n AuthorizeResult,\n PolicyDecision,\n} from '@backstage/plugin-permission-common';\nimport { scaffolderActionRules } from '../../service/rules';\nimport { actionExecutePermission } from '@backstage/plugin-scaffolder-common/alpha';\nimport { PermissionsService } from '@backstage/backend-plugin-api';\nimport { loggerToWinstonLogger } from '@backstage/backend-common';\nimport { BackstageLoggerTransport, WinstonLogger } from './logger';\n\ntype NunjucksWorkflowRunnerOptions = {\n workingDirectory: string;\n actionRegistry: TemplateActionRegistry;\n integrations: ScmIntegrations;\n logger: winston.Logger;\n additionalTemplateFilters?: Record<string, TemplateFilter>;\n additionalTemplateGlobals?: Record<string, TemplateGlobal>;\n permissions?: PermissionsService;\n};\n\ntype TemplateContext = {\n parameters: JsonObject;\n EXPERIMENTAL_recovery?: TaskRecovery;\n steps: {\n [stepName: string]: { output: { [outputName: string]: JsonValue } };\n };\n secrets?: Record<string, string>;\n user?: {\n entity?: UserEntity;\n ref?: string;\n };\n each?: JsonValue;\n context: {\n task: {\n id: string;\n };\n };\n};\n\ntype CheckpointState =\n | {\n status: 'failed';\n reason: string;\n }\n | {\n status: 'success';\n value: JsonValue;\n };\n\nconst isValidTaskSpec = (taskSpec: TaskSpec): taskSpec is TaskSpecV1beta3 => {\n return taskSpec.apiVersion === 'scaffolder.backstage.io/v1beta3';\n};\n\nconst createStepLogger = ({\n task,\n step,\n rootLogger,\n}: {\n task: TaskContext;\n step: TaskStep;\n rootLogger: winston.Logger;\n}) => {\n const taskLogger = WinstonLogger.create({\n level: process.env.LOG_LEVEL || 'info',\n format: winston.format.combine(\n winston.format.colorize(),\n winston.format.simple(),\n ),\n transports: [new BackstageLoggerTransport(rootLogger, task, step.id)],\n });\n\n taskLogger.addRedactions(Object.values(task.secrets ?? {}));\n\n // This stream logger should be deprecated. We're going to replace it with\n // just using the logger directly, as all those logs get written to step logs\n // using the stepLogStream above.\n // Initially this stream used to be the only way to write to the client logs, but that\n // has changed over time, there's not really a need for this anymore.\n // You can just create a simple wrapper like the below in your action to write to the main logger.\n // This way we also get recactions for free.\n const streamLogger = new PassThrough();\n streamLogger.on('data', async data => {\n const message = data.toString().trim();\n if (message?.length > 1) {\n taskLogger.info(message);\n }\n });\n\n return { taskLogger, streamLogger };\n};\n\nconst isActionAuthorized = createConditionAuthorizer(\n Object.values(scaffolderActionRules),\n);\n\nexport class NunjucksWorkflowRunner implements WorkflowRunner {\n private readonly defaultTemplateFilters: Record<string, TemplateFilter>;\n\n constructor(private readonly options: NunjucksWorkflowRunnerOptions) {\n this.defaultTemplateFilters = createDefaultFilters({\n integrations: this.options.integrations,\n });\n }\n\n private readonly tracker = scaffoldingTracker();\n\n private isSingleTemplateString(input: string) {\n const { parser, nodes } = nunjucks as unknown as {\n parser: {\n parse(\n template: string,\n ctx: object,\n options: nunjucks.ConfigureOptions,\n ): { children: { children?: unknown[] }[] };\n };\n nodes: { TemplateData: Function };\n };\n\n const parsed = parser.parse(\n input,\n {},\n {\n autoescape: false,\n tags: {\n variableStart: '${{',\n variableEnd: '}}',\n },\n },\n );\n\n return (\n parsed.children.length === 1 &&\n !(parsed.children[0]?.children?.[0] instanceof nodes.TemplateData)\n );\n }\n\n private render<T>(\n input: T,\n context: TemplateContext,\n renderTemplate: SecureTemplateRenderer,\n ): T {\n return JSON.parse(JSON.stringify(input), (_key, value) => {\n try {\n if (typeof value === 'string') {\n try {\n if (this.isSingleTemplateString(value)) {\n // Lets convert ${{ parameters.bob }} to ${{ (parameters.bob) | dump }} so we can keep the input type\n const wrappedDumped = value.replace(\n /\\${{(.+)}}/g,\n '${{ ( $1 ) | dump }}',\n );\n\n // Run the templating\n const templated = renderTemplate(wrappedDumped, context);\n\n // If there's an empty string returned, then it's undefined\n if (templated === '') {\n return undefined;\n }\n\n // Reparse the dumped string\n return JSON.parse(templated);\n }\n } catch (ex) {\n this.options.logger.error(\n `Failed to parse template string: ${value} with error ${ex.message}`,\n );\n }\n\n // Fallback to default behaviour\n const templated = renderTemplate(value, context);\n\n if (templated === '') {\n return undefined;\n }\n\n return templated;\n }\n } catch {\n return value;\n }\n return value;\n });\n }\n\n async executeStep(\n task: TaskContext,\n step: TaskStep,\n context: TemplateContext,\n renderTemplate: (template: string, values: unknown) => string,\n taskTrack: TaskTrackType,\n workspacePath: string,\n decision: PolicyDecision,\n ) {\n const stepTrack = await this.tracker.stepStart(task, step);\n\n if (task.cancelSignal.aborted) {\n throw new Error(`Step ${step.name} has been cancelled.`);\n }\n\n try {\n if (\n step.if === false ||\n (typeof step.if === 'string' &&\n !isTruthy(this.render(step.if, context, renderTemplate)))\n ) {\n await stepTrack.skipFalsy();\n return;\n }\n const action: TemplateAction<JsonObject> =\n this.options.actionRegistry.get(step.action);\n const { taskLogger, streamLogger } = createStepLogger({\n task,\n step,\n rootLogger: this.options.logger,\n });\n\n if (task.isDryRun) {\n const redactedSecrets = Object.fromEntries(\n Object.entries(task.secrets ?? {}).map(secret => [secret[0], '***']),\n );\n const debugInput =\n (step.input &&\n this.render(\n step.input,\n {\n ...context,\n secrets: redactedSecrets,\n },\n renderTemplate,\n )) ??\n {};\n taskLogger.info(\n `Running ${\n action.id\n } in dry-run mode with inputs (secrets redacted): ${JSON.stringify(\n debugInput,\n undefined,\n 2,\n )}`,\n );\n if (!action.supportsDryRun) {\n await taskTrack.skipDryRun(step, action);\n const outputSchema = action.schema?.output;\n if (outputSchema) {\n context.steps[step.id] = {\n output: generateExampleOutput(outputSchema) as {\n [name in string]: JsonValue;\n },\n };\n } else {\n context.steps[step.id] = { output: {} };\n }\n return;\n }\n }\n const iterations = (\n step.each\n ? Object.entries(this.render(step.each, context, renderTemplate)).map(\n ([key, value]) => ({\n each: { key, value },\n }),\n )\n : [{}]\n ).map(i => ({\n ...i,\n // Secrets are only passed when templating the input to actions for security reasons\n input: step.input\n ? this.render(\n step.input,\n { ...context, secrets: task.secrets ?? {}, ...i },\n renderTemplate,\n )\n : {},\n }));\n for (const iteration of iterations) {\n const actionId = `${action.id}${\n iteration.each ? `[${iteration.each.key}]` : ''\n }`;\n\n if (action.schema?.input) {\n const validateResult = validateJsonSchema(\n iteration.input,\n action.schema.input,\n );\n if (!validateResult.valid) {\n const errors = validateResult.errors.join(', ');\n throw new InputError(\n `Invalid input passed to action ${actionId}, ${errors}`,\n );\n }\n }\n if (\n !isActionAuthorized(decision, {\n action: action.id,\n input: iteration.input,\n })\n ) {\n throw new NotAllowedError(\n `Unauthorized action: ${actionId}. The action is not allowed. Input: ${JSON.stringify(\n iteration.input,\n null,\n 2,\n )}`,\n );\n }\n }\n const tmpDirs = new Array<string>();\n const stepOutput: { [outputName: string]: JsonValue } = {};\n const prevTaskState = await task.getTaskState?.();\n\n for (const iteration of iterations) {\n if (iteration.each) {\n taskLogger.info(\n `Running step each: ${JSON.stringify(\n iteration.each,\n (k, v) => (k ? v.toString() : v),\n 0,\n )}`,\n );\n }\n\n await action.handler({\n input: iteration.input,\n task: {\n id: await task.getWorkspaceName(),\n },\n secrets: task.secrets ?? {},\n // TODO(blam): move to LoggerService and away from Winston\n logger: loggerToWinstonLogger(taskLogger),\n logStream: streamLogger,\n workspacePath,\n async checkpoint<T extends JsonValue | void>(opts: {\n key?: string;\n fn: () => Promise<T> | T;\n }) {\n const { key: checkpointKey, fn } = opts;\n const key = `v1.task.checkpoint.${step.id}.${checkpointKey}`;\n\n try {\n let prevValue: T | undefined;\n\n if (prevTaskState) {\n const prevState = (\n prevTaskState.state?.checkpoints as {\n [key: string]: CheckpointState;\n }\n )?.[key];\n\n if (prevState && prevState.status === 'success') {\n prevValue = prevState.value as T;\n }\n }\n\n const value = prevValue ? prevValue : await fn();\n\n if (!prevValue) {\n task.updateCheckpoint?.({\n key,\n status: 'success',\n value: value ?? {},\n });\n }\n return value;\n } catch (err) {\n task.updateCheckpoint?.({\n key,\n status: 'failed',\n reason: stringifyError(err),\n });\n throw err;\n } finally {\n await task.serializeWorkspace?.({ path: workspacePath });\n }\n },\n createTemporaryDirectory: async () => {\n const tmpDir = await fs.mkdtemp(\n `${workspacePath}_step-${step.id}-`,\n );\n tmpDirs.push(tmpDir);\n return tmpDir;\n },\n output(name: string, value: JsonValue) {\n if (step.each) {\n stepOutput[name] = stepOutput[name] || [];\n (stepOutput[name] as JsonArray).push(value);\n } else {\n stepOutput[name] = value;\n }\n },\n templateInfo: task.spec.templateInfo,\n user: task.spec.user,\n isDryRun: task.isDryRun,\n signal: task.cancelSignal,\n getInitiatorCredentials: () => task.getInitiatorCredentials(),\n });\n }\n\n // Remove all temporary directories that were created when executing the action\n for (const tmpDir of tmpDirs) {\n await fs.remove(tmpDir);\n }\n\n context.steps[step.id] = { output: stepOutput };\n\n if (task.cancelSignal.aborted) {\n throw new Error(`Step ${step.name} has been cancelled.`);\n }\n\n await stepTrack.markSuccessful();\n } catch (err) {\n await taskTrack.markFailed(step, err);\n await stepTrack.markFailed();\n throw err;\n } finally {\n await task.serializeWorkspace?.({ path: workspacePath });\n }\n }\n\n async execute(task: TaskContext): Promise<WorkflowResponse> {\n if (!isValidTaskSpec(task.spec)) {\n throw new InputError(\n 'Wrong template version executed with the workflow engine',\n );\n }\n const taskId = await task.getWorkspaceName();\n\n const workspacePath = path.join(this.options.workingDirectory, taskId);\n\n const { additionalTemplateFilters, additionalTemplateGlobals } =\n this.options;\n\n const renderTemplate = await SecureTemplater.loadRenderer({\n templateFilters: {\n ...this.defaultTemplateFilters,\n ...additionalTemplateFilters,\n },\n templateGlobals: additionalTemplateGlobals,\n });\n\n try {\n await task.rehydrateWorkspace?.({ taskId, targetPath: workspacePath });\n\n const taskTrack = await this.tracker.taskStart(task);\n await fs.ensureDir(workspacePath);\n\n const context: TemplateContext = {\n parameters: task.spec.parameters,\n steps: {},\n user: task.spec.user,\n context: {\n task: {\n id: taskId,\n },\n },\n };\n\n const [decision]: PolicyDecision[] =\n this.options.permissions && task.spec.steps.length\n ? await this.options.permissions.authorizeConditional(\n [{ permission: actionExecutePermission }],\n { credentials: await task.getInitiatorCredentials() },\n )\n : [{ result: AuthorizeResult.ALLOW }];\n\n for (const step of task.spec.steps) {\n await this.executeStep(\n task,\n step,\n context,\n renderTemplate,\n taskTrack,\n workspacePath,\n decision,\n );\n }\n\n const output = this.render(task.spec.output, context, renderTemplate);\n await taskTrack.markSuccessful();\n await task.cleanWorkspace?.();\n\n return { output };\n } finally {\n if (workspacePath) {\n await fs.remove(workspacePath);\n }\n }\n }\n}\n\nfunction scaffoldingTracker() {\n // prom-client metrics are deprecated in favour of OpenTelemetry metrics.\n const promTaskCount = createCounterMetric({\n name: 'scaffolder_task_count',\n help: 'Count of task runs',\n labelNames: ['template', 'user', 'result'],\n });\n const promTaskDuration = createHistogramMetric({\n name: 'scaffolder_task_duration',\n help: 'Duration of a task run',\n labelNames: ['template', 'result'],\n });\n const promtStepCount = createCounterMetric({\n name: 'scaffolder_step_count',\n help: 'Count of step runs',\n labelNames: ['template', 'step', 'result'],\n });\n const promStepDuration = createHistogramMetric({\n name: 'scaffolder_step_duration',\n help: 'Duration of a step runs',\n labelNames: ['template', 'step', 'result'],\n });\n\n const meter = metrics.getMeter('default');\n const taskCount = meter.createCounter('scaffolder.task.count', {\n description: 'Count of task runs',\n });\n\n const taskDuration = meter.createHistogram('scaffolder.task.duration', {\n description: 'Duration of a task run',\n unit: 'seconds',\n });\n\n const stepCount = meter.createCounter('scaffolder.step.count', {\n description: 'Count of step runs',\n });\n\n const stepDuration = meter.createHistogram('scaffolder.step.duration', {\n description: 'Duration of a step runs',\n unit: 'seconds',\n });\n\n async function taskStart(task: TaskContext) {\n await task.emitLog(`Starting up task with ${task.spec.steps.length} steps`);\n const template = task.spec.templateInfo?.entityRef || '';\n const user = task.spec.user?.ref || '';\n\n const startTime = process.hrtime();\n const taskTimer = promTaskDuration.startTimer({\n template,\n });\n\n function endTime() {\n const delta = process.hrtime(startTime);\n return delta[0] + delta[1] / 1e9;\n }\n\n async function skipDryRun(\n step: TaskStep,\n action: TemplateAction<JsonObject>,\n ) {\n task.emitLog(`Skipping because ${action.id} does not support dry-run`, {\n stepId: step.id,\n status: 'skipped',\n });\n }\n\n async function markSuccessful() {\n promTaskCount.inc({\n template,\n user,\n result: 'ok',\n });\n taskTimer({ result: 'ok' });\n\n taskCount.add(1, { template, user, result: 'ok' });\n taskDuration.record(endTime(), {\n result: 'ok',\n });\n }\n\n async function markFailed(step: TaskStep, err: Error) {\n await task.emitLog(String(err.stack), {\n stepId: step.id,\n status: 'failed',\n });\n promTaskCount.inc({\n template,\n user,\n result: 'failed',\n });\n taskTimer({ result: 'failed' });\n\n taskCount.add(1, { template, user, result: 'failed' });\n taskDuration.record(endTime(), {\n result: 'failed',\n });\n }\n\n async function markCancelled(step: TaskStep) {\n await task.emitLog(`Step ${step.id} has been cancelled.`, {\n stepId: step.id,\n status: 'cancelled',\n });\n promTaskCount.inc({\n template,\n user,\n result: 'cancelled',\n });\n taskTimer({ result: 'cancelled' });\n\n taskCount.add(1, { template, user, result: 'cancelled' });\n taskDuration.record(endTime(), {\n result: 'cancelled',\n });\n }\n\n return {\n skipDryRun,\n markCancelled,\n markSuccessful,\n markFailed,\n };\n }\n\n async function stepStart(task: TaskContext, step: TaskStep) {\n await task.emitLog(`Beginning step ${step.name}`, {\n stepId: step.id,\n status: 'processing',\n });\n const template = task.spec.templateInfo?.entityRef || '';\n\n const startTime = process.hrtime();\n const stepTimer = promStepDuration.startTimer({\n template,\n step: step.name,\n });\n\n function endTime() {\n const delta = process.hrtime(startTime);\n return delta[0] + delta[1] / 1e9;\n }\n\n async function markSuccessful() {\n await task.emitLog(`Finished step ${step.name}`, {\n stepId: step.id,\n status: 'completed',\n });\n promtStepCount.inc({\n template,\n step: step.name,\n result: 'ok',\n });\n stepTimer({ result: 'ok' });\n\n stepCount.add(1, { template, step: step.name, result: 'ok' });\n stepDuration.record(endTime(), {\n result: 'ok',\n });\n }\n\n async function markCancelled() {\n promtStepCount.inc({\n template,\n step: step.name,\n result: 'cancelled',\n });\n stepTimer({ result: 'cancelled' });\n\n stepCount.add(1, { template, step: step.name, result: 'cancelled' });\n stepDuration.record(endTime(), {\n result: 'cancelled',\n });\n }\n\n async function markFailed() {\n promtStepCount.inc({\n template,\n step: step.name,\n result: 'failed',\n });\n stepTimer({ result: 'failed' });\n\n stepCount.add(1, { template, step: step.name, result: 'failed' });\n stepDuration.record(endTime(), {\n result: 'failed',\n });\n }\n\n async function skipFalsy() {\n await task.emitLog(\n `Skipping step ${step.id} because its if condition was false`,\n { stepId: step.id, status: 'skipped' },\n );\n stepTimer({ result: 'skipped' });\n\n stepCount.add(1, { template, step: step.name, result: 'skipped' });\n stepDuration.record(endTime(), {\n result: 'skipped',\n });\n }\n\n return {\n markCancelled,\n markFailed,\n markSuccessful,\n skipFalsy,\n };\n }\n\n return {\n taskStart,\n stepStart,\n };\n}\n"],"names":["WinstonLogger","winston","BackstageLoggerTransport","PassThrough","createConditionAuthorizer","scaffolderActionRules","createDefaultFilters","nunjucks","templated","isTruthy","generateExampleOutput","validateJsonSchema","errors","InputError","NotAllowedError","loggerToWinstonLogger","stringifyError","fs","path","SecureTemplater","actionExecutePermission","AuthorizeResult","createCounterMetric","createHistogramMetric","metrics"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"NunjucksWorkflowRunner.cjs.js","sources":["../../../src/scaffolder/tasks/NunjucksWorkflowRunner.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 { InputError, NotAllowedError, stringifyError } from '@backstage/errors';\nimport { ScmIntegrations } from '@backstage/integration';\nimport {\n TaskRecovery,\n TaskSpec,\n TaskSpecV1beta3,\n TaskStep,\n} from '@backstage/plugin-scaffolder-common';\nimport { JsonArray, JsonObject, JsonValue } from '@backstage/types';\nimport { metrics } from '@opentelemetry/api';\nimport fs from 'fs-extra';\nimport { validate as validateJsonSchema } from 'jsonschema';\nimport nunjucks from 'nunjucks';\nimport path from 'path';\nimport { PassThrough } from 'stream';\nimport * as winston from 'winston';\nimport {\n SecureTemplater,\n SecureTemplateRenderer,\n} from '../../lib/templating/SecureTemplater';\nimport { TemplateActionRegistry } from '../actions';\nimport { generateExampleOutput, isTruthy } from './helper';\nimport { TaskTrackType, WorkflowResponse, WorkflowRunner } from './types';\n\nimport { loggerToWinstonLogger } from '@backstage/backend-common';\nimport type {\n AuditorService,\n PermissionsService,\n} from '@backstage/backend-plugin-api';\nimport { UserEntity } from '@backstage/catalog-model';\nimport {\n AuthorizeResult,\n PolicyDecision,\n} from '@backstage/plugin-permission-common';\nimport { createConditionAuthorizer } from '@backstage/plugin-permission-node';\nimport { actionExecutePermission } from '@backstage/plugin-scaffolder-common/alpha';\nimport {\n TaskContext,\n TemplateAction,\n TemplateFilter,\n TemplateGlobal,\n} from '@backstage/plugin-scaffolder-node';\nimport { createDefaultFilters } from '../../lib/templating/filters';\nimport { scaffolderActionRules } from '../../service/rules';\nimport { createCounterMetric, createHistogramMetric } from '../../util/metrics';\nimport { BackstageLoggerTransport, WinstonLogger } from './logger';\n\ntype NunjucksWorkflowRunnerOptions = {\n workingDirectory: string;\n actionRegistry: TemplateActionRegistry;\n integrations: ScmIntegrations;\n logger: winston.Logger;\n auditor?: AuditorService;\n additionalTemplateFilters?: Record<string, TemplateFilter>;\n additionalTemplateGlobals?: Record<string, TemplateGlobal>;\n permissions?: PermissionsService;\n};\n\ntype TemplateContext = {\n parameters: JsonObject;\n EXPERIMENTAL_recovery?: TaskRecovery;\n steps: {\n [stepName: string]: { output: { [outputName: string]: JsonValue } };\n };\n secrets?: Record<string, string>;\n user?: {\n entity?: UserEntity;\n ref?: string;\n };\n each?: JsonValue;\n context: {\n task: {\n id: string;\n };\n };\n};\n\ntype CheckpointState =\n | {\n status: 'failed';\n reason: string;\n }\n | {\n status: 'success';\n value: JsonValue;\n };\n\nconst isValidTaskSpec = (taskSpec: TaskSpec): taskSpec is TaskSpecV1beta3 => {\n return taskSpec.apiVersion === 'scaffolder.backstage.io/v1beta3';\n};\n\nconst createStepLogger = ({\n task,\n step,\n rootLogger,\n}: {\n task: TaskContext;\n step: TaskStep;\n rootLogger: winston.Logger;\n}) => {\n const taskLogger = WinstonLogger.create({\n level: process.env.LOG_LEVEL || 'info',\n format: winston.format.combine(\n winston.format.colorize(),\n winston.format.simple(),\n ),\n transports: [new BackstageLoggerTransport(rootLogger, task, step.id)],\n });\n\n taskLogger.addRedactions(Object.values(task.secrets ?? {}));\n\n // This stream logger should be deprecated. We're going to replace it with\n // just using the logger directly, as all those logs get written to step logs\n // using the stepLogStream above.\n // Initially this stream used to be the only way to write to the client logs, but that\n // has changed over time, there's not really a need for this anymore.\n // You can just create a simple wrapper like the below in your action to write to the main logger.\n // This way we also get redactions for free.\n const streamLogger = new PassThrough();\n streamLogger.on('data', async data => {\n const message = data.toString().trim();\n if (message?.length > 1) {\n taskLogger.info(message);\n }\n });\n\n return { taskLogger, streamLogger };\n};\n\nconst isActionAuthorized = createConditionAuthorizer(\n Object.values(scaffolderActionRules),\n);\n\nexport class NunjucksWorkflowRunner implements WorkflowRunner {\n private readonly defaultTemplateFilters: Record<string, TemplateFilter>;\n\n constructor(private readonly options: NunjucksWorkflowRunnerOptions) {\n this.defaultTemplateFilters = createDefaultFilters({\n integrations: this.options.integrations,\n });\n }\n\n private readonly tracker = scaffoldingTracker();\n\n private isSingleTemplateString(input: string) {\n const { parser, nodes } = nunjucks as unknown as {\n parser: {\n parse(\n template: string,\n ctx: object,\n options: nunjucks.ConfigureOptions,\n ): { children: { children?: unknown[] }[] };\n };\n nodes: { TemplateData: Function };\n };\n\n const parsed = parser.parse(\n input,\n {},\n {\n autoescape: false,\n tags: {\n variableStart: '${{',\n variableEnd: '}}',\n },\n },\n );\n\n return (\n parsed.children.length === 1 &&\n !(parsed.children[0]?.children?.[0] instanceof nodes.TemplateData)\n );\n }\n\n private render<T>(\n input: T,\n context: TemplateContext,\n renderTemplate: SecureTemplateRenderer,\n ): T {\n return JSON.parse(JSON.stringify(input), (_key, value) => {\n try {\n if (typeof value === 'string') {\n try {\n if (this.isSingleTemplateString(value)) {\n // Lets convert ${{ parameters.bob }} to ${{ (parameters.bob) | dump }} so we can keep the input type\n const wrappedDumped = value.replace(\n /\\${{(.+)}}/g,\n '${{ ( $1 ) | dump }}',\n );\n\n // Run the templating\n const templated = renderTemplate(wrappedDumped, context);\n\n // If there's an empty string returned, then it's undefined\n if (templated === '') {\n return undefined;\n }\n\n // Reparse the dumped string\n return JSON.parse(templated);\n }\n } catch (ex) {\n this.options.logger.error(\n `Failed to parse template string: ${value} with error ${ex.message}`,\n );\n }\n\n // Fallback to default behaviour\n const templated = renderTemplate(value, context);\n\n if (templated === '') {\n return undefined;\n }\n\n return templated;\n }\n } catch {\n return value;\n }\n return value;\n });\n }\n\n async executeStep(\n task: TaskContext,\n step: TaskStep,\n context: TemplateContext,\n renderTemplate: (template: string, values: unknown) => string,\n taskTrack: TaskTrackType,\n workspacePath: string,\n decision: PolicyDecision,\n ) {\n const stepTrack = await this.tracker.stepStart(task, step);\n\n if (task.cancelSignal.aborted) {\n throw new Error(\n `Step ${step.id} (${step.name}) of task ${task.taskId} has been cancelled.`,\n );\n }\n\n try {\n if (\n step.if === false ||\n (typeof step.if === 'string' &&\n !isTruthy(this.render(step.if, context, renderTemplate)))\n ) {\n await stepTrack.skipFalsy();\n return;\n }\n const action: TemplateAction<JsonObject> =\n this.options.actionRegistry.get(step.action);\n const { taskLogger, streamLogger } = createStepLogger({\n task,\n step,\n rootLogger: this.options.logger,\n });\n\n if (task.isDryRun) {\n const redactedSecrets = Object.fromEntries(\n Object.entries(task.secrets ?? {}).map(secret => [secret[0], '***']),\n );\n const debugInput =\n (step.input &&\n this.render(\n step.input,\n {\n ...context,\n secrets: redactedSecrets,\n },\n renderTemplate,\n )) ??\n {};\n taskLogger.info(\n `Running ${\n action.id\n } in dry-run mode with inputs (secrets redacted): ${JSON.stringify(\n debugInput,\n undefined,\n 2,\n )}`,\n );\n if (!action.supportsDryRun) {\n await taskTrack.skipDryRun(step, action);\n const outputSchema = action.schema?.output;\n if (outputSchema) {\n context.steps[step.id] = {\n output: generateExampleOutput(outputSchema) as {\n [name in string]: JsonValue;\n },\n };\n } else {\n context.steps[step.id] = { output: {} };\n }\n return;\n }\n }\n const iterations = (\n step.each\n ? Object.entries(this.render(step.each, context, renderTemplate)).map(\n ([key, value]) => ({\n each: { key, value },\n }),\n )\n : [{}]\n ).map(i => ({\n ...i,\n // Secrets are only passed when templating the input to actions for security reasons\n input: step.input\n ? this.render(\n step.input,\n { ...context, secrets: task.secrets ?? {}, ...i },\n renderTemplate,\n )\n : {},\n }));\n for (const iteration of iterations) {\n const actionId = `${action.id}${\n iteration.each ? `[${iteration.each.key}]` : ''\n }`;\n\n if (action.schema?.input) {\n const validateResult = validateJsonSchema(\n iteration.input,\n action.schema.input,\n );\n if (!validateResult.valid) {\n const errors = validateResult.errors.join(', ');\n throw new InputError(\n `Invalid input passed to action ${actionId}, ${errors}`,\n );\n }\n }\n if (\n !isActionAuthorized(decision, {\n action: action.id,\n input: iteration.input,\n })\n ) {\n throw new NotAllowedError(\n `Unauthorized action: ${actionId}. The action is not allowed. Input: ${JSON.stringify(\n iteration.input,\n null,\n 2,\n )}`,\n );\n }\n }\n const tmpDirs = new Array<string>();\n const stepOutput: { [outputName: string]: JsonValue } = {};\n const prevTaskState = await task.getTaskState?.();\n\n for (const iteration of iterations) {\n if (iteration.each) {\n taskLogger.info(\n `Running step each: ${JSON.stringify(\n iteration.each,\n (k, v) => (k ? v.toString() : v),\n 0,\n )}`,\n );\n }\n\n await action.handler({\n input: iteration.input,\n task: {\n id: await task.getWorkspaceName(),\n },\n secrets: task.secrets ?? {},\n // TODO(blam): move to LoggerService and away from Winston\n logger: loggerToWinstonLogger(taskLogger),\n logStream: streamLogger,\n workspacePath,\n async checkpoint<T extends JsonValue | void>(opts: {\n key?: string;\n fn: () => Promise<T> | T;\n }) {\n const { key: checkpointKey, fn } = opts;\n const key = `v1.task.checkpoint.${step.id}.${checkpointKey}`;\n\n try {\n let prevValue: T | undefined;\n\n if (prevTaskState) {\n const prevState = (\n prevTaskState.state?.checkpoints as {\n [key: string]: CheckpointState;\n }\n )?.[key];\n\n if (prevState && prevState.status === 'success') {\n prevValue = prevState.value as T;\n }\n }\n\n const value = prevValue ? prevValue : await fn();\n\n if (!prevValue) {\n task.updateCheckpoint?.({\n key,\n status: 'success',\n value: value ?? {},\n });\n }\n return value;\n } catch (err) {\n task.updateCheckpoint?.({\n key,\n status: 'failed',\n reason: stringifyError(err),\n });\n throw err;\n } finally {\n await task.serializeWorkspace?.({ path: workspacePath });\n }\n },\n createTemporaryDirectory: async () => {\n const tmpDir = await fs.mkdtemp(\n `${workspacePath}_step-${step.id}-`,\n );\n tmpDirs.push(tmpDir);\n return tmpDir;\n },\n output(name: string, value: JsonValue) {\n if (step.each) {\n stepOutput[name] = stepOutput[name] || [];\n (stepOutput[name] as JsonArray).push(value);\n } else {\n stepOutput[name] = value;\n }\n },\n templateInfo: task.spec.templateInfo,\n user: task.spec.user,\n isDryRun: task.isDryRun,\n signal: task.cancelSignal,\n getInitiatorCredentials: () => task.getInitiatorCredentials(),\n });\n }\n\n // Remove all temporary directories that were created when executing the action\n for (const tmpDir of tmpDirs) {\n await fs.remove(tmpDir);\n }\n\n context.steps[step.id] = { output: stepOutput };\n\n if (task.cancelSignal.aborted) {\n throw new Error(\n `Step ${step.id} (${step.name}) of task ${task.taskId} has been cancelled.`,\n );\n }\n\n await stepTrack.markSuccessful();\n } catch (err) {\n await taskTrack.markFailed(step, err);\n await stepTrack.markFailed();\n throw err;\n } finally {\n await task.serializeWorkspace?.({ path: workspacePath });\n }\n }\n\n async execute(task: TaskContext): Promise<WorkflowResponse> {\n if (!isValidTaskSpec(task.spec)) {\n throw new InputError(\n 'Wrong template version executed with the workflow engine',\n );\n }\n const taskId = await task.getWorkspaceName();\n\n const workspacePath = path.join(this.options.workingDirectory, taskId);\n\n const { additionalTemplateFilters, additionalTemplateGlobals } =\n this.options;\n\n const renderTemplate = await SecureTemplater.loadRenderer({\n templateFilters: {\n ...this.defaultTemplateFilters,\n ...additionalTemplateFilters,\n },\n templateGlobals: additionalTemplateGlobals,\n });\n\n try {\n await task.rehydrateWorkspace?.({ taskId, targetPath: workspacePath });\n\n const taskTrack = await this.tracker.taskStart(task);\n await fs.ensureDir(workspacePath);\n\n const context: TemplateContext = {\n parameters: task.spec.parameters,\n steps: {},\n user: task.spec.user,\n context: {\n task: {\n id: taskId,\n },\n },\n };\n\n const [decision]: PolicyDecision[] =\n this.options.permissions && task.spec.steps.length\n ? await this.options.permissions.authorizeConditional(\n [{ permission: actionExecutePermission }],\n { credentials: await task.getInitiatorCredentials() },\n )\n : [{ result: AuthorizeResult.ALLOW }];\n\n for (const step of task.spec.steps) {\n await this.executeStep(\n task,\n step,\n context,\n renderTemplate,\n taskTrack,\n workspacePath,\n decision,\n );\n }\n\n const output = this.render(task.spec.output, context, renderTemplate);\n await taskTrack.markSuccessful();\n await task.cleanWorkspace?.();\n\n return { output };\n } finally {\n if (workspacePath) {\n await fs.remove(workspacePath);\n }\n }\n }\n}\n\nfunction scaffoldingTracker() {\n // prom-client metrics are deprecated in favour of OpenTelemetry metrics.\n const promTaskCount = createCounterMetric({\n name: 'scaffolder_task_count',\n help: 'Count of task runs',\n labelNames: ['template', 'user', 'result'],\n });\n const promTaskDuration = createHistogramMetric({\n name: 'scaffolder_task_duration',\n help: 'Duration of a task run',\n labelNames: ['template', 'result'],\n });\n const promtStepCount = createCounterMetric({\n name: 'scaffolder_step_count',\n help: 'Count of step runs',\n labelNames: ['template', 'step', 'result'],\n });\n const promStepDuration = createHistogramMetric({\n name: 'scaffolder_step_duration',\n help: 'Duration of a step runs',\n labelNames: ['template', 'step', 'result'],\n });\n\n const meter = metrics.getMeter('default');\n const taskCount = meter.createCounter('scaffolder.task.count', {\n description: 'Count of task runs',\n });\n\n const taskDuration = meter.createHistogram('scaffolder.task.duration', {\n description: 'Duration of a task run',\n unit: 'seconds',\n });\n\n const stepCount = meter.createCounter('scaffolder.step.count', {\n description: 'Count of step runs',\n });\n\n const stepDuration = meter.createHistogram('scaffolder.step.duration', {\n description: 'Duration of a step runs',\n unit: 'seconds',\n });\n\n async function taskStart(task: TaskContext) {\n await task.emitLog(`Starting up task with ${task.spec.steps.length} steps`);\n const template = task.spec.templateInfo?.entityRef || '';\n const user = task.spec.user?.ref || '';\n\n const startTime = process.hrtime();\n const taskTimer = promTaskDuration.startTimer({\n template,\n });\n\n function endTime() {\n const delta = process.hrtime(startTime);\n return delta[0] + delta[1] / 1e9;\n }\n\n async function skipDryRun(\n step: TaskStep,\n action: TemplateAction<JsonObject>,\n ) {\n task.emitLog(`Skipping because ${action.id} does not support dry-run`, {\n stepId: step.id,\n status: 'skipped',\n });\n }\n\n async function markSuccessful() {\n promTaskCount.inc({\n template,\n user,\n result: 'ok',\n });\n taskTimer({ result: 'ok' });\n\n taskCount.add(1, { template, user, result: 'ok' });\n taskDuration.record(endTime(), {\n result: 'ok',\n });\n }\n\n async function markFailed(step: TaskStep, err: Error) {\n await task.emitLog(String(err.stack), {\n stepId: step.id,\n status: 'failed',\n });\n promTaskCount.inc({\n template,\n user,\n result: 'failed',\n });\n taskTimer({ result: 'failed' });\n\n taskCount.add(1, { template, user, result: 'failed' });\n taskDuration.record(endTime(), {\n result: 'failed',\n });\n }\n\n async function markCancelled(step: TaskStep) {\n await task.emitLog(`Step ${step.id} has been cancelled.`, {\n stepId: step.id,\n status: 'cancelled',\n });\n promTaskCount.inc({\n template,\n user,\n result: 'cancelled',\n });\n taskTimer({ result: 'cancelled' });\n\n taskCount.add(1, { template, user, result: 'cancelled' });\n taskDuration.record(endTime(), {\n result: 'cancelled',\n });\n }\n\n return {\n skipDryRun,\n markCancelled,\n markSuccessful,\n markFailed,\n };\n }\n\n async function stepStart(task: TaskContext, step: TaskStep) {\n await task.emitLog(`Beginning step ${step.name}`, {\n stepId: step.id,\n status: 'processing',\n });\n const template = task.spec.templateInfo?.entityRef || '';\n\n const startTime = process.hrtime();\n const stepTimer = promStepDuration.startTimer({\n template,\n step: step.name,\n });\n\n function endTime() {\n const delta = process.hrtime(startTime);\n return delta[0] + delta[1] / 1e9;\n }\n\n async function markSuccessful() {\n await task.emitLog(`Finished step ${step.name}`, {\n stepId: step.id,\n status: 'completed',\n });\n promtStepCount.inc({\n template,\n step: step.name,\n result: 'ok',\n });\n stepTimer({ result: 'ok' });\n\n stepCount.add(1, { template, step: step.name, result: 'ok' });\n stepDuration.record(endTime(), {\n result: 'ok',\n });\n }\n\n async function markCancelled() {\n promtStepCount.inc({\n template,\n step: step.name,\n result: 'cancelled',\n });\n stepTimer({ result: 'cancelled' });\n\n stepCount.add(1, { template, step: step.name, result: 'cancelled' });\n stepDuration.record(endTime(), {\n result: 'cancelled',\n });\n }\n\n async function markFailed() {\n promtStepCount.inc({\n template,\n step: step.name,\n result: 'failed',\n });\n stepTimer({ result: 'failed' });\n\n stepCount.add(1, { template, step: step.name, result: 'failed' });\n stepDuration.record(endTime(), {\n result: 'failed',\n });\n }\n\n async function skipFalsy() {\n await task.emitLog(\n `Skipping step ${step.id} because its if condition was false`,\n { stepId: step.id, status: 'skipped' },\n );\n stepTimer({ result: 'skipped' });\n\n stepCount.add(1, { template, step: step.name, result: 'skipped' });\n stepDuration.record(endTime(), {\n result: 'skipped',\n });\n }\n\n return {\n markCancelled,\n markFailed,\n markSuccessful,\n skipFalsy,\n };\n }\n\n return {\n taskStart,\n stepStart,\n };\n}\n"],"names":["WinstonLogger","winston","BackstageLoggerTransport","PassThrough","createConditionAuthorizer","scaffolderActionRules","createDefaultFilters","nunjucks","templated","isTruthy","generateExampleOutput","validateJsonSchema","errors","InputError","NotAllowedError","loggerToWinstonLogger","stringifyError","fs","path","SecureTemplater","actionExecutePermission","AuthorizeResult","createCounterMetric","createHistogramMetric","metrics"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuGA,MAAM,eAAA,GAAkB,CAAC,QAAoD,KAAA;AAC3E,EAAA,OAAO,SAAS,UAAe,KAAA,iCAAA;AACjC,CAAA;AAEA,MAAM,mBAAmB,CAAC;AAAA,EACxB,IAAA;AAAA,EACA,IAAA;AAAA,EACA;AACF,CAIM,KAAA;AACJ,EAAM,MAAA,UAAA,GAAaA,qBAAc,MAAO,CAAA;AAAA,IACtC,KAAA,EAAO,OAAQ,CAAA,GAAA,CAAI,SAAa,IAAA,MAAA;AAAA,IAChC,MAAA,EAAQC,mBAAQ,MAAO,CAAA,OAAA;AAAA,MACrBA,kBAAA,CAAQ,OAAO,QAAS,EAAA;AAAA,MACxBA,kBAAA,CAAQ,OAAO,MAAO;AAAA,KACxB;AAAA,IACA,UAAA,EAAY,CAAC,IAAIC,+BAAA,CAAyB,YAAY,IAAM,EAAA,IAAA,CAAK,EAAE,CAAC;AAAA,GACrE,CAAA;AAED,EAAA,UAAA,CAAW,cAAc,MAAO,CAAA,MAAA,CAAO,KAAK,OAAW,IAAA,EAAE,CAAC,CAAA;AAS1D,EAAM,MAAA,YAAA,GAAe,IAAIC,kBAAY,EAAA;AACrC,EAAa,YAAA,CAAA,EAAA,CAAG,MAAQ,EAAA,OAAM,IAAQ,KAAA;AACpC,IAAA,MAAM,OAAU,GAAA,IAAA,CAAK,QAAS,EAAA,CAAE,IAAK,EAAA;AACrC,IAAI,IAAA,OAAA,EAAS,SAAS,CAAG,EAAA;AACvB,MAAA,UAAA,CAAW,KAAK,OAAO,CAAA;AAAA;AACzB,GACD,CAAA;AAED,EAAO,OAAA,EAAE,YAAY,YAAa,EAAA;AACpC,CAAA;AAEA,MAAM,kBAAqB,GAAAC,8CAAA;AAAA,EACzB,MAAA,CAAO,OAAOC,2BAAqB;AACrC,CAAA;AAEO,MAAM,sBAAiD,CAAA;AAAA,EAG5D,YAA6B,OAAwC,EAAA;AAAxC,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAC3B,IAAA,IAAA,CAAK,yBAAyBC,4BAAqB,CAAA;AAAA,MACjD,YAAA,EAAc,KAAK,OAAQ,CAAA;AAAA,KAC5B,CAAA;AAAA;AACH,EANiB,sBAAA;AAAA,EAQA,UAAU,kBAAmB,EAAA;AAAA,EAEtC,uBAAuB,KAAe,EAAA;AAC5C,IAAM,MAAA,EAAE,MAAQ,EAAA,KAAA,EAAU,GAAAC,yBAAA;AAW1B,IAAA,MAAM,SAAS,MAAO,CAAA,KAAA;AAAA,MACpB,KAAA;AAAA,MACA,EAAC;AAAA,MACD;AAAA,QACE,UAAY,EAAA,KAAA;AAAA,QACZ,IAAM,EAAA;AAAA,UACJ,aAAe,EAAA,KAAA;AAAA,UACf,WAAa,EAAA;AAAA;AACf;AACF,KACF;AAEA,IAAA,OACE,MAAO,CAAA,QAAA,CAAS,MAAW,KAAA,CAAA,IAC3B,EAAE,MAAA,CAAO,QAAS,CAAA,CAAC,CAAG,EAAA,QAAA,GAAW,CAAC,CAAA,YAAa,KAAM,CAAA,YAAA,CAAA;AAAA;AAEzD,EAEQ,MAAA,CACN,KACA,EAAA,OAAA,EACA,cACG,EAAA;AACH,IAAO,OAAA,IAAA,CAAK,MAAM,IAAK,CAAA,SAAA,CAAU,KAAK,CAAG,EAAA,CAAC,MAAM,KAAU,KAAA;AACxD,MAAI,IAAA;AACF,QAAI,IAAA,OAAO,UAAU,QAAU,EAAA;AAC7B,UAAI,IAAA;AACF,YAAI,IAAA,IAAA,CAAK,sBAAuB,CAAA,KAAK,CAAG,EAAA;AAEtC,cAAA,MAAM,gBAAgB,KAAM,CAAA,OAAA;AAAA,gBAC1B,aAAA;AAAA,gBACA;AAAA,eACF;AAGA,cAAMC,MAAAA,UAAAA,GAAY,cAAe,CAAA,aAAA,EAAe,OAAO,CAAA;AAGvD,cAAA,IAAIA,eAAc,EAAI,EAAA;AACpB,gBAAO,OAAA,KAAA,CAAA;AAAA;AAIT,cAAO,OAAA,IAAA,CAAK,MAAMA,UAAS,CAAA;AAAA;AAC7B,mBACO,EAAI,EAAA;AACX,YAAA,IAAA,CAAK,QAAQ,MAAO,CAAA,KAAA;AAAA,cAClB,CAAoC,iCAAA,EAAA,KAAK,CAAe,YAAA,EAAA,EAAA,CAAG,OAAO,CAAA;AAAA,aACpE;AAAA;AAIF,UAAM,MAAA,SAAA,GAAY,cAAe,CAAA,KAAA,EAAO,OAAO,CAAA;AAE/C,UAAA,IAAI,cAAc,EAAI,EAAA;AACpB,YAAO,OAAA,KAAA,CAAA;AAAA;AAGT,UAAO,OAAA,SAAA;AAAA;AACT,OACM,CAAA,MAAA;AACN,QAAO,OAAA,KAAA;AAAA;AAET,MAAO,OAAA,KAAA;AAAA,KACR,CAAA;AAAA;AACH,EAEA,MAAM,YACJ,IACA,EAAA,IAAA,EACA,SACA,cACA,EAAA,SAAA,EACA,eACA,QACA,EAAA;AACA,IAAA,MAAM,YAAY,MAAM,IAAA,CAAK,OAAQ,CAAA,SAAA,CAAU,MAAM,IAAI,CAAA;AAEzD,IAAI,IAAA,IAAA,CAAK,aAAa,OAAS,EAAA;AAC7B,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,KAAA,EAAQ,KAAK,EAAE,CAAA,EAAA,EAAK,KAAK,IAAI,CAAA,UAAA,EAAa,KAAK,MAAM,CAAA,oBAAA;AAAA,OACvD;AAAA;AAGF,IAAI,IAAA;AACF,MAAA,IACE,KAAK,EAAO,KAAA,KAAA,IACX,OAAO,IAAA,CAAK,OAAO,QAClB,IAAA,CAACC,eAAS,CAAA,IAAA,CAAK,OAAO,IAAK,CAAA,EAAA,EAAI,OAAS,EAAA,cAAc,CAAC,CACzD,EAAA;AACA,QAAA,MAAM,UAAU,SAAU,EAAA;AAC1B,QAAA;AAAA;AAEF,MAAA,MAAM,SACJ,IAAK,CAAA,OAAA,CAAQ,cAAe,CAAA,GAAA,CAAI,KAAK,MAAM,CAAA;AAC7C,MAAA,MAAM,EAAE,UAAA,EAAY,YAAa,EAAA,GAAI,gBAAiB,CAAA;AAAA,QACpD,IAAA;AAAA,QACA,IAAA;AAAA,QACA,UAAA,EAAY,KAAK,OAAQ,CAAA;AAAA,OAC1B,CAAA;AAED,MAAA,IAAI,KAAK,QAAU,EAAA;AACjB,QAAA,MAAM,kBAAkB,MAAO,CAAA,WAAA;AAAA,UAC7B,MAAO,CAAA,OAAA,CAAQ,IAAK,CAAA,OAAA,IAAW,EAAE,CAAA,CAAE,GAAI,CAAA,CAAA,MAAA,KAAU,CAAC,MAAA,CAAO,CAAC,CAAA,EAAG,KAAK,CAAC;AAAA,SACrE;AACA,QAAM,MAAA,UAAA,GAAA,CACH,IAAK,CAAA,KAAA,IACJ,IAAK,CAAA,MAAA;AAAA,UACH,IAAK,CAAA,KAAA;AAAA,UACL;AAAA,YACE,GAAG,OAAA;AAAA,YACH,OAAS,EAAA;AAAA,WACX;AAAA,UACA;AAAA,cAEJ,EAAC;AACH,QAAW,UAAA,CAAA,IAAA;AAAA,UACT,CACE,QAAA,EAAA,MAAA,CAAO,EACT,CAAA,iDAAA,EAAoD,IAAK,CAAA,SAAA;AAAA,YACvD,UAAA;AAAA,YACA,KAAA,CAAA;AAAA,YACA;AAAA,WACD,CAAA;AAAA,SACH;AACA,QAAI,IAAA,CAAC,OAAO,cAAgB,EAAA;AAC1B,UAAM,MAAA,SAAA,CAAU,UAAW,CAAA,IAAA,EAAM,MAAM,CAAA;AACvC,UAAM,MAAA,YAAA,GAAe,OAAO,MAAQ,EAAA,MAAA;AACpC,UAAA,IAAI,YAAc,EAAA;AAChB,YAAQ,OAAA,CAAA,KAAA,CAAM,IAAK,CAAA,EAAE,CAAI,GAAA;AAAA,cACvB,MAAA,EAAQC,6BAAsB,YAAY;AAAA,aAG5C;AAAA,WACK,MAAA;AACL,YAAA,OAAA,CAAQ,MAAM,IAAK,CAAA,EAAE,IAAI,EAAE,MAAA,EAAQ,EAAG,EAAA;AAAA;AAExC,UAAA;AAAA;AACF;AAEF,MAAA,MAAM,UACJ,GAAA,CAAA,IAAA,CAAK,IACD,GAAA,MAAA,CAAO,OAAQ,CAAA,IAAA,CAAK,MAAO,CAAA,IAAA,CAAK,IAAM,EAAA,OAAA,EAAS,cAAc,CAAC,CAAE,CAAA,GAAA;AAAA,QAC9D,CAAC,CAAC,GAAK,EAAA,KAAK,CAAO,MAAA;AAAA,UACjB,IAAA,EAAM,EAAE,GAAA,EAAK,KAAM;AAAA,SACrB;AAAA,UAEF,CAAC,EAAE,CAAA,EACP,IAAI,CAAM,CAAA,MAAA;AAAA,QACV,GAAG,CAAA;AAAA;AAAA,QAEH,KAAA,EAAO,IAAK,CAAA,KAAA,GACR,IAAK,CAAA,MAAA;AAAA,UACH,IAAK,CAAA,KAAA;AAAA,UACL,EAAE,GAAG,OAAS,EAAA,OAAA,EAAS,KAAK,OAAW,IAAA,EAAI,EAAA,GAAG,CAAE,EAAA;AAAA,UAChD;AAAA,YAEF;AAAC,OACL,CAAA,CAAA;AACF,MAAA,KAAA,MAAW,aAAa,UAAY,EAAA;AAClC,QAAA,MAAM,QAAW,GAAA,CAAA,EAAG,MAAO,CAAA,EAAE,CAC3B,EAAA,SAAA,CAAU,IAAO,GAAA,CAAA,CAAA,EAAI,SAAU,CAAA,IAAA,CAAK,GAAG,CAAA,CAAA,CAAA,GAAM,EAC/C,CAAA,CAAA;AAEA,QAAI,IAAA,MAAA,CAAO,QAAQ,KAAO,EAAA;AACxB,UAAA,MAAM,cAAiB,GAAAC,mBAAA;AAAA,YACrB,SAAU,CAAA,KAAA;AAAA,YACV,OAAO,MAAO,CAAA;AAAA,WAChB;AACA,UAAI,IAAA,CAAC,eAAe,KAAO,EAAA;AACzB,YAAA,MAAMC,QAAS,GAAA,cAAA,CAAe,MAAO,CAAA,IAAA,CAAK,IAAI,CAAA;AAC9C,YAAA,MAAM,IAAIC,iBAAA;AAAA,cACR,CAAA,+BAAA,EAAkC,QAAQ,CAAA,EAAA,EAAKD,QAAM,CAAA;AAAA,aACvD;AAAA;AACF;AAEF,QACE,IAAA,CAAC,mBAAmB,QAAU,EAAA;AAAA,UAC5B,QAAQ,MAAO,CAAA,EAAA;AAAA,UACf,OAAO,SAAU,CAAA;AAAA,SAClB,CACD,EAAA;AACA,UAAA,MAAM,IAAIE,sBAAA;AAAA,YACR,CAAA,qBAAA,EAAwB,QAAQ,CAAA,oCAAA,EAAuC,IAAK,CAAA,SAAA;AAAA,cAC1E,SAAU,CAAA,KAAA;AAAA,cACV,IAAA;AAAA,cACA;AAAA,aACD,CAAA;AAAA,WACH;AAAA;AACF;AAEF,MAAM,MAAA,OAAA,GAAU,IAAI,KAAc,EAAA;AAClC,MAAA,MAAM,aAAkD,EAAC;AACzD,MAAM,MAAA,aAAA,GAAgB,MAAM,IAAA,CAAK,YAAe,IAAA;AAEhD,MAAA,KAAA,MAAW,aAAa,UAAY,EAAA;AAClC,QAAA,IAAI,UAAU,IAAM,EAAA;AAClB,UAAW,UAAA,CAAA,IAAA;AAAA,YACT,sBAAsB,IAAK,CAAA,SAAA;AAAA,cACzB,SAAU,CAAA,IAAA;AAAA,cACV,CAAC,CAAG,EAAA,CAAA,KAAO,CAAI,GAAA,CAAA,CAAE,UAAa,GAAA,CAAA;AAAA,cAC9B;AAAA,aACD,CAAA;AAAA,WACH;AAAA;AAGF,QAAA,MAAM,OAAO,OAAQ,CAAA;AAAA,UACnB,OAAO,SAAU,CAAA,KAAA;AAAA,UACjB,IAAM,EAAA;AAAA,YACJ,EAAA,EAAI,MAAM,IAAA,CAAK,gBAAiB;AAAA,WAClC;AAAA,UACA,OAAA,EAAS,IAAK,CAAA,OAAA,IAAW,EAAC;AAAA;AAAA,UAE1B,MAAA,EAAQC,oCAAsB,UAAU,CAAA;AAAA,UACxC,SAAW,EAAA,YAAA;AAAA,UACX,aAAA;AAAA,UACA,MAAM,WAAuC,IAG1C,EAAA;AACD,YAAA,MAAM,EAAE,GAAA,EAAK,aAAe,EAAA,EAAA,EAAO,GAAA,IAAA;AACnC,YAAA,MAAM,GAAM,GAAA,CAAA,mBAAA,EAAsB,IAAK,CAAA,EAAE,IAAI,aAAa,CAAA,CAAA;AAE1D,YAAI,IAAA;AACF,cAAI,IAAA,SAAA;AAEJ,cAAA,IAAI,aAAe,EAAA;AACjB,gBAAA,MAAM,SACJ,GAAA,aAAA,CAAc,KAAO,EAAA,WAAA,GAGnB,GAAG,CAAA;AAEP,gBAAI,IAAA,SAAA,IAAa,SAAU,CAAA,MAAA,KAAW,SAAW,EAAA;AAC/C,kBAAA,SAAA,GAAY,SAAU,CAAA,KAAA;AAAA;AACxB;AAGF,cAAA,MAAM,KAAQ,GAAA,SAAA,GAAY,SAAY,GAAA,MAAM,EAAG,EAAA;AAE/C,cAAA,IAAI,CAAC,SAAW,EAAA;AACd,gBAAA,IAAA,CAAK,gBAAmB,GAAA;AAAA,kBACtB,GAAA;AAAA,kBACA,MAAQ,EAAA,SAAA;AAAA,kBACR,KAAA,EAAO,SAAS;AAAC,iBAClB,CAAA;AAAA;AAEH,cAAO,OAAA,KAAA;AAAA,qBACA,GAAK,EAAA;AACZ,cAAA,IAAA,CAAK,gBAAmB,GAAA;AAAA,gBACtB,GAAA;AAAA,gBACA,MAAQ,EAAA,QAAA;AAAA,gBACR,MAAA,EAAQC,sBAAe,GAAG;AAAA,eAC3B,CAAA;AACD,cAAM,MAAA,GAAA;AAAA,aACN,SAAA;AACA,cAAA,MAAM,IAAK,CAAA,kBAAA,GAAqB,EAAE,IAAA,EAAM,eAAe,CAAA;AAAA;AACzD,WACF;AAAA,UACA,0BAA0B,YAAY;AACpC,YAAM,MAAA,MAAA,GAAS,MAAMC,mBAAG,CAAA,OAAA;AAAA,cACtB,CAAG,EAAA,aAAa,CAAS,MAAA,EAAA,IAAA,CAAK,EAAE,CAAA,CAAA;AAAA,aAClC;AACA,YAAA,OAAA,CAAQ,KAAK,MAAM,CAAA;AACnB,YAAO,OAAA,MAAA;AAAA,WACT;AAAA,UACA,MAAA,CAAO,MAAc,KAAkB,EAAA;AACrC,YAAA,IAAI,KAAK,IAAM,EAAA;AACb,cAAA,UAAA,CAAW,IAAI,CAAA,GAAI,UAAW,CAAA,IAAI,KAAK,EAAC;AACxC,cAAC,UAAW,CAAA,IAAI,CAAgB,CAAA,IAAA,CAAK,KAAK,CAAA;AAAA,aACrC,MAAA;AACL,cAAA,UAAA,CAAW,IAAI,CAAI,GAAA,KAAA;AAAA;AACrB,WACF;AAAA,UACA,YAAA,EAAc,KAAK,IAAK,CAAA,YAAA;AAAA,UACxB,IAAA,EAAM,KAAK,IAAK,CAAA,IAAA;AAAA,UAChB,UAAU,IAAK,CAAA,QAAA;AAAA,UACf,QAAQ,IAAK,CAAA,YAAA;AAAA,UACb,uBAAA,EAAyB,MAAM,IAAA,CAAK,uBAAwB;AAAA,SAC7D,CAAA;AAAA;AAIH,MAAA,KAAA,MAAW,UAAU,OAAS,EAAA;AAC5B,QAAM,MAAAA,mBAAA,CAAG,OAAO,MAAM,CAAA;AAAA;AAGxB,MAAA,OAAA,CAAQ,MAAM,IAAK,CAAA,EAAE,CAAI,GAAA,EAAE,QAAQ,UAAW,EAAA;AAE9C,MAAI,IAAA,IAAA,CAAK,aAAa,OAAS,EAAA;AAC7B,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,CAAA,KAAA,EAAQ,KAAK,EAAE,CAAA,EAAA,EAAK,KAAK,IAAI,CAAA,UAAA,EAAa,KAAK,MAAM,CAAA,oBAAA;AAAA,SACvD;AAAA;AAGF,MAAA,MAAM,UAAU,cAAe,EAAA;AAAA,aACxB,GAAK,EAAA;AACZ,MAAM,MAAA,SAAA,CAAU,UAAW,CAAA,IAAA,EAAM,GAAG,CAAA;AACpC,MAAA,MAAM,UAAU,UAAW,EAAA;AAC3B,MAAM,MAAA,GAAA;AAAA,KACN,SAAA;AACA,MAAA,MAAM,IAAK,CAAA,kBAAA,GAAqB,EAAE,IAAA,EAAM,eAAe,CAAA;AAAA;AACzD;AACF,EAEA,MAAM,QAAQ,IAA8C,EAAA;AAC1D,IAAA,IAAI,CAAC,eAAA,CAAgB,IAAK,CAAA,IAAI,CAAG,EAAA;AAC/B,MAAA,MAAM,IAAIJ,iBAAA;AAAA,QACR;AAAA,OACF;AAAA;AAEF,IAAM,MAAA,MAAA,GAAS,MAAM,IAAA,CAAK,gBAAiB,EAAA;AAE3C,IAAA,MAAM,gBAAgBK,qBAAK,CAAA,IAAA,CAAK,IAAK,CAAA,OAAA,CAAQ,kBAAkB,MAAM,CAAA;AAErE,IAAA,MAAM,EAAE,yBAAA,EAA2B,yBAA0B,EAAA,GAC3D,IAAK,CAAA,OAAA;AAEP,IAAM,MAAA,cAAA,GAAiB,MAAMC,+BAAA,CAAgB,YAAa,CAAA;AAAA,MACxD,eAAiB,EAAA;AAAA,QACf,GAAG,IAAK,CAAA,sBAAA;AAAA,QACR,GAAG;AAAA,OACL;AAAA,MACA,eAAiB,EAAA;AAAA,KAClB,CAAA;AAED,IAAI,IAAA;AACF,MAAA,MAAM,KAAK,kBAAqB,GAAA,EAAE,MAAQ,EAAA,UAAA,EAAY,eAAe,CAAA;AAErE,MAAA,MAAM,SAAY,GAAA,MAAM,IAAK,CAAA,OAAA,CAAQ,UAAU,IAAI,CAAA;AACnD,MAAM,MAAAF,mBAAA,CAAG,UAAU,aAAa,CAAA;AAEhC,MAAA,MAAM,OAA2B,GAAA;AAAA,QAC/B,UAAA,EAAY,KAAK,IAAK,CAAA,UAAA;AAAA,QACtB,OAAO,EAAC;AAAA,QACR,IAAA,EAAM,KAAK,IAAK,CAAA,IAAA;AAAA,QAChB,OAAS,EAAA;AAAA,UACP,IAAM,EAAA;AAAA,YACJ,EAAI,EAAA;AAAA;AACN;AACF,OACF;AAEA,MAAA,MAAM,CAAC,QAAQ,CACb,GAAA,IAAA,CAAK,OAAQ,CAAA,WAAA,IAAe,IAAK,CAAA,IAAA,CAAK,KAAM,CAAA,MAAA,GACxC,MAAM,IAAA,CAAK,QAAQ,WAAY,CAAA,oBAAA;AAAA,QAC7B,CAAC,EAAE,UAAY,EAAAG,6BAAA,EAAyB,CAAA;AAAA,QACxC,EAAE,WAAA,EAAa,MAAM,IAAA,CAAK,yBAA0B;AAAA,UAEtD,CAAC,EAAE,MAAQ,EAAAC,sCAAA,CAAgB,OAAO,CAAA;AAExC,MAAW,KAAA,MAAA,IAAA,IAAQ,IAAK,CAAA,IAAA,CAAK,KAAO,EAAA;AAClC,QAAA,MAAM,IAAK,CAAA,WAAA;AAAA,UACT,IAAA;AAAA,UACA,IAAA;AAAA,UACA,OAAA;AAAA,UACA,cAAA;AAAA,UACA,SAAA;AAAA,UACA,aAAA;AAAA,UACA;AAAA,SACF;AAAA;AAGF,MAAA,MAAM,SAAS,IAAK,CAAA,MAAA,CAAO,KAAK,IAAK,CAAA,MAAA,EAAQ,SAAS,cAAc,CAAA;AACpE,MAAA,MAAM,UAAU,cAAe,EAAA;AAC/B,MAAA,MAAM,KAAK,cAAiB,IAAA;AAE5B,MAAA,OAAO,EAAE,MAAO,EAAA;AAAA,KAChB,SAAA;AACA,MAAA,IAAI,aAAe,EAAA;AACjB,QAAM,MAAAJ,mBAAA,CAAG,OAAO,aAAa,CAAA;AAAA;AAC/B;AACF;AAEJ;AAEA,SAAS,kBAAqB,GAAA;AAE5B,EAAA,MAAM,gBAAgBK,2BAAoB,CAAA;AAAA,IACxC,IAAM,EAAA,uBAAA;AAAA,IACN,IAAM,EAAA,oBAAA;AAAA,IACN,UAAY,EAAA,CAAC,UAAY,EAAA,MAAA,EAAQ,QAAQ;AAAA,GAC1C,CAAA;AACD,EAAA,MAAM,mBAAmBC,6BAAsB,CAAA;AAAA,IAC7C,IAAM,EAAA,0BAAA;AAAA,IACN,IAAM,EAAA,wBAAA;AAAA,IACN,UAAA,EAAY,CAAC,UAAA,EAAY,QAAQ;AAAA,GAClC,CAAA;AACD,EAAA,MAAM,iBAAiBD,2BAAoB,CAAA;AAAA,IACzC,IAAM,EAAA,uBAAA;AAAA,IACN,IAAM,EAAA,oBAAA;AAAA,IACN,UAAY,EAAA,CAAC,UAAY,EAAA,MAAA,EAAQ,QAAQ;AAAA,GAC1C,CAAA;AACD,EAAA,MAAM,mBAAmBC,6BAAsB,CAAA;AAAA,IAC7C,IAAM,EAAA,0BAAA;AAAA,IACN,IAAM,EAAA,yBAAA;AAAA,IACN,UAAY,EAAA,CAAC,UAAY,EAAA,MAAA,EAAQ,QAAQ;AAAA,GAC1C,CAAA;AAED,EAAM,MAAA,KAAA,GAAQC,WAAQ,CAAA,QAAA,CAAS,SAAS,CAAA;AACxC,EAAM,MAAA,SAAA,GAAY,KAAM,CAAA,aAAA,CAAc,uBAAyB,EAAA;AAAA,IAC7D,WAAa,EAAA;AAAA,GACd,CAAA;AAED,EAAM,MAAA,YAAA,GAAe,KAAM,CAAA,eAAA,CAAgB,0BAA4B,EAAA;AAAA,IACrE,WAAa,EAAA,wBAAA;AAAA,IACb,IAAM,EAAA;AAAA,GACP,CAAA;AAED,EAAM,MAAA,SAAA,GAAY,KAAM,CAAA,aAAA,CAAc,uBAAyB,EAAA;AAAA,IAC7D,WAAa,EAAA;AAAA,GACd,CAAA;AAED,EAAM,MAAA,YAAA,GAAe,KAAM,CAAA,eAAA,CAAgB,0BAA4B,EAAA;AAAA,IACrE,WAAa,EAAA,yBAAA;AAAA,IACb,IAAM,EAAA;AAAA,GACP,CAAA;AAED,EAAA,eAAe,UAAU,IAAmB,EAAA;AAC1C,IAAA,MAAM,KAAK,OAAQ,CAAA,CAAA,sBAAA,EAAyB,KAAK,IAAK,CAAA,KAAA,CAAM,MAAM,CAAQ,MAAA,CAAA,CAAA;AAC1E,IAAA,MAAM,QAAW,GAAA,IAAA,CAAK,IAAK,CAAA,YAAA,EAAc,SAAa,IAAA,EAAA;AACtD,IAAA,MAAM,IAAO,GAAA,IAAA,CAAK,IAAK,CAAA,IAAA,EAAM,GAAO,IAAA,EAAA;AAEpC,IAAM,MAAA,SAAA,GAAY,QAAQ,MAAO,EAAA;AACjC,IAAM,MAAA,SAAA,GAAY,iBAAiB,UAAW,CAAA;AAAA,MAC5C;AAAA,KACD,CAAA;AAED,IAAA,SAAS,OAAU,GAAA;AACjB,MAAM,MAAA,KAAA,GAAQ,OAAQ,CAAA,MAAA,CAAO,SAAS,CAAA;AACtC,MAAA,OAAO,KAAM,CAAA,CAAC,CAAI,GAAA,KAAA,CAAM,CAAC,CAAI,GAAA,GAAA;AAAA;AAG/B,IAAe,eAAA,UAAA,CACb,MACA,MACA,EAAA;AACA,MAAA,IAAA,CAAK,OAAQ,CAAA,CAAA,iBAAA,EAAoB,MAAO,CAAA,EAAE,CAA6B,yBAAA,CAAA,EAAA;AAAA,QACrE,QAAQ,IAAK,CAAA,EAAA;AAAA,QACb,MAAQ,EAAA;AAAA,OACT,CAAA;AAAA;AAGH,IAAA,eAAe,cAAiB,GAAA;AAC9B,MAAA,aAAA,CAAc,GAAI,CAAA;AAAA,QAChB,QAAA;AAAA,QACA,IAAA;AAAA,QACA,MAAQ,EAAA;AAAA,OACT,CAAA;AACD,MAAU,SAAA,CAAA,EAAE,MAAQ,EAAA,IAAA,EAAM,CAAA;AAE1B,MAAA,SAAA,CAAU,IAAI,CAAG,EAAA,EAAE,UAAU,IAAM,EAAA,MAAA,EAAQ,MAAM,CAAA;AACjD,MAAa,YAAA,CAAA,MAAA,CAAO,SAAW,EAAA;AAAA,QAC7B,MAAQ,EAAA;AAAA,OACT,CAAA;AAAA;AAGH,IAAe,eAAA,UAAA,CAAW,MAAgB,GAAY,EAAA;AACpD,MAAA,MAAM,IAAK,CAAA,OAAA,CAAQ,MAAO,CAAA,GAAA,CAAI,KAAK,CAAG,EAAA;AAAA,QACpC,QAAQ,IAAK,CAAA,EAAA;AAAA,QACb,MAAQ,EAAA;AAAA,OACT,CAAA;AACD,MAAA,aAAA,CAAc,GAAI,CAAA;AAAA,QAChB,QAAA;AAAA,QACA,IAAA;AAAA,QACA,MAAQ,EAAA;AAAA,OACT,CAAA;AACD,MAAU,SAAA,CAAA,EAAE,MAAQ,EAAA,QAAA,EAAU,CAAA;AAE9B,MAAA,SAAA,CAAU,IAAI,CAAG,EAAA,EAAE,UAAU,IAAM,EAAA,MAAA,EAAQ,UAAU,CAAA;AACrD,MAAa,YAAA,CAAA,MAAA,CAAO,SAAW,EAAA;AAAA,QAC7B,MAAQ,EAAA;AAAA,OACT,CAAA;AAAA;AAGH,IAAA,eAAe,cAAc,IAAgB,EAAA;AAC3C,MAAA,MAAM,IAAK,CAAA,OAAA,CAAQ,CAAQ,KAAA,EAAA,IAAA,CAAK,EAAE,CAAwB,oBAAA,CAAA,EAAA;AAAA,QACxD,QAAQ,IAAK,CAAA,EAAA;AAAA,QACb,MAAQ,EAAA;AAAA,OACT,CAAA;AACD,MAAA,aAAA,CAAc,GAAI,CAAA;AAAA,QAChB,QAAA;AAAA,QACA,IAAA;AAAA,QACA,MAAQ,EAAA;AAAA,OACT,CAAA;AACD,MAAU,SAAA,CAAA,EAAE,MAAQ,EAAA,WAAA,EAAa,CAAA;AAEjC,MAAA,SAAA,CAAU,IAAI,CAAG,EAAA,EAAE,UAAU,IAAM,EAAA,MAAA,EAAQ,aAAa,CAAA;AACxD,MAAa,YAAA,CAAA,MAAA,CAAO,SAAW,EAAA;AAAA,QAC7B,MAAQ,EAAA;AAAA,OACT,CAAA;AAAA;AAGH,IAAO,OAAA;AAAA,MACL,UAAA;AAAA,MACA,aAAA;AAAA,MACA,cAAA;AAAA,MACA;AAAA,KACF;AAAA;AAGF,EAAe,eAAA,SAAA,CAAU,MAAmB,IAAgB,EAAA;AAC1D,IAAA,MAAM,IAAK,CAAA,OAAA,CAAQ,CAAkB,eAAA,EAAA,IAAA,CAAK,IAAI,CAAI,CAAA,EAAA;AAAA,MAChD,QAAQ,IAAK,CAAA,EAAA;AAAA,MACb,MAAQ,EAAA;AAAA,KACT,CAAA;AACD,IAAA,MAAM,QAAW,GAAA,IAAA,CAAK,IAAK,CAAA,YAAA,EAAc,SAAa,IAAA,EAAA;AAEtD,IAAM,MAAA,SAAA,GAAY,QAAQ,MAAO,EAAA;AACjC,IAAM,MAAA,SAAA,GAAY,iBAAiB,UAAW,CAAA;AAAA,MAC5C,QAAA;AAAA,MACA,MAAM,IAAK,CAAA;AAAA,KACZ,CAAA;AAED,IAAA,SAAS,OAAU,GAAA;AACjB,MAAM,MAAA,KAAA,GAAQ,OAAQ,CAAA,MAAA,CAAO,SAAS,CAAA;AACtC,MAAA,OAAO,KAAM,CAAA,CAAC,CAAI,GAAA,KAAA,CAAM,CAAC,CAAI,GAAA,GAAA;AAAA;AAG/B,IAAA,eAAe,cAAiB,GAAA;AAC9B,MAAA,MAAM,IAAK,CAAA,OAAA,CAAQ,CAAiB,cAAA,EAAA,IAAA,CAAK,IAAI,CAAI,CAAA,EAAA;AAAA,QAC/C,QAAQ,IAAK,CAAA,EAAA;AAAA,QACb,MAAQ,EAAA;AAAA,OACT,CAAA;AACD,MAAA,cAAA,CAAe,GAAI,CAAA;AAAA,QACjB,QAAA;AAAA,QACA,MAAM,IAAK,CAAA,IAAA;AAAA,QACX,MAAQ,EAAA;AAAA,OACT,CAAA;AACD,MAAU,SAAA,CAAA,EAAE,MAAQ,EAAA,IAAA,EAAM,CAAA;AAE1B,MAAU,SAAA,CAAA,GAAA,CAAI,GAAG,EAAE,QAAA,EAAU,MAAM,IAAK,CAAA,IAAA,EAAM,MAAQ,EAAA,IAAA,EAAM,CAAA;AAC5D,MAAa,YAAA,CAAA,MAAA,CAAO,SAAW,EAAA;AAAA,QAC7B,MAAQ,EAAA;AAAA,OACT,CAAA;AAAA;AAGH,IAAA,eAAe,aAAgB,GAAA;AAC7B,MAAA,cAAA,CAAe,GAAI,CAAA;AAAA,QACjB,QAAA;AAAA,QACA,MAAM,IAAK,CAAA,IAAA;AAAA,QACX,MAAQ,EAAA;AAAA,OACT,CAAA;AACD,MAAU,SAAA,CAAA,EAAE,MAAQ,EAAA,WAAA,EAAa,CAAA;AAEjC,MAAU,SAAA,CAAA,GAAA,CAAI,GAAG,EAAE,QAAA,EAAU,MAAM,IAAK,CAAA,IAAA,EAAM,MAAQ,EAAA,WAAA,EAAa,CAAA;AACnE,MAAa,YAAA,CAAA,MAAA,CAAO,SAAW,EAAA;AAAA,QAC7B,MAAQ,EAAA;AAAA,OACT,CAAA;AAAA;AAGH,IAAA,eAAe,UAAa,GAAA;AAC1B,MAAA,cAAA,CAAe,GAAI,CAAA;AAAA,QACjB,QAAA;AAAA,QACA,MAAM,IAAK,CAAA,IAAA;AAAA,QACX,MAAQ,EAAA;AAAA,OACT,CAAA;AACD,MAAU,SAAA,CAAA,EAAE,MAAQ,EAAA,QAAA,EAAU,CAAA;AAE9B,MAAU,SAAA,CAAA,GAAA,CAAI,GAAG,EAAE,QAAA,EAAU,MAAM,IAAK,CAAA,IAAA,EAAM,MAAQ,EAAA,QAAA,EAAU,CAAA;AAChE,MAAa,YAAA,CAAA,MAAA,CAAO,SAAW,EAAA;AAAA,QAC7B,MAAQ,EAAA;AAAA,OACT,CAAA;AAAA;AAGH,IAAA,eAAe,SAAY,GAAA;AACzB,MAAA,MAAM,IAAK,CAAA,OAAA;AAAA,QACT,CAAA,cAAA,EAAiB,KAAK,EAAE,CAAA,mCAAA,CAAA;AAAA,QACxB,EAAE,MAAA,EAAQ,IAAK,CAAA,EAAA,EAAI,QAAQ,SAAU;AAAA,OACvC;AACA,MAAU,SAAA,CAAA,EAAE,MAAQ,EAAA,SAAA,EAAW,CAAA;AAE/B,MAAU,SAAA,CAAA,GAAA,CAAI,GAAG,EAAE,QAAA,EAAU,MAAM,IAAK,CAAA,IAAA,EAAM,MAAQ,EAAA,SAAA,EAAW,CAAA;AACjE,MAAa,YAAA,CAAA,MAAA,CAAO,SAAW,EAAA;AAAA,QAC7B,MAAQ,EAAA;AAAA,OACT,CAAA;AAAA;AAGH,IAAO,OAAA;AAAA,MACL,aAAA;AAAA,MACA,UAAA;AAAA,MACA,cAAA;AAAA,MACA;AAAA,KACF;AAAA;AAGF,EAAO,OAAA;AAAA,IACL,SAAA;AAAA,IACA;AAAA,GACF;AACF;;;;"}
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
var types = require('@backstage/types');
|
|
4
4
|
var ObservableImpl = require('zen-observable');
|
|
5
|
-
var helper = require('./helper.cjs.js');
|
|
6
5
|
var WorkspaceService = require('./WorkspaceService.cjs.js');
|
|
6
|
+
var helper = require('./helper.cjs.js');
|
|
7
7
|
|
|
8
8
|
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
|
|
9
9
|
|
|
@@ -129,12 +129,13 @@ class TaskManager {
|
|
|
129
129
|
}
|
|
130
130
|
}
|
|
131
131
|
class StorageTaskBroker {
|
|
132
|
-
constructor(storage, logger, config, auth, additionalWorkspaceProviders) {
|
|
132
|
+
constructor(storage, logger, config, auth, additionalWorkspaceProviders, auditor) {
|
|
133
133
|
this.storage = storage;
|
|
134
134
|
this.logger = logger;
|
|
135
135
|
this.config = config;
|
|
136
136
|
this.auth = auth;
|
|
137
137
|
this.additionalWorkspaceProviders = additionalWorkspaceProviders;
|
|
138
|
+
this.auditor = auditor;
|
|
138
139
|
}
|
|
139
140
|
async list(options) {
|
|
140
141
|
if (!this.storage.list) {
|
|
@@ -168,9 +169,7 @@ class StorageTaskBroker {
|
|
|
168
169
|
});
|
|
169
170
|
}
|
|
170
171
|
async recoverTasks() {
|
|
171
|
-
const enabled =
|
|
172
|
-
"scaffolder.EXPERIMENTAL_recoverTasks"
|
|
173
|
-
)) ?? false;
|
|
172
|
+
const enabled = this.config?.getOptionalBoolean("scaffolder.EXPERIMENTAL_recoverTasks") ?? false;
|
|
174
173
|
if (enabled) {
|
|
175
174
|
const defaultTimeout = { seconds: 30 };
|
|
176
175
|
const timeout = helper.readDuration(
|
|
@@ -267,6 +266,14 @@ class StorageTaskBroker {
|
|
|
267
266
|
const { tasks } = await this.storage.listStaleTasks(options);
|
|
268
267
|
await Promise.all(
|
|
269
268
|
tasks.map(async (task) => {
|
|
269
|
+
const auditorEvent = await this.auditor?.createEvent({
|
|
270
|
+
eventId: "task",
|
|
271
|
+
severityLevel: "medium",
|
|
272
|
+
meta: {
|
|
273
|
+
actionType: "stale-cancel",
|
|
274
|
+
taskId: task.taskId
|
|
275
|
+
}
|
|
276
|
+
});
|
|
270
277
|
try {
|
|
271
278
|
await this.storage.completeTask({
|
|
272
279
|
taskId: task.taskId,
|
|
@@ -275,8 +282,10 @@ class StorageTaskBroker {
|
|
|
275
282
|
message: "The task was cancelled because the task worker lost connection to the task broker"
|
|
276
283
|
}
|
|
277
284
|
});
|
|
285
|
+
await auditorEvent?.success();
|
|
278
286
|
} catch (error) {
|
|
279
287
|
this.logger.warn(`Failed to cancel task '${task.taskId}', ${error}`);
|
|
288
|
+
await auditorEvent?.fail({ error });
|
|
280
289
|
}
|
|
281
290
|
})
|
|
282
291
|
);
|