@backstage/plugin-scaffolder-backend 1.27.0 → 1.28.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 CHANGED
@@ -1,5 +1,42 @@
1
1
  # @backstage/plugin-scaffolder-backend
2
2
 
3
+ ## 1.28.0-next.0
4
+
5
+ ### Minor Changes
6
+
7
+ - c05a343: Emit scaffolder events using the optional `EventsService`
8
+
9
+ ### Patch Changes
10
+
11
+ - 3c62a50: Experimental support for `formDecorators` to enable secret collection and mutations to the parameters for scaffolder tasks
12
+ - 8f59dc5: Add fs:readdir to scaffolder startup
13
+ - Updated dependencies
14
+ - @backstage/backend-defaults@0.6.0-next.0
15
+ - @backstage/integration@1.16.0-next.0
16
+ - @backstage/plugin-scaffolder-common@1.5.8-next.0
17
+ - @backstage/backend-plugin-api@1.0.3-next.0
18
+ - @backstage/plugin-events-node@0.4.6-next.0
19
+ - @backstage/plugin-scaffolder-backend-module-gitlab@0.7.0-next.0
20
+ - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.3-next.0
21
+ - @backstage/plugin-scaffolder-node@0.6.1-next.0
22
+ - @backstage/plugin-auth-node@0.5.5-next.0
23
+ - @backstage/plugin-scaffolder-backend-module-bitbucket@0.3.4-next.0
24
+ - @backstage/catalog-client@1.8.1-next.0
25
+ - @backstage/catalog-model@1.7.1
26
+ - @backstage/config@1.3.0
27
+ - @backstage/errors@1.2.5
28
+ - @backstage/types@1.2.0
29
+ - @backstage/plugin-bitbucket-cloud-common@0.2.26-next.0
30
+ - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.3-next.0
31
+ - @backstage/plugin-catalog-node@1.14.1-next.0
32
+ - @backstage/plugin-permission-common@0.8.2
33
+ - @backstage/plugin-permission-node@0.8.6-next.0
34
+ - @backstage/plugin-scaffolder-backend-module-azure@0.2.3-next.0
35
+ - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.3-next.0
36
+ - @backstage/plugin-scaffolder-backend-module-gerrit@0.2.3-next.0
37
+ - @backstage/plugin-scaffolder-backend-module-gitea@0.2.3-next.0
38
+ - @backstage/plugin-scaffolder-backend-module-github@0.5.3-next.0
39
+
3
40
  ## 1.27.0
4
41
 
5
42
  ### Minor Changes
@@ -16,7 +16,7 @@ var template = require('./scaffolder/actions/builtin/fetch/template.cjs.js');
16
16
  var templateFile = require('./scaffolder/actions/builtin/fetch/templateFile.cjs.js');
17
17
  var _delete = require('./scaffolder/actions/builtin/filesystem/delete.cjs.js');
18
18
  var rename = require('./scaffolder/actions/builtin/filesystem/rename.cjs.js');
19
- require('./scaffolder/actions/builtin/filesystem/read.cjs.js');
19
+ var read = require('./scaffolder/actions/builtin/filesystem/read.cjs.js');
20
20
  require('@backstage/plugin-scaffolder-backend-module-github');
21
21
  require('@backstage/plugin-scaffolder-backend-module-azure');
22
22
  require('@backstage/plugin-scaffolder-backend-module-bitbucket');
@@ -35,6 +35,7 @@ require('fs-extra');
35
35
  require('p-queue');
36
36
  require('./scaffolder/tasks/NunjucksWorkflowRunner.cjs.js');
37
37
  var router = require('./service/router.cjs.js');
38
+ var pluginEventsNode = require('@backstage/plugin-events-node');
38
39
 
