@backstage/plugin-scaffolder-backend 1.30.0-next.2 → 1.30.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,89 @@
1
1
  # @backstage/plugin-scaffolder-backend
2
2
 
3
+ ## 1.30.0
4
+
5
+ ### Minor Changes
6
+
7
+ - dc8dd4b: Added new `createTemplateFilter`, `createTemplateGlobalFunction`, `createTemplateGlobalValue` for template extensions.
8
+ - a4aa244: This change integrates the `auditor` service into the Scaffolder plugin.
9
+ - 3d6ef79: Support file globbing in fs:delete
10
+ - 91f3313: Added experimental flag for scaffolder to wait for running tasks to complete on shutdown
11
+
12
+ Enabling the `EXPERIMENTAL_gracefulShutdown` flag in the scaffolder config will make the
13
+ scaffolder block the shutdown process until all running tasks have completed. This is useful
14
+ when there is a need to ensure that all tasks have completed before the scaffolder is shut down.
15
+
16
+ Please note, that the `TaskWorker` `stop` method is now asynchronous and awaited for the
17
+ tasks to complete when the experimental flag is enabled.
18
+
19
+ ### Patch Changes
20
+
21
+ - 37ab712: Fixed an issue where invalid expressions or non-object values in `step.each` caused an error.
22
+ - 1e935f0: Added conditional rendering of `oneOf` output schemas on the Installed Actions page for scaffolder actions
23
+ - Updated dependencies
24
+ - @backstage/plugin-permission-node@0.8.8
25
+ - @backstage/plugin-scaffolder-backend-module-gitlab@0.8.0
26
+ - @backstage/backend-defaults@0.8.0
27
+ - @backstage/plugin-scaffolder-backend-module-github@0.6.0
28
+ - @backstage/backend-plugin-api@1.2.0
29
+ - @backstage/plugin-catalog-node@1.16.0
30
+ - @backstage/plugin-auth-node@0.6.0
31
+ - @backstage/plugin-scaffolder-node@0.7.0
32
+ - @backstage/catalog-client@1.9.1
33
+ - @backstage/catalog-model@1.7.3
34
+ - @backstage/config@1.3.2
35
+ - @backstage/errors@1.2.7
36
+ - @backstage/integration@1.16.1
37
+ - @backstage/types@1.2.1
38
+ - @backstage/plugin-bitbucket-cloud-common@0.2.27
39
+ - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.5
40
+ - @backstage/plugin-events-node@0.4.8
41
+ - @backstage/plugin-permission-common@0.8.4
42
+ - @backstage/plugin-scaffolder-backend-module-azure@0.2.6
43
+ - @backstage/plugin-scaffolder-backend-module-bitbucket@0.3.7
44
+ - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.6
45
+ - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.6
46
+ - @backstage/plugin-scaffolder-backend-module-gerrit@0.2.6
47
+ - @backstage/plugin-scaffolder-backend-module-gitea@0.2.6
48
+ - @backstage/plugin-scaffolder-common@1.5.9
49
+
50
+ ## 1.30.0-next.3
51
+
52
+ ### Minor Changes
53
+
54
+ - dc8dd4b: Added new `createTemplateFilter`, `createTemplateGlobalFunction`, `createTemplateGlobalValue` for template extensions.
55
+ - 3d6ef79: Support file globbing in fs:delete
56
+
57
+ ### Patch Changes
58
+
59
+ - 1e935f0: Added conditional rendering of `oneOf` output schemas on the Installed Actions page for scaffolder actions
60
+ - Updated dependencies
61
+ - @backstage/plugin-scaffolder-backend-module-github@0.6.0-next.2
62
+ - @backstage/plugin-catalog-node@1.16.0-next.3
63
+ - @backstage/plugin-permission-node@0.8.8-next.2
64
+ - @backstage/plugin-scaffolder-node@0.7.0-next.2
65
+ - @backstage/backend-defaults@0.8.0-next.3
66
+ - @backstage/backend-plugin-api@1.2.0-next.2
67
+ - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.5-next.3
68
+ - @backstage/plugin-auth-node@0.6.0-next.2
69
+ - @backstage/plugin-events-node@0.4.8-next.2
70
+ - @backstage/plugin-scaffolder-backend-module-bitbucket@0.3.7-next.2
71
+ - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.6-next.2
72
+ - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.6-next.2
73
+ - @backstage/plugin-scaffolder-backend-module-gerrit@0.2.6-next.2
74
+ - @backstage/plugin-scaffolder-backend-module-gitea@0.2.6-next.2
75
+ - @backstage/plugin-scaffolder-backend-module-gitlab@0.8.0-next.3
76
+ - @backstage/plugin-scaffolder-backend-module-azure@0.2.6-next.2
77
+ - @backstage/catalog-client@1.9.1
78
+ - @backstage/catalog-model@1.7.3
79
+ - @backstage/config@1.3.2
80
+ - @backstage/errors@1.2.7
81
+ - @backstage/integration@1.16.1
82
+ - @backstage/types@1.2.1
83
+ - @backstage/plugin-bitbucket-cloud-common@0.2.27
84
+ - @backstage/plugin-permission-common@0.8.4
85
+ - @backstage/plugin-scaffolder-common@1.5.9
86
+
3
87
  ## 1.30.0-next.2
4
88
 
5
89
  ### Minor Changes
