@backstage/plugin-scaffolder-backend 1.22.9 → 1.23.0-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +38 -0
- package/alpha/package.json +2 -2
- package/config.d.ts +7 -0
- package/dist/alpha.cjs.js +17 -6
- package/dist/alpha.cjs.js.map +1 -1
- package/dist/cjs/{router-BtUx0eIt.cjs.js → router-BpffhBor.cjs.js} +134 -75
- package/dist/cjs/router-BpffhBor.cjs.js.map +1 -0
- package/dist/index.cjs.js +3 -5
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +5 -3
- package/package.json +24 -22
- package/dist/cjs/router-BtUx0eIt.cjs.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,43 @@
|
|
|
1
1
|
# @backstage/plugin-scaffolder-backend
|
|
2
2
|
|
|
3
|
+
## 1.23.0-next.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- b5deed0: Add support for `autocomplete` extension point to provide additional `autocomplete` handlers
|
|
8
|
+
- 0b52438: Serialization of the scaffolder workspace into GCP bucket
|
|
9
|
+
|
|
10
|
+
### Patch Changes
|
|
11
|
+
|
|
12
|
+
- da90cce: Updated dependency `esbuild` to `^0.21.0`.
|
|
13
|
+
- 62d1fe3: Fix user entity not being fetched for scaffolder dry runner
|
|
14
|
+
- Updated dependencies
|
|
15
|
+
- @backstage/backend-plugin-api@0.6.21-next.0
|
|
16
|
+
- @backstage/backend-common@0.23.2-next.0
|
|
17
|
+
- @backstage/backend-tasks@0.5.26-next.0
|
|
18
|
+
- @backstage/plugin-scaffolder-backend-module-gitlab@0.4.3-next.0
|
|
19
|
+
- @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.1.11-next.0
|
|
20
|
+
- @backstage/integration@1.13.0-next.0
|
|
21
|
+
- @backstage/plugin-scaffolder-backend-module-azure@0.1.13-next.0
|
|
22
|
+
- @backstage/plugin-scaffolder-node@0.4.7-next.0
|
|
23
|
+
- @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.1.11-next.0
|
|
24
|
+
- @backstage/plugin-bitbucket-cloud-common@0.2.21-next.0
|
|
25
|
+
- @backstage/plugin-scaffolder-backend-module-github@0.4.0-next.0
|
|
26
|
+
- @backstage/plugin-auth-node@0.4.16-next.0
|
|
27
|
+
- @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.19-next.0
|
|
28
|
+
- @backstage/plugin-catalog-node@1.12.3-next.0
|
|
29
|
+
- @backstage/plugin-permission-node@0.7.32-next.0
|
|
30
|
+
- @backstage/plugin-scaffolder-backend-module-bitbucket@0.2.11-next.0
|
|
31
|
+
- @backstage/plugin-scaffolder-backend-module-gerrit@0.1.13-next.0
|
|
32
|
+
- @backstage/plugin-scaffolder-backend-module-gitea@0.1.11-next.0
|
|
33
|
+
- @backstage/catalog-client@1.6.5
|
|
34
|
+
- @backstage/catalog-model@1.5.0
|
|
35
|
+
- @backstage/config@1.2.0
|
|
36
|
+
- @backstage/errors@1.2.4
|
|
37
|
+
- @backstage/types@1.1.1
|
|
38
|
+
- @backstage/plugin-permission-common@0.7.14
|
|
39
|
+
- @backstage/plugin-scaffolder-common@1.5.3
|
|
40
|
+
|
|
3
41
|
## 1.22.9
|
|
4
42
|
|
|
5
43
|
### Patch Changes
|
package/alpha/package.json
CHANGED
package/config.d.ts
CHANGED
|
@@ -52,6 +52,13 @@ export interface Config {
|
|
|
52
52
|
*/
|
|
53
53
|
EXPERIMENTAL_workspaceSerialization?: boolean;
|
|
54
54
|
|
|
55
|
+
/**
|
|
56
|
+
* Sets the provider for workspace serialization.
|
|
57
|
+
*
|
|
58
|
+
* By default, it is your database.
|
|
59
|
+
*/
|
|
60
|
+
EXPERIMENTAL_workspaceSerializationProvider?: string;
|
|
61
|
+
|
|
55
62
|
/**
|
|
56
63
|
* Every task which is in progress state and having a last heartbeat longer than a specified timeout is going to
|
|
57
64
|
* be attempted to recover.
|
package/dist/alpha.cjs.js
CHANGED
|
@@ -4,7 +4,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
4
4
|
|
|
5
5
|
var alpha = require('@backstage/plugin-scaffolder-common/alpha');
|
|
6
6
|
var pluginPermissionNode = require('@backstage/plugin-permission-node');
|
|
7
|
-
var router = require('./cjs/router-
|
|
7
|
+
var router = require('./cjs/router-BpffhBor.cjs.js');
|
|
8
8
|
var backendPluginApi = require('@backstage/backend-plugin-api');
|
|
9
9
|
var backendCommon = require('@backstage/backend-common');
|
|
10
10
|
var integration = require('@backstage/integration');
|
|
@@ -39,12 +39,9 @@ require('isbinaryfile');
|
|
|
39
39
|
require('isolated-vm');
|
|
40
40
|
require('lodash/get');
|
|
41
41
|
require('uuid');
|
|
42
|
-
require('tar');
|
|
43
|
-
require('concat-stream');
|
|
44
|
-
require('util');
|
|
45
|
-
require('stream');
|
|
46
42
|
require('winston');
|
|
47
43
|
require('nunjucks');
|
|
44
|
+
require('stream');
|
|
48
45
|
require('prom-client');
|
|
49
46
|
require('@backstage/plugin-permission-common');
|
|
50
47
|
require('winston-transport');
|
|
@@ -95,6 +92,18 @@ const scaffolderPlugin = backendPluginApi.createBackendPlugin({
|
|
|
95
92
|
Object.assign(additionalTemplateGlobals, newGlobals);
|
|
96
93
|
}
|
|
97
94
|
});
|
|
95
|
+
const autocompleteHandlers = {};
|
|
96
|
+
env.registerExtensionPoint(alpha$1.scaffolderAutocompleteExtensionPoint, {
|
|
97
|
+
addAutocompleteProvider(provider) {
|
|
98
|
+
autocompleteHandlers[provider.id] = provider.handler;
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
const additionalWorkspaceProviders = {};
|
|
102
|
+
env.registerExtensionPoint(alpha$1.scaffolderWorkspaceProviderExtensionPoint, {
|
|
103
|
+
addProviders(provider) {
|
|
104
|
+
Object.assign(additionalWorkspaceProviders, provider);
|
|
105
|
+
}
|
|
106
|
+
});
|
|
98
107
|
env.registerInit({
|
|
99
108
|
deps: {
|
|
100
109
|
logger: backendPluginApi.coreServices.logger,
|
|
@@ -169,7 +178,9 @@ const scaffolderPlugin = backendPluginApi.createBackendPlugin({
|
|
|
169
178
|
auth,
|
|
170
179
|
httpAuth,
|
|
171
180
|
discovery,
|
|
172
|
-
permissions
|
|
181
|
+
permissions,
|
|
182
|
+
autocompleteHandlers,
|
|
183
|
+
additionalWorkspaceProviders
|
|
173
184
|
});
|
|
174
185
|
httpRouter.use(router$1);
|
|
175
186
|
}
|
package/dist/alpha.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"alpha.cjs.js","sources":["../src/service/conditionExports.ts","../src/ScaffolderPlugin.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n RESOURCE_TYPE_SCAFFOLDER_TEMPLATE,\n RESOURCE_TYPE_SCAFFOLDER_ACTION,\n} from '@backstage/plugin-scaffolder-common/alpha';\nimport { createConditionExports } from '@backstage/plugin-permission-node';\nimport { scaffolderTemplateRules, scaffolderActionRules } from './rules';\n\nconst templateConditionExports = createConditionExports({\n pluginId: 'scaffolder',\n resourceType: RESOURCE_TYPE_SCAFFOLDER_TEMPLATE,\n rules: scaffolderTemplateRules,\n});\n\nconst actionsConditionExports = createConditionExports({\n pluginId: 'scaffolder',\n resourceType: RESOURCE_TYPE_SCAFFOLDER_ACTION,\n rules: scaffolderActionRules,\n});\n\n/**\n * `createScaffolderTemplateConditionalDecision` can be used when authoring policies to\n * create conditional decisions. It requires a permission of type\n * `ResourcePermission<'scaffolder-template'>` to be passed as the first parameter.\n * It's recommended that you use the provided `isResourcePermission` and\n * `isPermission` helper methods to narrow the type of the permission passed to\n * the handle method as shown below.\n *\n * ```\n * // MyAuthorizationPolicy.ts\n * ...\n * import { createScaffolderPolicyDecision } from '@backstage/plugin-scaffolder-backend';\n * import { RESOURCE_TYPE_SCAFFOLDER_TEMPLATE } from '@backstage/plugin-scaffolder-common';\n *\n * class MyAuthorizationPolicy implements PermissionPolicy {\n * async handle(request, user) {\n * ...\n *\n * if (isResourcePermission(request.permission, RESOURCE_TYPE_SCAFFOLDER_TEMPLATE)) {\n * return createScaffolderConditionalDecision(\n * request.permission,\n * { anyOf: [...insert conditions here...] }\n * );\n * }\n *\n * ...\n * }\n *\n * ```\n *\n * @alpha\n */\nexport const createScaffolderTemplateConditionalDecision =\n templateConditionExports.createConditionalDecision;\n\n/**\n * These conditions are used when creating conditional decisions for scaffolder\n * templates that are returned by authorization policies.\n *\n * @alpha\n */\nexport const scaffolderTemplateConditions = templateConditionExports.conditions;\n\n/**\n * @alpha\n */\nexport const createScaffolderActionConditionalDecision =\n actionsConditionExports.createConditionalDecision;\n\n/**\n *\n * These conditions are used when creating conditional decisions for scaffolder\n * actions that are returned by authorization policies.\n *\n * @alpha\n */\nexport const scaffolderActionConditions = actionsConditionExports.conditions;\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createBackendPlugin,\n coreServices,\n} from '@backstage/backend-plugin-api';\nimport { loggerToWinstonLogger } from '@backstage/backend-common';\nimport { ScmIntegrations } from '@backstage/integration';\nimport { catalogServiceRef } from '@backstage/plugin-catalog-node/alpha';\nimport {\n TaskBroker,\n TemplateAction,\n TemplateFilter,\n TemplateGlobal,\n} from '@backstage/plugin-scaffolder-node';\nimport {\n scaffolderActionsExtensionPoint,\n scaffolderTaskBrokerExtensionPoint,\n scaffolderTemplatingExtensionPoint,\n} from '@backstage/plugin-scaffolder-node/alpha';\nimport {\n createCatalogRegisterAction,\n createCatalogWriteAction,\n createDebugLogAction,\n createFetchCatalogEntityAction,\n createFetchPlainAction,\n createFetchPlainFileAction,\n createFetchTemplateAction,\n createFilesystemDeleteAction,\n createFilesystemRenameAction,\n createWaitAction,\n} from './scaffolder';\nimport { createRouter } from './service/router';\n\n/**\n * Scaffolder plugin\n *\n * @alpha\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 env.registerInit({\n deps: {\n logger: coreServices.logger,\n config: coreServices.rootConfig,\n lifecycle: coreServices.rootLifecycle,\n reader: coreServices.urlReader,\n permissions: coreServices.permissions,\n database: coreServices.database,\n auth: coreServices.auth,\n discovery: coreServices.discovery,\n httpRouter: coreServices.httpRouter,\n httpAuth: coreServices.httpAuth,\n catalogClient: catalogServiceRef,\n },\n async init({\n logger,\n config,\n lifecycle,\n reader,\n database,\n auth,\n discovery,\n httpRouter,\n httpAuth,\n catalogClient,\n permissions,\n }) {\n const log = loggerToWinstonLogger(logger);\n const integrations = ScmIntegrations.fromConfig(config);\n\n const actions = [\n // actions provided from other modules\n ...addedActions,\n\n // built-in actions for the scaffolder\n createFetchPlainAction({\n reader,\n integrations,\n }),\n createFetchPlainFileAction({\n reader,\n integrations,\n }),\n createFetchTemplateAction({\n integrations,\n reader,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n }),\n createDebugLogAction(),\n createWaitAction(),\n // todo(blam): maybe these should be a -catalog module?\n createCatalogRegisterAction({ catalogClient, integrations, auth }),\n createFetchCatalogEntityAction({ catalogClient, auth }),\n createCatalogWriteAction(),\n createFilesystemDeleteAction(),\n createFilesystemRenameAction(),\n ];\n\n const actionIds = actions.map(action => action.id).join(', ');\n\n log.info(\n `Starting scaffolder with the following actions enabled ${actionIds}`,\n );\n\n const router = await createRouter({\n logger: log,\n config,\n database,\n catalogClient,\n reader,\n lifecycle,\n actions,\n taskBroker,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n auth,\n httpAuth,\n discovery,\n permissions,\n });\n httpRouter.use(router);\n },\n });\n },\n});\n"],"names":["createConditionExports","RESOURCE_TYPE_SCAFFOLDER_TEMPLATE","scaffolderTemplateRules","RESOURCE_TYPE_SCAFFOLDER_ACTION","scaffolderActionRules","createBackendPlugin","scaffolderActionsExtensionPoint","scaffolderTaskBrokerExtensionPoint","scaffolderTemplatingExtensionPoint","coreServices","catalogServiceRef","loggerToWinstonLogger","ScmIntegrations","createFetchPlainAction","createFetchPlainFileAction","createFetchTemplateAction","createDebugLogAction","createWaitAction","createCatalogRegisterAction","createFetchCatalogEntityAction","createCatalogWriteAction","createFilesystemDeleteAction","createFilesystemRenameAction","router","createRouter"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"alpha.cjs.js","sources":["../src/service/conditionExports.ts","../src/ScaffolderPlugin.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n RESOURCE_TYPE_SCAFFOLDER_TEMPLATE,\n RESOURCE_TYPE_SCAFFOLDER_ACTION,\n} from '@backstage/plugin-scaffolder-common/alpha';\nimport { createConditionExports } from '@backstage/plugin-permission-node';\nimport { scaffolderTemplateRules, scaffolderActionRules } from './rules';\n\nconst templateConditionExports = createConditionExports({\n pluginId: 'scaffolder',\n resourceType: RESOURCE_TYPE_SCAFFOLDER_TEMPLATE,\n rules: scaffolderTemplateRules,\n});\n\nconst actionsConditionExports = createConditionExports({\n pluginId: 'scaffolder',\n resourceType: RESOURCE_TYPE_SCAFFOLDER_ACTION,\n rules: scaffolderActionRules,\n});\n\n/**\n * `createScaffolderTemplateConditionalDecision` can be used when authoring policies to\n * create conditional decisions. It requires a permission of type\n * `ResourcePermission<'scaffolder-template'>` to be passed as the first parameter.\n * It's recommended that you use the provided `isResourcePermission` and\n * `isPermission` helper methods to narrow the type of the permission passed to\n * the handle method as shown below.\n *\n * ```\n * // MyAuthorizationPolicy.ts\n * ...\n * import { createScaffolderPolicyDecision } from '@backstage/plugin-scaffolder-backend';\n * import { RESOURCE_TYPE_SCAFFOLDER_TEMPLATE } from '@backstage/plugin-scaffolder-common';\n *\n * class MyAuthorizationPolicy implements PermissionPolicy {\n * async handle(request, user) {\n * ...\n *\n * if (isResourcePermission(request.permission, RESOURCE_TYPE_SCAFFOLDER_TEMPLATE)) {\n * return createScaffolderConditionalDecision(\n * request.permission,\n * { anyOf: [...insert conditions here...] }\n * );\n * }\n *\n * ...\n * }\n *\n * ```\n *\n * @alpha\n */\nexport const createScaffolderTemplateConditionalDecision =\n templateConditionExports.createConditionalDecision;\n\n/**\n * These conditions are used when creating conditional decisions for scaffolder\n * templates that are returned by authorization policies.\n *\n * @alpha\n */\nexport const scaffolderTemplateConditions = templateConditionExports.conditions;\n\n/**\n * @alpha\n */\nexport const createScaffolderActionConditionalDecision =\n actionsConditionExports.createConditionalDecision;\n\n/**\n *\n * These conditions are used when creating conditional decisions for scaffolder\n * actions that are returned by authorization policies.\n *\n * @alpha\n */\nexport const scaffolderActionConditions = actionsConditionExports.conditions;\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createBackendPlugin,\n coreServices,\n} from '@backstage/backend-plugin-api';\nimport { loggerToWinstonLogger } from '@backstage/backend-common';\nimport { ScmIntegrations } from '@backstage/integration';\nimport { catalogServiceRef } from '@backstage/plugin-catalog-node/alpha';\nimport {\n TaskBroker,\n TemplateAction,\n TemplateFilter,\n TemplateGlobal,\n} from '@backstage/plugin-scaffolder-node';\nimport {\n AutocompleteHandler,\n scaffolderActionsExtensionPoint,\n scaffolderAutocompleteExtensionPoint,\n scaffolderTaskBrokerExtensionPoint,\n scaffolderTemplatingExtensionPoint,\n scaffolderWorkspaceProviderExtensionPoint,\n WorkspaceProvider,\n} from '@backstage/plugin-scaffolder-node/alpha';\nimport {\n createCatalogRegisterAction,\n createCatalogWriteAction,\n createDebugLogAction,\n createFetchCatalogEntityAction,\n createFetchPlainAction,\n createFetchPlainFileAction,\n createFetchTemplateAction,\n createFilesystemDeleteAction,\n createFilesystemRenameAction,\n createWaitAction,\n} from './scaffolder';\nimport { createRouter } from './service/router';\n\n/**\n * Scaffolder plugin\n *\n * @alpha\n */\nexport const scaffolderPlugin = createBackendPlugin({\n pluginId: 'scaffolder',\n register(env) {\n const addedActions = new Array<TemplateAction<any, any>>();\n env.registerExtensionPoint(scaffolderActionsExtensionPoint, {\n addActions(...newActions: TemplateAction<any>[]) {\n addedActions.push(...newActions);\n },\n });\n\n let taskBroker: TaskBroker | undefined;\n env.registerExtensionPoint(scaffolderTaskBrokerExtensionPoint, {\n setTaskBroker(newTaskBroker) {\n if (taskBroker) {\n throw new Error('Task broker may only be set once');\n }\n taskBroker = newTaskBroker;\n },\n });\n\n const additionalTemplateFilters: Record<string, TemplateFilter> = {};\n const additionalTemplateGlobals: Record<string, TemplateGlobal> = {};\n env.registerExtensionPoint(scaffolderTemplatingExtensionPoint, {\n addTemplateFilters(newFilters) {\n Object.assign(additionalTemplateFilters, newFilters);\n },\n addTemplateGlobals(newGlobals) {\n Object.assign(additionalTemplateGlobals, newGlobals);\n },\n });\n\n const autocompleteHandlers: Record<string, AutocompleteHandler> = {};\n env.registerExtensionPoint(scaffolderAutocompleteExtensionPoint, {\n addAutocompleteProvider(provider) {\n autocompleteHandlers[provider.id] = provider.handler;\n },\n });\n\n const additionalWorkspaceProviders: Record<string, WorkspaceProvider> = {};\n env.registerExtensionPoint(scaffolderWorkspaceProviderExtensionPoint, {\n addProviders(provider) {\n Object.assign(additionalWorkspaceProviders, provider);\n },\n });\n\n env.registerInit({\n deps: {\n logger: coreServices.logger,\n config: coreServices.rootConfig,\n lifecycle: coreServices.rootLifecycle,\n reader: coreServices.urlReader,\n permissions: coreServices.permissions,\n database: coreServices.database,\n auth: coreServices.auth,\n discovery: coreServices.discovery,\n httpRouter: coreServices.httpRouter,\n httpAuth: coreServices.httpAuth,\n catalogClient: catalogServiceRef,\n },\n async init({\n logger,\n config,\n lifecycle,\n reader,\n database,\n auth,\n discovery,\n httpRouter,\n httpAuth,\n catalogClient,\n permissions,\n }) {\n const log = loggerToWinstonLogger(logger);\n const integrations = ScmIntegrations.fromConfig(config);\n\n const actions = [\n // actions provided from other modules\n ...addedActions,\n\n // built-in actions for the scaffolder\n createFetchPlainAction({\n reader,\n integrations,\n }),\n createFetchPlainFileAction({\n reader,\n integrations,\n }),\n createFetchTemplateAction({\n integrations,\n reader,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n }),\n createDebugLogAction(),\n createWaitAction(),\n // todo(blam): maybe these should be a -catalog module?\n createCatalogRegisterAction({ catalogClient, integrations, auth }),\n createFetchCatalogEntityAction({ catalogClient, auth }),\n createCatalogWriteAction(),\n createFilesystemDeleteAction(),\n createFilesystemRenameAction(),\n ];\n\n const actionIds = actions.map(action => action.id).join(', ');\n\n log.info(\n `Starting scaffolder with the following actions enabled ${actionIds}`,\n );\n\n const router = await createRouter({\n logger: log,\n config,\n database,\n catalogClient,\n reader,\n lifecycle,\n actions,\n taskBroker,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n auth,\n httpAuth,\n discovery,\n permissions,\n autocompleteHandlers,\n additionalWorkspaceProviders,\n });\n httpRouter.use(router);\n },\n });\n },\n});\n"],"names":["createConditionExports","RESOURCE_TYPE_SCAFFOLDER_TEMPLATE","scaffolderTemplateRules","RESOURCE_TYPE_SCAFFOLDER_ACTION","scaffolderActionRules","createBackendPlugin","scaffolderActionsExtensionPoint","scaffolderTaskBrokerExtensionPoint","scaffolderTemplatingExtensionPoint","scaffolderAutocompleteExtensionPoint","scaffolderWorkspaceProviderExtensionPoint","coreServices","catalogServiceRef","loggerToWinstonLogger","ScmIntegrations","createFetchPlainAction","createFetchPlainFileAction","createFetchTemplateAction","createDebugLogAction","createWaitAction","createCatalogRegisterAction","createFetchCatalogEntityAction","createCatalogWriteAction","createFilesystemDeleteAction","createFilesystemRenameAction","router","createRouter"],"mappings":"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"}
|
|
@@ -6,7 +6,7 @@ var config = require('@backstage/config');
|
|
|
6
6
|
var errors = require('@backstage/errors');
|
|
7
7
|
var integration = require('@backstage/integration');
|
|
8
8
|
var pluginScaffolderCommon = require('@backstage/plugin-scaffolder-common');
|
|
9
|
-
var alpha = require('@backstage/plugin-scaffolder-common/alpha');
|
|
9
|
+
var alpha$1 = require('@backstage/plugin-scaffolder-common/alpha');
|
|
10
10
|
var express = require('express');
|
|
11
11
|
var Router = require('express-promise-router');
|
|
12
12
|
var jsonschema = require('jsonschema');
|
|
@@ -30,15 +30,13 @@ var gerrit = require('@backstage/plugin-scaffolder-backend-module-gerrit');
|
|
|
30
30
|
var gitlab = require('@backstage/plugin-scaffolder-backend-module-gitlab');
|
|
31
31
|
var pluginScaffolderBackendModuleGitea = require('@backstage/plugin-scaffolder-backend-module-gitea');
|
|
32
32
|
var uuid = require('uuid');
|
|
33
|
-
var
|
|
34
|
-
var concatStream = require('concat-stream');
|
|
35
|
-
var util = require('util');
|
|
36
|
-
var stream = require('stream');
|
|
33
|
+
var alpha = require('@backstage/plugin-scaffolder-node/alpha');
|
|
37
34
|
var ObservableImpl = require('zen-observable');
|
|
38
35
|
var lodash = require('lodash');
|
|
39
36
|
var PQueue = require('p-queue');
|
|
40
37
|
var winston = require('winston');
|
|
41
38
|
var nunjucks = require('nunjucks');
|
|
39
|
+
var stream = require('stream');
|
|
42
40
|
var pluginPermissionNode = require('@backstage/plugin-permission-node');
|
|
43
41
|
var promClient = require('prom-client');
|
|
44
42
|
var pluginPermissionCommon = require('@backstage/plugin-permission-common');
|
|
@@ -74,8 +72,6 @@ var fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
|
|
|
74
72
|
var path__default = /*#__PURE__*/_interopDefaultCompat(path);
|
|
75
73
|
var globby__default = /*#__PURE__*/_interopDefaultCompat(globby);
|
|
76
74
|
var get__default = /*#__PURE__*/_interopDefaultCompat(get);
|
|
77
|
-
var tar__default = /*#__PURE__*/_interopDefaultCompat(tar);
|
|
78
|
-
var concatStream__default = /*#__PURE__*/_interopDefaultCompat(concatStream);
|
|
79
75
|
var ObservableImpl__default = /*#__PURE__*/_interopDefaultCompat(ObservableImpl);
|
|
80
76
|
var PQueue__default = /*#__PURE__*/_interopDefaultCompat(PQueue);
|
|
81
77
|
var winston__namespace = /*#__PURE__*/_interopNamespaceCompat(winston);
|
|
@@ -1509,23 +1505,6 @@ const intervalFromNowTill = (timeoutS, knex) => {
|
|
|
1509
1505
|
return heartbeatInterval;
|
|
1510
1506
|
};
|
|
1511
1507
|
|
|
1512
|
-
const pipeline = util.promisify(stream.pipeline);
|
|
1513
|
-
const serializeWorkspace = async (path) => {
|
|
1514
|
-
return await new Promise(async (resolve) => {
|
|
1515
|
-
await pipeline(tar__default.default.create({ cwd: path }, [""]), concatStream__default.default(resolve));
|
|
1516
|
-
});
|
|
1517
|
-
};
|
|
1518
|
-
const restoreWorkspace = async (path, buffer) => {
|
|
1519
|
-
if (buffer) {
|
|
1520
|
-
await pipeline(
|
|
1521
|
-
stream.Readable.from(buffer),
|
|
1522
|
-
tar__default.default.extract({
|
|
1523
|
-
C: path
|
|
1524
|
-
})
|
|
1525
|
-
);
|
|
1526
|
-
}
|
|
1527
|
-
};
|
|
1528
|
-
|
|
1529
1508
|
const migrationsDir = backendPluginApi.resolvePackagePath(
|
|
1530
1509
|
"@backstage/plugin-scaffolder-backend",
|
|
1531
1510
|
"migrations"
|
|
@@ -1837,7 +1816,10 @@ class DatabaseTaskStore {
|
|
|
1837
1816
|
}
|
|
1838
1817
|
async rehydrateWorkspace(options) {
|
|
1839
1818
|
const [result] = await this.db("tasks").where({ id: options.taskId }).select("workspace");
|
|
1840
|
-
await restoreWorkspace(
|
|
1819
|
+
await alpha.restoreWorkspace({
|
|
1820
|
+
path: options.targetPath,
|
|
1821
|
+
buffer: result.workspace
|
|
1822
|
+
});
|
|
1841
1823
|
}
|
|
1842
1824
|
async cleanWorkspace({ taskId }) {
|
|
1843
1825
|
await this.db("tasks").where({ id: taskId }).update({
|
|
@@ -1847,7 +1829,7 @@ class DatabaseTaskStore {
|
|
|
1847
1829
|
async serializeWorkspace(options) {
|
|
1848
1830
|
if (options.path) {
|
|
1849
1831
|
await this.db("tasks").where({ id: options.taskId }).update({
|
|
1850
|
-
workspace: await serializeWorkspace(options.
|
|
1832
|
+
workspace: (await alpha.serializeWorkspace(options)).contents
|
|
1851
1833
|
});
|
|
1852
1834
|
}
|
|
1853
1835
|
}
|
|
@@ -1925,26 +1907,88 @@ const readDuration$1 = (config$1, key, defaultValue) => {
|
|
|
1925
1907
|
return defaultValue;
|
|
1926
1908
|
};
|
|
1927
1909
|
|
|
1910
|
+
class DatabaseWorkspaceProvider {
|
|
1911
|
+
constructor(storage) {
|
|
1912
|
+
this.storage = storage;
|
|
1913
|
+
}
|
|
1914
|
+
static create(storage) {
|
|
1915
|
+
return new DatabaseWorkspaceProvider(storage);
|
|
1916
|
+
}
|
|
1917
|
+
async serializeWorkspace(options) {
|
|
1918
|
+
this.storage.serializeWorkspace?.(options);
|
|
1919
|
+
}
|
|
1920
|
+
async rehydrateWorkspace(options) {
|
|
1921
|
+
return this.storage.rehydrateWorkspace?.(options);
|
|
1922
|
+
}
|
|
1923
|
+
async cleanWorkspace(options) {
|
|
1924
|
+
return this.storage.cleanWorkspace?.(options);
|
|
1925
|
+
}
|
|
1926
|
+
}
|
|
1927
|
+
|
|
1928
|
+
class DefaultWorkspaceService {
|
|
1929
|
+
constructor(task, workspaceProvider, config) {
|
|
1930
|
+
this.task = task;
|
|
1931
|
+
this.workspaceProvider = workspaceProvider;
|
|
1932
|
+
this.config = config;
|
|
1933
|
+
}
|
|
1934
|
+
static create(task, storage, additionalWorkspaceProviders, config) {
|
|
1935
|
+
const workspaceProviderName = config?.getOptionalString(
|
|
1936
|
+
"scaffolder.EXPERIMENTAL_workspaceSerializationProvider"
|
|
1937
|
+
) ?? "database";
|
|
1938
|
+
const workspaceProvider = additionalWorkspaceProviders?.[workspaceProviderName] ?? DatabaseWorkspaceProvider.create(storage);
|
|
1939
|
+
return new DefaultWorkspaceService(task, workspaceProvider, config);
|
|
1940
|
+
}
|
|
1941
|
+
async serializeWorkspace(options) {
|
|
1942
|
+
if (this.isWorkspaceSerializationEnabled()) {
|
|
1943
|
+
await this.workspaceProvider.serializeWorkspace({
|
|
1944
|
+
path: options.path,
|
|
1945
|
+
taskId: this.task.taskId
|
|
1946
|
+
});
|
|
1947
|
+
}
|
|
1948
|
+
}
|
|
1949
|
+
async cleanWorkspace() {
|
|
1950
|
+
if (this.isWorkspaceSerializationEnabled()) {
|
|
1951
|
+
await this.workspaceProvider.cleanWorkspace({ taskId: this.task.taskId });
|
|
1952
|
+
}
|
|
1953
|
+
}
|
|
1954
|
+
async rehydrateWorkspace(options) {
|
|
1955
|
+
if (this.isWorkspaceSerializationEnabled()) {
|
|
1956
|
+
await this.workspaceProvider.rehydrateWorkspace(options);
|
|
1957
|
+
}
|
|
1958
|
+
}
|
|
1959
|
+
isWorkspaceSerializationEnabled() {
|
|
1960
|
+
return this.config?.getOptionalBoolean(
|
|
1961
|
+
"scaffolder.EXPERIMENTAL_workspaceSerialization"
|
|
1962
|
+
) ?? false;
|
|
1963
|
+
}
|
|
1964
|
+
}
|
|
1965
|
+
|
|
1928
1966
|
class TaskManager {
|
|
1929
1967
|
// Runs heartbeat internally
|
|
1930
|
-
constructor(task, storage, signal, logger,
|
|
1968
|
+
constructor(task, storage, signal, logger, workspaceService, auth) {
|
|
1931
1969
|
this.task = task;
|
|
1932
1970
|
this.storage = storage;
|
|
1933
1971
|
this.signal = signal;
|
|
1934
1972
|
this.logger = logger;
|
|
1973
|
+
this.workspaceService = workspaceService;
|
|
1935
1974
|
this.auth = auth;
|
|
1936
|
-
this.config = config;
|
|
1937
1975
|
}
|
|
1938
1976
|
isDone = false;
|
|
1939
1977
|
heartbeatTimeoutId;
|
|
1940
|
-
static create(task, storage, abortSignal, logger, auth, config) {
|
|
1978
|
+
static create(task, storage, abortSignal, logger, auth, config, additionalWorkspaceProviders) {
|
|
1979
|
+
const workspaceService = DefaultWorkspaceService.create(
|
|
1980
|
+
task,
|
|
1981
|
+
storage,
|
|
1982
|
+
additionalWorkspaceProviders,
|
|
1983
|
+
config
|
|
1984
|
+
);
|
|
1941
1985
|
const agent = new TaskManager(
|
|
1942
1986
|
task,
|
|
1943
1987
|
storage,
|
|
1944
1988
|
abortSignal,
|
|
1945
1989
|
logger,
|
|
1946
|
-
|
|
1947
|
-
|
|
1990
|
+
workspaceService,
|
|
1991
|
+
auth
|
|
1948
1992
|
);
|
|
1949
1993
|
agent.startTimeout();
|
|
1950
1994
|
return agent;
|
|
@@ -1965,9 +2009,7 @@ class TaskManager {
|
|
|
1965
2009
|
return this.task.taskId;
|
|
1966
2010
|
}
|
|
1967
2011
|
async rehydrateWorkspace(options) {
|
|
1968
|
-
|
|
1969
|
-
this.storage.rehydrateWorkspace?.(options);
|
|
1970
|
-
}
|
|
2012
|
+
await this.workspaceService.rehydrateWorkspace(options);
|
|
1971
2013
|
}
|
|
1972
2014
|
get done() {
|
|
1973
2015
|
return this.isDone;
|
|
@@ -1994,17 +2036,10 @@ class TaskManager {
|
|
|
1994
2036
|
});
|
|
1995
2037
|
}
|
|
1996
2038
|
async serializeWorkspace(options) {
|
|
1997
|
-
|
|
1998
|
-
await this.storage.serializeWorkspace?.({
|
|
1999
|
-
path: options.path,
|
|
2000
|
-
taskId: this.task.taskId
|
|
2001
|
-
});
|
|
2002
|
-
}
|
|
2039
|
+
await this.workspaceService.serializeWorkspace(options);
|
|
2003
2040
|
}
|
|
2004
2041
|
async cleanWorkspace() {
|
|
2005
|
-
|
|
2006
|
-
await this.storage.cleanWorkspace?.({ taskId: this.task.taskId });
|
|
2007
|
-
}
|
|
2042
|
+
await this.workspaceService.cleanWorkspace();
|
|
2008
2043
|
}
|
|
2009
2044
|
async complete(result, metadata) {
|
|
2010
2045
|
await this.storage.completeTask({
|
|
@@ -2034,11 +2069,6 @@ class TaskManager {
|
|
|
2034
2069
|
}
|
|
2035
2070
|
}, 1e3);
|
|
2036
2071
|
}
|
|
2037
|
-
isWorkspaceSerializationEnabled() {
|
|
2038
|
-
return this.config?.getOptionalBoolean(
|
|
2039
|
-
"scaffolder.EXPERIMENTAL_workspaceSerialization"
|
|
2040
|
-
) ?? false;
|
|
2041
|
-
}
|
|
2042
2072
|
async getInitiatorCredentials() {
|
|
2043
2073
|
const secrets = this.task.secrets;
|
|
2044
2074
|
if (secrets && secrets.__initiatorCredentials) {
|
|
@@ -2061,11 +2091,12 @@ function defer() {
|
|
|
2061
2091
|
return { promise, resolve };
|
|
2062
2092
|
}
|
|
2063
2093
|
class StorageTaskBroker {
|
|
2064
|
-
constructor(storage, logger, config, auth) {
|
|
2094
|
+
constructor(storage, logger, config, auth, additionalWorkspaceProviders) {
|
|
2065
2095
|
this.storage = storage;
|
|
2066
2096
|
this.logger = logger;
|
|
2067
2097
|
this.config = config;
|
|
2068
2098
|
this.auth = auth;
|
|
2099
|
+
this.additionalWorkspaceProviders = additionalWorkspaceProviders;
|
|
2069
2100
|
}
|
|
2070
2101
|
async list(options) {
|
|
2071
2102
|
if (!this.storage.list) {
|
|
@@ -2138,7 +2169,8 @@ class StorageTaskBroker {
|
|
|
2138
2169
|
abortController.signal,
|
|
2139
2170
|
this.logger,
|
|
2140
2171
|
this.auth,
|
|
2141
|
-
this.config
|
|
2172
|
+
this.config,
|
|
2173
|
+
this.additionalWorkspaceProviders
|
|
2142
2174
|
);
|
|
2143
2175
|
}
|
|
2144
2176
|
await this.waitForDispatch();
|
|
@@ -2246,7 +2278,7 @@ function createHistogramMetric(config) {
|
|
|
2246
2278
|
const createTemplatePermissionRule = pluginPermissionNode.makeCreatePermissionRule();
|
|
2247
2279
|
const hasTag = createTemplatePermissionRule({
|
|
2248
2280
|
name: "HAS_TAG",
|
|
2249
|
-
resourceType: alpha.RESOURCE_TYPE_SCAFFOLDER_TEMPLATE,
|
|
2281
|
+
resourceType: alpha$1.RESOURCE_TYPE_SCAFFOLDER_TEMPLATE,
|
|
2250
2282
|
description: `Match parameters or steps with the given tag`,
|
|
2251
2283
|
paramsSchema: zod.z.object({
|
|
2252
2284
|
tag: zod.z.string().describe("Name of the tag to match on")
|
|
@@ -2259,7 +2291,7 @@ const hasTag = createTemplatePermissionRule({
|
|
|
2259
2291
|
const createActionPermissionRule = pluginPermissionNode.makeCreatePermissionRule();
|
|
2260
2292
|
const hasActionId = createActionPermissionRule({
|
|
2261
2293
|
name: "HAS_ACTION_ID",
|
|
2262
|
-
resourceType: alpha.RESOURCE_TYPE_SCAFFOLDER_ACTION,
|
|
2294
|
+
resourceType: alpha$1.RESOURCE_TYPE_SCAFFOLDER_ACTION,
|
|
2263
2295
|
description: `Match actions with the given actionId`,
|
|
2264
2296
|
paramsSchema: zod.z.object({
|
|
2265
2297
|
actionId: zod.z.string().describe("Name of the actionId to match on")
|
|
@@ -2294,7 +2326,7 @@ function buildHasProperty({
|
|
|
2294
2326
|
return createActionPermissionRule({
|
|
2295
2327
|
name,
|
|
2296
2328
|
description: `Allow actions with the specified property`,
|
|
2297
|
-
resourceType: alpha.RESOURCE_TYPE_SCAFFOLDER_ACTION,
|
|
2329
|
+
resourceType: alpha$1.RESOURCE_TYPE_SCAFFOLDER_ACTION,
|
|
2298
2330
|
paramsSchema: zod.z.object({
|
|
2299
2331
|
key: zod.z.string().describe(`Property within the action parameters to match on`),
|
|
2300
2332
|
value: valueSchema.optional().describe(`Value of the given property to match on`)
|
|
@@ -2722,7 +2754,6 @@ class NunjucksWorkflowRunner {
|
|
|
2722
2754
|
if (task.cancelSignal.aborted) {
|
|
2723
2755
|
throw new Error(`Step ${step.name} has been cancelled.`);
|
|
2724
2756
|
}
|
|
2725
|
-
await task.cleanWorkspace?.();
|
|
2726
2757
|
await stepTrack.markSuccessful();
|
|
2727
2758
|
} catch (err) {
|
|
2728
2759
|
await taskTrack.markFailed(step, err);
|
|
@@ -2758,7 +2789,7 @@ class NunjucksWorkflowRunner {
|
|
|
2758
2789
|
user: task.spec.user
|
|
2759
2790
|
};
|
|
2760
2791
|
const [decision] = this.options.permissions && task.spec.steps.length ? await this.options.permissions.authorizeConditional(
|
|
2761
|
-
[{ permission: alpha.actionExecutePermission }],
|
|
2792
|
+
[{ permission: alpha$1.actionExecutePermission }],
|
|
2762
2793
|
{ credentials: await task.getInitiatorCredentials() }
|
|
2763
2794
|
) : [{ result: pluginPermissionCommon.AuthorizeResult.ALLOW }];
|
|
2764
2795
|
for (const step of task.spec.steps) {
|
|
@@ -2777,6 +2808,7 @@ class NunjucksWorkflowRunner {
|
|
|
2777
2808
|
return { output };
|
|
2778
2809
|
} finally {
|
|
2779
2810
|
if (workspacePath) {
|
|
2811
|
+
await task.cleanWorkspace?.();
|
|
2780
2812
|
await fs__default.default.remove(workspacePath);
|
|
2781
2813
|
}
|
|
2782
2814
|
}
|
|
@@ -3175,10 +3207,10 @@ async function checkPermission(options) {
|
|
|
3175
3207
|
}
|
|
3176
3208
|
|
|
3177
3209
|
function isTemplatePermissionRuleInput(permissionRule) {
|
|
3178
|
-
return permissionRule.resourceType === alpha.RESOURCE_TYPE_SCAFFOLDER_TEMPLATE;
|
|
3210
|
+
return permissionRule.resourceType === alpha$1.RESOURCE_TYPE_SCAFFOLDER_TEMPLATE;
|
|
3179
3211
|
}
|
|
3180
3212
|
function isActionPermissionRuleInput(permissionRule) {
|
|
3181
|
-
return permissionRule.resourceType === alpha.RESOURCE_TYPE_SCAFFOLDER_ACTION;
|
|
3213
|
+
return permissionRule.resourceType === alpha$1.RESOURCE_TYPE_SCAFFOLDER_ACTION;
|
|
3182
3214
|
}
|
|
3183
3215
|
function isSupportedTemplate(entity) {
|
|
3184
3216
|
return entity.apiVersion === "scaffolder.backstage.io/v1beta3";
|
|
@@ -3246,10 +3278,12 @@ async function createRouter(options) {
|
|
|
3246
3278
|
scheduler,
|
|
3247
3279
|
additionalTemplateFilters,
|
|
3248
3280
|
additionalTemplateGlobals,
|
|
3281
|
+
additionalWorkspaceProviders,
|
|
3249
3282
|
permissions,
|
|
3250
3283
|
permissionRules,
|
|
3251
3284
|
discovery = backendCommon.HostDiscovery.fromConfig(config),
|
|
3252
|
-
identity = buildDefaultIdentityClient(options)
|
|
3285
|
+
identity = buildDefaultIdentityClient(options),
|
|
3286
|
+
autocompleteHandlers = {}
|
|
3253
3287
|
} = options;
|
|
3254
3288
|
const { auth, httpAuth } = backendCommon.createLegacyAuthAdapters({
|
|
3255
3289
|
...options,
|
|
@@ -3263,7 +3297,13 @@ async function createRouter(options) {
|
|
|
3263
3297
|
let taskBroker;
|
|
3264
3298
|
if (!options.taskBroker) {
|
|
3265
3299
|
const databaseTaskStore = await DatabaseTaskStore.create({ database });
|
|
3266
|
-
taskBroker = new StorageTaskBroker(
|
|
3300
|
+
taskBroker = new StorageTaskBroker(
|
|
3301
|
+
databaseTaskStore,
|
|
3302
|
+
logger,
|
|
3303
|
+
config,
|
|
3304
|
+
auth,
|
|
3305
|
+
additionalWorkspaceProviders
|
|
3306
|
+
);
|
|
3267
3307
|
if (scheduler && databaseTaskStore.listStaleTasks) {
|
|
3268
3308
|
await scheduler.scheduleTask({
|
|
3269
3309
|
id: "close_stale_tasks",
|
|
@@ -3356,17 +3396,17 @@ async function createRouter(options) {
|
|
|
3356
3396
|
const permissionIntegrationRouter = pluginPermissionNode.createPermissionIntegrationRouter({
|
|
3357
3397
|
resources: [
|
|
3358
3398
|
{
|
|
3359
|
-
resourceType: alpha.RESOURCE_TYPE_SCAFFOLDER_TEMPLATE,
|
|
3360
|
-
permissions: alpha.scaffolderTemplatePermissions,
|
|
3399
|
+
resourceType: alpha$1.RESOURCE_TYPE_SCAFFOLDER_TEMPLATE,
|
|
3400
|
+
permissions: alpha$1.scaffolderTemplatePermissions,
|
|
3361
3401
|
rules: templateRules
|
|
3362
3402
|
},
|
|
3363
3403
|
{
|
|
3364
|
-
resourceType: alpha.RESOURCE_TYPE_SCAFFOLDER_ACTION,
|
|
3365
|
-
permissions: alpha.scaffolderActionPermissions,
|
|
3404
|
+
resourceType: alpha$1.RESOURCE_TYPE_SCAFFOLDER_ACTION,
|
|
3405
|
+
permissions: alpha$1.scaffolderActionPermissions,
|
|
3366
3406
|
rules: actionRules
|
|
3367
3407
|
}
|
|
3368
3408
|
],
|
|
3369
|
-
permissions: alpha.scaffolderTaskPermissions
|
|
3409
|
+
permissions: alpha$1.scaffolderTaskPermissions
|
|
3370
3410
|
});
|
|
3371
3411
|
router.use(permissionIntegrationRouter);
|
|
3372
3412
|
router.get(
|
|
@@ -3414,7 +3454,7 @@ async function createRouter(options) {
|
|
|
3414
3454
|
const credentials = await httpAuth.credentials(req);
|
|
3415
3455
|
await checkPermission({
|
|
3416
3456
|
credentials,
|
|
3417
|
-
permissions: [alpha.taskCreatePermission],
|
|
3457
|
+
permissions: [alpha$1.taskCreatePermission],
|
|
3418
3458
|
permissionService: permissions
|
|
3419
3459
|
});
|
|
3420
3460
|
const { token } = await auth.getPluginRequestToken({
|
|
@@ -3479,7 +3519,7 @@ async function createRouter(options) {
|
|
|
3479
3519
|
const credentials = await httpAuth.credentials(req);
|
|
3480
3520
|
await checkPermission({
|
|
3481
3521
|
credentials,
|
|
3482
|
-
permissions: [alpha.taskReadPermission],
|
|
3522
|
+
permissions: [alpha$1.taskReadPermission],
|
|
3483
3523
|
permissionService: permissions
|
|
3484
3524
|
});
|
|
3485
3525
|
const [userEntityRef] = [req.query.createdBy].flat();
|
|
@@ -3499,7 +3539,7 @@ async function createRouter(options) {
|
|
|
3499
3539
|
const credentials = await httpAuth.credentials(req);
|
|
3500
3540
|
await checkPermission({
|
|
3501
3541
|
credentials,
|
|
3502
|
-
permissions: [alpha.taskReadPermission],
|
|
3542
|
+
permissions: [alpha$1.taskReadPermission],
|
|
3503
3543
|
permissionService: permissions
|
|
3504
3544
|
});
|
|
3505
3545
|
const { taskId } = req.params;
|
|
@@ -3513,7 +3553,7 @@ async function createRouter(options) {
|
|
|
3513
3553
|
const credentials = await httpAuth.credentials(req);
|
|
3514
3554
|
await checkPermission({
|
|
3515
3555
|
credentials,
|
|
3516
|
-
permissions: [alpha.taskCancelPermission, alpha.taskReadPermission],
|
|
3556
|
+
permissions: [alpha$1.taskCancelPermission, alpha$1.taskReadPermission],
|
|
3517
3557
|
permissionService: permissions
|
|
3518
3558
|
});
|
|
3519
3559
|
const { taskId } = req.params;
|
|
@@ -3523,7 +3563,7 @@ async function createRouter(options) {
|
|
|
3523
3563
|
const credentials = await httpAuth.credentials(req);
|
|
3524
3564
|
await checkPermission({
|
|
3525
3565
|
credentials,
|
|
3526
|
-
permissions: [alpha.taskReadPermission],
|
|
3566
|
+
permissions: [alpha$1.taskReadPermission],
|
|
3527
3567
|
permissionService: permissions
|
|
3528
3568
|
});
|
|
3529
3569
|
const { taskId } = req.params;
|
|
@@ -3569,7 +3609,7 @@ data: ${JSON.stringify(event)}
|
|
|
3569
3609
|
const credentials = await httpAuth.credentials(req);
|
|
3570
3610
|
await checkPermission({
|
|
3571
3611
|
credentials,
|
|
3572
|
-
permissions: [alpha.taskReadPermission],
|
|
3612
|
+
permissions: [alpha$1.taskReadPermission],
|
|
3573
3613
|
permissionService: permissions
|
|
3574
3614
|
});
|
|
3575
3615
|
const { taskId } = req.params;
|
|
@@ -3597,7 +3637,7 @@ data: ${JSON.stringify(event)}
|
|
|
3597
3637
|
const credentials = await httpAuth.credentials(req);
|
|
3598
3638
|
await checkPermission({
|
|
3599
3639
|
credentials,
|
|
3600
|
-
permissions: [alpha.taskCreatePermission],
|
|
3640
|
+
permissions: [alpha$1.taskCreatePermission],
|
|
3601
3641
|
permissionService: permissions
|
|
3602
3642
|
});
|
|
3603
3643
|
const bodySchema = zod.z.object({
|
|
@@ -3619,6 +3659,8 @@ data: ${JSON.stringify(event)}
|
|
|
3619
3659
|
onBehalfOf: credentials,
|
|
3620
3660
|
targetPluginId: "catalog"
|
|
3621
3661
|
});
|
|
3662
|
+
const userEntityRef = auth.isPrincipal(credentials, "user") ? credentials.principal.userEntityRef : void 0;
|
|
3663
|
+
const userEntity = userEntityRef ? await catalogClient.getEntityByRef(userEntityRef, { token }) : void 0;
|
|
3622
3664
|
for (const parameters of [template.spec.parameters ?? []].flat()) {
|
|
3623
3665
|
const result2 = jsonschema.validate(body.values, parameters);
|
|
3624
3666
|
if (!result2.valid) {
|
|
@@ -3636,7 +3678,11 @@ data: ${JSON.stringify(event)}
|
|
|
3636
3678
|
apiVersion: template.apiVersion,
|
|
3637
3679
|
steps,
|
|
3638
3680
|
output: template.spec.output ?? {},
|
|
3639
|
-
parameters: body.values
|
|
3681
|
+
parameters: body.values,
|
|
3682
|
+
user: {
|
|
3683
|
+
entity: userEntity,
|
|
3684
|
+
ref: userEntityRef
|
|
3685
|
+
}
|
|
3640
3686
|
},
|
|
3641
3687
|
directoryContents: (body.directoryContents ?? []).map((file) => ({
|
|
3642
3688
|
path: file.path,
|
|
@@ -3657,6 +3703,19 @@ data: ${JSON.stringify(event)}
|
|
|
3657
3703
|
base64Content: file.content.toString("base64")
|
|
3658
3704
|
}))
|
|
3659
3705
|
});
|
|
3706
|
+
}).post("/v2/autocomplete/:provider/:resource", async (req, res) => {
|
|
3707
|
+
const { token, context } = req.body;
|
|
3708
|
+
const { provider, resource } = req.params;
|
|
3709
|
+
if (!token) throw new errors.InputError("Missing token query parameter");
|
|
3710
|
+
if (!autocompleteHandlers[provider]) {
|
|
3711
|
+
throw new errors.InputError(`Unsupported provider: ${provider}`);
|
|
3712
|
+
}
|
|
3713
|
+
const { results } = await autocompleteHandlers[provider]({
|
|
3714
|
+
resource,
|
|
3715
|
+
token,
|
|
3716
|
+
context
|
|
3717
|
+
});
|
|
3718
|
+
res.status(200).json({ results });
|
|
3660
3719
|
});
|
|
3661
3720
|
const app = express__default.default();
|
|
3662
3721
|
app.set("logger", logger);
|
|
@@ -3677,8 +3736,8 @@ data: ${JSON.stringify(event)}
|
|
|
3677
3736
|
}
|
|
3678
3737
|
const [parameterDecision, stepDecision] = await permissions.authorizeConditional(
|
|
3679
3738
|
[
|
|
3680
|
-
{ permission: alpha.templateParameterReadPermission },
|
|
3681
|
-
{ permission: alpha.templateStepReadPermission }
|
|
3739
|
+
{ permission: alpha$1.templateParameterReadPermission },
|
|
3740
|
+
{ permission: alpha$1.templateStepReadPermission }
|
|
3682
3741
|
],
|
|
3683
3742
|
{ credentials }
|
|
3684
3743
|
);
|
|
@@ -3715,4 +3774,4 @@ exports.createRouter = createRouter;
|
|
|
3715
3774
|
exports.createWaitAction = createWaitAction;
|
|
3716
3775
|
exports.scaffolderActionRules = scaffolderActionRules;
|
|
3717
3776
|
exports.scaffolderTemplateRules = scaffolderTemplateRules;
|
|
3718
|
-
//# sourceMappingURL=router-
|
|
3777
|
+
//# sourceMappingURL=router-BpffhBor.cjs.js.map
|