39
40
  const scaffolderPlugin = backendPluginApi.createBackendPlugin({
40
41
  pluginId: "scaffolder",
@@ -88,7 +89,8 @@ const scaffolderPlugin = backendPluginApi.createBackendPlugin({
88
89
  discovery: backendPluginApi.coreServices.discovery,
89
90
  httpRouter: backendPluginApi.coreServices.httpRouter,
90
91
  httpAuth: backendPluginApi.coreServices.httpAuth,
91
- catalogClient: alpha$1.catalogServiceRef
92
+ catalogClient: alpha$1.catalogServiceRef,
93
+ events: pluginEventsNode.eventsServiceRef
92
94
  },
93
95
  async init({
94
96
  logger,
@@ -101,7 +103,8 @@ const scaffolderPlugin = backendPluginApi.createBackendPlugin({
101
103
  httpRouter,
102
104
  httpAuth,
103
105
  catalogClient,
104
- permissions
106
+ permissions,
107
+ events
105
108
  }) {
106
109
  const log$1 = backendCommon.loggerToWinstonLogger(logger);
107
110
  const integrations = integration.ScmIntegrations.fromConfig(config);
@@ -136,7 +139,8 @@ const scaffolderPlugin = backendPluginApi.createBackendPlugin({
136
139
  fetch.createFetchCatalogEntityAction({ catalogClient, auth }),
137
140
  write.createCatalogWriteAction(),
138
141
  _delete.createFilesystemDeleteAction(),
139
- rename.createFilesystemRenameAction()
142
+ rename.createFilesystemRenameAction(),
143
+ read.createFilesystemReadDirAction()
140
144
  ];
141
145
  const actionIds = actions.map((action) => action.id).join(", ");
142
146
  log$1.info(
@@ -158,7 +162,8 @@ const scaffolderPlugin = backendPluginApi.createBackendPlugin({
158
162
  discovery,
159
163
  permissions,
160
164
  autocompleteHandlers,
161
- additionalWorkspaceProviders
165
+ additionalWorkspaceProviders,
166
+ events
162
167
  });
163
168
  httpRouter.use(router$1);
164
169
  }
@@ -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 createBackendPlugin,\n coreServices,\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 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 catalogClient: catalogServiceRef,\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 }) {\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 ];\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 });\n httpRouter.use(router);\n },\n });\n },\n});\n"],"names":["createBackendPlugin","scaffolderActionsExtensionPoint","scaffolderTaskBrokerExtensionPoint","scaffolderTemplatingExtensionPoint","scaffolderAutocompleteExtensionPoint","scaffolderWorkspaceProviderExtensionPoint","coreServices","catalogServiceRef","log","loggerToWinstonLogger","ScmIntegrations","createFetchPlainAction","createFetchPlainFileAction","createFetchTemplateAction","createFetchTemplateFileAction","createDebugLogAction","createWaitAction","createCatalogRegisterAction","createFetchCatalogEntityAction","createCatalogWriteAction","createFilesystemDeleteAction","createFilesystemRenameAction","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 {\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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"}
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  import * as _backstage_backend_plugin_api from '@backstage/backend-plugin-api';
3
3
  import { AuthService, UrlReaderService, BackstageCredentials, LifecycleService, DatabaseService, SchedulerService, PermissionsService, HttpAuthService, DiscoveryService } from '@backstage/backend-plugin-api';
4
4
  import * as _backstage_plugin_scaffolder_node from '@backstage/plugin-scaffolder-node';
5
- import { TemplateFilter as TemplateFilter$1, TemplateGlobal as TemplateGlobal$1, TemplateAction as TemplateAction$1, TaskSecrets as TaskSecrets$1, SerializedTask as SerializedTask$1, TaskStatus as TaskStatus$1, SerializedTaskEvent as SerializedTaskEvent$1, TaskCompletionState as TaskCompletionState$1, TaskEventType as TaskEventType$1, TaskBroker as TaskBroker$1, TaskContext as TaskContext$1, TaskBrokerDispatchResult as TaskBrokerDispatchResult$1, TaskBrokerDispatchOptions as TaskBrokerDispatchOptions$1, ActionContext as ActionContext$1, ExecuteShellCommandOptions, executeShellCommand as executeShellCommand$1, fetchContents as fetchContents$1 } from '@backstage/plugin-scaffolder-node';
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';
7
7
  import { HumanDuration, JsonObject, JsonValue } from '@backstage/types';
8
8
  import * as _backstage_integration from '@backstage/integration';
@@ -21,6 +21,7 @@ import { PluginDatabaseManager } from '@backstage/backend-common';
21
21
  import { Knex } from 'knex';
22
22
  import * as _backstage_plugin_scaffolder_common from '@backstage/plugin-scaffolder-common';
23
23
  import { TaskSpec, TaskRecovery, TemplateEntityStepV1beta3, TemplateParametersV1beta3 } from '@backstage/plugin-scaffolder-common';
24
+ import { EventsService } from '@backstage/plugin-events-node';
24
25
  import { Logger } from 'winston';
25
26
  import { WorkspaceProvider, AutocompleteHandler } from '@backstage/plugin-scaffolder-node/alpha';
26
27
  import { PermissionEvaluator, PermissionRuleParams } from '@backstage/plugin-permission-common';
@@ -631,6 +632,7 @@ interface TaskStore {
631
632
  */
632
633
  type DatabaseTaskStoreOptions = {
633
634
  database: PluginDatabaseManager | Knex;
635
+ events?: EventsService;
634
636
  };
635
637
  /**
636
638
  * DatabaseTaskStore
@@ -639,6 +641,7 @@ type DatabaseTaskStoreOptions = {
639
641
  */
640
642
  declare class DatabaseTaskStore implements TaskStore {
641
643
  private readonly db;
644
+ private readonly events?;
642
645
  static create(options: DatabaseTaskStoreOptions): Promise<DatabaseTaskStore>;
643
646
  private isRecoverableTask;
644
647
  private parseSpec;
@@ -646,6 +649,7 @@ declare class DatabaseTaskStore implements TaskStore {
646
649
  private static getClient;
647
650
  private static runMigrations;
648
651
  private constructor();
652
+ private getState;
649
653
  list(options: {
650
654
  createdBy?: string;
651
655
  status?: TaskStatus$1;
@@ -891,6 +895,7 @@ interface RouterOptions {
891
895
  httpAuth?: HttpAuthService;
892
896
  identity?: IdentityApi;
893
897
  discovery?: DiscoveryService;
898
+ events?: EventsService;
894
899
  autocompleteHandlers?: Record<string, AutocompleteHandler>;
895
900
  }
896
901
  /**
@@ -1,15 +1,15 @@
1
1
  'use strict';
2
2
 
3
- var fs = require('fs-extra');
3
+ var fs$1 = require('fs-extra');
4
4
  var path = require('path');
5
5
  var pluginScaffolderNode = require('@backstage/plugin-scaffolder-node');
6
6
  var log_examples = require('./log.examples.cjs.js');
7
- var fs$1 = require('fs');
7
+ var fs = require('fs');
8
8
  var z = require('zod');
9
9
 
10
10
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
11
11
 
12
- var fs__default = /*#__PURE__*/_interopDefaultCompat(fs$1);
12
+ var fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
13
13
 
14
14
  const id = "debug:log";
15
15
  function createDebugLogAction() {
@@ -51,11 +51,11 @@ ${files.map((f) => {
51
51
  });
52
52
  }
53
53
  async function recursiveReadDir(dir) {
54
- const subdirs = await fs.readdir(dir);
54
+ const subdirs = await fs$1.readdir(dir);
55
55
  const files = await Promise.all(
56
56
  subdirs.map(async (subdir) => {
57
57
  const res = path.join(dir, subdir);
58
- return (await fs.stat(res)).isDirectory() ? recursiveReadDir(res) : [res];
58
+ return (await fs$1.stat(res)).isDirectory() ? recursiveReadDir(res) : [res];
59
59
  })
60
60
  );
61
61
  return files.reduce((a, f) => a.concat(f), []);
@@ -1 +1 @@
1
- {"version":3,"file":"log.cjs.js","sources":["../../../../../src/scaffolder/actions/builtin/debug/log.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 { readdir, stat } from 'fs-extra';\nimport { join, relative } from 'path';\nimport { createTemplateAction } from '@backstage/plugin-scaffolder-node';\nimport { examples } from './log.examples';\nimport fs from 'fs';\nimport { z } from 'zod';\n\nconst id = 'debug:log';\n\n/**\n * Writes a message into the log or lists all files in the workspace\n *\n * @remarks\n *\n * This task is useful for local development and testing of both the scaffolder\n * and scaffolder templates.\n *\n * @public\n */\nexport function createDebugLogAction() {\n return createTemplateAction<{\n message?: string;\n listWorkspace?: boolean | 'with-filenames' | 'with-contents';\n }>({\n id,\n description:\n 'Writes a message into the log and/or lists all files in the workspace.',\n examples,\n schema: {\n input: z.object({\n message: z.string({ description: 'Message to output.' }).optional(),\n listWorkspace: z\n .union([z.boolean(), z.enum(['with-filenames', 'with-contents'])], {\n description:\n 'List all files in the workspace. If used with \"with-contents\", also the file contents are listed.',\n })\n .optional(),\n }),\n },\n supportsDryRun: true,\n async handler(ctx) {\n ctx.logger.info(JSON.stringify(ctx.input, null, 2));\n\n if (ctx.input?.message) {\n ctx.logger.info(ctx.input.message);\n }\n\n if (ctx.input?.listWorkspace) {\n const files = await recursiveReadDir(ctx.workspacePath);\n ctx.logger.info(\n `Workspace:\\n${files\n .map(f => {\n const relativePath = relative(ctx.workspacePath, f);\n if (ctx.input?.listWorkspace === 'with-contents') {\n const content = fs.readFileSync(f, 'utf-8');\n return ` - ${relativePath}:\\n\\n ${content}`;\n }\n return ` - ${relativePath}`;\n })\n .join('\\n')}`,\n );\n }\n },\n });\n}\n\nexport async function recursiveReadDir(dir: string): Promise<string[]> {\n const subdirs = await readdir(dir);\n const files = await Promise.all(\n subdirs.map(async subdir => {\n const res = join(dir, subdir);\n return (await stat(res)).isDirectory() ? recursiveReadDir(res) : [res];\n }),\n );\n return files.reduce((a, f) => a.concat(f), []);\n}\n"],"names":["createTemplateAction","examples","z","relative","fs","readdir","join","stat"],"mappings":";;;;;;;;;;;;;AAuBA,MAAM,EAAK,GAAA,WAAA;AAYJ,SAAS,oBAAuB,GAAA;AACrC,EAAA,OAAOA,yCAGJ,CAAA;AAAA,IACD,EAAA;AAAA,IACA,WACE,EAAA,wEAAA;AAAA,cACFC,qBAAA;AAAA,IACA,MAAQ,EAAA;AAAA,MACN,KAAA,EAAOC,IAAE,MAAO,CAAA;AAAA,QACd,OAAA,EAASA,IAAE,MAAO,CAAA,EAAE,aAAa,oBAAqB,EAAC,EAAE,QAAS,EAAA;AAAA,QAClE,aAAe,EAAAA,GAAA,CACZ,KAAM,CAAA,CAACA,IAAE,OAAQ,EAAA,EAAGA,GAAE,CAAA,IAAA,CAAK,CAAC,gBAAA,EAAkB,eAAe,CAAC,CAAC,CAAG,EAAA;AAAA,UACjE,WACE,EAAA;AAAA,SACH,EACA,QAAS;AAAA,OACb;AAAA,KACH;AAAA,IACA,cAAgB,EAAA,IAAA;AAAA,IAChB,MAAM,QAAQ,GAAK,EAAA;AACjB,MAAI,GAAA,CAAA,MAAA,CAAO,KAAK,IAAK,CAAA,SAAA,CAAU,IAAI,KAAO,EAAA,IAAA,EAAM,CAAC,CAAC,CAAA;AAElD,MAAI,IAAA,GAAA,CAAI,OAAO,OAAS,EAAA;AACtB,QAAA,GAAA,CAAI,MAAO,CAAA,IAAA,CAAK,GAAI,CAAA,KAAA,CAAM,OAAO,CAAA;AAAA;AAGnC,MAAI,IAAA,GAAA,CAAI,OAAO,aAAe,EAAA;AAC5B,QAAA,MAAM,KAAQ,GAAA,MAAM,gBAAiB,CAAA,GAAA,CAAI,aAAa,CAAA;AACtD,QAAA,GAAA,CAAI,MAAO,CAAA,IAAA;AAAA,UACT,CAAA;AAAA,EAAe,KAAA,CACZ,IAAI,CAAK,CAAA,KAAA;AACR,YAAA,MAAM,YAAe,GAAAC,aAAA,CAAS,GAAI,CAAA,aAAA,EAAe,CAAC,CAAA;AAClD,YAAI,IAAA,GAAA,CAAI,KAAO,EAAA,aAAA,KAAkB,eAAiB,EAAA;AAChD,cAAA,MAAM,OAAU,GAAAC,mBAAA,CAAG,YAAa,CAAA,CAAA,EAAG,OAAO,CAAA;AAC1C,cAAA,OAAO,MAAM,YAAY,CAAA;;AAAA,EAAA,EAAU,OAAO,CAAA,CAAA;AAAA;AAE5C,YAAA,OAAO,OAAO,YAAY,CAAA,CAAA;AAAA,WAC3B,CAAA,CACA,IAAK,CAAA,IAAI,CAAC,CAAA;AAAA,SACf;AAAA;AACF;AACF,GACD,CAAA;AACH;AAEA,eAAsB,iBAAiB,GAAgC,EAAA;AACrE,EAAM,MAAA,OAAA,GAAU,MAAMC,UAAA,CAAQ,GAAG,CAAA;AACjC,EAAM,MAAA,KAAA,GAAQ,MAAM,OAAQ,CAAA,GAAA;AAAA,IAC1B,OAAA,CAAQ,GAAI,CAAA,OAAM,MAAU,KAAA;AAC1B,MAAM,MAAA,GAAA,GAAMC,SAAK,CAAA,GAAA,EAAK,MAAM,CAAA;AAC5B,MAAQ,OAAA,CAAA,MAAMC,OAAK,CAAA,GAAG,CAAG,EAAA,WAAA,KAAgB,gBAAiB,CAAA,GAAG,CAAI,GAAA,CAAC,GAAG,CAAA;AAAA,KACtE;AAAA,GACH;AACA,EAAO,OAAA,KAAA,CAAM,MAAO,CAAA,CAAC,CAAG,EAAA,CAAA,KAAM,EAAE,MAAO,CAAA,CAAC,CAAG,EAAA,EAAE,CAAA;AAC/C;;;;;"}
1
+ {"version":3,"file":"log.cjs.js","sources":["../../../../../src/scaffolder/actions/builtin/debug/log.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 { readdir, stat } from 'fs-extra';\nimport { join, relative } from 'path';\nimport { createTemplateAction } from '@backstage/plugin-scaffolder-node';\nimport { examples } from './log.examples';\nimport fs from 'fs';\nimport { z } from 'zod';\n\nconst id = 'debug:log';\n\n/**\n * Writes a message into the log or lists all files in the workspace\n *\n * @remarks\n *\n * This task is useful for local development and testing of both the scaffolder\n * and scaffolder templates.\n *\n * @public\n */\nexport function createDebugLogAction() {\n return createTemplateAction<{\n message?: string;\n listWorkspace?: boolean | 'with-filenames' | 'with-contents';\n }>({\n id,\n description:\n 'Writes a message into the log and/or lists all files in the workspace.',\n examples,\n schema: {\n input: z.object({\n message: z.string({ description: 'Message to output.' }).optional(),\n listWorkspace: z\n .union([z.boolean(), z.enum(['with-filenames', 'with-contents'])], {\n description:\n 'List all files in the workspace. If used with \"with-contents\", also the file contents are listed.',\n })\n .optional(),\n }),\n },\n supportsDryRun: true,\n async handler(ctx) {\n ctx.logger.info(JSON.stringify(ctx.input, null, 2));\n\n if (ctx.input?.message) {\n ctx.logger.info(ctx.input.message);\n }\n\n if (ctx.input?.listWorkspace) {\n const files = await recursiveReadDir(ctx.workspacePath);\n ctx.logger.info(\n `Workspace:\\n${files\n .map(f => {\n const relativePath = relative(ctx.workspacePath, f);\n if (ctx.input?.listWorkspace === 'with-contents') {\n const content = fs.readFileSync(f, 'utf-8');\n return ` - ${relativePath}:\\n\\n ${content}`;\n }\n return ` - ${relativePath}`;\n })\n .join('\\n')}`,\n );\n }\n },\n });\n}\n\nexport async function recursiveReadDir(dir: string): Promise<string[]> {\n const subdirs = await readdir(dir);\n const files = await Promise.all(\n subdirs.map(async subdir => {\n const res = join(dir, subdir);\n return (await stat(res)).isDirectory() ? recursiveReadDir(res) : [res];\n }),\n );\n return files.reduce((a, f) => a.concat(f), []);\n}\n"],"names":["createTemplateAction","examples","z","relative","fs","readdir","join","stat"],"mappings":";;;;;;;;;;;;;AAuBA,MAAM,EAAK,GAAA,WAAA;AAYJ,SAAS,oBAAuB,GAAA;AACrC,EAAA,OAAOA,yCAGJ,CAAA;AAAA,IACD,EAAA;AAAA,IACA,WACE,EAAA,wEAAA;AAAA,cACFC,qBAAA;AAAA,IACA,MAAQ,EAAA;AAAA,MACN,KAAA,EAAOC,IAAE,MAAO,CAAA;AAAA,QACd,OAAA,EAASA,IAAE,MAAO,CAAA,EAAE,aAAa,oBAAqB,EAAC,EAAE,QAAS,EAAA;AAAA,QAClE,aAAe,EAAAA,GAAA,CACZ,KAAM,CAAA,CAACA,IAAE,OAAQ,EAAA,EAAGA,GAAE,CAAA,IAAA,CAAK,CAAC,gBAAA,EAAkB,eAAe,CAAC,CAAC,CAAG,EAAA;AAAA,UACjE,WACE,EAAA;AAAA,SACH,EACA,QAAS;AAAA,OACb;AAAA,KACH;AAAA,IACA,cAAgB,EAAA,IAAA;AAAA,IAChB,MAAM,QAAQ,GAAK,EAAA;AACjB,MAAI,GAAA,CAAA,MAAA,CAAO,KAAK,IAAK,CAAA,SAAA,CAAU,IAAI,KAAO,EAAA,IAAA,EAAM,CAAC,CAAC,CAAA;AAElD,MAAI,IAAA,GAAA,CAAI,OAAO,OAAS,EAAA;AACtB,QAAA,GAAA,CAAI,MAAO,CAAA,IAAA,CAAK,GAAI,CAAA,KAAA,CAAM,OAAO,CAAA;AAAA;AAGnC,MAAI,IAAA,GAAA,CAAI,OAAO,aAAe,EAAA;AAC5B,QAAA,MAAM,KAAQ,GAAA,MAAM,gBAAiB,CAAA,GAAA,CAAI,aAAa,CAAA;AACtD,QAAA,GAAA,CAAI,MAAO,CAAA,IAAA;AAAA,UACT,CAAA;AAAA,EAAe,KAAA,CACZ,IAAI,CAAK,CAAA,KAAA;AACR,YAAA,MAAM,YAAe,GAAAC,aAAA,CAAS,GAAI,CAAA,aAAA,EAAe,CAAC,CAAA;AAClD,YAAI,IAAA,GAAA,CAAI,KAAO,EAAA,aAAA,KAAkB,eAAiB,EAAA;AAChD,cAAA,MAAM,OAAU,GAAAC,mBAAA,CAAG,YAAa,CAAA,CAAA,EAAG,OAAO,CAAA;AAC1C,cAAA,OAAO,MAAM,YAAY,CAAA;;AAAA,EAAA,EAAU,OAAO,CAAA,CAAA;AAAA;AAE5C,YAAA,OAAO,OAAO,YAAY,CAAA,CAAA;AAAA,WAC3B,CAAA,CACA,IAAK,CAAA,IAAI,CAAC,CAAA;AAAA,SACf;AAAA;AACF;AACF,GACD,CAAA;AACH;AAEA,eAAsB,iBAAiB,GAAgC,EAAA;AACrE,EAAM,MAAA,OAAA,GAAU,MAAMC,YAAA,CAAQ,GAAG,CAAA;AACjC,EAAM,MAAA,KAAA,GAAQ,MAAM,OAAQ,CAAA,GAAA;AAAA,IAC1B,OAAA,CAAQ,GAAI,CAAA,OAAM,MAAU,KAAA;AAC1B,MAAM,MAAA,GAAA,GAAMC,SAAK,CAAA,GAAA,EAAK,MAAM,CAAA;AAC5B,MAAQ,OAAA,CAAA,MAAMC,SAAK,CAAA,GAAG,CAAG,EAAA,WAAA,KAAgB,gBAAiB,CAAA,GAAG,CAAI,GAAA,CAAC,GAAG,CAAA;AAAA,KACtE;AAAA,GACH;AACA,EAAO,OAAA,KAAA,CAAM,MAAO,CAAA,CAAC,CAAG,EAAA,CAAA,KAAM,EAAE,MAAO,CAAA,CAAC,CAAG,EAAA,EAAE,CAAA;AAC/C;;;;;"}
@@ -30,11 +30,12 @@ const parseSqlDateToIsoString = (input) => {
30
30
  };
31
31
  class DatabaseTaskStore {
32
32
  db;
33
+ events;
33
34
  static async create(options) {
34
35
  const { database } = options;
35
36
  const client = await this.getClient(database);
36
37
  await this.runMigrations(database, client);
37
- return new DatabaseTaskStore(client);
38
+ return new DatabaseTaskStore(client, options.events);
38
39
  }
39
40
  isRecoverableTask(spec) {
40
41
  return ["startOver"].includes(
@@ -76,8 +77,18 @@ class DatabaseTaskStore {
76
77
  });
77
78
  }
78
79
  }
79
- constructor(client) {
80
+ constructor(client, events) {
80
81
  this.db = client;
82
+ this.events = events;
83
+ }
84
+ getState(task) {
85
+ try {
86
+ return task.state ? JSON.parse(task.state).state : void 0;
87
+ } catch (error) {
88
+ throw new Error(
89
+ `Failed to parse state of the task '${task.id}', ${error}`
90
+ );
91
+ }
81
92
  }
82
93
  async list(options) {
83
94
  const { createdBy, status, pagination, order, filters } = options ?? {};
@@ -133,7 +144,7 @@ class DatabaseTaskStore {
133
144
  try {
134
145
  const spec = JSON.parse(result.spec);
135
146
  const secrets = result.secrets ? JSON.parse(result.secrets) : void 0;
136
- const state = result.state ? JSON.parse(result.state).state : void 0;
147
+ const state = this.getState(result);
137
148
  return {
138
149
  id: result.id,
139
150
  spec,
@@ -157,6 +168,15 @@ class DatabaseTaskStore {
157
168
  created_by: options.createdBy ?? null,
158
169
  status: "open"
159
170
  });
171
+ this.events?.publish({
172
+ topic: "scaffolder.task",
173
+ eventPayload: {
174
+ id: taskId,
175
+ spec: options.spec,
176
+ createdBy: options.createdBy,
177
+ status: "open"
178
+ }
179
+ });
160
180
  return { taskId };
161
181
  }
162
182
  async claimTask() {
@@ -177,26 +197,21 @@ class DatabaseTaskStore {
177
197
  if (updateCount < 1) {
178
198
  return void 0;
179
199
  }
180
- const getState = () => {
181
- try {
182
- return task.state ? JSON.parse(task.state).state : void 0;
183
- } catch (error) {
184
- throw new Error(
185
- `Failed to parse state of the task '${task.id}', ${error}`
186
- );
187
- }
188
- };
189
- const secrets = this.parseTaskSecrets(task);
190
- return {
200
+ const ret = {
191
201
  id: task.id,
192
202
  spec,
193
203
  status: "processing",
194
204
  lastHeartbeatAt: task.last_heartbeat_at,
195
205
  createdAt: task.created_at,
196
206
  createdBy: task.created_by ?? void 0,
197
- secrets,
198
- state: getState()
207
+ state: this.getState(task)
199
208
  };
209
+ this.events?.publish({
210
+ topic: "scaffolder.task",
211
+ eventPayload: ret
212
+ });
213
+ const secrets = this.parseTaskSecrets(task);
214
+ return { ...ret, secrets };
200
215
  });
201
216
  }
202
217
  async heartbeatTask(taskId) {
@@ -241,11 +256,22 @@ class DatabaseTaskStore {
241
256
  `Failed to update status to '${status}' for taskId ${taskId}`
242
257
  );
243
258
  }
259
+ this.events?.publish({
260
+ topic: "scaffolder.task",
261
+ eventPayload: {
262
+ id: taskId,
263
+ status,
264
+ lastHeartbeatAt: task.last_heartbeat_at,
265
+ createdAt: task.created_at,
266
+ createdBy: task.created_by,
267
+ state: this.getState(task)
268
+ }
269
+ });
244
270
  await tx("task_events").insert({
245
271
  task_id: taskId,
246
272
  event_type: "completion",
247
273
  body: JSON.stringify(eventBody)
248
- });
274
+ }).returning("id");
249
275
  };
250
276
  if (status === "cancelled") {
251
277
  await updateTask({
@@ -277,7 +303,7 @@ class DatabaseTaskStore {
277
303
  task_id: taskId,
278
304
  event_type: "log",
279
305
  body: serializedBody
280
- });
306
+ }).returning("id");
281
307
  }
282
308
  async getTaskState({ taskId }) {
283
309
  const [result] = await this.db("tasks").where({ id: taskId }).select("state");
@@ -370,10 +396,19 @@ class DatabaseTaskStore {
370
396
  async cancelTask(options) {
371
397
  const { taskId, body } = options;
372
398
  const serializedBody = JSON.stringify(body);
373
- await this.db("task_events").insert({
399
+ const [ret] = await this.db("task_events").insert({
374
400
  task_id: taskId,
375
401
  event_type: "cancelled",
376
402
  body: serializedBody
403
+ }).returning("id");
404
+ this.events?.publish({
405
+ topic: "scaffolder.task",
406
+ eventPayload: {
407
+ id: ret.id,
408
+ taskId,
409
+ status: "cancelled",
410
+ body
411
+ }
377
412
  });
378
413
  }
379
414
  async retryTask(options) {
@@ -413,12 +448,22 @@ class DatabaseTaskStore {
413
448
  taskIdsToRecover.push(...result.map((i) => i.id));
414
449
  for (const { id, spec } of result) {
415
450
  const taskSpec = JSON.parse(spec);
416
- await tx("task_events").insert({
451
+ const event = {
452
+ recoverStrategy: taskSpec.EXPERIMENTAL_recovery?.EXPERIMENTAL_strategy ?? "none"
453
+ };
454
+ const [ret] = await tx("task_events").insert({
417
455
  task_id: id,
418
456
  event_type: "recovered",
419
- body: JSON.stringify({
420
- recoverStrategy: taskSpec.EXPERIMENTAL_recovery?.EXPERIMENTAL_strategy ?? "none"
421
- })
457
+ body: JSON.stringify(event)
458
+ }).returning("id");
459
+ this.events?.publish({
460
+ topic: "scaffolder.task",
461
+ eventPayload: {
462
+ id: ret.id,
463
+ taskId: id,
464
+ status: "recovered",
465
+ body: event
466
+ }
422
467
  });
423
468
  }
424
469
  });
@@ -1 +1 @@
1
- {"version":3,"file":"DatabaseTaskStore.cjs.js","sources":["../../../src/scaffolder/tasks/DatabaseTaskStore.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 { JsonObject } from '@backstage/types';\nimport { PluginDatabaseManager } from '@backstage/backend-common';\nimport { resolvePackagePath } from '@backstage/backend-plugin-api';\nimport { ConflictError, NotFoundError } from '@backstage/errors';\nimport { Knex } from 'knex';\nimport { v4 as uuid } from 'uuid';\nimport {\n TaskStore,\n TaskStoreCreateTaskOptions,\n TaskStoreCreateTaskResult,\n TaskStoreEmitOptions,\n TaskStoreListEventsOptions,\n TaskStoreRecoverTaskOptions,\n TaskStoreShutDownTaskOptions,\n} from './types';\nimport {\n SerializedTask,\n SerializedTaskEvent,\n TaskEventType,\n TaskSecrets,\n TaskStatus,\n} from '@backstage/plugin-scaffolder-node';\nimport { DateTime, Duration } from 'luxon';\nimport { TaskRecovery, TaskSpec } from '@backstage/plugin-scaffolder-common';\nimport { trimEventsTillLastRecovery } from './taskRecoveryHelper';\nimport { intervalFromNowTill } from './dbUtil';\nimport {\n restoreWorkspace,\n serializeWorkspace,\n} from '@backstage/plugin-scaffolder-node/alpha';\nimport { flattenParams } from '../../service/helpers';\n\nconst migrationsDir = resolvePackagePath(\n '@backstage/plugin-scaffolder-backend',\n 'migrations',\n);\n\nexport type RawDbTaskRow = {\n id: string;\n spec: string;\n status: TaskStatus;\n state?: string;\n last_heartbeat_at?: string;\n created_at: string;\n created_by: string | null;\n secrets?: string | null;\n workspace?: Buffer;\n};\n\nexport type RawDbTaskEventRow = {\n id: number;\n task_id: string;\n body: string;\n event_type: TaskEventType;\n created_at: string;\n};\n\n/**\n * DatabaseTaskStore\n *\n * @public\n */\nexport type DatabaseTaskStoreOptions = {\n database: PluginDatabaseManager | Knex;\n};\n\n/**\n * Type guard to help DatabaseTaskStore understand when database is PluginDatabaseManager vs. when database is a Knex instance.\n *\n * * @public\n */\nfunction isPluginDatabaseManager(\n opt: PluginDatabaseManager | Knex,\n): opt is PluginDatabaseManager {\n return (opt as PluginDatabaseManager).getClient !== undefined;\n}\n\nconst parseSqlDateToIsoString = <T>(input: T): T | string => {\n if (typeof input === 'string') {\n const parsed = DateTime.fromSQL(input, { zone: 'UTC' });\n if (!parsed.isValid) {\n throw new Error(\n `Failed to parse database timestamp '${input}', ${parsed.invalidReason}: ${parsed.invalidExplanation}`,\n );\n }\n return parsed.toISO()!;\n }\n\n return input;\n};\n\n/**\n * DatabaseTaskStore\n *\n * @public\n */\nexport class DatabaseTaskStore implements TaskStore {\n private readonly db: Knex;\n\n static async create(\n options: DatabaseTaskStoreOptions,\n ): Promise<DatabaseTaskStore> {\n const { database } = options;\n const client = await this.getClient(database);\n\n await this.runMigrations(database, client);\n\n return new DatabaseTaskStore(client);\n }\n\n private isRecoverableTask(spec: TaskSpec): boolean {\n return ['startOver'].includes(\n spec.EXPERIMENTAL_recovery?.EXPERIMENTAL_strategy ?? 'none',\n );\n }\n\n private parseSpec({ spec, id }: { spec: string; id: string }): TaskSpec {\n try {\n return JSON.parse(spec);\n } catch (error) {\n throw new Error(`Failed to parse spec of task '${id}', ${error}`);\n }\n }\n\n private parseTaskSecrets(taskRow: RawDbTaskRow): TaskSecrets | undefined {\n try {\n return taskRow.secrets ? JSON.parse(taskRow.secrets) : undefined;\n } catch (error) {\n throw new Error(\n `Failed to parse secrets of task '${taskRow.id}', ${error}`,\n );\n }\n }\n\n private static async getClient(\n database: PluginDatabaseManager | Knex,\n ): Promise<Knex> {\n if (isPluginDatabaseManager(database)) {\n return database.getClient();\n }\n\n return database;\n }\n\n private static async runMigrations(\n database: PluginDatabaseManager | Knex,\n client: Knex,\n ): Promise<void> {\n if (!isPluginDatabaseManager(database)) {\n await client.migrate.latest({\n directory: migrationsDir,\n });\n\n return;\n }\n\n if (!database.migrations?.skip) {\n await client.migrate.latest({\n directory: migrationsDir,\n });\n }\n }\n\n private constructor(client: Knex) {\n this.db = client;\n }\n\n async list(options: {\n createdBy?: string;\n status?: TaskStatus;\n filters?: {\n createdBy?: string | string[];\n status?: TaskStatus | TaskStatus[];\n };\n pagination?: {\n limit?: number;\n offset?: number;\n };\n order?: { order: 'asc' | 'desc'; field: string }[];\n }): Promise<{ tasks: SerializedTask[]; totalTasks?: number }> {\n const { createdBy, status, pagination, order, filters } = options ?? {};\n const queryBuilder = this.db<RawDbTaskRow & { count: number }>('tasks');\n\n if (createdBy || filters?.createdBy) {\n const arr: string[] = flattenParams<string>(\n createdBy,\n filters?.createdBy,\n );\n queryBuilder.whereIn('created_by', [...new Set(arr)]);\n }\n\n if (status || filters?.status) {\n const arr: TaskStatus[] = flattenParams<TaskStatus>(\n status,\n filters?.status,\n );\n queryBuilder.whereIn('status', [...new Set(arr)]);\n }\n\n const countQuery = queryBuilder.clone();\n countQuery.count('tasks.id', { as: 'count' });\n\n if (order) {\n order.forEach(f => {\n queryBuilder.orderBy(f.field, f.order);\n });\n } else {\n queryBuilder.orderBy('created_at', 'desc');\n }\n\n if (pagination?.limit !== undefined) {\n queryBuilder.limit(pagination.limit);\n }\n\n if (pagination?.offset !== undefined) {\n queryBuilder.offset(pagination.offset);\n }\n\n const [results, [{ count }]] = await Promise.all([\n queryBuilder.select(),\n countQuery,\n ]);\n\n const tasks = results.map(result => ({\n id: result.id,\n spec: JSON.parse(result.spec),\n status: result.status,\n createdBy: result.created_by ?? undefined,\n lastHeartbeatAt: parseSqlDateToIsoString(result.last_heartbeat_at),\n createdAt: parseSqlDateToIsoString(result.created_at),\n }));\n\n return { tasks, totalTasks: count };\n }\n\n async getTask(taskId: string): Promise<SerializedTask> {\n const [result] = await this.db<RawDbTaskRow>('tasks')\n .where({ id: taskId })\n .select();\n if (!result) {\n throw new NotFoundError(`No task with id '${taskId}' found`);\n }\n try {\n const spec = JSON.parse(result.spec);\n const secrets = result.secrets ? JSON.parse(result.secrets) : undefined;\n const state = result.state ? JSON.parse(result.state).state : undefined;\n return {\n id: result.id,\n spec,\n status: result.status,\n lastHeartbeatAt: parseSqlDateToIsoString(result.last_heartbeat_at),\n createdAt: parseSqlDateToIsoString(result.created_at),\n createdBy: result.created_by ?? undefined,\n secrets,\n state,\n };\n } catch (error) {\n throw new Error(`Failed to parse spec of task '${taskId}', ${error}`);\n }\n }\n\n async createTask(\n options: TaskStoreCreateTaskOptions,\n ): Promise<TaskStoreCreateTaskResult> {\n const taskId = uuid();\n await this.db<RawDbTaskRow>('tasks').insert({\n id: taskId,\n spec: JSON.stringify(options.spec),\n secrets: options.secrets ? JSON.stringify(options.secrets) : undefined,\n created_by: options.createdBy ?? null,\n status: 'open',\n });\n return { taskId };\n }\n\n async claimTask(): Promise<SerializedTask | undefined> {\n return this.db.transaction(async tx => {\n const [task] = await tx<RawDbTaskRow>('tasks')\n .where({\n status: 'open',\n })\n .limit(1)\n .select();\n\n if (!task) {\n return undefined;\n }\n\n const spec = this.parseSpec(task);\n\n const updateCount = await tx<RawDbTaskRow>('tasks')\n .where({ id: task.id, status: 'open' })\n .update({\n status: 'processing',\n last_heartbeat_at: this.db.fn.now(),\n // remove the secrets for non-recoverable tasks when moving to processing state.\n secrets: this.isRecoverableTask(spec) ? task.secrets : null,\n });\n\n if (updateCount < 1) {\n return undefined;\n }\n\n const getState = () => {\n try {\n return task.state ? JSON.parse(task.state).state : undefined;\n } catch (error) {\n throw new Error(\n `Failed to parse state of the task '${task.id}', ${error}`,\n );\n }\n };\n\n const secrets = this.parseTaskSecrets(task);\n return {\n id: task.id,\n spec,\n status: 'processing',\n lastHeartbeatAt: task.last_heartbeat_at,\n createdAt: task.created_at,\n createdBy: task.created_by ?? undefined,\n secrets,\n state: getState(),\n };\n });\n }\n\n async heartbeatTask(taskId: string): Promise<void> {\n const updateCount = await this.db<RawDbTaskRow>('tasks')\n .where({ id: taskId, status: 'processing' })\n .update({\n last_heartbeat_at: this.db.fn.now(),\n });\n if (updateCount === 0) {\n throw new ConflictError(`No running task with taskId ${taskId} found`);\n }\n }\n\n async listStaleTasks(options: { timeoutS: number }): Promise<{\n tasks: { taskId: string; recovery?: TaskRecovery }[];\n }> {\n const { timeoutS } = options;\n const heartbeatInterval = intervalFromNowTill(timeoutS, this.db);\n const rawRows = await this.db<RawDbTaskRow>('tasks')\n .where('status', 'processing')\n .andWhere('last_heartbeat_at', '<=', heartbeatInterval);\n const tasks = rawRows.map(row => ({\n recovery: (JSON.parse(row.spec) as TaskSpec).EXPERIMENTAL_recovery,\n taskId: row.id,\n }));\n return { tasks };\n }\n\n async completeTask(options: {\n taskId: string;\n status: TaskStatus;\n eventBody: JsonObject;\n }): Promise<void> {\n const { taskId, status, eventBody } = options;\n\n let oldStatus: TaskStatus;\n if (['failed', 'completed', 'cancelled'].includes(status)) {\n oldStatus = 'processing';\n } else {\n throw new Error(\n `Invalid status update of run '${taskId}' to status '${status}'`,\n );\n }\n\n await this.db.transaction(async tx => {\n const [task] = await tx<RawDbTaskRow>('tasks')\n .where({\n id: taskId,\n })\n .limit(1)\n .select();\n\n const updateTask = async (criteria: {\n id: string;\n status?: TaskStatus;\n }) => {\n const updateCount = await tx<RawDbTaskRow>('tasks')\n .where(criteria)\n .update({\n status,\n secrets: null,\n });\n\n if (updateCount !== 1) {\n throw new ConflictError(\n `Failed to update status to '${status}' for taskId ${taskId}`,\n );\n }\n\n await tx<RawDbTaskEventRow>('task_events').insert({\n task_id: taskId,\n event_type: 'completion',\n body: JSON.stringify(eventBody),\n });\n };\n\n if (status === 'cancelled') {\n await updateTask({\n id: taskId,\n });\n return;\n }\n\n if (task.status === 'cancelled') {\n return;\n }\n\n if (!task) {\n throw new Error(`No task with taskId ${taskId} found`);\n }\n if (task.status !== oldStatus) {\n throw new ConflictError(\n `Refusing to update status of run '${taskId}' to status '${status}' ` +\n `as it is currently '${task.status}', expected '${oldStatus}'`,\n );\n }\n\n await updateTask({\n id: taskId,\n status: oldStatus,\n });\n });\n }\n\n async emitLogEvent(\n options: TaskStoreEmitOptions<{ message: string } & JsonObject>,\n ): Promise<void> {\n const { taskId, body } = options;\n const serializedBody = JSON.stringify(body);\n await this.db<RawDbTaskEventRow>('task_events').insert({\n task_id: taskId,\n event_type: 'log',\n body: serializedBody,\n });\n }\n\n async getTaskState({ taskId }: { taskId: string }): Promise<\n | {\n state: JsonObject;\n }\n | undefined\n > {\n const [result] = await this.db<RawDbTaskRow>('tasks')\n .where({ id: taskId })\n .select('state');\n return result.state ? JSON.parse(result.state) : undefined;\n }\n\n async saveTaskState(options: {\n taskId: string;\n state?: JsonObject;\n }): Promise<void> {\n if (options.state) {\n const serializedState = JSON.stringify({ state: options.state });\n await this.db<RawDbTaskRow>('tasks')\n .where({ id: options.taskId })\n .update({\n state: serializedState,\n });\n }\n }\n\n async listEvents(\n options: TaskStoreListEventsOptions,\n ): Promise<{ events: SerializedTaskEvent[] }> {\n const { isTaskRecoverable, taskId, after } = options;\n const rawEvents = await this.db<RawDbTaskEventRow>('task_events')\n .where({\n task_id: taskId,\n })\n .andWhere(builder => {\n if (typeof after === 'number') {\n builder.where('id', '>', after).orWhere('event_type', 'completion');\n }\n })\n .orderBy('id')\n .select();\n\n const events = rawEvents.map(event => {\n try {\n const body = JSON.parse(event.body) as JsonObject;\n return {\n id: Number(event.id),\n isTaskRecoverable,\n taskId,\n body,\n type: event.event_type,\n createdAt: parseSqlDateToIsoString(event.created_at),\n };\n } catch (error) {\n throw new Error(\n `Failed to parse event body from event taskId=${taskId} id=${event.id}, ${error}`,\n );\n }\n });\n\n return trimEventsTillLastRecovery(events);\n }\n\n async shutdownTask(options: TaskStoreShutDownTaskOptions): Promise<void> {\n const { taskId } = options;\n const message = `This task was marked as stale as it exceeded its timeout`;\n\n const statusStepEvents = (await this.listEvents({ taskId })).events.filter(\n ({ body }) => body?.stepId,\n );\n\n const completedSteps = statusStepEvents\n .filter(\n ({ body: { status } }) => status === 'failed' || status === 'completed',\n )\n .map(step => step.body.stepId);\n\n const hungProcessingSteps = statusStepEvents\n .filter(({ body: { status } }) => status === 'processing')\n .map(event => event.body.stepId)\n .filter(step => !completedSteps.includes(step));\n\n for (const step of hungProcessingSteps) {\n await this.emitLogEvent({\n taskId,\n body: {\n message,\n stepId: step,\n status: 'failed',\n },\n });\n }\n\n await this.completeTask({\n taskId,\n status: 'failed',\n eventBody: {\n message,\n },\n });\n }\n\n async rehydrateWorkspace(options: {\n taskId: string;\n targetPath: string;\n }): Promise<void> {\n const [result] = await this.db<RawDbTaskRow>('tasks')\n .where({ id: options.taskId })\n .select('workspace');\n\n await restoreWorkspace({\n path: options.targetPath,\n buffer: result.workspace,\n });\n }\n\n async cleanWorkspace({ taskId }: { taskId: string }): Promise<void> {\n await this.db('tasks').where({ id: taskId }).update({\n workspace: null,\n });\n }\n\n async serializeWorkspace(options: {\n path: string;\n taskId: string;\n }): Promise<void> {\n if (options.path) {\n const workspace = (await serializeWorkspace(options)).contents;\n await this.db<RawDbTaskRow>('tasks')\n .where({ id: options.taskId })\n .update({\n workspace,\n });\n }\n }\n\n async cancelTask(\n options: TaskStoreEmitOptions<{ message: string } & JsonObject>,\n ): Promise<void> {\n const { taskId, body } = options;\n const serializedBody = JSON.stringify(body);\n await this.db<RawDbTaskEventRow>('task_events').insert({\n task_id: taskId,\n event_type: 'cancelled',\n body: serializedBody,\n });\n }\n\n async retryTask?(options: { taskId: string }): Promise<void> {\n await this.db.transaction(async tx => {\n const result = await tx<RawDbTaskRow>('tasks')\n .where('id', options.taskId)\n .update(\n {\n status: 'open',\n last_heartbeat_at: this.db.fn.now(),\n },\n ['id', 'spec'],\n );\n\n for (const { id, spec } of result) {\n const taskSpec = JSON.parse(spec as string) as TaskSpec;\n\n /**\n * Once task is picked up, all event types are replayed.\n * We have to remove cancelled or completion event_type as these are as actions for frontend to perform.\n * In contrary, we send 'recovered' event_type to reset the state on the frontend side.\n *\n */\n await tx<RawDbTaskEventRow>('task_events')\n .where('task_id', id)\n .andWhere(q => q.whereIn('event_type', ['cancelled', 'completion']))\n .del();\n\n await tx<RawDbTaskEventRow>('task_events').insert({\n task_id: id,\n event_type: 'recovered',\n body: JSON.stringify({\n recoverStrategy:\n taskSpec.EXPERIMENTAL_recovery?.EXPERIMENTAL_strategy ?? 'none',\n }),\n });\n }\n });\n }\n\n async recoverTasks(\n options: TaskStoreRecoverTaskOptions,\n ): Promise<{ ids: string[] }> {\n const taskIdsToRecover: string[] = [];\n const timeoutS = Duration.fromObject(options.timeout).as('seconds');\n\n await this.db.transaction(async tx => {\n const heartbeatInterval = intervalFromNowTill(timeoutS, this.db);\n\n const result = await tx<RawDbTaskRow>('tasks')\n .where('status', 'processing')\n .andWhere('last_heartbeat_at', '<=', heartbeatInterval)\n .update(\n {\n status: 'open',\n last_heartbeat_at: this.db.fn.now(),\n },\n ['id', 'spec'],\n );\n\n taskIdsToRecover.push(...result.map(i => i.id));\n\n for (const { id, spec } of result) {\n const taskSpec = JSON.parse(spec as string) as TaskSpec;\n await tx<RawDbTaskEventRow>('task_events').insert({\n task_id: id,\n event_type: 'recovered',\n body: JSON.stringify({\n recoverStrategy:\n taskSpec.EXPERIMENTAL_recovery?.EXPERIMENTAL_strategy ?? 'none',\n }),\n });\n }\n });\n\n return { ids: taskIdsToRecover };\n }\n}\n"],"names":["resolvePackagePath","DateTime","flattenParams","NotFoundError","uuid","ConflictError","intervalFromNowTill","trimEventsTillLastRecovery","restoreWorkspace","serializeWorkspace","Duration"],"mappings":"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"}
1
+ {"version":3,"file":"DatabaseTaskStore.cjs.js","sources":["../../../src/scaffolder/tasks/DatabaseTaskStore.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 { JsonObject } from '@backstage/types';\nimport { PluginDatabaseManager } from '@backstage/backend-common';\nimport { resolvePackagePath } from '@backstage/backend-plugin-api';\nimport { ConflictError, NotFoundError } from '@backstage/errors';\nimport { Knex } from 'knex';\nimport { v4 as uuid } from 'uuid';\nimport {\n TaskStore,\n TaskStoreCreateTaskOptions,\n TaskStoreCreateTaskResult,\n TaskStoreEmitOptions,\n TaskStoreListEventsOptions,\n TaskStoreRecoverTaskOptions,\n TaskStoreShutDownTaskOptions,\n} from './types';\nimport {\n SerializedTask,\n SerializedTaskEvent,\n TaskEventType,\n TaskSecrets,\n TaskStatus,\n} from '@backstage/plugin-scaffolder-node';\nimport { DateTime, Duration } from 'luxon';\nimport { TaskRecovery, TaskSpec } from '@backstage/plugin-scaffolder-common';\nimport { trimEventsTillLastRecovery } from './taskRecoveryHelper';\nimport { intervalFromNowTill } from './dbUtil';\nimport {\n restoreWorkspace,\n serializeWorkspace,\n} from '@backstage/plugin-scaffolder-node/alpha';\nimport { flattenParams } from '../../service/helpers';\nimport { EventsService } from '@backstage/plugin-events-node';\n\nconst migrationsDir = resolvePackagePath(\n '@backstage/plugin-scaffolder-backend',\n 'migrations',\n);\n\nexport type RawDbTaskRow = {\n id: string;\n spec: string;\n status: TaskStatus;\n state?: string;\n last_heartbeat_at?: string;\n created_at: string;\n created_by: string | null;\n secrets?: string | null;\n workspace?: Buffer;\n};\n\nexport type RawDbTaskEventRow = {\n id: number;\n task_id: string;\n body: string;\n event_type: TaskEventType;\n created_at: string;\n};\n\n/**\n * DatabaseTaskStore\n *\n * @public\n */\nexport type DatabaseTaskStoreOptions = {\n database: PluginDatabaseManager | Knex;\n events?: EventsService;\n};\n\n/**\n * Type guard to help DatabaseTaskStore understand when database is PluginDatabaseManager vs. when database is a Knex instance.\n *\n * * @public\n */\nfunction isPluginDatabaseManager(\n opt: PluginDatabaseManager | Knex,\n): opt is PluginDatabaseManager {\n return (opt as PluginDatabaseManager).getClient !== undefined;\n}\n\nconst parseSqlDateToIsoString = <T>(input: T): T | string => {\n if (typeof input === 'string') {\n const parsed = DateTime.fromSQL(input, { zone: 'UTC' });\n if (!parsed.isValid) {\n throw new Error(\n `Failed to parse database timestamp '${input}', ${parsed.invalidReason}: ${parsed.invalidExplanation}`,\n );\n }\n return parsed.toISO()!;\n }\n\n return input;\n};\n\n/**\n * DatabaseTaskStore\n *\n * @public\n */\nexport class DatabaseTaskStore implements TaskStore {\n private readonly db: Knex;\n private readonly events?: EventsService;\n\n static async create(\n options: DatabaseTaskStoreOptions,\n ): Promise<DatabaseTaskStore> {\n const { database } = options;\n const client = await this.getClient(database);\n\n await this.runMigrations(database, client);\n\n return new DatabaseTaskStore(client, options.events);\n }\n\n private isRecoverableTask(spec: TaskSpec): boolean {\n return ['startOver'].includes(\n spec.EXPERIMENTAL_recovery?.EXPERIMENTAL_strategy ?? 'none',\n );\n }\n\n private parseSpec({ spec, id }: { spec: string; id: string }): TaskSpec {\n try {\n return JSON.parse(spec);\n } catch (error) {\n throw new Error(`Failed to parse spec of task '${id}', ${error}`);\n }\n }\n\n private parseTaskSecrets(taskRow: RawDbTaskRow): TaskSecrets | undefined {\n try {\n return taskRow.secrets ? JSON.parse(taskRow.secrets) : undefined;\n } catch (error) {\n throw new Error(\n `Failed to parse secrets of task '${taskRow.id}', ${error}`,\n );\n }\n }\n\n private static async getClient(\n database: PluginDatabaseManager | Knex,\n ): Promise<Knex> {\n if (isPluginDatabaseManager(database)) {\n return database.getClient();\n }\n\n return database;\n }\n\n private static async runMigrations(\n database: PluginDatabaseManager | Knex,\n client: Knex,\n ): Promise<void> {\n if (!isPluginDatabaseManager(database)) {\n await client.migrate.latest({\n directory: migrationsDir,\n });\n\n return;\n }\n\n if (!database.migrations?.skip) {\n await client.migrate.latest({\n directory: migrationsDir,\n });\n }\n }\n\n private constructor(client: Knex, events?: EventsService) {\n this.db = client;\n this.events = events;\n }\n\n private getState(task: RawDbTaskRow) {\n try {\n return task.state ? JSON.parse(task.state).state : undefined;\n } catch (error) {\n throw new Error(\n `Failed to parse state of the task '${task.id}', ${error}`,\n );\n }\n }\n\n async list(options: {\n createdBy?: string;\n status?: TaskStatus;\n filters?: {\n createdBy?: string | string[];\n status?: TaskStatus | TaskStatus[];\n };\n pagination?: {\n limit?: number;\n offset?: number;\n };\n order?: { order: 'asc' | 'desc'; field: string }[];\n }): Promise<{ tasks: SerializedTask[]; totalTasks?: number }> {\n const { createdBy, status, pagination, order, filters } = options ?? {};\n const queryBuilder = this.db<RawDbTaskRow & { count: number }>('tasks');\n\n if (createdBy || filters?.createdBy) {\n const arr: string[] = flattenParams<string>(\n createdBy,\n filters?.createdBy,\n );\n queryBuilder.whereIn('created_by', [...new Set(arr)]);\n }\n\n if (status || filters?.status) {\n const arr: TaskStatus[] = flattenParams<TaskStatus>(\n status,\n filters?.status,\n );\n queryBuilder.whereIn('status', [...new Set(arr)]);\n }\n\n const countQuery = queryBuilder.clone();\n countQuery.count('tasks.id', { as: 'count' });\n\n if (order) {\n order.forEach(f => {\n queryBuilder.orderBy(f.field, f.order);\n });\n } else {\n queryBuilder.orderBy('created_at', 'desc');\n }\n\n if (pagination?.limit !== undefined) {\n queryBuilder.limit(pagination.limit);\n }\n\n if (pagination?.offset !== undefined) {\n queryBuilder.offset(pagination.offset);\n }\n\n const [results, [{ count }]] = await Promise.all([\n queryBuilder.select(),\n countQuery,\n ]);\n\n const tasks = results.map(result => ({\n id: result.id,\n spec: JSON.parse(result.spec),\n status: result.status,\n createdBy: result.created_by ?? undefined,\n lastHeartbeatAt: parseSqlDateToIsoString(result.last_heartbeat_at),\n createdAt: parseSqlDateToIsoString(result.created_at),\n }));\n\n return { tasks, totalTasks: count };\n }\n\n async getTask(taskId: string): Promise<SerializedTask> {\n const [result] = await this.db<RawDbTaskRow>('tasks')\n .where({ id: taskId })\n .select();\n if (!result) {\n throw new NotFoundError(`No task with id '${taskId}' found`);\n }\n try {\n const spec = JSON.parse(result.spec);\n const secrets = result.secrets ? JSON.parse(result.secrets) : undefined;\n const state = this.getState(result);\n return {\n id: result.id,\n spec,\n status: result.status,\n lastHeartbeatAt: parseSqlDateToIsoString(result.last_heartbeat_at),\n createdAt: parseSqlDateToIsoString(result.created_at),\n createdBy: result.created_by ?? undefined,\n secrets,\n state,\n };\n } catch (error) {\n throw new Error(`Failed to parse spec of task '${taskId}', ${error}`);\n }\n }\n\n async createTask(\n options: TaskStoreCreateTaskOptions,\n ): Promise<TaskStoreCreateTaskResult> {\n const taskId = uuid();\n await this.db<RawDbTaskRow>('tasks').insert({\n id: taskId,\n spec: JSON.stringify(options.spec),\n secrets: options.secrets ? JSON.stringify(options.secrets) : undefined,\n created_by: options.createdBy ?? null,\n status: 'open',\n });\n\n this.events?.publish({\n topic: 'scaffolder.task',\n eventPayload: {\n id: taskId,\n spec: options.spec,\n createdBy: options.createdBy,\n status: 'open',\n },\n });\n\n return { taskId };\n }\n\n async claimTask(): Promise<SerializedTask | undefined> {\n return this.db.transaction(async tx => {\n const [task] = await tx<RawDbTaskRow>('tasks')\n .where({\n status: 'open',\n })\n .limit(1)\n .select();\n\n if (!task) {\n return undefined;\n }\n\n const spec = this.parseSpec(task);\n\n const updateCount = await tx<RawDbTaskRow>('tasks')\n .where({ id: task.id, status: 'open' })\n .update({\n status: 'processing',\n last_heartbeat_at: this.db.fn.now(),\n // remove the secrets for non-recoverable tasks when moving to processing state.\n secrets: this.isRecoverableTask(spec) ? task.secrets : null,\n });\n\n if (updateCount < 1) {\n return undefined;\n }\n\n const ret: SerializedTask = {\n id: task.id,\n spec,\n status: 'processing',\n lastHeartbeatAt: task.last_heartbeat_at,\n createdAt: task.created_at,\n createdBy: task.created_by ?? undefined,\n state: this.getState(task),\n };\n\n this.events?.publish({\n topic: 'scaffolder.task',\n eventPayload: ret,\n });\n\n const secrets = this.parseTaskSecrets(task);\n return { ...ret, secrets };\n });\n }\n\n async heartbeatTask(taskId: string): Promise<void> {\n const updateCount = await this.db<RawDbTaskRow>('tasks')\n .where({ id: taskId, status: 'processing' })\n .update({\n last_heartbeat_at: this.db.fn.now(),\n });\n if (updateCount === 0) {\n throw new ConflictError(`No running task with taskId ${taskId} found`);\n }\n }\n\n async listStaleTasks(options: { timeoutS: number }): Promise<{\n tasks: { taskId: string; recovery?: TaskRecovery }[];\n }> {\n const { timeoutS } = options;\n const heartbeatInterval = intervalFromNowTill(timeoutS, this.db);\n const rawRows = await this.db<RawDbTaskRow>('tasks')\n .where('status', 'processing')\n .andWhere('last_heartbeat_at', '<=', heartbeatInterval);\n const tasks = rawRows.map(row => ({\n recovery: (JSON.parse(row.spec) as TaskSpec).EXPERIMENTAL_recovery,\n taskId: row.id,\n }));\n return { tasks };\n }\n\n async completeTask(options: {\n taskId: string;\n status: TaskStatus;\n eventBody: JsonObject;\n }): Promise<void> {\n const { taskId, status, eventBody } = options;\n\n let oldStatus: TaskStatus;\n if (['failed', 'completed', 'cancelled'].includes(status)) {\n oldStatus = 'processing';\n } else {\n throw new Error(\n `Invalid status update of run '${taskId}' to status '${status}'`,\n );\n }\n\n await this.db.transaction(async tx => {\n const [task] = await tx<RawDbTaskRow>('tasks')\n .where({\n id: taskId,\n })\n .limit(1)\n .select();\n\n const updateTask = async (criteria: {\n id: string;\n status?: TaskStatus;\n }) => {\n const updateCount = await tx<RawDbTaskRow>('tasks')\n .where(criteria)\n .update({\n status,\n secrets: null,\n });\n\n if (updateCount !== 1) {\n throw new ConflictError(\n `Failed to update status to '${status}' for taskId ${taskId}`,\n );\n }\n\n this.events?.publish({\n topic: 'scaffolder.task',\n eventPayload: {\n id: taskId,\n status: status,\n lastHeartbeatAt: task.last_heartbeat_at,\n createdAt: task.created_at,\n createdBy: task.created_by,\n state: this.getState(task),\n },\n });\n\n await tx<RawDbTaskEventRow>('task_events')\n .insert({\n task_id: taskId,\n event_type: 'completion',\n body: JSON.stringify(eventBody),\n })\n .returning('id');\n };\n\n if (status === 'cancelled') {\n await updateTask({\n id: taskId,\n });\n return;\n }\n\n if (task.status === 'cancelled') {\n return;\n }\n\n if (!task) {\n throw new Error(`No task with taskId ${taskId} found`);\n }\n if (task.status !== oldStatus) {\n throw new ConflictError(\n `Refusing to update status of run '${taskId}' to status '${status}' ` +\n `as it is currently '${task.status}', expected '${oldStatus}'`,\n );\n }\n\n await updateTask({\n id: taskId,\n status: oldStatus,\n });\n });\n }\n\n async emitLogEvent(\n options: TaskStoreEmitOptions<{ message: string } & JsonObject>,\n ): Promise<void> {\n const { taskId, body } = options;\n const serializedBody = JSON.stringify(body);\n await this.db<RawDbTaskEventRow>('task_events')\n .insert({\n task_id: taskId,\n event_type: 'log',\n body: serializedBody,\n })\n .returning('id');\n }\n\n async getTaskState({ taskId }: { taskId: string }): Promise<\n | {\n state: JsonObject;\n }\n | undefined\n > {\n const [result] = await this.db<RawDbTaskRow>('tasks')\n .where({ id: taskId })\n .select('state');\n return result.state ? JSON.parse(result.state) : undefined;\n }\n\n async saveTaskState(options: {\n taskId: string;\n state?: JsonObject;\n }): Promise<void> {\n if (options.state) {\n const serializedState = JSON.stringify({ state: options.state });\n await this.db<RawDbTaskRow>('tasks')\n .where({ id: options.taskId })\n .update({\n state: serializedState,\n });\n }\n }\n\n async listEvents(\n options: TaskStoreListEventsOptions,\n ): Promise<{ events: SerializedTaskEvent[] }> {\n const { isTaskRecoverable, taskId, after } = options;\n const rawEvents = await this.db<RawDbTaskEventRow>('task_events')\n .where({\n task_id: taskId,\n })\n .andWhere(builder => {\n if (typeof after === 'number') {\n builder.where('id', '>', after).orWhere('event_type', 'completion');\n }\n })\n .orderBy('id')\n .select();\n\n const events = rawEvents.map(event => {\n try {\n const body = JSON.parse(event.body) as JsonObject;\n return {\n id: Number(event.id),\n isTaskRecoverable,\n taskId,\n body,\n type: event.event_type,\n createdAt: parseSqlDateToIsoString(event.created_at),\n };\n } catch (error) {\n throw new Error(\n `Failed to parse event body from event taskId=${taskId} id=${event.id}, ${error}`,\n );\n }\n });\n\n return trimEventsTillLastRecovery(events);\n }\n\n async shutdownTask(options: TaskStoreShutDownTaskOptions): Promise<void> {\n const { taskId } = options;\n const message = `This task was marked as stale as it exceeded its timeout`;\n\n const statusStepEvents = (await this.listEvents({ taskId })).events.filter(\n ({ body }) => body?.stepId,\n );\n\n const completedSteps = statusStepEvents\n .filter(\n ({ body: { status } }) => status === 'failed' || status === 'completed',\n )\n .map(step => step.body.stepId);\n\n const hungProcessingSteps = statusStepEvents\n .filter(({ body: { status } }) => status === 'processing')\n .map(event => event.body.stepId)\n .filter(step => !completedSteps.includes(step));\n\n for (const step of hungProcessingSteps) {\n await this.emitLogEvent({\n taskId,\n body: {\n message,\n stepId: step,\n status: 'failed',\n },\n });\n }\n\n await this.completeTask({\n taskId,\n status: 'failed',\n eventBody: {\n message,\n },\n });\n }\n\n async rehydrateWorkspace(options: {\n taskId: string;\n targetPath: string;\n }): Promise<void> {\n const [result] = await this.db<RawDbTaskRow>('tasks')\n .where({ id: options.taskId })\n .select('workspace');\n\n await restoreWorkspace({\n path: options.targetPath,\n buffer: result.workspace,\n });\n }\n\n async cleanWorkspace({ taskId }: { taskId: string }): Promise<void> {\n await this.db('tasks').where({ id: taskId }).update({\n workspace: null,\n });\n }\n\n async serializeWorkspace(options: {\n path: string;\n taskId: string;\n }): Promise<void> {\n if (options.path) {\n const workspace = (await serializeWorkspace(options)).contents;\n await this.db<RawDbTaskRow>('tasks')\n .where({ id: options.taskId })\n .update({\n workspace,\n });\n }\n }\n\n async cancelTask(\n options: TaskStoreEmitOptions<{ message: string } & JsonObject>,\n ): Promise<void> {\n const { taskId, body } = options;\n const serializedBody = JSON.stringify(body);\n const [ret] = await this.db<RawDbTaskEventRow>('task_events')\n .insert({\n task_id: taskId,\n event_type: 'cancelled',\n body: serializedBody,\n })\n .returning('id');\n\n this.events?.publish({\n topic: 'scaffolder.task',\n eventPayload: {\n id: ret.id,\n taskId,\n status: 'cancelled',\n body,\n },\n });\n }\n\n async retryTask?(options: { taskId: string }): Promise<void> {\n await this.db.transaction(async tx => {\n const result = await tx<RawDbTaskRow>('tasks')\n .where('id', options.taskId)\n .update(\n {\n status: 'open',\n last_heartbeat_at: this.db.fn.now(),\n },\n ['id', 'spec'],\n );\n\n for (const { id, spec } of result) {\n const taskSpec = JSON.parse(spec as string) as TaskSpec;\n\n /**\n * Once task is picked up, all event types are replayed.\n * We have to remove cancelled or completion event_type as these are as actions for frontend to perform.\n * In contrary, we send 'recovered' event_type to reset the state on the frontend side.\n *\n */\n await tx<RawDbTaskEventRow>('task_events')\n .where('task_id', id)\n .andWhere(q => q.whereIn('event_type', ['cancelled', 'completion']))\n .del();\n\n await tx<RawDbTaskEventRow>('task_events').insert({\n task_id: id,\n event_type: 'recovered',\n body: JSON.stringify({\n recoverStrategy:\n taskSpec.EXPERIMENTAL_recovery?.EXPERIMENTAL_strategy ?? 'none',\n }),\n });\n }\n });\n }\n\n async recoverTasks(\n options: TaskStoreRecoverTaskOptions,\n ): Promise<{ ids: string[] }> {\n const taskIdsToRecover: string[] = [];\n const timeoutS = Duration.fromObject(options.timeout).as('seconds');\n\n await this.db.transaction(async tx => {\n const heartbeatInterval = intervalFromNowTill(timeoutS, this.db);\n\n const result = await tx<RawDbTaskRow>('tasks')\n .where('status', 'processing')\n .andWhere('last_heartbeat_at', '<=', heartbeatInterval)\n .update(\n {\n status: 'open',\n last_heartbeat_at: this.db.fn.now(),\n },\n ['id', 'spec'],\n );\n\n taskIdsToRecover.push(...result.map(i => i.id));\n\n for (const { id, spec } of result) {\n const taskSpec = JSON.parse(spec as string) as TaskSpec;\n const event = {\n recoverStrategy:\n taskSpec.EXPERIMENTAL_recovery?.EXPERIMENTAL_strategy ?? 'none',\n };\n const [ret] = await tx<RawDbTaskEventRow>('task_events')\n .insert({\n task_id: id,\n event_type: 'recovered',\n body: JSON.stringify(event),\n })\n .returning('id');\n\n this.events?.publish({\n topic: 'scaffolder.task',\n eventPayload: {\n id: ret.id,\n taskId: id,\n status: 'recovered',\n body: event,\n },\n });\n }\n });\n\n return { ids: taskIdsToRecover };\n }\n}\n"],"names":["resolvePackagePath","DateTime","flattenParams","NotFoundError","uuid","ConflictError","intervalFromNowTill","trimEventsTillLastRecovery","restoreWorkspace","serializeWorkspace","Duration"],"mappings":"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"}
@@ -136,7 +136,8 @@ async function createRouter(options) {
136
136
  permissionRules,
137
137
  discovery = backendCommon.HostDiscovery.fromConfig(config),
138
138
  identity = buildDefaultIdentityClient(options),
139
- autocompleteHandlers = {}
139
+ autocompleteHandlers = {},
140
+ events: eventsService
140
141
  } = options;
141
142
  const { auth, httpAuth } = backendCommon.createLegacyAuthAdapters({
142
143
  ...options,
@@ -149,7 +150,10 @@ async function createRouter(options) {
149
150
  const integrations = integration.ScmIntegrations.fromConfig(config);
150
151
  let taskBroker;
151
152
  if (!options.taskBroker) {
152
- const databaseTaskStore = await DatabaseTaskStore.DatabaseTaskStore.create({ database });
153
+ const databaseTaskStore = await DatabaseTaskStore.DatabaseTaskStore.create({
154
+ database,
155
+ events: eventsService
156
+ });
153
157
  taskBroker = new StorageTaskBroker.StorageTaskBroker(
154
158
  databaseTaskStore,
155
159
  logger,
@@ -286,7 +290,8 @@ async function createRouter(options) {
286
290
  title: schema.title ?? "Please enter the following information",
287
291
  description: schema.description,
288
292
  schema
289
- }))
293
+ })),
294
+ EXPERIMENTAL_formDecorators: template.spec.EXPERIMENTAL_formDecorators
290
295
  });
291
296
  }
292
297
  ).get("/v2/actions", async (_req, res) => {
@@ -1 +1 @@
1
- {"version":3,"file":"router.cjs.js","sources":["../../src/service/router.ts"],"sourcesContent":["/*\n * Copyright 2020 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 createLegacyAuthAdapters,\n HostDiscovery,\n} from '@backstage/backend-common';\nimport { CatalogApi } from '@backstage/catalog-client';\nimport {\n CompoundEntityRef,\n Entity,\n parseEntityRef,\n stringifyEntityRef,\n UserEntity,\n} from '@backstage/catalog-model';\nimport { Config, readDurationFromConfig } from '@backstage/config';\nimport { InputError, NotFoundError, stringifyError } from '@backstage/errors';\nimport { ScmIntegrations } from '@backstage/integration';\nimport { HumanDuration, JsonObject, JsonValue } from '@backstage/types';\nimport {\n TaskSpec,\n TemplateEntityStepV1beta3,\n TemplateEntityV1beta3,\n templateEntityV1beta3Validator,\n TemplateParametersV1beta3,\n} from '@backstage/plugin-scaffolder-common';\nimport {\n RESOURCE_TYPE_SCAFFOLDER_ACTION,\n RESOURCE_TYPE_SCAFFOLDER_TEMPLATE,\n scaffolderActionPermissions,\n scaffolderTaskPermissions,\n scaffolderTemplatePermissions,\n taskCancelPermission,\n taskCreatePermission,\n taskReadPermission,\n templateParameterReadPermission,\n templateStepReadPermission,\n} from '@backstage/plugin-scaffolder-common/alpha';\nimport express from 'express';\nimport Router from 'express-promise-router';\nimport { validate } from 'jsonschema';\nimport { Logger } from 'winston';\nimport { z } from 'zod';\nimport {\n TaskBroker,\n TaskStatus,\n TemplateAction,\n TemplateFilter,\n TemplateGlobal,\n} from '@backstage/plugin-scaffolder-node';\nimport {\n createBuiltinActions,\n DatabaseTaskStore,\n TaskWorker,\n TemplateActionRegistry,\n} from '../scaffolder';\nimport { createDryRunner } from '../scaffolder/dryrun';\nimport { StorageTaskBroker } from '../scaffolder/tasks/StorageTaskBroker';\nimport {\n findTemplate,\n getEntityBaseUrl,\n getWorkingDirectory,\n parseNumberParam,\n parseStringsParam,\n} from './helpers';\nimport { PermissionRuleParams } from '@backstage/plugin-permission-common';\nimport {\n createConditionAuthorizer,\n createPermissionIntegrationRouter,\n PermissionRule,\n} from '@backstage/plugin-permission-node';\nimport { scaffolderActionRules, scaffolderTemplateRules } from './rules';\nimport { Duration } from 'luxon';\nimport {\n AuthService,\n BackstageCredentials,\n DatabaseService,\n DiscoveryService,\n HttpAuthService,\n LifecycleService,\n PermissionsService,\n SchedulerService,\n UrlReaderService,\n resolveSafeChildPath,\n} from '@backstage/backend-plugin-api';\nimport {\n IdentityApi,\n IdentityApiGetIdentityRequest,\n} from '@backstage/plugin-auth-node';\nimport { InternalTaskSecrets } from '../scaffolder/tasks/types';\nimport { checkPermission } from '../util/checkPermissions';\nimport {\n AutocompleteHandler,\n WorkspaceProvider,\n} from '@backstage/plugin-scaffolder-node/alpha';\nimport { pathToFileURL } from 'url';\nimport { v4 as uuid } from 'uuid';\n\n/**\n *\n * @public\n */\nexport type TemplatePermissionRuleInput<\n TParams extends PermissionRuleParams = PermissionRuleParams,\n> = PermissionRule<\n TemplateEntityStepV1beta3 | TemplateParametersV1beta3,\n {},\n typeof RESOURCE_TYPE_SCAFFOLDER_TEMPLATE,\n TParams\n>;\nfunction isTemplatePermissionRuleInput(\n permissionRule: TemplatePermissionRuleInput | ActionPermissionRuleInput,\n): permissionRule is TemplatePermissionRuleInput {\n return permissionRule.resourceType === RESOURCE_TYPE_SCAFFOLDER_TEMPLATE;\n}\n\n/**\n *\n * @public\n */\nexport type ActionPermissionRuleInput<\n TParams extends PermissionRuleParams = PermissionRuleParams,\n> = PermissionRule<\n TemplateEntityStepV1beta3 | TemplateParametersV1beta3,\n {},\n typeof RESOURCE_TYPE_SCAFFOLDER_ACTION,\n TParams\n>;\nfunction isActionPermissionRuleInput(\n permissionRule: TemplatePermissionRuleInput | ActionPermissionRuleInput,\n): permissionRule is ActionPermissionRuleInput {\n return permissionRule.resourceType === RESOURCE_TYPE_SCAFFOLDER_ACTION;\n}\n\n/**\n * RouterOptions\n *\n * @public\n * @deprecated Please migrate to the new backend system as this will be removed in the future.\n */\nexport interface RouterOptions {\n logger: Logger;\n config: Config;\n reader: UrlReaderService;\n lifecycle?: LifecycleService;\n database: DatabaseService;\n catalogClient: CatalogApi;\n scheduler?: SchedulerService;\n actions?: TemplateAction<any, any>[];\n /**\n * @deprecated taskWorkers is deprecated in favor of concurrentTasksLimit option with a single TaskWorker\n * @defaultValue 1\n */\n taskWorkers?: number;\n /**\n * Sets the number of concurrent tasks that can be run at any given time on the TaskWorker\n * @defaultValue 10\n */\n concurrentTasksLimit?: number;\n taskBroker?: TaskBroker;\n additionalTemplateFilters?: Record<string, TemplateFilter>;\n additionalTemplateGlobals?: Record<string, TemplateGlobal>;\n additionalWorkspaceProviders?: Record<string, WorkspaceProvider>;\n permissions?: PermissionsService;\n permissionRules?: Array<\n TemplatePermissionRuleInput | ActionPermissionRuleInput\n >;\n auth?: AuthService;\n httpAuth?: HttpAuthService;\n identity?: IdentityApi;\n discovery?: DiscoveryService;\n\n autocompleteHandlers?: Record<string, AutocompleteHandler>;\n}\n\nfunction isSupportedTemplate(entity: TemplateEntityV1beta3) {\n return entity.apiVersion === 'scaffolder.backstage.io/v1beta3';\n}\n\n/*\n * @deprecated This function remains as the DefaultIdentityClient behaves slightly differently to the pre-existing\n * scaffolder behaviour. Specifically if the token fails to parse, the DefaultIdentityClient will raise an error.\n * The scaffolder did not raise an error in this case. As such we chose to allow it to behave as it did previously\n * until someone explicitly passes an IdentityApi. When we have reasonable confidence that most backstage deployments\n * are using the IdentityApi, we can remove this function.\n */\nfunction buildDefaultIdentityClient(options: RouterOptions): IdentityApi {\n return {\n getIdentity: async ({ request }: IdentityApiGetIdentityRequest) => {\n const header = request.headers.authorization;\n const { logger } = options;\n\n if (!header) {\n return undefined;\n }\n\n try {\n const token = header.match(/^Bearer\\s(\\S+\\.\\S+\\.\\S+)$/i)?.[1];\n if (!token) {\n throw new TypeError('Expected Bearer with JWT');\n }\n\n const [_header, rawPayload, _signature] = token.split('.');\n const payload: JsonValue = JSON.parse(\n Buffer.from(rawPayload, 'base64').toString(),\n );\n\n if (\n typeof payload !== 'object' ||\n payload === null ||\n Array.isArray(payload)\n ) {\n throw new TypeError('Malformed JWT payload');\n }\n\n const sub = payload.sub;\n if (typeof sub !== 'string') {\n throw new TypeError('Expected string sub claim');\n }\n\n if (sub === 'backstage-server') {\n return undefined;\n }\n\n // Check that it's a valid ref, otherwise this will throw.\n parseEntityRef(sub);\n\n return {\n identity: {\n userEntityRef: sub,\n ownershipEntityRefs: [],\n type: 'user',\n },\n token,\n };\n } catch (e) {\n logger.error(`Invalid authorization header: ${stringifyError(e)}`);\n return undefined;\n }\n },\n };\n}\n\nconst readDuration = (\n config: Config,\n key: string,\n defaultValue: HumanDuration,\n) => {\n if (config.has(key)) {\n return readDurationFromConfig(config, { key });\n }\n return defaultValue;\n};\n\n/**\n * A method to create a router for the scaffolder backend plugin.\n * @public\n * @deprecated Please migrate to the new backend system as this will be removed in the future.\n */\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const router = Router();\n // Be generous in upload size to support a wide range of templates in dry-run mode.\n router.use(express.json({ limit: '10MB' }));\n\n const {\n logger: parentLogger,\n config,\n reader,\n database,\n catalogClient,\n actions,\n taskWorkers,\n scheduler,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n additionalWorkspaceProviders,\n permissions,\n permissionRules,\n discovery = HostDiscovery.fromConfig(config),\n identity = buildDefaultIdentityClient(options),\n autocompleteHandlers = {},\n } = options;\n\n const { auth, httpAuth } = createLegacyAuthAdapters({\n ...options,\n identity,\n discovery,\n });\n\n const concurrentTasksLimit =\n options.concurrentTasksLimit ??\n options.config.getOptionalNumber('scaffolder.concurrentTasksLimit');\n\n const logger = parentLogger.child({ plugin: 'scaffolder' });\n\n const workingDirectory = await getWorkingDirectory(config, logger);\n const integrations = ScmIntegrations.fromConfig(config);\n\n let taskBroker: TaskBroker;\n if (!options.taskBroker) {\n const databaseTaskStore = await DatabaseTaskStore.create({ database });\n taskBroker = new StorageTaskBroker(\n databaseTaskStore,\n logger,\n config,\n auth,\n additionalWorkspaceProviders,\n );\n\n if (scheduler && databaseTaskStore.listStaleTasks) {\n await scheduler.scheduleTask({\n id: 'close_stale_tasks',\n frequency: readDuration(\n config,\n 'scaffolder.taskTimeoutJanitorFrequency',\n {\n minutes: 5,\n },\n ),\n timeout: { minutes: 15 },\n fn: async () => {\n const { tasks } = await databaseTaskStore.listStaleTasks({\n timeoutS: Duration.fromObject(\n readDuration(config, 'scaffolder.taskTimeout', {\n hours: 24,\n }),\n ).as('seconds'),\n });\n\n for (const task of tasks) {\n await databaseTaskStore.shutdownTask(task);\n logger.info(`Successfully closed stale task ${task.taskId}`);\n }\n },\n });\n }\n } else {\n taskBroker = options.taskBroker;\n }\n\n const actionRegistry = new TemplateActionRegistry();\n\n const workers: TaskWorker[] = [];\n if (concurrentTasksLimit !== 0) {\n for (let i = 0; i < (taskWorkers || 1); i++) {\n const worker = await TaskWorker.create({\n taskBroker,\n actionRegistry,\n integrations,\n logger,\n workingDirectory,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n concurrentTasksLimit,\n permissions,\n });\n workers.push(worker);\n }\n }\n\n const actionsToRegister = Array.isArray(actions)\n ? actions\n : createBuiltinActions({\n integrations,\n catalogClient,\n reader,\n config,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n auth,\n });\n\n actionsToRegister.forEach(action => actionRegistry.register(action));\n\n const launchWorkers = () => workers.forEach(worker => worker.start());\n\n const shutdownWorkers = () => {\n workers.forEach(worker => worker.stop());\n };\n\n if (options.lifecycle) {\n options.lifecycle.addStartupHook(launchWorkers);\n options.lifecycle.addShutdownHook(shutdownWorkers);\n } else {\n launchWorkers();\n }\n\n const dryRunner = createDryRunner({\n actionRegistry,\n integrations,\n logger,\n workingDirectory,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n permissions,\n });\n\n const templateRules: TemplatePermissionRuleInput[] = Object.values(\n scaffolderTemplateRules,\n );\n const actionRules: ActionPermissionRuleInput[] = Object.values(\n scaffolderActionRules,\n );\n\n if (permissionRules) {\n templateRules.push(\n ...permissionRules.filter(isTemplatePermissionRuleInput),\n );\n actionRules.push(...permissionRules.filter(isActionPermissionRuleInput));\n }\n\n const isAuthorized = createConditionAuthorizer(Object.values(templateRules));\n\n const permissionIntegrationRouter = createPermissionIntegrationRouter({\n resources: [\n {\n resourceType: RESOURCE_TYPE_SCAFFOLDER_TEMPLATE,\n permissions: scaffolderTemplatePermissions,\n rules: templateRules,\n },\n {\n resourceType: RESOURCE_TYPE_SCAFFOLDER_ACTION,\n permissions: scaffolderActionPermissions,\n rules: actionRules,\n },\n ],\n permissions: scaffolderTaskPermissions,\n });\n\n router.use(permissionIntegrationRouter);\n\n router\n .get(\n '/v2/templates/:namespace/:kind/:name/parameter-schema',\n async (req, res) => {\n const credentials = await httpAuth.credentials(req);\n\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: credentials,\n targetPluginId: 'catalog',\n });\n\n const template = await authorizeTemplate(\n req.params,\n token,\n credentials,\n );\n\n const parameters = [template.spec.parameters ?? []].flat();\n\n const presentation = template.spec.presentation;\n\n res.json({\n title: template.metadata.title ?? template.metadata.name,\n ...(presentation ? { presentation } : {}),\n description: template.metadata.description,\n 'ui:options': template.metadata['ui:options'],\n steps: parameters.map(schema => ({\n title: schema.title ?? 'Please enter the following information',\n description: schema.description,\n schema,\n })),\n });\n },\n )\n .get('/v2/actions', async (_req, res) => {\n const actionsList = actionRegistry.list().map(action => {\n return {\n id: action.id,\n description: action.description,\n examples: action.examples,\n schema: action.schema,\n };\n });\n res.json(actionsList);\n })\n .post('/v2/tasks', async (req, res) => {\n const templateRef: string = req.body.templateRef;\n const { kind, namespace, name } = parseEntityRef(templateRef, {\n defaultKind: 'template',\n });\n\n const credentials = await httpAuth.credentials(req);\n\n await checkPermission({\n credentials,\n permissions: [taskCreatePermission],\n permissionService: permissions,\n });\n\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: credentials,\n targetPluginId: 'catalog',\n });\n\n const userEntityRef = auth.isPrincipal(credentials, 'user')\n ? credentials.principal.userEntityRef\n : undefined;\n\n const userEntity = userEntityRef\n ? await catalogClient.getEntityByRef(userEntityRef, { token })\n : undefined;\n\n let auditLog = `Scaffolding task for ${templateRef}`;\n if (userEntityRef) {\n auditLog += ` created by ${userEntityRef}`;\n }\n logger.info(auditLog);\n\n const values = req.body.values;\n\n const template = await authorizeTemplate(\n { kind, namespace, name },\n token,\n credentials,\n );\n\n for (const parameters of [template.spec.parameters ?? []].flat()) {\n const result = validate(values, parameters);\n\n if (!result.valid) {\n res.status(400).json({ errors: result.errors });\n return;\n }\n }\n\n const baseUrl = getEntityBaseUrl(template);\n\n const taskSpec: TaskSpec = {\n apiVersion: template.apiVersion,\n steps: template.spec.steps.map((step, index) => ({\n ...step,\n id: step.id ?? `step-${index + 1}`,\n name: step.name ?? step.action,\n })),\n EXPERIMENTAL_recovery: template.spec.EXPERIMENTAL_recovery,\n output: template.spec.output ?? {},\n parameters: values,\n user: {\n entity: userEntity as UserEntity,\n ref: userEntityRef,\n },\n templateInfo: {\n entityRef: stringifyEntityRef({ kind, name, namespace }),\n baseUrl,\n entity: {\n metadata: template.metadata,\n },\n },\n };\n\n const secrets: InternalTaskSecrets = {\n ...req.body.secrets,\n backstageToken: token,\n __initiatorCredentials: JSON.stringify({\n ...credentials,\n // credentials.token is nonenumerable and will not be serialized, so we need to add it explicitly\n token: (credentials as any).token,\n }),\n };\n\n const result = await taskBroker.dispatch({\n spec: taskSpec,\n createdBy: userEntityRef,\n secrets,\n });\n\n res.status(201).json({ id: result.taskId });\n })\n .get('/v2/tasks', async (req, res) => {\n const credentials = await httpAuth.credentials(req);\n await checkPermission({\n credentials,\n permissions: [taskReadPermission],\n permissionService: permissions,\n });\n\n if (!taskBroker.list) {\n throw new Error(\n 'TaskBroker does not support listing tasks, please implement the list method on the TaskBroker.',\n );\n }\n\n const createdBy = parseStringsParam(req.query.createdBy, 'createdBy');\n const status = parseStringsParam(req.query.status, 'status');\n\n const order = parseStringsParam(req.query.order, 'order')?.map(item => {\n const match = item.match(/^(asc|desc):(.+)$/);\n if (!match) {\n throw new InputError(\n `Invalid order parameter \"${item}\", expected \"<asc or desc>:<field name>\"`,\n );\n }\n\n return {\n order: match[1] as 'asc' | 'desc',\n field: match[2],\n };\n });\n\n const limit = parseNumberParam(req.query.limit, 'limit');\n const offset = parseNumberParam(req.query.offset, 'offset');\n\n const tasks = await taskBroker.list({\n filters: {\n createdBy,\n status: status ? (status as TaskStatus[]) : undefined,\n },\n order,\n pagination: {\n limit: limit ? limit[0] : undefined,\n offset: offset ? offset[0] : undefined,\n },\n });\n\n res.status(200).json(tasks);\n })\n .get('/v2/tasks/:taskId', async (req, res) => {\n const credentials = await httpAuth.credentials(req);\n await checkPermission({\n credentials,\n permissions: [taskReadPermission],\n permissionService: permissions,\n });\n\n const { taskId } = req.params;\n const task = await taskBroker.get(taskId);\n if (!task) {\n throw new NotFoundError(`Task with id ${taskId} does not exist`);\n }\n // Do not disclose secrets\n delete task.secrets;\n res.status(200).json(task);\n })\n .post('/v2/tasks/:taskId/cancel', async (req, res) => {\n const credentials = await httpAuth.credentials(req);\n // Requires both read and cancel permissions\n await checkPermission({\n credentials,\n permissions: [taskCancelPermission, taskReadPermission],\n permissionService: permissions,\n });\n\n const { taskId } = req.params;\n await taskBroker.cancel?.(taskId);\n res.status(200).json({ status: 'cancelled' });\n })\n .post('/v2/tasks/:taskId/retry', async (req, res) => {\n const credentials = await httpAuth.credentials(req);\n // Requires both read and cancel permissions\n await checkPermission({\n credentials,\n permissions: [taskCreatePermission, taskReadPermission],\n permissionService: permissions,\n });\n\n const { taskId } = req.params;\n await taskBroker.retry?.(taskId);\n res.status(201).json({ id: taskId });\n })\n .get('/v2/tasks/:taskId/eventstream', async (req, res) => {\n const credentials = await httpAuth.credentials(req);\n await checkPermission({\n credentials,\n permissions: [taskReadPermission],\n permissionService: permissions,\n });\n\n const { taskId } = req.params;\n const after =\n req.query.after !== undefined ? Number(req.query.after) : undefined;\n\n logger.debug(`Event stream observing taskId '${taskId}' opened`);\n\n // Mandatory headers and http status to keep connection open\n res.writeHead(200, {\n Connection: 'keep-alive',\n 'Cache-Control': 'no-cache',\n 'Content-Type': 'text/event-stream',\n });\n\n // After client opens connection send all events as string\n const subscription = taskBroker.event$({ taskId, after }).subscribe({\n error: error => {\n logger.error(\n `Received error from event stream when observing taskId '${taskId}', ${error}`,\n );\n res.end();\n },\n next: ({ events }) => {\n let shouldUnsubscribe = false;\n for (const event of events) {\n res.write(\n `event: ${event.type}\\ndata: ${JSON.stringify(event)}\\n\\n`,\n );\n if (event.type === 'completion' && !event.isTaskRecoverable) {\n shouldUnsubscribe = true;\n }\n }\n // res.flush() is only available with the compression middleware\n res.flush?.();\n if (shouldUnsubscribe) {\n subscription.unsubscribe();\n res.end();\n }\n },\n });\n\n // When client closes connection we update the clients list\n // avoiding the disconnected one\n req.on('close', () => {\n subscription.unsubscribe();\n logger.debug(`Event stream observing taskId '${taskId}' closed`);\n });\n })\n .get('/v2/tasks/:taskId/events', async (req, res) => {\n const credentials = await httpAuth.credentials(req);\n await checkPermission({\n credentials,\n permissions: [taskReadPermission],\n permissionService: permissions,\n });\n\n const { taskId } = req.params;\n const after = Number(req.query.after) || undefined;\n\n // cancel the request after 30 seconds. this aligns with the recommendations of RFC 6202.\n const timeout = setTimeout(() => {\n res.json([]);\n }, 30_000);\n\n // Get all known events after an id (always includes the completion event) and return the first callback\n const subscription = taskBroker.event$({ taskId, after }).subscribe({\n error: error => {\n logger.error(\n `Received error from event stream when observing taskId '${taskId}', ${error}`,\n );\n },\n next: ({ events }) => {\n clearTimeout(timeout);\n subscription.unsubscribe();\n res.json(events);\n },\n });\n\n // When client closes connection we update the clients list\n // avoiding the disconnected one\n req.on('close', () => {\n subscription.unsubscribe();\n clearTimeout(timeout);\n });\n })\n .post('/v2/dry-run', async (req, res) => {\n const credentials = await httpAuth.credentials(req);\n await checkPermission({\n credentials,\n permissions: [taskCreatePermission],\n permissionService: permissions,\n });\n\n const bodySchema = z.object({\n template: z.unknown(),\n values: z.record(z.unknown()),\n secrets: z.record(z.string()).optional(),\n directoryContents: z.array(\n z.object({ path: z.string(), base64Content: z.string() }),\n ),\n });\n const body = await bodySchema.parseAsync(req.body).catch(e => {\n throw new InputError(`Malformed request: ${e}`);\n });\n\n const template = body.template as TemplateEntityV1beta3;\n if (!(await templateEntityV1beta3Validator.check(template))) {\n throw new InputError('Input template is not a template');\n }\n\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: credentials,\n targetPluginId: 'catalog',\n });\n\n const userEntityRef = auth.isPrincipal(credentials, 'user')\n ? credentials.principal.userEntityRef\n : undefined;\n\n const userEntity = userEntityRef\n ? await catalogClient.getEntityByRef(userEntityRef, { token })\n : undefined;\n\n for (const parameters of [template.spec.parameters ?? []].flat()) {\n const result = validate(body.values, parameters);\n if (!result.valid) {\n res.status(400).json({ errors: result.errors });\n return;\n }\n }\n\n const steps = template.spec.steps.map((step, index) => ({\n ...step,\n id: step.id ?? `step-${index + 1}`,\n name: step.name ?? step.action,\n }));\n\n const dryRunId = uuid();\n const contentsPath = resolveSafeChildPath(\n workingDirectory,\n `dry-run-content-${dryRunId}`,\n );\n\n const templateInfo = {\n entityRef: stringifyEntityRef(template),\n entity: {\n metadata: template.metadata,\n },\n baseUrl: pathToFileURL(\n resolveSafeChildPath(contentsPath, 'template.yaml'),\n ).toString(),\n };\n\n const result = await dryRunner({\n spec: {\n apiVersion: template.apiVersion,\n steps,\n output: template.spec.output ?? {},\n parameters: body.values as JsonObject,\n user: {\n entity: userEntity as UserEntity,\n ref: userEntityRef,\n },\n },\n templateInfo: templateInfo,\n directoryContents: (body.directoryContents ?? []).map(file => ({\n path: file.path,\n content: Buffer.from(file.base64Content, 'base64'),\n })),\n secrets: {\n ...body.secrets,\n ...(token && { backstageToken: token }),\n },\n credentials,\n });\n\n res.status(200).json({\n ...result,\n steps,\n directoryContents: result.directoryContents.map(file => ({\n path: file.path,\n executable: file.executable,\n base64Content: file.content.toString('base64'),\n })),\n });\n })\n .post('/v2/autocomplete/:provider/:resource', async (req, res) => {\n const { token, context } = req.body;\n const { provider, resource } = req.params;\n\n if (!token) throw new InputError('Missing token query parameter');\n\n if (!autocompleteHandlers[provider]) {\n throw new InputError(`Unsupported provider: ${provider}`);\n }\n\n const { results } = await autocompleteHandlers[provider]({\n resource,\n token,\n context,\n });\n\n res.status(200).json({ results });\n });\n\n const app = express();\n app.set('logger', logger);\n app.use('/', router);\n\n async function authorizeTemplate(\n entityRef: CompoundEntityRef,\n token: string | undefined,\n credentials: BackstageCredentials,\n ) {\n const template = await findTemplate({\n catalogApi: catalogClient,\n entityRef,\n token,\n });\n\n if (!isSupportedTemplate(template)) {\n throw new InputError(\n `Unsupported apiVersion field in schema entity, ${\n (template as Entity).apiVersion\n }`,\n );\n }\n\n if (!permissions) {\n return template;\n }\n\n const [parameterDecision, stepDecision] =\n await permissions.authorizeConditional(\n [\n { permission: templateParameterReadPermission },\n { permission: templateStepReadPermission },\n ],\n { credentials },\n );\n\n // Authorize parameters\n if (Array.isArray(template.spec.parameters)) {\n template.spec.parameters = template.spec.parameters.filter(step =>\n isAuthorized(parameterDecision, step),\n );\n } else if (\n template.spec.parameters &&\n !isAuthorized(parameterDecision, template.spec.parameters)\n ) {\n template.spec.parameters = undefined;\n }\n\n // Authorize steps\n template.spec.steps = template.spec.steps.filter(step =>\n isAuthorized(stepDecision, step),\n );\n\n return template;\n }\n\n return app;\n}\n"],"names":["RESOURCE_TYPE_SCAFFOLDER_TEMPLATE","RESOURCE_TYPE_SCAFFOLDER_ACTION","parseEntityRef","stringifyError","config","readDurationFromConfig","Router","express","HostDiscovery","createLegacyAuthAdapters","getWorkingDirectory","ScmIntegrations","DatabaseTaskStore","StorageTaskBroker","Duration","TemplateActionRegistry","TaskWorker","createBuiltinActions","createDryRunner","scaffolderTemplateRules","scaffolderActionRules","createConditionAuthorizer","createPermissionIntegrationRouter","scaffolderTemplatePermissions","scaffolderActionPermissions","scaffolderTaskPermissions","checkPermission","taskCreatePermission","result","validate","getEntityBaseUrl","stringifyEntityRef","taskReadPermission","parseStringsParam","InputError","parseNumberParam","NotFoundError","taskCancelPermission","z","templateEntityV1beta3Validator","uuid","resolveSafeChildPath","pathToFileURL","findTemplate","templateParameterReadPermission","templateStepReadPermission"],"mappings":"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"}
1
+ {"version":3,"file":"router.cjs.js","sources":["../../src/service/router.ts"],"sourcesContent":["/*\n * Copyright 2020 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 createLegacyAuthAdapters,\n HostDiscovery,\n} from '@backstage/backend-common';\nimport { CatalogApi } from '@backstage/catalog-client';\nimport {\n CompoundEntityRef,\n Entity,\n parseEntityRef,\n stringifyEntityRef,\n UserEntity,\n} from '@backstage/catalog-model';\nimport { Config, readDurationFromConfig } from '@backstage/config';\nimport { InputError, NotFoundError, stringifyError } from '@backstage/errors';\nimport { ScmIntegrations } from '@backstage/integration';\nimport { HumanDuration, JsonObject, JsonValue } from '@backstage/types';\nimport {\n TaskSpec,\n TemplateEntityStepV1beta3,\n TemplateEntityV1beta3,\n templateEntityV1beta3Validator,\n TemplateParametersV1beta3,\n} from '@backstage/plugin-scaffolder-common';\nimport {\n RESOURCE_TYPE_SCAFFOLDER_ACTION,\n RESOURCE_TYPE_SCAFFOLDER_TEMPLATE,\n scaffolderActionPermissions,\n scaffolderTaskPermissions,\n scaffolderTemplatePermissions,\n taskCancelPermission,\n taskCreatePermission,\n taskReadPermission,\n templateParameterReadPermission,\n templateStepReadPermission,\n} from '@backstage/plugin-scaffolder-common/alpha';\nimport express from 'express';\nimport Router from 'express-promise-router';\nimport { validate } from 'jsonschema';\nimport { Logger } from 'winston';\nimport { z } from 'zod';\nimport {\n TaskBroker,\n TaskStatus,\n TemplateAction,\n TemplateFilter,\n TemplateGlobal,\n} from '@backstage/plugin-scaffolder-node';\nimport {\n createBuiltinActions,\n DatabaseTaskStore,\n TaskWorker,\n TemplateActionRegistry,\n} from '../scaffolder';\nimport { createDryRunner } from '../scaffolder/dryrun';\nimport { StorageTaskBroker } from '../scaffolder/tasks/StorageTaskBroker';\nimport {\n findTemplate,\n getEntityBaseUrl,\n getWorkingDirectory,\n parseNumberParam,\n parseStringsParam,\n} from './helpers';\nimport { PermissionRuleParams } from '@backstage/plugin-permission-common';\nimport {\n createConditionAuthorizer,\n createPermissionIntegrationRouter,\n PermissionRule,\n} from '@backstage/plugin-permission-node';\nimport { scaffolderActionRules, scaffolderTemplateRules } from './rules';\nimport { Duration } from 'luxon';\nimport {\n AuthService,\n BackstageCredentials,\n DatabaseService,\n DiscoveryService,\n HttpAuthService,\n LifecycleService,\n PermissionsService,\n resolveSafeChildPath,\n SchedulerService,\n UrlReaderService,\n} from '@backstage/backend-plugin-api';\nimport {\n IdentityApi,\n IdentityApiGetIdentityRequest,\n} from '@backstage/plugin-auth-node';\nimport { InternalTaskSecrets } from '../scaffolder/tasks/types';\nimport { checkPermission } from '../util/checkPermissions';\nimport {\n AutocompleteHandler,\n WorkspaceProvider,\n} from '@backstage/plugin-scaffolder-node/alpha';\nimport { pathToFileURL } from 'url';\nimport { v4 as uuid } from 'uuid';\nimport { EventsService } from '@backstage/plugin-events-node';\n\n/**\n *\n * @public\n */\nexport type TemplatePermissionRuleInput<\n TParams extends PermissionRuleParams = PermissionRuleParams,\n> = PermissionRule<\n TemplateEntityStepV1beta3 | TemplateParametersV1beta3,\n {},\n typeof RESOURCE_TYPE_SCAFFOLDER_TEMPLATE,\n TParams\n>;\nfunction isTemplatePermissionRuleInput(\n permissionRule: TemplatePermissionRuleInput | ActionPermissionRuleInput,\n): permissionRule is TemplatePermissionRuleInput {\n return permissionRule.resourceType === RESOURCE_TYPE_SCAFFOLDER_TEMPLATE;\n}\n\n/**\n *\n * @public\n */\nexport type ActionPermissionRuleInput<\n TParams extends PermissionRuleParams = PermissionRuleParams,\n> = PermissionRule<\n TemplateEntityStepV1beta3 | TemplateParametersV1beta3,\n {},\n typeof RESOURCE_TYPE_SCAFFOLDER_ACTION,\n TParams\n>;\nfunction isActionPermissionRuleInput(\n permissionRule: TemplatePermissionRuleInput | ActionPermissionRuleInput,\n): permissionRule is ActionPermissionRuleInput {\n return permissionRule.resourceType === RESOURCE_TYPE_SCAFFOLDER_ACTION;\n}\n\n/**\n * RouterOptions\n *\n * @public\n * @deprecated Please migrate to the new backend system as this will be removed in the future.\n */\nexport interface RouterOptions {\n logger: Logger;\n config: Config;\n reader: UrlReaderService;\n lifecycle?: LifecycleService;\n database: DatabaseService;\n catalogClient: CatalogApi;\n scheduler?: SchedulerService;\n actions?: TemplateAction<any, any>[];\n /**\n * @deprecated taskWorkers is deprecated in favor of concurrentTasksLimit option with a single TaskWorker\n * @defaultValue 1\n */\n taskWorkers?: number;\n /**\n * Sets the number of concurrent tasks that can be run at any given time on the TaskWorker\n * @defaultValue 10\n */\n concurrentTasksLimit?: number;\n taskBroker?: TaskBroker;\n additionalTemplateFilters?: Record<string, TemplateFilter>;\n additionalTemplateGlobals?: Record<string, TemplateGlobal>;\n additionalWorkspaceProviders?: Record<string, WorkspaceProvider>;\n permissions?: PermissionsService;\n permissionRules?: Array<\n TemplatePermissionRuleInput | ActionPermissionRuleInput\n >;\n auth?: AuthService;\n httpAuth?: HttpAuthService;\n identity?: IdentityApi;\n discovery?: DiscoveryService;\n events?: EventsService;\n\n autocompleteHandlers?: Record<string, AutocompleteHandler>;\n}\n\nfunction isSupportedTemplate(entity: TemplateEntityV1beta3) {\n return entity.apiVersion === 'scaffolder.backstage.io/v1beta3';\n}\n\n/*\n * @deprecated This function remains as the DefaultIdentityClient behaves slightly differently to the pre-existing\n * scaffolder behaviour. Specifically if the token fails to parse, the DefaultIdentityClient will raise an error.\n * The scaffolder did not raise an error in this case. As such we chose to allow it to behave as it did previously\n * until someone explicitly passes an IdentityApi. When we have reasonable confidence that most backstage deployments\n * are using the IdentityApi, we can remove this function.\n */\nfunction buildDefaultIdentityClient(options: RouterOptions): IdentityApi {\n return {\n getIdentity: async ({ request }: IdentityApiGetIdentityRequest) => {\n const header = request.headers.authorization;\n const { logger } = options;\n\n if (!header) {\n return undefined;\n }\n\n try {\n const token = header.match(/^Bearer\\s(\\S+\\.\\S+\\.\\S+)$/i)?.[1];\n if (!token) {\n throw new TypeError('Expected Bearer with JWT');\n }\n\n const [_header, rawPayload, _signature] = token.split('.');\n const payload: JsonValue = JSON.parse(\n Buffer.from(rawPayload, 'base64').toString(),\n );\n\n if (\n typeof payload !== 'object' ||\n payload === null ||\n Array.isArray(payload)\n ) {\n throw new TypeError('Malformed JWT payload');\n }\n\n const sub = payload.sub;\n if (typeof sub !== 'string') {\n throw new TypeError('Expected string sub claim');\n }\n\n if (sub === 'backstage-server') {\n return undefined;\n }\n\n // Check that it's a valid ref, otherwise this will throw.\n parseEntityRef(sub);\n\n return {\n identity: {\n userEntityRef: sub,\n ownershipEntityRefs: [],\n type: 'user',\n },\n token,\n };\n } catch (e) {\n logger.error(`Invalid authorization header: ${stringifyError(e)}`);\n return undefined;\n }\n },\n };\n}\n\nconst readDuration = (\n config: Config,\n key: string,\n defaultValue: HumanDuration,\n) => {\n if (config.has(key)) {\n return readDurationFromConfig(config, { key });\n }\n return defaultValue;\n};\n\n/**\n * A method to create a router for the scaffolder backend plugin.\n * @public\n * @deprecated Please migrate to the new backend system as this will be removed in the future.\n */\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const router = Router();\n // Be generous in upload size to support a wide range of templates in dry-run mode.\n router.use(express.json({ limit: '10MB' }));\n\n const {\n logger: parentLogger,\n config,\n reader,\n database,\n catalogClient,\n actions,\n taskWorkers,\n scheduler,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n additionalWorkspaceProviders,\n permissions,\n permissionRules,\n discovery = HostDiscovery.fromConfig(config),\n identity = buildDefaultIdentityClient(options),\n autocompleteHandlers = {},\n events: eventsService,\n } = options;\n\n const { auth, httpAuth } = createLegacyAuthAdapters({\n ...options,\n identity,\n discovery,\n });\n\n const concurrentTasksLimit =\n options.concurrentTasksLimit ??\n options.config.getOptionalNumber('scaffolder.concurrentTasksLimit');\n\n const logger = parentLogger.child({ plugin: 'scaffolder' });\n\n const workingDirectory = await getWorkingDirectory(config, logger);\n const integrations = ScmIntegrations.fromConfig(config);\n\n let taskBroker: TaskBroker;\n if (!options.taskBroker) {\n const databaseTaskStore = await DatabaseTaskStore.create({\n database,\n events: eventsService,\n });\n taskBroker = new StorageTaskBroker(\n databaseTaskStore,\n logger,\n config,\n auth,\n additionalWorkspaceProviders,\n );\n\n if (scheduler && databaseTaskStore.listStaleTasks) {\n await scheduler.scheduleTask({\n id: 'close_stale_tasks',\n frequency: readDuration(\n config,\n 'scaffolder.taskTimeoutJanitorFrequency',\n {\n minutes: 5,\n },\n ),\n timeout: { minutes: 15 },\n fn: async () => {\n const { tasks } = await databaseTaskStore.listStaleTasks({\n timeoutS: Duration.fromObject(\n readDuration(config, 'scaffolder.taskTimeout', {\n hours: 24,\n }),\n ).as('seconds'),\n });\n\n for (const task of tasks) {\n await databaseTaskStore.shutdownTask(task);\n logger.info(`Successfully closed stale task ${task.taskId}`);\n }\n },\n });\n }\n } else {\n taskBroker = options.taskBroker;\n }\n\n const actionRegistry = new TemplateActionRegistry();\n\n const workers: TaskWorker[] = [];\n if (concurrentTasksLimit !== 0) {\n for (let i = 0; i < (taskWorkers || 1); i++) {\n const worker = await TaskWorker.create({\n taskBroker,\n actionRegistry,\n integrations,\n logger,\n workingDirectory,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n concurrentTasksLimit,\n permissions,\n });\n workers.push(worker);\n }\n }\n\n const actionsToRegister = Array.isArray(actions)\n ? actions\n : createBuiltinActions({\n integrations,\n catalogClient,\n reader,\n config,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n auth,\n });\n\n actionsToRegister.forEach(action => actionRegistry.register(action));\n\n const launchWorkers = () => workers.forEach(worker => worker.start());\n\n const shutdownWorkers = () => {\n workers.forEach(worker => worker.stop());\n };\n\n if (options.lifecycle) {\n options.lifecycle.addStartupHook(launchWorkers);\n options.lifecycle.addShutdownHook(shutdownWorkers);\n } else {\n launchWorkers();\n }\n\n const dryRunner = createDryRunner({\n actionRegistry,\n integrations,\n logger,\n workingDirectory,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n permissions,\n });\n\n const templateRules: TemplatePermissionRuleInput[] = Object.values(\n scaffolderTemplateRules,\n );\n const actionRules: ActionPermissionRuleInput[] = Object.values(\n scaffolderActionRules,\n );\n\n if (permissionRules) {\n templateRules.push(\n ...permissionRules.filter(isTemplatePermissionRuleInput),\n );\n actionRules.push(...permissionRules.filter(isActionPermissionRuleInput));\n }\n\n const isAuthorized = createConditionAuthorizer(Object.values(templateRules));\n\n const permissionIntegrationRouter = createPermissionIntegrationRouter({\n resources: [\n {\n resourceType: RESOURCE_TYPE_SCAFFOLDER_TEMPLATE,\n permissions: scaffolderTemplatePermissions,\n rules: templateRules,\n },\n {\n resourceType: RESOURCE_TYPE_SCAFFOLDER_ACTION,\n permissions: scaffolderActionPermissions,\n rules: actionRules,\n },\n ],\n permissions: scaffolderTaskPermissions,\n });\n\n router.use(permissionIntegrationRouter);\n\n router\n .get(\n '/v2/templates/:namespace/:kind/:name/parameter-schema',\n async (req, res) => {\n const credentials = await httpAuth.credentials(req);\n\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: credentials,\n targetPluginId: 'catalog',\n });\n\n const template = await authorizeTemplate(\n req.params,\n token,\n credentials,\n );\n\n const parameters = [template.spec.parameters ?? []].flat();\n\n const presentation = template.spec.presentation;\n\n res.json({\n title: template.metadata.title ?? template.metadata.name,\n ...(presentation ? { presentation } : {}),\n description: template.metadata.description,\n 'ui:options': template.metadata['ui:options'],\n steps: parameters.map(schema => ({\n title: schema.title ?? 'Please enter the following information',\n description: schema.description,\n schema,\n })),\n EXPERIMENTAL_formDecorators:\n template.spec.EXPERIMENTAL_formDecorators,\n });\n },\n )\n .get('/v2/actions', async (_req, res) => {\n const actionsList = actionRegistry.list().map(action => {\n return {\n id: action.id,\n description: action.description,\n examples: action.examples,\n schema: action.schema,\n };\n });\n res.json(actionsList);\n })\n .post('/v2/tasks', async (req, res) => {\n const templateRef: string = req.body.templateRef;\n const { kind, namespace, name } = parseEntityRef(templateRef, {\n defaultKind: 'template',\n });\n\n const credentials = await httpAuth.credentials(req);\n\n await checkPermission({\n credentials,\n permissions: [taskCreatePermission],\n permissionService: permissions,\n });\n\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: credentials,\n targetPluginId: 'catalog',\n });\n\n const userEntityRef = auth.isPrincipal(credentials, 'user')\n ? credentials.principal.userEntityRef\n : undefined;\n\n const userEntity = userEntityRef\n ? await catalogClient.getEntityByRef(userEntityRef, { token })\n : undefined;\n\n let auditLog = `Scaffolding task for ${templateRef}`;\n if (userEntityRef) {\n auditLog += ` created by ${userEntityRef}`;\n }\n logger.info(auditLog);\n\n const values = req.body.values;\n\n const template = await authorizeTemplate(\n { kind, namespace, name },\n token,\n credentials,\n );\n\n for (const parameters of [template.spec.parameters ?? []].flat()) {\n const result = validate(values, parameters);\n\n if (!result.valid) {\n res.status(400).json({ errors: result.errors });\n return;\n }\n }\n\n const baseUrl = getEntityBaseUrl(template);\n\n const taskSpec: TaskSpec = {\n apiVersion: template.apiVersion,\n steps: template.spec.steps.map((step, index) => ({\n ...step,\n id: step.id ?? `step-${index + 1}`,\n name: step.name ?? step.action,\n })),\n EXPERIMENTAL_recovery: template.spec.EXPERIMENTAL_recovery,\n output: template.spec.output ?? {},\n parameters: values,\n user: {\n entity: userEntity as UserEntity,\n ref: userEntityRef,\n },\n templateInfo: {\n entityRef: stringifyEntityRef({ kind, name, namespace }),\n baseUrl,\n entity: {\n metadata: template.metadata,\n },\n },\n };\n\n const secrets: InternalTaskSecrets = {\n ...req.body.secrets,\n backstageToken: token,\n __initiatorCredentials: JSON.stringify({\n ...credentials,\n // credentials.token is nonenumerable and will not be serialized, so we need to add it explicitly\n token: (credentials as any).token,\n }),\n };\n\n const result = await taskBroker.dispatch({\n spec: taskSpec,\n createdBy: userEntityRef,\n secrets,\n });\n\n res.status(201).json({ id: result.taskId });\n })\n .get('/v2/tasks', async (req, res) => {\n const credentials = await httpAuth.credentials(req);\n await checkPermission({\n credentials,\n permissions: [taskReadPermission],\n permissionService: permissions,\n });\n\n if (!taskBroker.list) {\n throw new Error(\n 'TaskBroker does not support listing tasks, please implement the list method on the TaskBroker.',\n );\n }\n\n const createdBy = parseStringsParam(req.query.createdBy, 'createdBy');\n const status = parseStringsParam(req.query.status, 'status');\n\n const order = parseStringsParam(req.query.order, 'order')?.map(item => {\n const match = item.match(/^(asc|desc):(.+)$/);\n if (!match) {\n throw new InputError(\n `Invalid order parameter \"${item}\", expected \"<asc or desc>:<field name>\"`,\n );\n }\n\n return {\n order: match[1] as 'asc' | 'desc',\n field: match[2],\n };\n });\n\n const limit = parseNumberParam(req.query.limit, 'limit');\n const offset = parseNumberParam(req.query.offset, 'offset');\n\n const tasks = await taskBroker.list({\n filters: {\n createdBy,\n status: status ? (status as TaskStatus[]) : undefined,\n },\n order,\n pagination: {\n limit: limit ? limit[0] : undefined,\n offset: offset ? offset[0] : undefined,\n },\n });\n\n res.status(200).json(tasks);\n })\n .get('/v2/tasks/:taskId', async (req, res) => {\n const credentials = await httpAuth.credentials(req);\n await checkPermission({\n credentials,\n permissions: [taskReadPermission],\n permissionService: permissions,\n });\n\n const { taskId } = req.params;\n const task = await taskBroker.get(taskId);\n if (!task) {\n throw new NotFoundError(`Task with id ${taskId} does not exist`);\n }\n // Do not disclose secrets\n delete task.secrets;\n res.status(200).json(task);\n })\n .post('/v2/tasks/:taskId/cancel', async (req, res) => {\n const credentials = await httpAuth.credentials(req);\n // Requires both read and cancel permissions\n await checkPermission({\n credentials,\n permissions: [taskCancelPermission, taskReadPermission],\n permissionService: permissions,\n });\n\n const { taskId } = req.params;\n await taskBroker.cancel?.(taskId);\n res.status(200).json({ status: 'cancelled' });\n })\n .post('/v2/tasks/:taskId/retry', async (req, res) => {\n const credentials = await httpAuth.credentials(req);\n // Requires both read and cancel permissions\n await checkPermission({\n credentials,\n permissions: [taskCreatePermission, taskReadPermission],\n permissionService: permissions,\n });\n\n const { taskId } = req.params;\n await taskBroker.retry?.(taskId);\n res.status(201).json({ id: taskId });\n })\n .get('/v2/tasks/:taskId/eventstream', async (req, res) => {\n const credentials = await httpAuth.credentials(req);\n await checkPermission({\n credentials,\n permissions: [taskReadPermission],\n permissionService: permissions,\n });\n\n const { taskId } = req.params;\n const after =\n req.query.after !== undefined ? Number(req.query.after) : undefined;\n\n logger.debug(`Event stream observing taskId '${taskId}' opened`);\n\n // Mandatory headers and http status to keep connection open\n res.writeHead(200, {\n Connection: 'keep-alive',\n 'Cache-Control': 'no-cache',\n 'Content-Type': 'text/event-stream',\n });\n\n // After client opens connection send all events as string\n const subscription = taskBroker.event$({ taskId, after }).subscribe({\n error: error => {\n logger.error(\n `Received error from event stream when observing taskId '${taskId}', ${error}`,\n );\n res.end();\n },\n next: ({ events }) => {\n let shouldUnsubscribe = false;\n for (const event of events) {\n res.write(\n `event: ${event.type}\\ndata: ${JSON.stringify(event)}\\n\\n`,\n );\n if (event.type === 'completion' && !event.isTaskRecoverable) {\n shouldUnsubscribe = true;\n }\n }\n // res.flush() is only available with the compression middleware\n res.flush?.();\n if (shouldUnsubscribe) {\n subscription.unsubscribe();\n res.end();\n }\n },\n });\n\n // When client closes connection we update the clients list\n // avoiding the disconnected one\n req.on('close', () => {\n subscription.unsubscribe();\n logger.debug(`Event stream observing taskId '${taskId}' closed`);\n });\n })\n .get('/v2/tasks/:taskId/events', async (req, res) => {\n const credentials = await httpAuth.credentials(req);\n await checkPermission({\n credentials,\n permissions: [taskReadPermission],\n permissionService: permissions,\n });\n\n const { taskId } = req.params;\n const after = Number(req.query.after) || undefined;\n\n // cancel the request after 30 seconds. this aligns with the recommendations of RFC 6202.\n const timeout = setTimeout(() => {\n res.json([]);\n }, 30_000);\n\n // Get all known events after an id (always includes the completion event) and return the first callback\n const subscription = taskBroker.event$({ taskId, after }).subscribe({\n error: error => {\n logger.error(\n `Received error from event stream when observing taskId '${taskId}', ${error}`,\n );\n },\n next: ({ events }) => {\n clearTimeout(timeout);\n subscription.unsubscribe();\n res.json(events);\n },\n });\n\n // When client closes connection we update the clients list\n // avoiding the disconnected one\n req.on('close', () => {\n subscription.unsubscribe();\n clearTimeout(timeout);\n });\n })\n .post('/v2/dry-run', async (req, res) => {\n const credentials = await httpAuth.credentials(req);\n await checkPermission({\n credentials,\n permissions: [taskCreatePermission],\n permissionService: permissions,\n });\n\n const bodySchema = z.object({\n template: z.unknown(),\n values: z.record(z.unknown()),\n secrets: z.record(z.string()).optional(),\n directoryContents: z.array(\n z.object({ path: z.string(), base64Content: z.string() }),\n ),\n });\n const body = await bodySchema.parseAsync(req.body).catch(e => {\n throw new InputError(`Malformed request: ${e}`);\n });\n\n const template = body.template as TemplateEntityV1beta3;\n if (!(await templateEntityV1beta3Validator.check(template))) {\n throw new InputError('Input template is not a template');\n }\n\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: credentials,\n targetPluginId: 'catalog',\n });\n\n const userEntityRef = auth.isPrincipal(credentials, 'user')\n ? credentials.principal.userEntityRef\n : undefined;\n\n const userEntity = userEntityRef\n ? await catalogClient.getEntityByRef(userEntityRef, { token })\n : undefined;\n\n for (const parameters of [template.spec.parameters ?? []].flat()) {\n const result = validate(body.values, parameters);\n if (!result.valid) {\n res.status(400).json({ errors: result.errors });\n return;\n }\n }\n\n const steps = template.spec.steps.map((step, index) => ({\n ...step,\n id: step.id ?? `step-${index + 1}`,\n name: step.name ?? step.action,\n }));\n\n const dryRunId = uuid();\n const contentsPath = resolveSafeChildPath(\n workingDirectory,\n `dry-run-content-${dryRunId}`,\n );\n\n const templateInfo = {\n entityRef: stringifyEntityRef(template),\n entity: {\n metadata: template.metadata,\n },\n baseUrl: pathToFileURL(\n resolveSafeChildPath(contentsPath, 'template.yaml'),\n ).toString(),\n };\n\n const result = await dryRunner({\n spec: {\n apiVersion: template.apiVersion,\n steps,\n output: template.spec.output ?? {},\n parameters: body.values as JsonObject,\n user: {\n entity: userEntity as UserEntity,\n ref: userEntityRef,\n },\n },\n templateInfo: templateInfo,\n directoryContents: (body.directoryContents ?? []).map(file => ({\n path: file.path,\n content: Buffer.from(file.base64Content, 'base64'),\n })),\n secrets: {\n ...body.secrets,\n ...(token && { backstageToken: token }),\n },\n credentials,\n });\n\n res.status(200).json({\n ...result,\n steps,\n directoryContents: result.directoryContents.map(file => ({\n path: file.path,\n executable: file.executable,\n base64Content: file.content.toString('base64'),\n })),\n });\n })\n .post('/v2/autocomplete/:provider/:resource', async (req, res) => {\n const { token, context } = req.body;\n const { provider, resource } = req.params;\n\n if (!token) throw new InputError('Missing token query parameter');\n\n if (!autocompleteHandlers[provider]) {\n throw new InputError(`Unsupported provider: ${provider}`);\n }\n\n const { results } = await autocompleteHandlers[provider]({\n resource,\n token,\n context,\n });\n\n res.status(200).json({ results });\n });\n\n const app = express();\n app.set('logger', logger);\n app.use('/', router);\n\n async function authorizeTemplate(\n entityRef: CompoundEntityRef,\n token: string | undefined,\n credentials: BackstageCredentials,\n ) {\n const template = await findTemplate({\n catalogApi: catalogClient,\n entityRef,\n token,\n });\n\n if (!isSupportedTemplate(template)) {\n throw new InputError(\n `Unsupported apiVersion field in schema entity, ${\n (template as Entity).apiVersion\n }`,\n );\n }\n\n if (!permissions) {\n return template;\n }\n\n const [parameterDecision, stepDecision] =\n await permissions.authorizeConditional(\n [\n { permission: templateParameterReadPermission },\n { permission: templateStepReadPermission },\n ],\n { credentials },\n );\n\n // Authorize parameters\n if (Array.isArray(template.spec.parameters)) {\n template.spec.parameters = template.spec.parameters.filter(step =>\n isAuthorized(parameterDecision, step),\n );\n } else if (\n template.spec.parameters &&\n !isAuthorized(parameterDecision, template.spec.parameters)\n ) {\n template.spec.parameters = undefined;\n }\n\n // Authorize steps\n template.spec.steps = template.spec.steps.filter(step =>\n isAuthorized(stepDecision, step),\n );\n\n return template;\n }\n\n return app;\n}\n"],"names":["RESOURCE_TYPE_SCAFFOLDER_TEMPLATE","RESOURCE_TYPE_SCAFFOLDER_ACTION","parseEntityRef","stringifyError","config","readDurationFromConfig","Router","express","HostDiscovery","createLegacyAuthAdapters","getWorkingDirectory","ScmIntegrations","DatabaseTaskStore","StorageTaskBroker","Duration","TemplateActionRegistry","TaskWorker","createBuiltinActions","createDryRunner","scaffolderTemplateRules","scaffolderActionRules","createConditionAuthorizer","createPermissionIntegrationRouter","scaffolderTemplatePermissions","scaffolderActionPermissions","scaffolderTaskPermissions","checkPermission","taskCreatePermission","result","validate","getEntityBaseUrl","stringifyEntityRef","taskReadPermission","parseStringsParam","InputError","parseNumberParam","NotFoundError","taskCancelPermission","z","templateEntityV1beta3Validator","uuid","resolveSafeChildPath","pathToFileURL","findTemplate","templateParameterReadPermission","templateStepReadPermission"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/plugin-scaffolder-backend",
3
- "version": "1.27.0",
3
+ "version": "1.28.0-next.0",
4
4
  "description": "The Backstage backend plugin that helps you create new things",
5
5
  "backstage": {
6
6
  "role": "backend-plugin",
@@ -72,30 +72,31 @@
72
72
  },
73
73
  "dependencies": {
74
74
  "@backstage/backend-common": "^0.25.0",
75
- "@backstage/backend-defaults": "^0.5.3",
76
- "@backstage/backend-plugin-api": "^1.0.2",
77
- "@backstage/catalog-client": "^1.8.0",
78
- "@backstage/catalog-model": "^1.7.1",
79
- "@backstage/config": "^1.3.0",
80
- "@backstage/errors": "^1.2.5",
81
- "@backstage/integration": "^1.15.2",
82
- "@backstage/plugin-auth-node": "^0.5.4",
83
- "@backstage/plugin-bitbucket-cloud-common": "^0.2.25",
84
- "@backstage/plugin-catalog-backend-module-scaffolder-entity-model": "^0.2.2",
85
- "@backstage/plugin-catalog-node": "^1.14.0",
86
- "@backstage/plugin-permission-common": "^0.8.2",
87
- "@backstage/plugin-permission-node": "^0.8.5",
88
- "@backstage/plugin-scaffolder-backend-module-azure": "^0.2.2",
89
- "@backstage/plugin-scaffolder-backend-module-bitbucket": "^0.3.2",
90
- "@backstage/plugin-scaffolder-backend-module-bitbucket-cloud": "^0.2.2",
91
- "@backstage/plugin-scaffolder-backend-module-bitbucket-server": "^0.2.2",
92
- "@backstage/plugin-scaffolder-backend-module-gerrit": "^0.2.2",
93
- "@backstage/plugin-scaffolder-backend-module-gitea": "^0.2.2",
94
- "@backstage/plugin-scaffolder-backend-module-github": "^0.5.2",
95
- "@backstage/plugin-scaffolder-backend-module-gitlab": "^0.6.1",
96
- "@backstage/plugin-scaffolder-common": "^1.5.7",
97
- "@backstage/plugin-scaffolder-node": "^0.6.0",
98
- "@backstage/types": "^1.2.0",
75
+ "@backstage/backend-defaults": "0.6.0-next.0",
76
+ "@backstage/backend-plugin-api": "1.0.3-next.0",
77
+ "@backstage/catalog-client": "1.8.1-next.0",
78
+ "@backstage/catalog-model": "1.7.1",
79
+ "@backstage/config": "1.3.0",
80
+ "@backstage/errors": "1.2.5",
81
+ "@backstage/integration": "1.16.0-next.0",
82
+ "@backstage/plugin-auth-node": "0.5.5-next.0",
83
+ "@backstage/plugin-bitbucket-cloud-common": "0.2.26-next.0",
84
+ "@backstage/plugin-catalog-backend-module-scaffolder-entity-model": "0.2.3-next.0",
85
+ "@backstage/plugin-catalog-node": "1.14.1-next.0",
86
+ "@backstage/plugin-events-node": "0.4.6-next.0",
87
+ "@backstage/plugin-permission-common": "0.8.2",
88
+ "@backstage/plugin-permission-node": "0.8.6-next.0",
89
+ "@backstage/plugin-scaffolder-backend-module-azure": "0.2.3-next.0",
90
+ "@backstage/plugin-scaffolder-backend-module-bitbucket": "0.3.4-next.0",
91
+ "@backstage/plugin-scaffolder-backend-module-bitbucket-cloud": "0.2.3-next.0",
92
+ "@backstage/plugin-scaffolder-backend-module-bitbucket-server": "0.2.3-next.0",
93
+ "@backstage/plugin-scaffolder-backend-module-gerrit": "0.2.3-next.0",
94
+ "@backstage/plugin-scaffolder-backend-module-gitea": "0.2.3-next.0",
95
+ "@backstage/plugin-scaffolder-backend-module-github": "0.5.3-next.0",
96
+ "@backstage/plugin-scaffolder-backend-module-gitlab": "0.7.0-next.0",
97
+ "@backstage/plugin-scaffolder-common": "1.5.8-next.0",
98
+ "@backstage/plugin-scaffolder-node": "0.6.1-next.0",
99
+ "@backstage/types": "1.2.0",
99
100
  "@opentelemetry/api": "^1.3.0",
100
101
  "@types/express": "^4.17.6",
101
102
  "@types/luxon": "^3.0.0",
@@ -125,11 +126,11 @@
125
126
  "zod": "^3.22.4"
126
127
  },
127
128
  "devDependencies": {
128
- "@backstage/backend-app-api": "^1.0.2",
129
- "@backstage/backend-defaults": "^0.5.3",
130
- "@backstage/backend-test-utils": "^1.1.0",
131
- "@backstage/cli": "^0.29.0",
132
- "@backstage/plugin-scaffolder-node-test-utils": "^0.1.15",
129
+ "@backstage/backend-app-api": "1.0.3-next.0",
130
+ "@backstage/backend-defaults": "0.6.0-next.0",
131
+ "@backstage/backend-test-utils": "1.2.0-next.0",
132
+ "@backstage/cli": "0.29.3-next.0",
133
+ "@backstage/plugin-scaffolder-node-test-utils": "0.1.16-next.0",
133
134
  "@types/fs-extra": "^11.0.0",
134
135
  "@types/nunjucks": "^3.1.4",
135
136
  "@types/supertest": "^2.0.8",