@@ -60,10 +60,23 @@ const scaffolderPlugin = backendPluginApi.createBackendPlugin({
60
60
  const additionalTemplateGlobals = {};
61
61
  env.registerExtensionPoint(alpha.scaffolderTemplatingExtensionPoint, {
62
62
  addTemplateFilters(newFilters) {
63
- Object.assign(additionalTemplateFilters, newFilters);
63
+ Object.assign(
64
+ additionalTemplateFilters,
65
+ Array.isArray(newFilters) ? Object.fromEntries(
66
+ newFilters.map((tf) => [tf.id, tf.filter])
67
+ ) : newFilters
68
+ );
64
69
  },
65
70
  addTemplateGlobals(newGlobals) {
66
- Object.assign(additionalTemplateGlobals, newGlobals);
71
+ Object.assign(
72
+ additionalTemplateGlobals,
73
+ Array.isArray(newGlobals) ? Object.fromEntries(
74
+ newGlobals.map((g) => [
75
+ g.id,
76
+ "value" in g ? g.value : g.fn
77
+ ])
78
+ ) : newGlobals
79
+ );
67
80
  }
68
81
  });
69
82
  const autocompleteHandlers = {};
@@ -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 { loggerToWinstonLogger } from '@backstage/backend-common';\nimport {\n coreServices,\n createBackendPlugin,\n} from '@backstage/backend-plugin-api';\nimport { ScmIntegrations } from '@backstage/integration';\nimport { catalogServiceRef } from '@backstage/plugin-catalog-node/alpha';\nimport { eventsServiceRef } from '@backstage/plugin-events-node';\nimport {\n TaskBroker,\n TemplateAction,\n TemplateFilter,\n TemplateGlobal,\n} from '@backstage/plugin-scaffolder-node';\nimport {\n AutocompleteHandler,\n scaffolderActionsExtensionPoint,\n scaffolderAutocompleteExtensionPoint,\n scaffolderTaskBrokerExtensionPoint,\n scaffolderTemplatingExtensionPoint,\n scaffolderWorkspaceProviderExtensionPoint,\n WorkspaceProvider,\n} from '@backstage/plugin-scaffolder-node/alpha';\nimport {\n createCatalogRegisterAction,\n createCatalogWriteAction,\n createDebugLogAction,\n createFetchCatalogEntityAction,\n createFetchPlainAction,\n createFetchPlainFileAction,\n createFetchTemplateAction,\n createFetchTemplateFileAction,\n createFilesystemDeleteAction,\n createFilesystemReadDirAction,\n createFilesystemRenameAction,\n createWaitAction,\n} from './scaffolder';\nimport { createRouter } from './service/router';\n\n/**\n * Scaffolder plugin\n *\n * @public\n */\nexport const scaffolderPlugin = createBackendPlugin({\n pluginId: 'scaffolder',\n register(env) {\n const addedActions = new Array<TemplateAction<any, any>>();\n env.registerExtensionPoint(scaffolderActionsExtensionPoint, {\n addActions(...newActions: TemplateAction<any>[]) {\n addedActions.push(...newActions);\n },\n });\n\n let taskBroker: TaskBroker | undefined;\n env.registerExtensionPoint(scaffolderTaskBrokerExtensionPoint, {\n setTaskBroker(newTaskBroker) {\n if (taskBroker) {\n throw new Error('Task broker may only be set once');\n }\n taskBroker = newTaskBroker;\n },\n });\n\n const additionalTemplateFilters: Record<string, TemplateFilter> = {};\n const additionalTemplateGlobals: Record<string, TemplateGlobal> = {};\n env.registerExtensionPoint(scaffolderTemplatingExtensionPoint, {\n addTemplateFilters(newFilters) {\n Object.assign(additionalTemplateFilters, newFilters);\n },\n addTemplateGlobals(newGlobals) {\n Object.assign(additionalTemplateGlobals, newGlobals);\n },\n });\n\n const autocompleteHandlers: Record<string, AutocompleteHandler> = {};\n env.registerExtensionPoint(scaffolderAutocompleteExtensionPoint, {\n addAutocompleteProvider(provider) {\n autocompleteHandlers[provider.id] = provider.handler;\n },\n });\n\n const additionalWorkspaceProviders: Record<string, WorkspaceProvider> = {};\n env.registerExtensionPoint(scaffolderWorkspaceProviderExtensionPoint, {\n addProviders(provider) {\n Object.assign(additionalWorkspaceProviders, provider);\n },\n });\n\n env.registerInit({\n deps: {\n logger: coreServices.logger,\n config: coreServices.rootConfig,\n lifecycle: coreServices.rootLifecycle,\n reader: coreServices.urlReader,\n permissions: coreServices.permissions,\n database: coreServices.database,\n auth: coreServices.auth,\n discovery: coreServices.discovery,\n httpRouter: coreServices.httpRouter,\n httpAuth: coreServices.httpAuth,\n auditor: coreServices.auditor,\n catalogClient: catalogServiceRef,\n events: eventsServiceRef,\n },\n async init({\n logger,\n config,\n lifecycle,\n reader,\n database,\n auth,\n discovery,\n httpRouter,\n httpAuth,\n catalogClient,\n permissions,\n events,\n auditor,\n }) {\n const log = loggerToWinstonLogger(logger);\n const integrations = ScmIntegrations.fromConfig(config);\n\n const actions = [\n // actions provided from other modules\n ...addedActions,\n\n // built-in actions for the scaffolder\n createFetchPlainAction({\n reader,\n integrations,\n }),\n createFetchPlainFileAction({\n reader,\n integrations,\n }),\n createFetchTemplateAction({\n integrations,\n reader,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n }),\n createFetchTemplateFileAction({\n integrations,\n reader,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n }),\n createDebugLogAction(),\n createWaitAction(),\n // todo(blam): maybe these should be a -catalog module?\n createCatalogRegisterAction({ catalogClient, integrations, auth }),\n createFetchCatalogEntityAction({ catalogClient, auth }),\n createCatalogWriteAction(),\n createFilesystemDeleteAction(),\n createFilesystemRenameAction(),\n createFilesystemReadDirAction(),\n ];\n\n const actionIds = actions.map(action => action.id).join(', ');\n\n log.info(\n `Starting scaffolder with the following actions enabled ${actionIds}`,\n );\n\n const router = await createRouter({\n logger: log,\n config,\n database,\n catalogClient,\n reader,\n lifecycle,\n actions,\n taskBroker,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n auth,\n httpAuth,\n discovery,\n permissions,\n autocompleteHandlers,\n additionalWorkspaceProviders,\n events,\n auditor,\n });\n httpRouter.use(router);\n },\n });\n },\n});\n"],"names":["createBackendPlugin","scaffolderActionsExtensionPoint","scaffolderTaskBrokerExtensionPoint","scaffolderTemplatingExtensionPoint","scaffolderAutocompleteExtensionPoint","scaffolderWorkspaceProviderExtensionPoint","coreServices","catalogServiceRef","eventsServiceRef","log","loggerToWinstonLogger","ScmIntegrations","createFetchPlainAction","createFetchPlainFileAction","createFetchTemplateAction","createFetchTemplateFileAction","createDebugLogAction","createWaitAction","createCatalogRegisterAction","createFetchCatalogEntityAction","createCatalogWriteAction","createFilesystemDeleteAction","createFilesystemRenameAction","createFilesystemReadDirAction","router","createRouter"],"mappings":"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"}
1
+ {"version":3,"file":"ScaffolderPlugin.cjs.js","sources":["../src/ScaffolderPlugin.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { loggerToWinstonLogger } from '@backstage/backend-common';\nimport {\n coreServices,\n createBackendPlugin,\n} from '@backstage/backend-plugin-api';\nimport { ScmIntegrations } from '@backstage/integration';\nimport { catalogServiceRef } from '@backstage/plugin-catalog-node/alpha';\nimport { eventsServiceRef } from '@backstage/plugin-events-node';\nimport {\n TaskBroker,\n TemplateAction,\n TemplateFilter,\n TemplateGlobal,\n} from '@backstage/plugin-scaffolder-node';\nimport {\n AutocompleteHandler,\n scaffolderActionsExtensionPoint,\n scaffolderAutocompleteExtensionPoint,\n scaffolderTaskBrokerExtensionPoint,\n scaffolderTemplatingExtensionPoint,\n scaffolderWorkspaceProviderExtensionPoint,\n WorkspaceProvider,\n} from '@backstage/plugin-scaffolder-node/alpha';\nimport {\n createCatalogRegisterAction,\n createCatalogWriteAction,\n createDebugLogAction,\n createFetchCatalogEntityAction,\n createFetchPlainAction,\n createFetchPlainFileAction,\n createFetchTemplateAction,\n createFetchTemplateFileAction,\n createFilesystemDeleteAction,\n createFilesystemReadDirAction,\n createFilesystemRenameAction,\n createWaitAction,\n} from './scaffolder';\nimport { createRouter } from './service/router';\n\n/**\n * Scaffolder plugin\n *\n * @public\n */\nexport const scaffolderPlugin = createBackendPlugin({\n pluginId: 'scaffolder',\n register(env) {\n const addedActions = new Array<TemplateAction<any, any>>();\n env.registerExtensionPoint(scaffolderActionsExtensionPoint, {\n addActions(...newActions: TemplateAction<any>[]) {\n addedActions.push(...newActions);\n },\n });\n\n let taskBroker: TaskBroker | undefined;\n env.registerExtensionPoint(scaffolderTaskBrokerExtensionPoint, {\n setTaskBroker(newTaskBroker) {\n if (taskBroker) {\n throw new Error('Task broker may only be set once');\n }\n taskBroker = newTaskBroker;\n },\n });\n\n const additionalTemplateFilters: Record<string, TemplateFilter> = {};\n const additionalTemplateGlobals: Record<string, TemplateGlobal> = {};\n env.registerExtensionPoint(scaffolderTemplatingExtensionPoint, {\n addTemplateFilters(newFilters) {\n Object.assign(\n additionalTemplateFilters,\n Array.isArray(newFilters)\n ? Object.fromEntries(\n newFilters.map(tf => [tf.id, tf.filter as TemplateFilter]),\n )\n : newFilters,\n );\n },\n addTemplateGlobals(newGlobals) {\n Object.assign(\n additionalTemplateGlobals,\n Array.isArray(newGlobals)\n ? Object.fromEntries(\n newGlobals.map(g => [\n g.id,\n ('value' in g ? g.value : g.fn) as TemplateGlobal,\n ]),\n )\n : newGlobals,\n );\n },\n });\n\n const autocompleteHandlers: Record<string, AutocompleteHandler> = {};\n env.registerExtensionPoint(scaffolderAutocompleteExtensionPoint, {\n addAutocompleteProvider(provider) {\n autocompleteHandlers[provider.id] = provider.handler;\n },\n });\n\n const additionalWorkspaceProviders: Record<string, WorkspaceProvider> = {};\n env.registerExtensionPoint(scaffolderWorkspaceProviderExtensionPoint, {\n addProviders(provider) {\n Object.assign(additionalWorkspaceProviders, provider);\n },\n });\n\n env.registerInit({\n deps: {\n logger: coreServices.logger,\n config: coreServices.rootConfig,\n lifecycle: coreServices.rootLifecycle,\n reader: coreServices.urlReader,\n permissions: coreServices.permissions,\n database: coreServices.database,\n auth: coreServices.auth,\n discovery: coreServices.discovery,\n httpRouter: coreServices.httpRouter,\n httpAuth: coreServices.httpAuth,\n auditor: coreServices.auditor,\n catalogClient: catalogServiceRef,\n events: eventsServiceRef,\n },\n async init({\n logger,\n config,\n lifecycle,\n reader,\n database,\n auth,\n discovery,\n httpRouter,\n httpAuth,\n catalogClient,\n permissions,\n events,\n auditor,\n }) {\n const log = loggerToWinstonLogger(logger);\n const integrations = ScmIntegrations.fromConfig(config);\n\n const actions = [\n // actions provided from other modules\n ...addedActions,\n\n // built-in actions for the scaffolder\n createFetchPlainAction({\n reader,\n integrations,\n }),\n createFetchPlainFileAction({\n reader,\n integrations,\n }),\n createFetchTemplateAction({\n integrations,\n reader,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n }),\n createFetchTemplateFileAction({\n integrations,\n reader,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n }),\n createDebugLogAction(),\n createWaitAction(),\n // todo(blam): maybe these should be a -catalog module?\n createCatalogRegisterAction({ catalogClient, integrations, auth }),\n createFetchCatalogEntityAction({ catalogClient, auth }),\n createCatalogWriteAction(),\n createFilesystemDeleteAction(),\n createFilesystemRenameAction(),\n createFilesystemReadDirAction(),\n ];\n\n const actionIds = actions.map(action => action.id).join(', ');\n\n log.info(\n `Starting scaffolder with the following actions enabled ${actionIds}`,\n );\n\n const router = await createRouter({\n logger: log,\n config,\n database,\n catalogClient,\n reader,\n lifecycle,\n actions,\n taskBroker,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n auth,\n httpAuth,\n discovery,\n permissions,\n autocompleteHandlers,\n additionalWorkspaceProviders,\n events,\n auditor,\n });\n httpRouter.use(router);\n },\n });\n },\n});\n"],"names":["createBackendPlugin","scaffolderActionsExtensionPoint","scaffolderTaskBrokerExtensionPoint","scaffolderTemplatingExtensionPoint","scaffolderAutocompleteExtensionPoint","scaffolderWorkspaceProviderExtensionPoint","coreServices","catalogServiceRef","eventsServiceRef","log","loggerToWinstonLogger","ScmIntegrations","createFetchPlainAction","createFetchPlainFileAction","createFetchTemplateAction","createFetchTemplateFileAction","createDebugLogAction","createWaitAction","createCatalogRegisterAction","createFetchCatalogEntityAction","createCatalogWriteAction","createFilesystemDeleteAction","createFilesystemRenameAction","createFilesystemReadDirAction","router","createRouter"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4DO,MAAM,mBAAmBA,oCAAoB,CAAA;AAAA,EAClD,QAAU,EAAA,YAAA;AAAA,EACV,SAAS,GAAK,EAAA;AACZ,IAAM,MAAA,YAAA,GAAe,IAAI,KAAgC,EAAA;AACzD,IAAA,GAAA,CAAI,uBAAuBC,qCAAiC,EAAA;AAAA,MAC1D,cAAc,UAAmC,EAAA;AAC/C,QAAa,YAAA,CAAA,IAAA,CAAK,GAAG,UAAU,CAAA;AAAA;AACjC,KACD,CAAA;AAED,IAAI,IAAA,UAAA;AACJ,IAAA,GAAA,CAAI,uBAAuBC,wCAAoC,EAAA;AAAA,MAC7D,cAAc,aAAe,EAAA;AAC3B,QAAA,IAAI,UAAY,EAAA;AACd,UAAM,MAAA,IAAI,MAAM,kCAAkC,CAAA;AAAA;AAEpD,QAAa,UAAA,GAAA,aAAA;AAAA;AACf,KACD,CAAA;AAED,IAAA,MAAM,4BAA4D,EAAC;AACnE,IAAA,MAAM,4BAA4D,EAAC;AACnE,IAAA,GAAA,CAAI,uBAAuBC,wCAAoC,EAAA;AAAA,MAC7D,mBAAmB,UAAY,EAAA;AAC7B,QAAO,MAAA,CAAA,MAAA;AAAA,UACL,yBAAA;AAAA,UACA,KAAM,CAAA,OAAA,CAAQ,UAAU,CAAA,GACpB,MAAO,CAAA,WAAA;AAAA,YACL,UAAA,CAAW,IAAI,CAAM,EAAA,KAAA,CAAC,GAAG,EAAI,EAAA,EAAA,CAAG,MAAwB,CAAC;AAAA,WAE3D,GAAA;AAAA,SACN;AAAA,OACF;AAAA,MACA,mBAAmB,UAAY,EAAA;AAC7B,QAAO,MAAA,CAAA,MAAA;AAAA,UACL,yBAAA;AAAA,UACA,KAAM,CAAA,OAAA,CAAQ,UAAU,CAAA,GACpB,MAAO,CAAA,WAAA;AAAA,YACL,UAAA,CAAW,IAAI,CAAK,CAAA,KAAA;AAAA,cAClB,CAAE,CAAA,EAAA;AAAA,cACD,OAAW,IAAA,CAAA,GAAI,CAAE,CAAA,KAAA,GAAQ,CAAE,CAAA;AAAA,aAC7B;AAAA,WAEH,GAAA;AAAA,SACN;AAAA;AACF,KACD,CAAA;AAED,IAAA,MAAM,uBAA4D,EAAC;AACnE,IAAA,GAAA,CAAI,uBAAuBC,0CAAsC,EAAA;AAAA,MAC/D,wBAAwB,QAAU,EAAA;AAChC,QAAqB,oBAAA,CAAA,QAAA,CAAS,EAAE,CAAA,GAAI,QAAS,CAAA,OAAA;AAAA;AAC/C,KACD,CAAA;AAED,IAAA,MAAM,+BAAkE,EAAC;AACzE,IAAA,GAAA,CAAI,uBAAuBC,+CAA2C,EAAA;AAAA,MACpE,aAAa,QAAU,EAAA;AACrB,QAAO,MAAA,CAAA,MAAA,CAAO,8BAA8B,QAAQ,CAAA;AAAA;AACtD,KACD,CAAA;AAED,IAAA,GAAA,CAAI,YAAa,CAAA;AAAA,MACf,IAAM,EAAA;AAAA,QACJ,QAAQC,6BAAa,CAAA,MAAA;AAAA,QACrB,QAAQA,6BAAa,CAAA,UAAA;AAAA,QACrB,WAAWA,6BAAa,CAAA,aAAA;AAAA,QACxB,QAAQA,6BAAa,CAAA,SAAA;AAAA,QACrB,aAAaA,6BAAa,CAAA,WAAA;AAAA,QAC1B,UAAUA,6BAAa,CAAA,QAAA;AAAA,QACvB,MAAMA,6BAAa,CAAA,IAAA;AAAA,QACnB,WAAWA,6BAAa,CAAA,SAAA;AAAA,QACxB,YAAYA,6BAAa,CAAA,UAAA;AAAA,QACzB,UAAUA,6BAAa,CAAA,QAAA;AAAA,QACvB,SAASA,6BAAa,CAAA,OAAA;AAAA,QACtB,aAAe,EAAAC,yBAAA;AAAA,QACf,MAAQ,EAAAC;AAAA,OACV;AAAA,MACA,MAAM,IAAK,CAAA;AAAA,QACT,MAAA;AAAA,QACA,MAAA;AAAA,QACA,SAAA;AAAA,QACA,MAAA;AAAA,QACA,QAAA;AAAA,QACA,IAAA;AAAA,QACA,SAAA;AAAA,QACA,UAAA;AAAA,QACA,QAAA;AAAA,QACA,aAAA;AAAA,QACA,WAAA;AAAA,QACA,MAAA;AAAA,QACA;AAAA,OACC,EAAA;AACD,QAAM,MAAAC,KAAA,GAAMC,oCAAsB,MAAM,CAAA;AACxC,QAAM,MAAA,YAAA,GAAeC,2BAAgB,CAAA,UAAA,CAAW,MAAM,CAAA;AAEtD,QAAA,MAAM,OAAU,GAAA;AAAA;AAAA,UAEd,GAAG,YAAA;AAAA;AAAA,UAGHC,4BAAuB,CAAA;AAAA,YACrB,MAAA;AAAA,YACA;AAAA,WACD,CAAA;AAAA,UACDC,oCAA2B,CAAA;AAAA,YACzB,MAAA;AAAA,YACA;AAAA,WACD,CAAA;AAAA,UACDC,kCAA0B,CAAA;AAAA,YACxB,YAAA;AAAA,YACA,MAAA;AAAA,YACA,yBAAA;AAAA,YACA;AAAA,WACD,CAAA;AAAA,UACDC,0CAA8B,CAAA;AAAA,YAC5B,YAAA;AAAA,YACA,MAAA;AAAA,YACA,yBAAA;AAAA,YACA;AAAA,WACD,CAAA;AAAA,UACDC,wBAAqB,EAAA;AAAA,UACrBC,qBAAiB,EAAA;AAAA;AAAA,UAEjBC,oCAA4B,CAAA,EAAE,aAAe,EAAA,YAAA,EAAc,MAAM,CAAA;AAAA,UACjEC,oCAA+B,CAAA,EAAE,aAAe,EAAA,IAAA,EAAM,CAAA;AAAA,UACtDC,8BAAyB,EAAA;AAAA,UACzBC,oCAA6B,EAAA;AAAA,UAC7BC,mCAA6B,EAAA;AAAA,UAC7BC,kCAA8B;AAAA,SAChC;AAEA,QAAM,MAAA,SAAA,GAAY,QAAQ,GAAI,CAAA,CAAA,MAAA,KAAU,OAAO,EAAE,CAAA,CAAE,KAAK,IAAI,CAAA;AAE5D,QAAId,KAAA,CAAA,IAAA;AAAA,UACF,0DAA0D,SAAS,CAAA;AAAA,SACrE;AAEA,QAAM,MAAAe,QAAA,GAAS,MAAMC,mBAAa,CAAA;AAAA,UAChC,MAAQ,EAAAhB,KAAA;AAAA,UACR,MAAA;AAAA,UACA,QAAA;AAAA,UACA,aAAA;AAAA,UACA,MAAA;AAAA,UACA,SAAA;AAAA,UACA,OAAA;AAAA,UACA,UAAA;AAAA,UACA,yBAAA;AAAA,UACA,yBAAA;AAAA,UACA,IAAA;AAAA,UACA,QAAA;AAAA,UACA,SAAA;AAAA,UACA,WAAA;AAAA,UACA,oBAAA;AAAA,UACA,4BAAA;AAAA,UACA,MAAA;AAAA,UACA;AAAA,SACD,CAAA;AACD,QAAA,UAAA,CAAW,IAAIe,QAAM,CAAA;AAAA;AACvB,KACD,CAAA;AAAA;AAEL,CAAC;;;;"}
package/dist/index.d.ts CHANGED
@@ -21,7 +21,7 @@ import { Knex } from 'knex';
21
21
  import * as _backstage_plugin_scaffolder_common from '@backstage/plugin-scaffolder-common';
22
22
  import { TaskSpec, TaskRecovery, TemplateEntityStepV1beta3, TemplateParametersV1beta3 } from '@backstage/plugin-scaffolder-common';
23
23
  import { EventsService } from '@backstage/plugin-events-node';
24
- import { WorkspaceProvider, AutocompleteHandler } from '@backstage/plugin-scaffolder-node/alpha';
24
+ import { WorkspaceProvider, CreatedTemplateFilter, CreatedTemplateGlobal, AutocompleteHandler } from '@backstage/plugin-scaffolder-node/alpha';
25
25
  import { Logger } from 'winston';
26
26
  import { PermissionEvaluator, PermissionRuleParams } from '@backstage/plugin-permission-common';
27
27
  import { IdentityApi } from '@backstage/plugin-auth-node';
@@ -343,6 +343,7 @@ declare const createPublishGithubPullRequestAction: (options: CreateGithubPullRe
343
343
  gitAuthorName?: string | undefined;
344
344
  gitAuthorEmail?: string | undefined;
345
345
  forceEmptyGitAuthor?: boolean | undefined;
346
+ createWhenEmpty?: boolean | undefined;
346
347
  }, _backstage_types.JsonObject>;
347
348
  /**
348
349
  * @public @deprecated use "createPublishBitbucketCloudAction" from \@backstage/plugin-scaffolder-backend-module-bitbucket-cloud or "createPublishBitbucketServerAction" from \@backstage/plugin-scaffolder-backend-module-bitbucket-server instead
@@ -890,8 +891,8 @@ interface RouterOptions {
890
891
  */
891
892
  concurrentTasksLimit?: number;
892
893
  taskBroker?: TaskBroker$1;
893
- additionalTemplateFilters?: Record<string, TemplateFilter$1>;
894
- additionalTemplateGlobals?: Record<string, TemplateGlobal$1>;
894
+ additionalTemplateFilters?: Record<string, TemplateFilter$1> | CreatedTemplateFilter[];
895
+ additionalTemplateGlobals?: Record<string, TemplateGlobal$1> | CreatedTemplateGlobal[];
895
896
  additionalWorkspaceProviders?: Record<string, WorkspaceProvider>;
896
897
  permissions?: PermissionsService;
897
898
  permissionRules?: Array<TemplatePermissionRuleInput | ActionPermissionRuleInput>;
@@ -136,7 +136,8 @@ class SecureTemplater {
136
136
  if (!Object.hasOwn(templateFilters, filterName)) {
137
137
  return "";
138
138
  }
139
- const rz = templateFilters[filterName](...args);
139
+ const [input, ...rest] = args;
140
+ const rz = templateFilters[filterName](input, ...rest);
140
141
  return rz === void 0 ? "" : JSON.stringify(rz);
141
142
  }
142
143
  );
@@ -1 +1 @@
1
- {"version":3,"file":"SecureTemplater.cjs.js","sources":["../../../src/lib/templating/SecureTemplater.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 { Isolate } from 'isolated-vm';\nimport { resolvePackagePath } from '@backstage/backend-plugin-api';\nimport {\n TemplateFilter as _TemplateFilter,\n TemplateGlobal as _TemplateGlobal,\n} from '@backstage/plugin-scaffolder-node';\nimport fs from 'fs-extra';\nimport { JsonValue } from '@backstage/types';\nimport { getMajorNodeVersion, isNoNodeSnapshotOptionProvided } from './helpers';\n\n// language=JavaScript\nconst mkScript = (nunjucksSource: string) => `\nconst { render, renderCompat } = (() => {\n const module = {};\n const process = { env: {} };\n const require = (pkg) => { if (pkg === 'events') { return function (){}; }};\n\n ${nunjucksSource}\n\n const env = module.exports.configure({\n autoescape: false,\n ...JSON.parse(nunjucksConfigs),\n tags: {\n variableStart: '\\${{',\n variableEnd: '}}',\n },\n });\n\n const compatEnv = module.exports.configure({\n autoescape: false,\n ...JSON.parse(nunjucksConfigs),\n tags: {\n variableStart: '{{',\n variableEnd: '}}',\n },\n });\n compatEnv.addFilter('jsonify', compatEnv.getFilter('dump'));\n\n const handleFunctionResult = (value) => {\n return value === '' ? undefined : JSON.parse(value);\n };\n for (const name of JSON.parse(availableTemplateFilters)) {\n env.addFilter(name, (...args) => handleFunctionResult(callFilter(name, args)));\n }\n for (const [name, value] of Object.entries(JSON.parse(availableTemplateGlobals))) {\n env.addGlobal(name, value);\n }\n for (const name of JSON.parse(availableTemplateCallbacks)) {\n env.addGlobal(name, (...args) => handleFunctionResult(callGlobal(name, args)));\n }\n\n let uninstallCompat = undefined;\n\n function render(str, values) {\n try {\n if (uninstallCompat) {\n uninstallCompat();\n uninstallCompat = undefined;\n }\n return env.renderString(str, JSON.parse(values));\n } catch (error) {\n // Make sure errors don't leak anything\n throw new Error(String(error.message));\n }\n }\n\n function renderCompat(str, values) {\n try {\n if (!uninstallCompat) {\n uninstallCompat = module.exports.installJinjaCompat();\n }\n return compatEnv.renderString(str, JSON.parse(values));\n } catch (error) {\n // Make sure errors don't leak anything\n throw new Error(String(error.message));\n }\n }\n\n return { render, renderCompat };\n})();\n`;\n\n/**\n * @public\n * @deprecated Import from `@backstage/plugin-scaffolder-node` instead.\n */\nexport type TemplateFilter = _TemplateFilter;\n\n/**\n * @public\n * @deprecated Import from `@backstage/plugin-scaffolder-node` instead.\n */\nexport type TemplateGlobal = _TemplateGlobal;\n\ninterface SecureTemplaterOptions {\n /* Enables jinja compatibility and the \"jsonify\" filter */\n cookiecutterCompat?: boolean;\n /* Extra user-provided nunjucks filters */\n templateFilters?: Record<string, TemplateFilter>;\n /* Extra user-provided nunjucks globals */\n templateGlobals?: Record<string, TemplateGlobal>;\n nunjucksConfigs?: { trimBlocks?: boolean; lstripBlocks?: boolean };\n}\n\nexport type SecureTemplateRenderer = (\n template: string,\n values: unknown,\n) => string;\n\nexport class SecureTemplater {\n static async loadRenderer(options: SecureTemplaterOptions = {}) {\n const {\n cookiecutterCompat,\n templateFilters = {},\n templateGlobals = {},\n nunjucksConfigs = {},\n } = options;\n\n const nodeVersion = getMajorNodeVersion();\n if (nodeVersion >= 20 && !isNoNodeSnapshotOptionProvided()) {\n throw new Error(\n `When using Node.js version 20 or newer, the scaffolder backend plugin requires that it be started with the --no-node-snapshot option. \n Please make sure that you have NODE_OPTIONS=--no-node-snapshot in your environment.`,\n );\n }\n\n const isolate = new Isolate({ memoryLimit: 128 });\n const context = await isolate.createContext();\n const contextGlobal = context.global;\n\n const nunjucksSource = await fs.readFile(\n resolvePackagePath(\n '@backstage/plugin-scaffolder-backend',\n 'assets/nunjucks.js.txt',\n ),\n 'utf-8',\n );\n\n const nunjucksScript = await isolate.compileScript(\n mkScript(nunjucksSource),\n );\n\n await contextGlobal.set('nunjucksConfigs', JSON.stringify(nunjucksConfigs));\n\n const availableFilters = Object.keys(templateFilters);\n\n await contextGlobal.set(\n 'availableTemplateFilters',\n JSON.stringify(availableFilters),\n );\n\n const globalCallbacks = [];\n const globalValues: Record<string, unknown> = {};\n for (const [name, value] of Object.entries(templateGlobals)) {\n if (typeof value === 'function') {\n globalCallbacks.push(name);\n } else {\n globalValues[name] = value;\n }\n }\n\n await contextGlobal.set(\n 'availableTemplateGlobals',\n JSON.stringify(globalValues),\n );\n await contextGlobal.set(\n 'availableTemplateCallbacks',\n JSON.stringify(globalCallbacks),\n );\n\n await contextGlobal.set(\n 'callFilter',\n (filterName: string, args: JsonValue[]) => {\n if (!Object.hasOwn(templateFilters, filterName)) {\n return '';\n }\n const rz = templateFilters[filterName](...args);\n return rz === undefined ? '' : JSON.stringify(rz);\n },\n );\n\n await contextGlobal.set(\n 'callGlobal',\n (globalName: string, args: JsonValue[]) => {\n if (!Object.hasOwn(templateGlobals, globalName)) {\n return '';\n }\n const global = templateGlobals[globalName];\n if (typeof global !== 'function') {\n return '';\n }\n const rz = global(...args);\n return rz === undefined ? '' : JSON.stringify(rz);\n },\n );\n\n await nunjucksScript.run(context);\n\n const render: SecureTemplateRenderer = (template, values) => {\n if (!context) {\n throw new Error('SecureTemplater has not been initialized');\n }\n\n contextGlobal.setSync('templateStr', String(template));\n contextGlobal.setSync('templateValues', JSON.stringify(values));\n\n if (cookiecutterCompat) {\n return context.evalSync(`renderCompat(templateStr, templateValues)`);\n }\n\n return context.evalSync(`render(templateStr, templateValues)`);\n };\n return render;\n }\n}\n"],"names":["getMajorNodeVersion","isNoNodeSnapshotOptionProvided","Isolate","fs","resolvePackagePath"],"mappings":"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"}
1
+ {"version":3,"file":"SecureTemplater.cjs.js","sources":["../../../src/lib/templating/SecureTemplater.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 { Isolate } from 'isolated-vm';\nimport { resolvePackagePath } from '@backstage/backend-plugin-api';\nimport {\n TemplateFilter as _TemplateFilter,\n TemplateGlobal as _TemplateGlobal,\n} from '@backstage/plugin-scaffolder-node';\nimport fs from 'fs-extra';\nimport { JsonValue } from '@backstage/types';\nimport { getMajorNodeVersion, isNoNodeSnapshotOptionProvided } from './helpers';\n\n// language=JavaScript\nconst mkScript = (nunjucksSource: string) => `\nconst { render, renderCompat } = (() => {\n const module = {};\n const process = { env: {} };\n const require = (pkg) => { if (pkg === 'events') { return function (){}; }};\n\n ${nunjucksSource}\n\n const env = module.exports.configure({\n autoescape: false,\n ...JSON.parse(nunjucksConfigs),\n tags: {\n variableStart: '\\${{',\n variableEnd: '}}',\n },\n });\n\n const compatEnv = module.exports.configure({\n autoescape: false,\n ...JSON.parse(nunjucksConfigs),\n tags: {\n variableStart: '{{',\n variableEnd: '}}',\n },\n });\n compatEnv.addFilter('jsonify', compatEnv.getFilter('dump'));\n\n const handleFunctionResult = (value) => {\n return value === '' ? undefined : JSON.parse(value);\n };\n for (const name of JSON.parse(availableTemplateFilters)) {\n env.addFilter(name, (...args) => handleFunctionResult(callFilter(name, args)));\n }\n for (const [name, value] of Object.entries(JSON.parse(availableTemplateGlobals))) {\n env.addGlobal(name, value);\n }\n for (const name of JSON.parse(availableTemplateCallbacks)) {\n env.addGlobal(name, (...args) => handleFunctionResult(callGlobal(name, args)));\n }\n\n let uninstallCompat = undefined;\n\n function render(str, values) {\n try {\n if (uninstallCompat) {\n uninstallCompat();\n uninstallCompat = undefined;\n }\n return env.renderString(str, JSON.parse(values));\n } catch (error) {\n // Make sure errors don't leak anything\n throw new Error(String(error.message));\n }\n }\n\n function renderCompat(str, values) {\n try {\n if (!uninstallCompat) {\n uninstallCompat = module.exports.installJinjaCompat();\n }\n return compatEnv.renderString(str, JSON.parse(values));\n } catch (error) {\n // Make sure errors don't leak anything\n throw new Error(String(error.message));\n }\n }\n\n return { render, renderCompat };\n})();\n`;\n\n/**\n * @public\n * @deprecated Import from `@backstage/plugin-scaffolder-node` instead.\n */\nexport type TemplateFilter = _TemplateFilter;\n\n/**\n * @public\n * @deprecated Import from `@backstage/plugin-scaffolder-node` instead.\n */\nexport type TemplateGlobal = _TemplateGlobal;\n\ninterface SecureTemplaterOptions {\n /* Enables jinja compatibility and the \"jsonify\" filter */\n cookiecutterCompat?: boolean;\n /* Extra user-provided nunjucks filters */\n templateFilters?: Record<string, TemplateFilter>;\n /* Extra user-provided nunjucks globals */\n templateGlobals?: Record<string, TemplateGlobal>;\n nunjucksConfigs?: { trimBlocks?: boolean; lstripBlocks?: boolean };\n}\n\nexport type SecureTemplateRenderer = (\n template: string,\n values: unknown,\n) => string;\n\nexport class SecureTemplater {\n static async loadRenderer(options: SecureTemplaterOptions = {}) {\n const {\n cookiecutterCompat,\n templateFilters = {},\n templateGlobals = {},\n nunjucksConfigs = {},\n } = options;\n\n const nodeVersion = getMajorNodeVersion();\n if (nodeVersion >= 20 && !isNoNodeSnapshotOptionProvided()) {\n throw new Error(\n `When using Node.js version 20 or newer, the scaffolder backend plugin requires that it be started with the --no-node-snapshot option. \n Please make sure that you have NODE_OPTIONS=--no-node-snapshot in your environment.`,\n );\n }\n\n const isolate = new Isolate({ memoryLimit: 128 });\n const context = await isolate.createContext();\n const contextGlobal = context.global;\n\n const nunjucksSource = await fs.readFile(\n resolvePackagePath(\n '@backstage/plugin-scaffolder-backend',\n 'assets/nunjucks.js.txt',\n ),\n 'utf-8',\n );\n\n const nunjucksScript = await isolate.compileScript(\n mkScript(nunjucksSource),\n );\n\n await contextGlobal.set('nunjucksConfigs', JSON.stringify(nunjucksConfigs));\n\n const availableFilters = Object.keys(templateFilters);\n\n await contextGlobal.set(\n 'availableTemplateFilters',\n JSON.stringify(availableFilters),\n );\n\n const globalCallbacks = [];\n const globalValues: Record<string, unknown> = {};\n for (const [name, value] of Object.entries(templateGlobals)) {\n if (typeof value === 'function') {\n globalCallbacks.push(name);\n } else {\n globalValues[name] = value;\n }\n }\n\n await contextGlobal.set(\n 'availableTemplateGlobals',\n JSON.stringify(globalValues),\n );\n await contextGlobal.set(\n 'availableTemplateCallbacks',\n JSON.stringify(globalCallbacks),\n );\n\n await contextGlobal.set(\n 'callFilter',\n (filterName: string, args: JsonValue[]) => {\n if (!Object.hasOwn(templateFilters, filterName)) {\n return '';\n }\n const [input, ...rest] = args;\n const rz = templateFilters[filterName](input, ...rest);\n return rz === undefined ? '' : JSON.stringify(rz);\n },\n );\n\n await contextGlobal.set(\n 'callGlobal',\n (globalName: string, args: JsonValue[]) => {\n if (!Object.hasOwn(templateGlobals, globalName)) {\n return '';\n }\n const global = templateGlobals[globalName];\n if (typeof global !== 'function') {\n return '';\n }\n const rz = global(...args);\n return rz === undefined ? '' : JSON.stringify(rz);\n },\n );\n\n await nunjucksScript.run(context);\n\n const render: SecureTemplateRenderer = (template, values) => {\n if (!context) {\n throw new Error('SecureTemplater has not been initialized');\n }\n\n contextGlobal.setSync('templateStr', String(template));\n contextGlobal.setSync('templateValues', JSON.stringify(values));\n\n if (cookiecutterCompat) {\n return context.evalSync(`renderCompat(templateStr, templateValues)`);\n }\n\n return context.evalSync(`render(templateStr, templateValues)`);\n };\n return render;\n }\n}\n"],"names":["getMajorNodeVersion","isNoNodeSnapshotOptionProvided","Isolate","fs","resolvePackagePath"],"mappings":"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"}
@@ -4,11 +4,13 @@ var pluginScaffolderNode = require('@backstage/plugin-scaffolder-node');
4
4
  var errors = require('@backstage/errors');
5
5
  var backendPluginApi = require('@backstage/backend-plugin-api');
6
6
  var fs = require('fs-extra');
7
+ var globby = require('globby');
7
8
  var delete_examples = require('./delete.examples.cjs.js');
8
9
 
9
10
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
10
11
 
11
12
  var fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
13
+ var globby__default = /*#__PURE__*/_interopDefaultCompat(globby);
12
14
 
13
15
  const createFilesystemDeleteAction = () => {
14
16
  return pluginScaffolderNode.createTemplateAction({
@@ -37,13 +39,19 @@ const createFilesystemDeleteAction = () => {
37
39
  throw new errors.InputError("files must be an Array");
38
40
  }
39
41
  for (const file of ctx.input.files) {
40
- const filepath = backendPluginApi.resolveSafeChildPath(ctx.workspacePath, file);
41
- try {
42
- await fs__default.default.remove(filepath);
43
- ctx.logger.info(`File ${filepath} deleted successfully`);
44
- } catch (err) {
45
- ctx.logger.error(`Failed to delete file ${filepath}:`, err);
46
- throw err;
42
+ const safeFilepath = backendPluginApi.resolveSafeChildPath(ctx.workspacePath, file);
43
+ const resolvedPaths = await globby__default.default(safeFilepath, {
44
+ cwd: ctx.workspacePath,
45
+ absolute: true
46
+ });
47
+ for (const filepath of resolvedPaths) {
48
+ try {
49
+ await fs__default.default.remove(filepath);
50
+ ctx.logger.info(`File ${filepath} deleted successfully`);
51
+ } catch (err) {
52
+ ctx.logger.error(`Failed to delete file ${filepath}:`, err);
53
+ throw err;
54
+ }
47
55
  }
48
56
  }
49
57
  }
@@ -1 +1 @@
1
- {"version":3,"file":"delete.cjs.js","sources":["../../../../../src/scaffolder/actions/builtin/filesystem/delete.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 { createTemplateAction } from '@backstage/plugin-scaffolder-node';\nimport { InputError } from '@backstage/errors';\nimport { resolveSafeChildPath } from '@backstage/backend-plugin-api';\nimport fs from 'fs-extra';\nimport { examples } from './delete.examples';\n\n/**\n * Creates new action that enables deletion of files and directories in the workspace.\n * @public\n */\nexport const createFilesystemDeleteAction = () => {\n return createTemplateAction<{ files: string[] }>({\n id: 'fs:delete',\n description: 'Deletes files and directories from the workspace',\n examples,\n schema: {\n input: {\n required: ['files'],\n type: 'object',\n properties: {\n files: {\n title: 'Files',\n description: 'A list of files and directories that will be deleted',\n type: 'array',\n items: {\n type: 'string',\n },\n },\n },\n },\n },\n supportsDryRun: true,\n async handler(ctx) {\n if (!Array.isArray(ctx.input?.files)) {\n throw new InputError('files must be an Array');\n }\n\n for (const file of ctx.input.files) {\n const filepath = resolveSafeChildPath(ctx.workspacePath, file);\n\n try {\n await fs.remove(filepath);\n ctx.logger.info(`File ${filepath} deleted successfully`);\n } catch (err) {\n ctx.logger.error(`Failed to delete file ${filepath}:`, err);\n throw err;\n }\n }\n },\n });\n};\n"],"names":["createTemplateAction","examples","InputError","resolveSafeChildPath","fs"],"mappings":";;;;;;;;;;;;AA0BO,MAAM,+BAA+B,MAAM;AAChD,EAAA,OAAOA,yCAA0C,CAAA;AAAA,IAC/C,EAAI,EAAA,WAAA;AAAA,IACJ,WAAa,EAAA,kDAAA;AAAA,cACbC,wBAAA;AAAA,IACA,MAAQ,EAAA;AAAA,MACN,KAAO,EAAA;AAAA,QACL,QAAA,EAAU,CAAC,OAAO,CAAA;AAAA,QAClB,IAAM,EAAA,QAAA;AAAA,QACN,UAAY,EAAA;AAAA,UACV,KAAO,EAAA;AAAA,YACL,KAAO,EAAA,OAAA;AAAA,YACP,WAAa,EAAA,sDAAA;AAAA,YACb,IAAM,EAAA,OAAA;AAAA,YACN,KAAO,EAAA;AAAA,cACL,IAAM,EAAA;AAAA;AACR;AACF;AACF;AACF,KACF;AAAA,IACA,cAAgB,EAAA,IAAA;AAAA,IAChB,MAAM,QAAQ,GAAK,EAAA;AACjB,MAAA,IAAI,CAAC,KAAM,CAAA,OAAA,CAAQ,GAAI,CAAA,KAAA,EAAO,KAAK,CAAG,EAAA;AACpC,QAAM,MAAA,IAAIC,kBAAW,wBAAwB,CAAA;AAAA;AAG/C,MAAW,KAAA,MAAA,IAAA,IAAQ,GAAI,CAAA,KAAA,CAAM,KAAO,EAAA;AAClC,QAAA,MAAM,QAAW,GAAAC,qCAAA,CAAqB,GAAI,CAAA,aAAA,EAAe,IAAI,CAAA;AAE7D,QAAI,IAAA;AACF,UAAM,MAAAC,mBAAA,CAAG,OAAO,QAAQ,CAAA;AACxB,UAAA,GAAA,CAAI,MAAO,CAAA,IAAA,CAAK,CAAQ,KAAA,EAAA,QAAQ,CAAuB,qBAAA,CAAA,CAAA;AAAA,iBAChD,GAAK,EAAA;AACZ,UAAA,GAAA,CAAI,MAAO,CAAA,KAAA,CAAM,CAAyB,sBAAA,EAAA,QAAQ,KAAK,GAAG,CAAA;AAC1D,UAAM,MAAA,GAAA;AAAA;AACR;AACF;AACF,GACD,CAAA;AACH;;;;"}
1
+ {"version":3,"file":"delete.cjs.js","sources":["../../../../../src/scaffolder/actions/builtin/filesystem/delete.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 { createTemplateAction } from '@backstage/plugin-scaffolder-node';\nimport { InputError } from '@backstage/errors';\nimport { resolveSafeChildPath } from '@backstage/backend-plugin-api';\nimport fs from 'fs-extra';\nimport globby from 'globby';\nimport { examples } from './delete.examples';\n\n/**\n * Creates new action that enables deletion of files and directories in the workspace.\n * @public\n */\nexport const createFilesystemDeleteAction = () => {\n return createTemplateAction<{ files: string[] }>({\n id: 'fs:delete',\n description: 'Deletes files and directories from the workspace',\n examples,\n schema: {\n input: {\n required: ['files'],\n type: 'object',\n properties: {\n files: {\n title: 'Files',\n description: 'A list of files and directories that will be deleted',\n type: 'array',\n items: {\n type: 'string',\n },\n },\n },\n },\n },\n supportsDryRun: true,\n async handler(ctx) {\n if (!Array.isArray(ctx.input?.files)) {\n throw new InputError('files must be an Array');\n }\n\n for (const file of ctx.input.files) {\n const safeFilepath = resolveSafeChildPath(ctx.workspacePath, file);\n const resolvedPaths = await globby(safeFilepath, {\n cwd: ctx.workspacePath,\n absolute: true,\n });\n\n for (const filepath of resolvedPaths) {\n try {\n await fs.remove(filepath);\n ctx.logger.info(`File ${filepath} deleted successfully`);\n } catch (err) {\n ctx.logger.error(`Failed to delete file ${filepath}:`, err);\n throw err;\n }\n }\n }\n },\n });\n};\n"],"names":["createTemplateAction","examples","InputError","resolveSafeChildPath","globby","fs"],"mappings":";;;;;;;;;;;;;;AA2BO,MAAM,+BAA+B,MAAM;AAChD,EAAA,OAAOA,yCAA0C,CAAA;AAAA,IAC/C,EAAI,EAAA,WAAA;AAAA,IACJ,WAAa,EAAA,kDAAA;AAAA,cACbC,wBAAA;AAAA,IACA,MAAQ,EAAA;AAAA,MACN,KAAO,EAAA;AAAA,QACL,QAAA,EAAU,CAAC,OAAO,CAAA;AAAA,QAClB,IAAM,EAAA,QAAA;AAAA,QACN,UAAY,EAAA;AAAA,UACV,KAAO,EAAA;AAAA,YACL,KAAO,EAAA,OAAA;AAAA,YACP,WAAa,EAAA,sDAAA;AAAA,YACb,IAAM,EAAA,OAAA;AAAA,YACN,KAAO,EAAA;AAAA,cACL,IAAM,EAAA;AAAA;AACR;AACF;AACF;AACF,KACF;AAAA,IACA,cAAgB,EAAA,IAAA;AAAA,IAChB,MAAM,QAAQ,GAAK,EAAA;AACjB,MAAA,IAAI,CAAC,KAAM,CAAA,OAAA,CAAQ,GAAI,CAAA,KAAA,EAAO,KAAK,CAAG,EAAA;AACpC,QAAM,MAAA,IAAIC,kBAAW,wBAAwB,CAAA;AAAA;AAG/C,MAAW,KAAA,MAAA,IAAA,IAAQ,GAAI,CAAA,KAAA,CAAM,KAAO,EAAA;AAClC,QAAA,MAAM,YAAe,GAAAC,qCAAA,CAAqB,GAAI,CAAA,aAAA,EAAe,IAAI,CAAA;AACjE,QAAM,MAAA,aAAA,GAAgB,MAAMC,uBAAA,CAAO,YAAc,EAAA;AAAA,UAC/C,KAAK,GAAI,CAAA,aAAA;AAAA,UACT,QAAU,EAAA;AAAA,SACX,CAAA;AAED,QAAA,KAAA,MAAW,YAAY,aAAe,EAAA;AACpC,UAAI,IAAA;AACF,YAAM,MAAAC,mBAAA,CAAG,OAAO,QAAQ,CAAA;AACxB,YAAA,GAAA,CAAI,MAAO,CAAA,IAAA,CAAK,CAAQ,KAAA,EAAA,QAAQ,CAAuB,qBAAA,CAAA,CAAA;AAAA,mBAChD,GAAK,EAAA;AACZ,YAAA,GAAA,CAAI,MAAO,CAAA,KAAA,CAAM,CAAyB,sBAAA,EAAA,QAAQ,KAAK,GAAG,CAAA;AAC1D,YAAM,MAAA,GAAA;AAAA;AACR;AACF;AACF;AACF,GACD,CAAA;AACH;;;;"}
@@ -37,6 +37,21 @@ const examples = [
37
37
  }
38
38
  ]
39
39
  })
40
+ },
41
+ {
42
+ description: "Delete files with wildcard",
43
+ example: yaml__namespace.stringify({
44
+ steps: [
45
+ {
46
+ action: "fs:delete",
47
+ id: "deleteFiles",
48
+ name: "Delete files",
49
+ input: {
50
+ files: ["*.txt"]
51
+ }
52
+ }
53
+ ]
54
+ })
40
55
  }
41
56
  ];
42
57
 
@@ -1 +1 @@
1
- {"version":3,"file":"delete.examples.cjs.js","sources":["../../../../../src/scaffolder/actions/builtin/filesystem/delete.examples.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 { TemplateExample } from '@backstage/plugin-scaffolder-node';\nimport * as yaml from 'yaml';\n\nexport const examples: TemplateExample[] = [\n {\n description: 'Delete specified files',\n example: yaml.stringify({\n steps: [\n {\n action: 'fs:delete',\n id: 'deleteFiles',\n name: 'Delete files',\n input: {\n files: ['file1.txt', 'file2.txt'],\n },\n },\n ],\n }),\n },\n];\n"],"names":["yaml"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAmBO,MAAM,QAA8B,GAAA;AAAA,EACzC;AAAA,IACE,WAAa,EAAA,wBAAA;AAAA,IACb,OAAA,EAASA,gBAAK,SAAU,CAAA;AAAA,MACtB,KAAO,EAAA;AAAA,QACL;AAAA,UACE,MAAQ,EAAA,WAAA;AAAA,UACR,EAAI,EAAA,aAAA;AAAA,UACJ,IAAM,EAAA,cAAA;AAAA,UACN,KAAO,EAAA;AAAA,YACL,KAAA,EAAO,CAAC,WAAA,EAAa,WAAW;AAAA;AAClC;AACF;AACF,KACD;AAAA;AAEL;;;;"}
1
+ {"version":3,"file":"delete.examples.cjs.js","sources":["../../../../../src/scaffolder/actions/builtin/filesystem/delete.examples.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 { TemplateExample } from '@backstage/plugin-scaffolder-node';\nimport * as yaml from 'yaml';\n\nexport const examples: TemplateExample[] = [\n {\n description: 'Delete specified files',\n example: yaml.stringify({\n steps: [\n {\n action: 'fs:delete',\n id: 'deleteFiles',\n name: 'Delete files',\n input: {\n files: ['file1.txt', 'file2.txt'],\n },\n },\n ],\n }),\n },\n {\n description: 'Delete files with wildcard',\n example: yaml.stringify({\n steps: [\n {\n action: 'fs:delete',\n id: 'deleteFiles',\n name: 'Delete files',\n input: {\n files: ['*.txt'],\n },\n },\n ],\n }),\n },\n];\n"],"names":["yaml"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAmBO,MAAM,QAA8B,GAAA;AAAA,EACzC;AAAA,IACE,WAAa,EAAA,wBAAA;AAAA,IACb,OAAA,EAASA,gBAAK,SAAU,CAAA;AAAA,MACtB,KAAO,EAAA;AAAA,QACL;AAAA,UACE,MAAQ,EAAA,WAAA;AAAA,UACR,EAAI,EAAA,aAAA;AAAA,UACJ,IAAM,EAAA,cAAA;AAAA,UACN,KAAO,EAAA;AAAA,YACL,KAAA,EAAO,CAAC,WAAA,EAAa,WAAW;AAAA;AAClC;AACF;AACF,KACD;AAAA,GACH;AAAA,EACA;AAAA,IACE,WAAa,EAAA,4BAAA;AAAA,IACb,OAAA,EAASA,gBAAK,SAAU,CAAA;AAAA,MACtB,KAAO,EAAA;AAAA,QACL;AAAA,UACE,MAAQ,EAAA,WAAA;AAAA,UACR,EAAI,EAAA,aAAA;AAAA,UACJ,IAAM,EAAA,cAAA;AAAA,UACN,KAAO,EAAA;AAAA,YACL,KAAA,EAAO,CAAC,OAAO;AAAA;AACjB;AACF;AACF,KACD;AAAA;AAEL;;;;"}
@@ -193,6 +193,20 @@ async function createRouter(options) {
193
193
  taskBroker = options.taskBroker;
194
194
  }
195
195
  const actionRegistry = new TemplateActionRegistry.TemplateActionRegistry();
196
+ const templateExtensions = {
197
+ additionalTemplateFilters: Array.isArray(additionalTemplateFilters) ? Object.fromEntries(
198
+ additionalTemplateFilters.map((f) => [
199
+ f.id,
200
+ f.filter
201
+ ])
202
+ ) : additionalTemplateFilters,
203
+ additionalTemplateGlobals: Array.isArray(additionalTemplateGlobals) ? Object.fromEntries(
204
+ additionalTemplateGlobals.map((g) => [
205
+ g.id,
206
+ "value" in g ? g.value : g.fn
207
+ ])
208
+ ) : additionalTemplateGlobals
209
+ };
196
210
  const workers = [];
197
211
  if (concurrentTasksLimit !== 0) {
198
212
  const gracefulShutdown = config.getOptionalBoolean(
@@ -206,11 +220,10 @@ async function createRouter(options) {
206
220
  logger,
207
221
  auditor,
208
222
  workingDirectory,
209
- additionalTemplateFilters,
210
- additionalTemplateGlobals,
211
223
  concurrentTasksLimit,
212
224
  permissions,
213
- gracefulShutdown
225
+ gracefulShutdown,
226
+ ...templateExtensions
214
227
  });
215
228
  workers.push(worker);
216
229
  }
@@ -220,9 +233,8 @@ async function createRouter(options) {
220
233
  catalogClient,
221
234
  reader,
222
235
  config,
223
- additionalTemplateFilters,
224
- additionalTemplateGlobals,
225
- auth
236
+ auth,
237
+ ...templateExtensions
226
238
  });
227
239
  actionsToRegister.forEach((action) => actionRegistry.register(action));
228
240
  const launchWorkers = () => workers.forEach((worker) => worker.start());
@@ -241,9 +253,8 @@ async function createRouter(options) {
241
253
  logger,
242
254
  auditor,
243
255
  workingDirectory,
244
- additionalTemplateFilters,
245
- additionalTemplateGlobals,
246
- permissions
256
+ permissions,
257
+ ...templateExtensions
247
258
  });
248
259
  const templateRules = Object.values(
249
260
  rules.scaffolderTemplateRules
@@ -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 {\n AuditorService,\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 { 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 {\n IdentityApi,\n IdentityApiGetIdentityRequest,\n} from '@backstage/plugin-auth-node';\nimport { EventsService } from '@backstage/plugin-events-node';\nimport { PermissionRuleParams } from '@backstage/plugin-permission-common';\nimport {\n createConditionAuthorizer,\n createPermissionIntegrationRouter,\n PermissionRule,\n} from '@backstage/plugin-permission-node';\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 scaffolderPermissions,\n scaffolderTemplatePermissions,\n taskCancelPermission,\n taskCreatePermission,\n taskReadPermission,\n templateParameterReadPermission,\n templateStepReadPermission,\n} from '@backstage/plugin-scaffolder-common/alpha';\nimport {\n TaskBroker,\n TaskStatus,\n TemplateAction,\n TemplateFilter,\n TemplateGlobal,\n} from '@backstage/plugin-scaffolder-node';\nimport {\n AutocompleteHandler,\n WorkspaceProvider,\n} from '@backstage/plugin-scaffolder-node/alpha';\nimport { HumanDuration, JsonObject, JsonValue } from '@backstage/types';\nimport express from 'express';\nimport Router from 'express-promise-router';\nimport { validate } from 'jsonschema';\nimport { Duration } from 'luxon';\nimport { pathToFileURL } from 'url';\nimport { v4 as uuid } from 'uuid';\nimport { Logger } from 'winston';\nimport { z } from 'zod';\nimport {\n createBuiltinActions,\n DatabaseTaskStore,\n TaskWorker,\n TemplateActionRegistry,\n} from '../scaffolder';\nimport { createDryRunner } from '../scaffolder/dryrun';\nimport { StorageTaskBroker } from '../scaffolder/tasks/StorageTaskBroker';\nimport { InternalTaskSecrets } from '../scaffolder/tasks/types';\nimport { checkPermission } from '../util/checkPermissions';\nimport {\n findTemplate,\n getEntityBaseUrl,\n getWorkingDirectory,\n parseNumberParam,\n parseStringsParam,\n} from './helpers';\nimport { scaffolderActionRules, scaffolderTemplateRules } from './rules';\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 auditor?: AuditorService;\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 auditor,\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 auditor,\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 const gracefulShutdown = config.getOptionalBoolean(\n 'scaffolder.EXPERIMENTAL_gracefulShutdown',\n );\n\n for (let i = 0; i < (taskWorkers || 1); i++) {\n const worker = await TaskWorker.create({\n taskBroker,\n actionRegistry,\n integrations,\n logger,\n auditor,\n workingDirectory,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n concurrentTasksLimit,\n permissions,\n gracefulShutdown,\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 = async () => {\n await Promise.allSettled(workers.map(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 auditor,\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: scaffolderPermissions,\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 requestedTemplateRef = `${req.params.kind}:${req.params.namespace}/${req.params.name}`;\n\n const auditorEvent = await auditor?.createEvent({\n eventId: 'template-parameter-schema',\n request: req,\n meta: { templateRef: requestedTemplateRef },\n });\n\n try {\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 const templateRef = `${template.kind}:${\n template.metadata.namespace || 'default'\n }/${template.metadata.name}`;\n\n await auditorEvent?.success({ meta: { templateRef: templateRef } });\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 } catch (err) {\n await auditorEvent?.fail({ error: err });\n throw err;\n }\n },\n )\n .get('/v2/actions', async (req, res) => {\n const auditorEvent = await auditor?.createEvent({\n eventId: 'action-fetch',\n request: req,\n });\n\n try {\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\n await auditorEvent?.success();\n\n res.json(actionsList);\n } catch (err) {\n await auditorEvent?.fail({ error: err });\n throw err;\n }\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 auditorEvent = await auditor?.createEvent({\n eventId: 'task',\n severityLevel: 'medium',\n request: req,\n meta: {\n actionType: 'create',\n templateRef: templateRef,\n },\n });\n\n try {\n const credentials = await httpAuth.credentials(req);\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 await auditorEvent?.fail({\n // TODO(Rugvip): Seems like there aren't proper types for AggregateError yet\n error: (AggregateError as any)(\n result.errors,\n 'Could not create entity',\n ),\n });\n\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 await auditorEvent?.success({ meta: { taskId: result.taskId } });\n\n res.status(201).json({ id: result.taskId });\n } catch (err) {\n await auditorEvent?.fail({ error: err });\n throw err;\n }\n })\n .get('/v2/tasks', async (req, res) => {\n const auditorEvent = await auditor?.createEvent({\n eventId: 'task',\n request: req,\n meta: {\n actionType: 'list',\n },\n });\n\n try {\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 await auditorEvent?.success();\n\n res.status(200).json(tasks);\n } catch (err) {\n await auditorEvent?.fail({ error: err });\n throw err;\n }\n })\n .get('/v2/tasks/:taskId', async (req, res) => {\n const { taskId } = req.params;\n\n const auditorEvent = await auditor?.createEvent({\n eventId: 'task',\n request: req,\n meta: {\n actionType: 'get',\n taskId: taskId,\n },\n });\n\n try {\n const credentials = await httpAuth.credentials(req);\n await checkPermission({\n credentials,\n permissions: [taskReadPermission],\n permissionService: permissions,\n });\n\n const task = await taskBroker.get(taskId);\n if (!task) {\n throw new NotFoundError(`Task with id ${taskId} does not exist`);\n }\n\n await auditorEvent?.success();\n\n // Do not disclose secrets\n delete task.secrets;\n res.status(200).json(task);\n } catch (err) {\n await auditorEvent?.fail({ error: err });\n throw err;\n }\n })\n .post('/v2/tasks/:taskId/cancel', async (req, res) => {\n const { taskId } = req.params;\n\n const auditorEvent = await auditor?.createEvent({\n eventId: 'task',\n severityLevel: 'medium',\n request: req,\n meta: {\n actionType: 'cancel',\n taskId: taskId,\n },\n });\n\n try {\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 await taskBroker.cancel?.(taskId);\n\n await auditorEvent?.success();\n\n res.status(200).json({ status: 'cancelled' });\n } catch (err) {\n await auditorEvent?.fail({ error: err });\n throw err;\n }\n })\n .post('/v2/tasks/:taskId/retry', async (req, res) => {\n const { taskId } = req.params;\n\n const auditorEvent = await auditor?.createEvent({\n eventId: 'task',\n severityLevel: 'medium',\n request: req,\n meta: {\n actionType: 'retry',\n taskId: taskId,\n },\n });\n\n try {\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 await auditorEvent?.success();\n\n await taskBroker.retry?.(taskId);\n res.status(201).json({ id: taskId });\n } catch (err) {\n await auditorEvent?.fail({ error: err });\n throw err;\n }\n })\n .get('/v2/tasks/:taskId/eventstream', async (req, res) => {\n const { taskId } = req.params;\n\n const auditorEvent = await auditor?.createEvent({\n eventId: 'task',\n request: req,\n meta: {\n actionType: 'stream',\n taskId: taskId,\n },\n });\n\n try {\n const credentials = await httpAuth.credentials(req);\n await checkPermission({\n credentials,\n permissions: [taskReadPermission],\n permissionService: permissions,\n });\n\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: async error => {\n logger.error(\n `Received error from event stream when observing taskId '${taskId}', ${error}`,\n );\n await auditorEvent?.fail({ error: error });\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', async () => {\n subscription.unsubscribe();\n logger.debug(`Event stream observing taskId '${taskId}' closed`);\n await auditorEvent?.success();\n });\n } catch (err) {\n await auditorEvent?.fail({ error: err });\n throw err;\n }\n })\n .get('/v2/tasks/:taskId/events', async (req, res) => {\n const { taskId } = req.params;\n\n const auditorEvent = await auditor?.createEvent({\n eventId: 'task',\n request: req,\n meta: {\n actionType: 'events',\n taskId: taskId,\n },\n });\n\n try {\n const credentials = await httpAuth.credentials(req);\n await checkPermission({\n credentials,\n permissions: [taskReadPermission],\n permissionService: permissions,\n });\n\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: async error => {\n logger.error(\n `Received error from event stream when observing taskId '${taskId}', ${error}`,\n );\n await auditorEvent?.fail({ error: error });\n },\n next: async ({ events }) => {\n clearTimeout(timeout);\n subscription.unsubscribe();\n await auditorEvent?.success();\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 } catch (err) {\n await auditorEvent?.fail({ error: err });\n throw err;\n }\n })\n .post('/v2/dry-run', async (req, res) => {\n const auditorEvent = await auditor?.createEvent({\n eventId: 'task',\n request: req,\n meta: {\n actionType: 'dry-run',\n },\n });\n\n try {\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 const templateRef: string = `${template.kind}:${\n template.metadata.namespace || 'default'\n }/${template.metadata.name}`;\n\n for (const parameters of [template.spec.parameters ?? []].flat()) {\n const result = validate(body.values, parameters);\n if (!result.valid) {\n await auditorEvent?.fail({\n // TODO(Rugvip): Seems like there aren't proper types for AggregateError yet\n error: (AggregateError as any)(\n result.errors,\n 'Could not execute dry run',\n ),\n meta: {\n templateRef: templateRef,\n parameters: template.spec.parameters,\n },\n });\n\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 const templateInfo = {\n entityRef: 'template:default/dry-run',\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 await auditorEvent?.success({\n meta: {\n templateRef: templateRef,\n parameters: template.spec.parameters,\n },\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 } catch (err) {\n await auditorEvent?.fail({ error: err });\n throw err;\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","scaffolderPermissions","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 {\n AuditorService,\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 { 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 {\n IdentityApi,\n IdentityApiGetIdentityRequest,\n} from '@backstage/plugin-auth-node';\nimport { EventsService } from '@backstage/plugin-events-node';\nimport { PermissionRuleParams } from '@backstage/plugin-permission-common';\nimport {\n createConditionAuthorizer,\n createPermissionIntegrationRouter,\n PermissionRule,\n} from '@backstage/plugin-permission-node';\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 scaffolderPermissions,\n scaffolderTemplatePermissions,\n taskCancelPermission,\n taskCreatePermission,\n taskReadPermission,\n templateParameterReadPermission,\n templateStepReadPermission,\n} from '@backstage/plugin-scaffolder-common/alpha';\nimport {\n TaskBroker,\n TaskStatus,\n TemplateAction,\n TemplateFilter,\n TemplateGlobal,\n} from '@backstage/plugin-scaffolder-node';\nimport {\n AutocompleteHandler,\n CreatedTemplateFilter,\n CreatedTemplateGlobal,\n WorkspaceProvider,\n} from '@backstage/plugin-scaffolder-node/alpha';\nimport { HumanDuration, JsonObject, JsonValue } from '@backstage/types';\nimport express from 'express';\nimport Router from 'express-promise-router';\nimport { validate } from 'jsonschema';\nimport { Duration } from 'luxon';\nimport { pathToFileURL } from 'url';\nimport { v4 as uuid } from 'uuid';\nimport { Logger } from 'winston';\nimport { z } from 'zod';\nimport {\n createBuiltinActions,\n DatabaseTaskStore,\n TaskWorker,\n TemplateActionRegistry,\n} from '../scaffolder';\nimport { createDryRunner } from '../scaffolder/dryrun';\nimport { StorageTaskBroker } from '../scaffolder/tasks/StorageTaskBroker';\nimport { InternalTaskSecrets } from '../scaffolder/tasks/types';\nimport { checkPermission } from '../util/checkPermissions';\nimport {\n findTemplate,\n getEntityBaseUrl,\n getWorkingDirectory,\n parseNumberParam,\n parseStringsParam,\n} from './helpers';\nimport { scaffolderActionRules, scaffolderTemplateRules } from './rules';\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?:\n | Record<string, TemplateFilter>\n | CreatedTemplateFilter[];\n additionalTemplateGlobals?:\n | Record<string, TemplateGlobal>\n | CreatedTemplateGlobal[];\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 auditor?: AuditorService;\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 auditor,\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 auditor,\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 const templateExtensions = {\n additionalTemplateFilters: Array.isArray(additionalTemplateFilters)\n ? Object.fromEntries(\n additionalTemplateFilters.map(f => [\n f.id,\n f.filter as TemplateFilter,\n ]),\n )\n : additionalTemplateFilters,\n additionalTemplateGlobals: Array.isArray(additionalTemplateGlobals)\n ? Object.fromEntries(\n additionalTemplateGlobals.map(g => [\n g.id,\n ('value' in g ? g.value : g.fn) as TemplateGlobal,\n ]),\n )\n : additionalTemplateGlobals,\n };\n\n const workers: TaskWorker[] = [];\n if (concurrentTasksLimit !== 0) {\n const gracefulShutdown = config.getOptionalBoolean(\n 'scaffolder.EXPERIMENTAL_gracefulShutdown',\n );\n\n for (let i = 0; i < (taskWorkers || 1); i++) {\n const worker = await TaskWorker.create({\n taskBroker,\n actionRegistry,\n integrations,\n logger,\n auditor,\n workingDirectory,\n concurrentTasksLimit,\n permissions,\n gracefulShutdown,\n ...templateExtensions,\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 auth,\n ...templateExtensions,\n });\n\n actionsToRegister.forEach(action => actionRegistry.register(action));\n\n const launchWorkers = () => workers.forEach(worker => worker.start());\n\n const shutdownWorkers = async () => {\n await Promise.allSettled(workers.map(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 auditor,\n workingDirectory,\n permissions,\n ...templateExtensions,\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: scaffolderPermissions,\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 requestedTemplateRef = `${req.params.kind}:${req.params.namespace}/${req.params.name}`;\n\n const auditorEvent = await auditor?.createEvent({\n eventId: 'template-parameter-schema',\n request: req,\n meta: { templateRef: requestedTemplateRef },\n });\n\n try {\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 const templateRef = `${template.kind}:${\n template.metadata.namespace || 'default'\n }/${template.metadata.name}`;\n\n await auditorEvent?.success({ meta: { templateRef: templateRef } });\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 } catch (err) {\n await auditorEvent?.fail({ error: err });\n throw err;\n }\n },\n )\n .get('/v2/actions', async (req, res) => {\n const auditorEvent = await auditor?.createEvent({\n eventId: 'action-fetch',\n request: req,\n });\n\n try {\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\n await auditorEvent?.success();\n\n res.json(actionsList);\n } catch (err) {\n await auditorEvent?.fail({ error: err });\n throw err;\n }\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 auditorEvent = await auditor?.createEvent({\n eventId: 'task',\n severityLevel: 'medium',\n request: req,\n meta: {\n actionType: 'create',\n templateRef: templateRef,\n },\n });\n\n try {\n const credentials = await httpAuth.credentials(req);\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 await auditorEvent?.fail({\n // TODO(Rugvip): Seems like there aren't proper types for AggregateError yet\n error: (AggregateError as any)(\n result.errors,\n 'Could not create entity',\n ),\n });\n\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 await auditorEvent?.success({ meta: { taskId: result.taskId } });\n\n res.status(201).json({ id: result.taskId });\n } catch (err) {\n await auditorEvent?.fail({ error: err });\n throw err;\n }\n })\n .get('/v2/tasks', async (req, res) => {\n const auditorEvent = await auditor?.createEvent({\n eventId: 'task',\n request: req,\n meta: {\n actionType: 'list',\n },\n });\n\n try {\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 await auditorEvent?.success();\n\n res.status(200).json(tasks);\n } catch (err) {\n await auditorEvent?.fail({ error: err });\n throw err;\n }\n })\n .get('/v2/tasks/:taskId', async (req, res) => {\n const { taskId } = req.params;\n\n const auditorEvent = await auditor?.createEvent({\n eventId: 'task',\n request: req,\n meta: {\n actionType: 'get',\n taskId: taskId,\n },\n });\n\n try {\n const credentials = await httpAuth.credentials(req);\n await checkPermission({\n credentials,\n permissions: [taskReadPermission],\n permissionService: permissions,\n });\n\n const task = await taskBroker.get(taskId);\n if (!task) {\n throw new NotFoundError(`Task with id ${taskId} does not exist`);\n }\n\n await auditorEvent?.success();\n\n // Do not disclose secrets\n delete task.secrets;\n res.status(200).json(task);\n } catch (err) {\n await auditorEvent?.fail({ error: err });\n throw err;\n }\n })\n .post('/v2/tasks/:taskId/cancel', async (req, res) => {\n const { taskId } = req.params;\n\n const auditorEvent = await auditor?.createEvent({\n eventId: 'task',\n severityLevel: 'medium',\n request: req,\n meta: {\n actionType: 'cancel',\n taskId: taskId,\n },\n });\n\n try {\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 await taskBroker.cancel?.(taskId);\n\n await auditorEvent?.success();\n\n res.status(200).json({ status: 'cancelled' });\n } catch (err) {\n await auditorEvent?.fail({ error: err });\n throw err;\n }\n })\n .post('/v2/tasks/:taskId/retry', async (req, res) => {\n const { taskId } = req.params;\n\n const auditorEvent = await auditor?.createEvent({\n eventId: 'task',\n severityLevel: 'medium',\n request: req,\n meta: {\n actionType: 'retry',\n taskId: taskId,\n },\n });\n\n try {\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 await auditorEvent?.success();\n\n await taskBroker.retry?.(taskId);\n res.status(201).json({ id: taskId });\n } catch (err) {\n await auditorEvent?.fail({ error: err });\n throw err;\n }\n })\n .get('/v2/tasks/:taskId/eventstream', async (req, res) => {\n const { taskId } = req.params;\n\n const auditorEvent = await auditor?.createEvent({\n eventId: 'task',\n request: req,\n meta: {\n actionType: 'stream',\n taskId: taskId,\n },\n });\n\n try {\n const credentials = await httpAuth.credentials(req);\n await checkPermission({\n credentials,\n permissions: [taskReadPermission],\n permissionService: permissions,\n });\n\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: async error => {\n logger.error(\n `Received error from event stream when observing taskId '${taskId}', ${error}`,\n );\n await auditorEvent?.fail({ error: error });\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', async () => {\n subscription.unsubscribe();\n logger.debug(`Event stream observing taskId '${taskId}' closed`);\n await auditorEvent?.success();\n });\n } catch (err) {\n await auditorEvent?.fail({ error: err });\n throw err;\n }\n })\n .get('/v2/tasks/:taskId/events', async (req, res) => {\n const { taskId } = req.params;\n\n const auditorEvent = await auditor?.createEvent({\n eventId: 'task',\n request: req,\n meta: {\n actionType: 'events',\n taskId: taskId,\n },\n });\n\n try {\n const credentials = await httpAuth.credentials(req);\n await checkPermission({\n credentials,\n permissions: [taskReadPermission],\n permissionService: permissions,\n });\n\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: async error => {\n logger.error(\n `Received error from event stream when observing taskId '${taskId}', ${error}`,\n );\n await auditorEvent?.fail({ error: error });\n },\n next: async ({ events }) => {\n clearTimeout(timeout);\n subscription.unsubscribe();\n await auditorEvent?.success();\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 } catch (err) {\n await auditorEvent?.fail({ error: err });\n throw err;\n }\n })\n .post('/v2/dry-run', async (req, res) => {\n const auditorEvent = await auditor?.createEvent({\n eventId: 'task',\n request: req,\n meta: {\n actionType: 'dry-run',\n },\n });\n\n try {\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 const templateRef: string = `${template.kind}:${\n template.metadata.namespace || 'default'\n }/${template.metadata.name}`;\n\n for (const parameters of [template.spec.parameters ?? []].flat()) {\n const result = validate(body.values, parameters);\n if (!result.valid) {\n await auditorEvent?.fail({\n // TODO(Rugvip): Seems like there aren't proper types for AggregateError yet\n error: (AggregateError as any)(\n result.errors,\n 'Could not execute dry run',\n ),\n meta: {\n templateRef: templateRef,\n parameters: template.spec.parameters,\n },\n });\n\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 const templateInfo = {\n entityRef: 'template:default/dry-run',\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 await auditorEvent?.success({\n meta: {\n templateRef: templateRef,\n parameters: template.spec.parameters,\n },\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 } catch (err) {\n await auditorEvent?.fail({ error: err });\n throw err;\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","scaffolderPermissions","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.30.0-next.2",
3
+ "version": "1.30.0",
4
4
  "description": "The Backstage backend plugin that helps you create new things",
5
5
  "backstage": {
6
6
  "role": "backend-plugin",
@@ -76,31 +76,31 @@
76
76
  },
77
77
  "dependencies": {
78
78
  "@backstage/backend-common": "^0.25.0",
79
- "@backstage/backend-defaults": "0.8.0-next.2",
80
- "@backstage/backend-plugin-api": "1.2.0-next.1",
81
- "@backstage/catalog-client": "1.9.1",
82
- "@backstage/catalog-model": "1.7.3",
83
- "@backstage/config": "1.3.2",
84
- "@backstage/errors": "1.2.7",
85
- "@backstage/integration": "1.16.1",
86
- "@backstage/plugin-auth-node": "0.6.0-next.1",
87
- "@backstage/plugin-bitbucket-cloud-common": "0.2.27",
88
- "@backstage/plugin-catalog-backend-module-scaffolder-entity-model": "0.2.5-next.2",
89
- "@backstage/plugin-catalog-node": "1.16.0-next.2",
90
- "@backstage/plugin-events-node": "0.4.8-next.1",
91
- "@backstage/plugin-permission-common": "0.8.4",
92
- "@backstage/plugin-permission-node": "0.8.8-next.1",
93
- "@backstage/plugin-scaffolder-backend-module-azure": "0.2.6-next.1",
94
- "@backstage/plugin-scaffolder-backend-module-bitbucket": "0.3.7-next.1",
95
- "@backstage/plugin-scaffolder-backend-module-bitbucket-cloud": "0.2.6-next.1",
96
- "@backstage/plugin-scaffolder-backend-module-bitbucket-server": "0.2.6-next.1",
97
- "@backstage/plugin-scaffolder-backend-module-gerrit": "0.2.6-next.1",
98
- "@backstage/plugin-scaffolder-backend-module-gitea": "0.2.6-next.1",
99
- "@backstage/plugin-scaffolder-backend-module-github": "0.5.6-next.1",
100
- "@backstage/plugin-scaffolder-backend-module-gitlab": "0.8.0-next.2",
101
- "@backstage/plugin-scaffolder-common": "1.5.9",
102
- "@backstage/plugin-scaffolder-node": "0.7.0-next.1",
103
- "@backstage/types": "1.2.1",
79
+ "@backstage/backend-defaults": "^0.8.0",
80
+ "@backstage/backend-plugin-api": "^1.2.0",
81
+ "@backstage/catalog-client": "^1.9.1",
82
+ "@backstage/catalog-model": "^1.7.3",
83
+ "@backstage/config": "^1.3.2",
84
+ "@backstage/errors": "^1.2.7",
85
+ "@backstage/integration": "^1.16.1",
86
+ "@backstage/plugin-auth-node": "^0.6.0",
87
+ "@backstage/plugin-bitbucket-cloud-common": "^0.2.27",
88
+ "@backstage/plugin-catalog-backend-module-scaffolder-entity-model": "^0.2.5",
89
+ "@backstage/plugin-catalog-node": "^1.16.0",
90
+ "@backstage/plugin-events-node": "^0.4.8",
91
+ "@backstage/plugin-permission-common": "^0.8.4",
92
+ "@backstage/plugin-permission-node": "^0.8.8",
93
+ "@backstage/plugin-scaffolder-backend-module-azure": "^0.2.6",
94
+ "@backstage/plugin-scaffolder-backend-module-bitbucket": "^0.3.7",
95
+ "@backstage/plugin-scaffolder-backend-module-bitbucket-cloud": "^0.2.6",
96
+ "@backstage/plugin-scaffolder-backend-module-bitbucket-server": "^0.2.6",
97
+ "@backstage/plugin-scaffolder-backend-module-gerrit": "^0.2.6",
98
+ "@backstage/plugin-scaffolder-backend-module-gitea": "^0.2.6",
99
+ "@backstage/plugin-scaffolder-backend-module-github": "^0.6.0",
100
+ "@backstage/plugin-scaffolder-backend-module-gitlab": "^0.8.0",
101
+ "@backstage/plugin-scaffolder-common": "^1.5.9",
102
+ "@backstage/plugin-scaffolder-node": "^0.7.0",
103
+ "@backstage/types": "^1.2.1",
104
104
  "@opentelemetry/api": "^1.9.0",
105
105
  "@types/express": "^4.17.6",
106
106
  "@types/luxon": "^3.0.0",
@@ -130,11 +130,11 @@
130
130
  "zod": "^3.22.4"
131
131
  },
132
132
  "devDependencies": {
133
- "@backstage/backend-app-api": "1.2.0-next.2",
134
- "@backstage/backend-defaults": "0.8.0-next.2",
135
- "@backstage/backend-test-utils": "1.3.0-next.2",
136
- "@backstage/cli": "0.30.0-next.2",
137
- "@backstage/plugin-scaffolder-node-test-utils": "0.1.19-next.2",
133
+ "@backstage/backend-app-api": "^1.2.0",
134
+ "@backstage/backend-defaults": "^0.8.0",
135
+ "@backstage/backend-test-utils": "^1.3.0",
136
+ "@backstage/cli": "^0.30.0",
137
+ "@backstage/plugin-scaffolder-node-test-utils": "^0.1.19",
138
138
  "@types/fs-extra": "^11.0.0",
139
139
  "@types/nunjucks": "^3.1.4",
140
140
  "@types/supertest": "^2.0.8",