@backstage/plugin-scaffolder-backend 3.2.1-next.0 → 3.3.0-next.1

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,22 @@
1
1
  # @backstage/plugin-scaffolder-backend
2
2
 
3
+ ## 3.3.0-next.1
4
+
5
+ ### Minor Changes
6
+
7
+ - 309b712: Added a new `execute-template` actions registry action that executes a scaffolder template with provided input values and returns a task ID for tracking progress.
8
+
9
+ ### Patch Changes
10
+
11
+ - 4559806: Removed unnecessary empty `examples` array from actions bridged via the actions registry.
12
+ - Updated dependencies
13
+ - @backstage/backend-plugin-api@1.9.0-next.1
14
+ - @backstage/backend-openapi-utils@0.6.8-next.1
15
+ - @backstage/plugin-catalog-node@2.1.1-next.1
16
+ - @backstage/plugin-events-node@0.4.21-next.1
17
+ - @backstage/plugin-permission-node@0.10.12-next.1
18
+ - @backstage/plugin-scaffolder-node@0.13.1-next.1
19
+
3
20
  ## 3.2.1-next.0
4
21
 
5
22
  ### Patch Changes
@@ -0,0 +1,52 @@
1
+ 'use strict';
2
+
3
+ const createExecuteTemplateAction = ({
4
+ actionsRegistry,
5
+ scaffolderService
6
+ }) => {
7
+ actionsRegistry.register({
8
+ name: "execute-template",
9
+ title: "Execute Scaffolder Template",
10
+ attributes: {
11
+ destructive: true,
12
+ readOnly: false,
13
+ idempotent: false
14
+ },
15
+ description: `Executes a Scaffolder template with its template ref and input parameter values.
16
+ The template is run using the credentials provided to this action, and respects any RBAC permissions associated with those credentials.
17
+ Returns a taskId that can be used to track execution progress.
18
+ Use the catalog.get-catalog-entity action to fetch the Template entity and discover its parameter schema and secrets definition before calling this action.`,
19
+ schema: {
20
+ input: (z) => z.object({
21
+ templateRef: z.string().describe(
22
+ 'The template entity reference to execute, e.g. "template:default/my-template"'
23
+ ),
24
+ values: z.record(z.unknown()).describe(
25
+ "Input parameter values required by the template. Use catalog.get-catalog-entity to discover the required parameters for the template."
26
+ ),
27
+ secrets: z.record(z.string()).optional().describe(
28
+ "Optional secrets to pass to the template execution. Use catalog.get-catalog-entity to discover the secrets definition on the Template entity."
29
+ )
30
+ }),
31
+ output: (z) => z.object({
32
+ taskId: z.string().describe(
33
+ "The task ID for the scaffolder execution. Use this to track progress or retrieve logs."
34
+ )
35
+ })
36
+ },
37
+ action: async ({ input, credentials }) => {
38
+ const { taskId } = await scaffolderService.scaffold(
39
+ {
40
+ templateRef: input.templateRef,
41
+ values: input.values,
42
+ ...input.secrets && { secrets: input.secrets }
43
+ },
44
+ { credentials }
45
+ );
46
+ return { output: { taskId } };
47
+ }
48
+ });
49
+ };
50
+
51
+ exports.createExecuteTemplateAction = createExecuteTemplateAction;
52
+ //# sourceMappingURL=createExecuteTemplateAction.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createExecuteTemplateAction.cjs.js","sources":["../../src/actions/createExecuteTemplateAction.ts"],"sourcesContent":["/*\n * Copyright 2026 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { ActionsRegistryService } from '@backstage/backend-plugin-api/alpha';\nimport { ScaffolderService } from '@backstage/plugin-scaffolder-node';\nimport { JsonValue } from '@backstage/types';\n\nexport const createExecuteTemplateAction = ({\n actionsRegistry,\n scaffolderService,\n}: {\n actionsRegistry: ActionsRegistryService;\n scaffolderService: ScaffolderService;\n}) => {\n actionsRegistry.register({\n name: 'execute-template',\n title: 'Execute Scaffolder Template',\n attributes: {\n destructive: true,\n readOnly: false,\n idempotent: false,\n },\n description: `Executes a Scaffolder template with its template ref and input parameter values.\nThe template is run using the credentials provided to this action, and respects any RBAC permissions associated with those credentials.\nReturns a taskId that can be used to track execution progress.\nUse the catalog.get-catalog-entity action to fetch the Template entity and discover its parameter schema and secrets definition before calling this action.`,\n schema: {\n input: z =>\n z.object({\n templateRef: z\n .string()\n .describe(\n 'The template entity reference to execute, e.g. \"template:default/my-template\"',\n ),\n values: z\n .record(z.unknown())\n .describe(\n 'Input parameter values required by the template. Use catalog.get-catalog-entity to discover the required parameters for the template.',\n ),\n secrets: z\n .record(z.string())\n .optional()\n .describe(\n 'Optional secrets to pass to the template execution. Use catalog.get-catalog-entity to discover the secrets definition on the Template entity.',\n ),\n }),\n output: z =>\n z.object({\n taskId: z\n .string()\n .describe(\n 'The task ID for the scaffolder execution. Use this to track progress or retrieve logs.',\n ),\n }),\n },\n action: async ({ input, credentials }) => {\n const { taskId } = await scaffolderService.scaffold(\n {\n templateRef: input.templateRef,\n values: input.values as Record<string, JsonValue>,\n ...(input.secrets && { secrets: input.secrets }),\n },\n { credentials },\n );\n\n return { output: { taskId } };\n },\n });\n};\n"],"names":[],"mappings":";;AAmBO,MAAM,8BAA8B,CAAC;AAAA,EAC1C,eAAA;AAAA,EACA;AACF,CAAA,KAGM;AACJ,EAAA,eAAA,CAAgB,QAAA,CAAS;AAAA,IACvB,IAAA,EAAM,kBAAA;AAAA,IACN,KAAA,EAAO,6BAAA;AAAA,IACP,UAAA,EAAY;AAAA,MACV,WAAA,EAAa,IAAA;AAAA,MACb,QAAA,EAAU,KAAA;AAAA,MACV,UAAA,EAAY;AAAA,KACd;AAAA,IACA,WAAA,EAAa,CAAA;AAAA;AAAA;AAAA,2JAAA,CAAA;AAAA,IAIb,MAAA,EAAQ;AAAA,MACN,KAAA,EAAO,CAAA,CAAA,KACL,CAAA,CAAE,MAAA,CAAO;AAAA,QACP,WAAA,EAAa,CAAA,CACV,MAAA,EAAO,CACP,QAAA;AAAA,UACC;AAAA,SACF;AAAA,QACF,QAAQ,CAAA,CACL,MAAA,CAAO,CAAA,CAAE,OAAA,EAAS,CAAA,CAClB,QAAA;AAAA,UACC;AAAA,SACF;AAAA,QACF,OAAA,EAAS,EACN,MAAA,CAAO,CAAA,CAAE,QAAQ,CAAA,CACjB,UAAS,CACT,QAAA;AAAA,UACC;AAAA;AACF,OACH,CAAA;AAAA,MACH,MAAA,EAAQ,CAAA,CAAA,KACN,CAAA,CAAE,MAAA,CAAO;AAAA,QACP,MAAA,EAAQ,CAAA,CACL,MAAA,EAAO,CACP,QAAA;AAAA,UACC;AAAA;AACF,OACH;AAAA,KACL;AAAA,IACA,MAAA,EAAQ,OAAO,EAAE,KAAA,EAAO,aAAY,KAAM;AACxC,MAAA,MAAM,EAAE,MAAA,EAAO,GAAI,MAAM,iBAAA,CAAkB,QAAA;AAAA,QACzC;AAAA,UACE,aAAa,KAAA,CAAM,WAAA;AAAA,UACnB,QAAQ,KAAA,CAAM,MAAA;AAAA,UACd,GAAI,KAAA,CAAM,OAAA,IAAW,EAAE,OAAA,EAAS,MAAM,OAAA;AAAQ,SAChD;AAAA,QACA,EAAE,WAAA;AAAY,OAChB;AAEA,MAAA,OAAO,EAAE,MAAA,EAAQ,EAAE,MAAA,EAAO,EAAE;AAAA,IAC9B;AAAA,GACD,CAAA;AACH;;;;"}
@@ -3,6 +3,7 @@
3
3
  var listScaffolderTasksAction = require('./listScaffolderTasksAction.cjs.js');
4
4
  var createDryRunTemplateAction = require('./createDryRunTemplateAction.cjs.js');
5
5
  var createListScaffolderActionsAction = require('./createListScaffolderActionsAction.cjs.js');
6
+ var createExecuteTemplateAction = require('./createExecuteTemplateAction.cjs.js');
6
7
  var createGetScaffolderTaskLogsAction = require('./createGetScaffolderTaskLogsAction.cjs.js');
7
8
 
8
9
  const createScaffolderActions = (options) => {
@@ -13,6 +14,7 @@ const createScaffolderActions = (options) => {
13
14
  });
14
15
  createDryRunTemplateAction.createDryRunTemplateAction(options);
15
16
  createListScaffolderActionsAction.createListScaffolderActionsAction(options);
17
+ createExecuteTemplateAction.createExecuteTemplateAction(options);
16
18
  createGetScaffolderTaskLogsAction.createGetScaffolderTaskLogsAction(options);
17
19
  };
18
20
 
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs.js","sources":["../../src/actions/index.ts"],"sourcesContent":["/*\n * Copyright 2026 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { ActionsRegistryService } from '@backstage/backend-plugin-api/alpha';\nimport { AuthService } from '@backstage/backend-plugin-api';\nimport { createListScaffolderTasksAction } from './listScaffolderTasksAction';\nimport { ScaffolderService } from '@backstage/plugin-scaffolder-node';\nimport { createDryRunTemplateAction } from './createDryRunTemplateAction';\nimport { createListScaffolderActionsAction } from './createListScaffolderActionsAction';\nimport { createGetScaffolderTaskLogsAction } from './createGetScaffolderTaskLogsAction';\n\nexport const createScaffolderActions = (options: {\n actionsRegistry: ActionsRegistryService;\n scaffolderService: ScaffolderService;\n auth: AuthService;\n}) => {\n createListScaffolderTasksAction({\n actionsRegistry: options.actionsRegistry,\n auth: options.auth,\n scaffolderService: options.scaffolderService,\n });\n createDryRunTemplateAction(options);\n createListScaffolderActionsAction(options);\n createGetScaffolderTaskLogsAction(options);\n};\n"],"names":["createListScaffolderTasksAction","createDryRunTemplateAction","createListScaffolderActionsAction","createGetScaffolderTaskLogsAction"],"mappings":";;;;;;;AAuBO,MAAM,uBAAA,GAA0B,CAAC,OAAA,KAIlC;AACJ,EAAAA,yDAAA,CAAgC;AAAA,IAC9B,iBAAiB,OAAA,CAAQ,eAAA;AAAA,IACzB,MAAM,OAAA,CAAQ,IAAA;AAAA,IACd,mBAAmB,OAAA,CAAQ;AAAA,GAC5B,CAAA;AACD,EAAAC,qDAAA,CAA2B,OAAO,CAAA;AAClC,EAAAC,mEAAA,CAAkC,OAAO,CAAA;AACzC,EAAAC,mEAAA,CAAkC,OAAO,CAAA;AAC3C;;;;"}
1
+ {"version":3,"file":"index.cjs.js","sources":["../../src/actions/index.ts"],"sourcesContent":["/*\n * Copyright 2026 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { ActionsRegistryService } from '@backstage/backend-plugin-api/alpha';\nimport { AuthService } from '@backstage/backend-plugin-api';\nimport { createListScaffolderTasksAction } from './listScaffolderTasksAction';\nimport { ScaffolderService } from '@backstage/plugin-scaffolder-node';\nimport { createDryRunTemplateAction } from './createDryRunTemplateAction';\nimport { createListScaffolderActionsAction } from './createListScaffolderActionsAction';\nimport { createExecuteTemplateAction } from './createExecuteTemplateAction';\nimport { createGetScaffolderTaskLogsAction } from './createGetScaffolderTaskLogsAction';\n\nexport const createScaffolderActions = (options: {\n actionsRegistry: ActionsRegistryService;\n scaffolderService: ScaffolderService;\n auth: AuthService;\n}) => {\n createListScaffolderTasksAction({\n actionsRegistry: options.actionsRegistry,\n auth: options.auth,\n scaffolderService: options.scaffolderService,\n });\n createDryRunTemplateAction(options);\n createListScaffolderActionsAction(options);\n createExecuteTemplateAction(options);\n createGetScaffolderTaskLogsAction(options);\n};\n"],"names":["createListScaffolderTasksAction","createDryRunTemplateAction","createListScaffolderActionsAction","createExecuteTemplateAction","createGetScaffolderTaskLogsAction"],"mappings":";;;;;;;;AAwBO,MAAM,uBAAA,GAA0B,CAAC,OAAA,KAIlC;AACJ,EAAAA,yDAAA,CAAgC;AAAA,IAC9B,iBAAiB,OAAA,CAAQ,eAAA;AAAA,IACzB,MAAM,OAAA,CAAQ,IAAA;AAAA,IACd,mBAAmB,OAAA,CAAQ;AAAA,GAC5B,CAAA;AACD,EAAAC,qDAAA,CAA2B,OAAO,CAAA;AAClC,EAAAC,mEAAA,CAAkC,OAAO,CAAA;AACzC,EAAAC,uDAAA,CAA4B,OAAO,CAAA;AACnC,EAAAC,mEAAA,CAAkC,OAAO,CAAA;AAC3C;;;;"}
package/dist/index.d.ts CHANGED
@@ -8,7 +8,7 @@ import { HumanDuration } from '@backstage/types';
8
8
  import { Duration } from 'luxon';
9
9
  import { PermissionRule } from '@backstage/plugin-permission-node';
10
10
  import { TemplateEntityStepV1beta3, TemplateParametersV1beta3 } from '@backstage/plugin-scaffolder-common';
11
- import { RESOURCE_TYPE_SCAFFOLDER_TEMPLATE, RESOURCE_TYPE_SCAFFOLDER_ACTION } from '@backstage/plugin-scaffolder-common/alpha';
11
+ import { RESOURCE_TYPE_SCAFFOLDER_ACTION, RESOURCE_TYPE_SCAFFOLDER_TEMPLATE } from '@backstage/plugin-scaffolder-common/alpha';
12
12
  import { PermissionRuleParams } from '@backstage/plugin-permission-common';
13
13
 
14
14
  /**
@@ -1,14 +1,14 @@
1
1
  'use strict';
2
2
 
3
- var filter = require('./parseRepoUrl/filter.cjs.js');
4
- var filter$1 = require('./parseEntityRef/filter.cjs.js');
5
- var filter$2 = require('./pick/filter.cjs.js');
3
+ var filter$2 = require('./parseRepoUrl/filter.cjs.js');
4
+ var filter = require('./parseEntityRef/filter.cjs.js');
5
+ var filter$1 = require('./pick/filter.cjs.js');
6
6
  var filter$3 = require('./projectSlug/filter.cjs.js');
7
7
 
8
8
  const createDefaultFilters = (options) => [
9
- filter.createParseRepoUrl(options.integrations),
10
- filter$1.parseEntityRef,
11
- filter$2.pick,
9
+ filter$2.createParseRepoUrl(options.integrations),
10
+ filter.parseEntityRef,
11
+ filter$1.pick,
12
12
  filter$3.createProjectSlug(options.integrations)
13
13
  ];
14
14
 
@@ -1 +1 @@
1
- {"version":3,"file":"createDefaultFilters.cjs.js","sources":["../../../../src/lib/templating/filters/createDefaultFilters.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { ScmIntegrations } from '@backstage/integration';\nimport { createParseRepoUrl } from './parseRepoUrl';\nimport { parseEntityRef } from './parseEntityRef';\nimport { pick } from './pick';\nimport { createProjectSlug } from './projectSlug';\n\nexport const createDefaultFilters = (options: {\n integrations: ScmIntegrations;\n}) => [\n createParseRepoUrl(options.integrations),\n parseEntityRef,\n pick,\n createProjectSlug(options.integrations),\n];\n"],"names":["createParseRepoUrl","parseEntityRef","pick","createProjectSlug"],"mappings":";;;;;;;AAqBO,MAAM,oBAAA,GAAuB,CAAC,OAAA,KAE/B;AAAA,EACJA,yBAAA,CAAmB,QAAQ,YAAY,CAAA;AAAA,EACvCC,uBAAA;AAAA,EACAC,aAAA;AAAA,EACAC,0BAAA,CAAkB,QAAQ,YAAY;AACxC;;;;"}
1
+ {"version":3,"file":"createDefaultFilters.cjs.js","sources":["../../../../src/lib/templating/filters/createDefaultFilters.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { ScmIntegrations } from '@backstage/integration';\nimport { createParseRepoUrl } from './parseRepoUrl';\nimport { parseEntityRef } from './parseEntityRef';\nimport { pick } from './pick';\nimport { createProjectSlug } from './projectSlug';\n\nexport const createDefaultFilters = (options: {\n integrations: ScmIntegrations;\n}) => [\n createParseRepoUrl(options.integrations),\n parseEntityRef,\n pick,\n createProjectSlug(options.integrations),\n];\n"],"names":["createParseRepoUrl","parseEntityRef","pick","createProjectSlug"],"mappings":";;;;;;;AAqBO,MAAM,oBAAA,GAAuB,CAAC,OAAA,KAE/B;AAAA,EACJA,2BAAA,CAAmB,QAAQ,YAAY,CAAA;AAAA,EACvCC,qBAAA;AAAA,EACAC,aAAA;AAAA,EACAC,0BAAA,CAAkB,QAAQ,YAAY;AACxC;;;;"}
@@ -41,7 +41,6 @@ class DefaultTemplateActionRegistry {
41
41
  ret.set(action.id, {
42
42
  id: action.id,
43
43
  description: action.description,
44
- examples: [],
45
44
  supportsDryRun: action.attributes?.readOnly === true && action.attributes?.destructive === false,
46
45
  handler: async (ctx) => {
47
46
  const { output } = await this.actionsRegistry.invoke({
@@ -1 +1 @@
1
- {"version":3,"file":"TemplateActionRegistry.cjs.js","sources":["../../../src/scaffolder/actions/TemplateActionRegistry.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 { ConflictError, NotFoundError } from '@backstage/errors';\nimport { TemplateAction } from '@backstage/plugin-scaffolder-node';\nimport { ActionsService } from '@backstage/backend-plugin-api/alpha';\nimport {\n BackstageCredentials,\n LoggerService,\n} from '@backstage/backend-plugin-api';\nimport { isPlainObject } from 'lodash';\nimport { Schema } from 'jsonschema';\nimport { JsonObject } from '@backstage/types';\n\n/**\n * @internal\n */\nexport interface TemplateActionRegistry {\n register(action: TemplateAction<any, any, any>): void;\n get(\n actionId: string,\n options: { credentials: BackstageCredentials },\n ): Promise<TemplateAction<any, any, any>>;\n list(options: {\n credentials: BackstageCredentials;\n }): Promise<Map<string, TemplateAction<any, any, any>>>;\n}\n\n/**\n * Registry of all registered template actions.\n */\nexport class DefaultTemplateActionRegistry implements TemplateActionRegistry {\n private readonly actions = new Map<string, TemplateAction>();\n\n constructor(\n private readonly actionsRegistry: ActionsService,\n private readonly logger: LoggerService,\n ) {}\n\n register(action: TemplateAction<any, any, any>) {\n if (this.actions.has(action.id)) {\n throw new ConflictError(\n `Template action with ID '${action.id}' has already been registered`,\n );\n }\n\n this.actions.set(action.id, action);\n }\n\n async get(\n actionId: string,\n options: { credentials: BackstageCredentials },\n ): Promise<TemplateAction<any, any, any>> {\n const action = (await this.list(options)).get(actionId);\n if (!action) {\n throw new NotFoundError(\n `Template action with ID '${actionId}' is not registered. See https://backstage.io/docs/features/software-templates/builtin-actions/ on how to add a new action module.`,\n );\n }\n return action;\n }\n\n async list(options: {\n credentials: BackstageCredentials;\n }): Promise<Map<string, TemplateAction<any, any, any>>> {\n const ret = new Map(this.actions);\n\n const { actions } = await this.actionsRegistry.list({\n credentials: options.credentials,\n });\n\n for (const action of actions) {\n if (ret.has(action.id)) {\n this.logger.warn(\n `Template action with ID '${action.id}' has already been registered, skipping action provided by actions service`,\n );\n continue;\n }\n\n ret.set(action.id, {\n id: action.id,\n description: action.description,\n examples: [],\n supportsDryRun:\n action.attributes?.readOnly === true &&\n action.attributes?.destructive === false,\n handler: async ctx => {\n const { output } = await this.actionsRegistry.invoke({\n id: action.id,\n input: ctx.input,\n credentials: await ctx.getInitiatorCredentials(),\n });\n\n if (isPlainObject(output)) {\n for (const [key, value] of Object.entries(output as JsonObject)) {\n ctx.output(key as keyof typeof output, value);\n }\n }\n },\n schema: {\n input: action.schema.input as Schema,\n output: action.schema.output as Schema,\n },\n });\n }\n return ret;\n }\n}\n"],"names":["ConflictError","NotFoundError","isPlainObject"],"mappings":";;;;;AA4CO,MAAM,6BAAA,CAAgE;AAAA,EAG3E,WAAA,CACmB,iBACA,MAAA,EACjB;AAFiB,IAAA,IAAA,CAAA,eAAA,GAAA,eAAA;AACA,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAAA,EAChB;AAAA,EALc,OAAA,uBAAc,GAAA,EAA4B;AAAA,EAO3D,SAAS,MAAA,EAAuC;AAC9C,IAAA,IAAI,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,MAAA,CAAO,EAAE,CAAA,EAAG;AAC/B,MAAA,MAAM,IAAIA,oBAAA;AAAA,QACR,CAAA,yBAAA,EAA4B,OAAO,EAAE,CAAA,6BAAA;AAAA,OACvC;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,MAAA,CAAO,EAAA,EAAI,MAAM,CAAA;AAAA,EACpC;AAAA,EAEA,MAAM,GAAA,CACJ,QAAA,EACA,OAAA,EACwC;AACxC,IAAA,MAAM,UAAU,MAAM,IAAA,CAAK,KAAK,OAAO,CAAA,EAAG,IAAI,QAAQ,CAAA;AACtD,IAAA,IAAI,CAAC,MAAA,EAAQ;AACX,MAAA,MAAM,IAAIC,oBAAA;AAAA,QACR,4BAA4B,QAAQ,CAAA,kIAAA;AAAA,OACtC;AAAA,IACF;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AAAA,EAEA,MAAM,KAAK,OAAA,EAE6C;AACtD,IAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,IAAA,CAAK,OAAO,CAAA;AAEhC,IAAA,MAAM,EAAE,OAAA,EAAQ,GAAI,MAAM,IAAA,CAAK,gBAAgB,IAAA,CAAK;AAAA,MAClD,aAAa,OAAA,CAAQ;AAAA,KACtB,CAAA;AAED,IAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,MAAA,IAAI,GAAA,CAAI,GAAA,CAAI,MAAA,CAAO,EAAE,CAAA,EAAG;AACtB,QAAA,IAAA,CAAK,MAAA,CAAO,IAAA;AAAA,UACV,CAAA,yBAAA,EAA4B,OAAO,EAAE,CAAA,0EAAA;AAAA,SACvC;AACA,QAAA;AAAA,MACF;AAEA,MAAA,GAAA,CAAI,GAAA,CAAI,OAAO,EAAA,EAAI;AAAA,QACjB,IAAI,MAAA,CAAO,EAAA;AAAA,QACX,aAAa,MAAA,CAAO,WAAA;AAAA,QACpB,UAAU,EAAC;AAAA,QACX,gBACE,MAAA,CAAO,UAAA,EAAY,aAAa,IAAA,IAChC,MAAA,CAAO,YAAY,WAAA,KAAgB,KAAA;AAAA,QACrC,OAAA,EAAS,OAAM,GAAA,KAAO;AACpB,UAAA,MAAM,EAAE,MAAA,EAAO,GAAI,MAAM,IAAA,CAAK,gBAAgB,MAAA,CAAO;AAAA,YACnD,IAAI,MAAA,CAAO,EAAA;AAAA,YACX,OAAO,GAAA,CAAI,KAAA;AAAA,YACX,WAAA,EAAa,MAAM,GAAA,CAAI,uBAAA;AAAwB,WAChD,CAAA;AAED,UAAA,IAAIC,oBAAA,CAAc,MAAM,CAAA,EAAG;AACzB,YAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,MAAoB,CAAA,EAAG;AAC/D,cAAA,GAAA,CAAI,MAAA,CAAO,KAA4B,KAAK,CAAA;AAAA,YAC9C;AAAA,UACF;AAAA,QACF,CAAA;AAAA,QACA,MAAA,EAAQ;AAAA,UACN,KAAA,EAAO,OAAO,MAAA,CAAO,KAAA;AAAA,UACrB,MAAA,EAAQ,OAAO,MAAA,CAAO;AAAA;AACxB,OACD,CAAA;AAAA,IACH;AACA,IAAA,OAAO,GAAA;AAAA,EACT;AACF;;;;"}
1
+ {"version":3,"file":"TemplateActionRegistry.cjs.js","sources":["../../../src/scaffolder/actions/TemplateActionRegistry.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 { ConflictError, NotFoundError } from '@backstage/errors';\nimport { TemplateAction } from '@backstage/plugin-scaffolder-node';\nimport { ActionsService } from '@backstage/backend-plugin-api/alpha';\nimport {\n BackstageCredentials,\n LoggerService,\n} from '@backstage/backend-plugin-api';\nimport { isPlainObject } from 'lodash';\nimport { Schema } from 'jsonschema';\nimport { JsonObject } from '@backstage/types';\n\n/**\n * @internal\n */\nexport interface TemplateActionRegistry {\n register(action: TemplateAction<any, any, any>): void;\n get(\n actionId: string,\n options: { credentials: BackstageCredentials },\n ): Promise<TemplateAction<any, any, any>>;\n list(options: {\n credentials: BackstageCredentials;\n }): Promise<Map<string, TemplateAction<any, any, any>>>;\n}\n\n/**\n * Registry of all registered template actions.\n */\nexport class DefaultTemplateActionRegistry implements TemplateActionRegistry {\n private readonly actions = new Map<string, TemplateAction>();\n\n constructor(\n private readonly actionsRegistry: ActionsService,\n private readonly logger: LoggerService,\n ) {}\n\n register(action: TemplateAction<any, any, any>) {\n if (this.actions.has(action.id)) {\n throw new ConflictError(\n `Template action with ID '${action.id}' has already been registered`,\n );\n }\n\n this.actions.set(action.id, action);\n }\n\n async get(\n actionId: string,\n options: { credentials: BackstageCredentials },\n ): Promise<TemplateAction<any, any, any>> {\n const action = (await this.list(options)).get(actionId);\n if (!action) {\n throw new NotFoundError(\n `Template action with ID '${actionId}' is not registered. See https://backstage.io/docs/features/software-templates/builtin-actions/ on how to add a new action module.`,\n );\n }\n return action;\n }\n\n async list(options: {\n credentials: BackstageCredentials;\n }): Promise<Map<string, TemplateAction<any, any, any>>> {\n const ret = new Map(this.actions);\n\n const { actions } = await this.actionsRegistry.list({\n credentials: options.credentials,\n });\n\n for (const action of actions) {\n if (ret.has(action.id)) {\n this.logger.warn(\n `Template action with ID '${action.id}' has already been registered, skipping action provided by actions service`,\n );\n continue;\n }\n\n ret.set(action.id, {\n id: action.id,\n description: action.description,\n supportsDryRun:\n action.attributes?.readOnly === true &&\n action.attributes?.destructive === false,\n handler: async ctx => {\n const { output } = await this.actionsRegistry.invoke({\n id: action.id,\n input: ctx.input,\n credentials: await ctx.getInitiatorCredentials(),\n });\n\n if (isPlainObject(output)) {\n for (const [key, value] of Object.entries(output as JsonObject)) {\n ctx.output(key as keyof typeof output, value);\n }\n }\n },\n schema: {\n input: action.schema.input as Schema,\n output: action.schema.output as Schema,\n },\n });\n }\n return ret;\n }\n}\n"],"names":["ConflictError","NotFoundError","isPlainObject"],"mappings":";;;;;AA4CO,MAAM,6BAAA,CAAgE;AAAA,EAG3E,WAAA,CACmB,iBACA,MAAA,EACjB;AAFiB,IAAA,IAAA,CAAA,eAAA,GAAA,eAAA;AACA,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAAA,EAChB;AAAA,EALc,OAAA,uBAAc,GAAA,EAA4B;AAAA,EAO3D,SAAS,MAAA,EAAuC;AAC9C,IAAA,IAAI,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,MAAA,CAAO,EAAE,CAAA,EAAG;AAC/B,MAAA,MAAM,IAAIA,oBAAA;AAAA,QACR,CAAA,yBAAA,EAA4B,OAAO,EAAE,CAAA,6BAAA;AAAA,OACvC;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,MAAA,CAAO,EAAA,EAAI,MAAM,CAAA;AAAA,EACpC;AAAA,EAEA,MAAM,GAAA,CACJ,QAAA,EACA,OAAA,EACwC;AACxC,IAAA,MAAM,UAAU,MAAM,IAAA,CAAK,KAAK,OAAO,CAAA,EAAG,IAAI,QAAQ,CAAA;AACtD,IAAA,IAAI,CAAC,MAAA,EAAQ;AACX,MAAA,MAAM,IAAIC,oBAAA;AAAA,QACR,4BAA4B,QAAQ,CAAA,kIAAA;AAAA,OACtC;AAAA,IACF;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AAAA,EAEA,MAAM,KAAK,OAAA,EAE6C;AACtD,IAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,IAAA,CAAK,OAAO,CAAA;AAEhC,IAAA,MAAM,EAAE,OAAA,EAAQ,GAAI,MAAM,IAAA,CAAK,gBAAgB,IAAA,CAAK;AAAA,MAClD,aAAa,OAAA,CAAQ;AAAA,KACtB,CAAA;AAED,IAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,MAAA,IAAI,GAAA,CAAI,GAAA,CAAI,MAAA,CAAO,EAAE,CAAA,EAAG;AACtB,QAAA,IAAA,CAAK,MAAA,CAAO,IAAA;AAAA,UACV,CAAA,yBAAA,EAA4B,OAAO,EAAE,CAAA,0EAAA;AAAA,SACvC;AACA,QAAA;AAAA,MACF;AAEA,MAAA,GAAA,CAAI,GAAA,CAAI,OAAO,EAAA,EAAI;AAAA,QACjB,IAAI,MAAA,CAAO,EAAA;AAAA,QACX,aAAa,MAAA,CAAO,WAAA;AAAA,QACpB,gBACE,MAAA,CAAO,UAAA,EAAY,aAAa,IAAA,IAChC,MAAA,CAAO,YAAY,WAAA,KAAgB,KAAA;AAAA,QACrC,OAAA,EAAS,OAAM,GAAA,KAAO;AACpB,UAAA,MAAM,EAAE,MAAA,EAAO,GAAI,MAAM,IAAA,CAAK,gBAAgB,MAAA,CAAO;AAAA,YACnD,IAAI,MAAA,CAAO,EAAA;AAAA,YACX,OAAO,GAAA,CAAI,KAAA;AAAA,YACX,WAAA,EAAa,MAAM,GAAA,CAAI,uBAAA;AAAwB,WAChD,CAAA;AAED,UAAA,IAAIC,oBAAA,CAAc,MAAM,CAAA,EAAG;AACzB,YAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,MAAoB,CAAA,EAAG;AAC/D,cAAA,GAAA,CAAI,MAAA,CAAO,KAA4B,KAAK,CAAA;AAAA,YAC9C;AAAA,UACF;AAAA,QACF,CAAA;AAAA,QACA,MAAA,EAAQ;AAAA,UACN,KAAA,EAAO,OAAO,MAAA,CAAO,KAAA;AAAA,UACrB,MAAA,EAAQ,OAAO,MAAA,CAAO;AAAA;AACxB,OACD,CAAA;AAAA,IACH;AACA,IAAA,OAAO,GAAA;AAAA,EACT;AACF;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/plugin-scaffolder-backend",
3
- "version": "3.2.1-next.0",
3
+ "version": "3.3.0-next.1",
4
4
  "description": "The Backstage backend plugin that helps you create new things",
5
5
  "backstage": {
6
6
  "role": "backend-plugin",
@@ -77,18 +77,18 @@
77
77
  "test": "backstage-cli package test"
78
78
  },
79
79
  "dependencies": {
80
- "@backstage/backend-openapi-utils": "0.6.8-next.0",
81
- "@backstage/backend-plugin-api": "1.8.1-next.0",
80
+ "@backstage/backend-openapi-utils": "0.6.8-next.1",
81
+ "@backstage/backend-plugin-api": "1.9.0-next.1",
82
82
  "@backstage/catalog-model": "1.7.7",
83
83
  "@backstage/config": "1.3.6",
84
84
  "@backstage/errors": "1.2.7",
85
85
  "@backstage/integration": "2.0.0",
86
- "@backstage/plugin-catalog-node": "2.1.1-next.0",
87
- "@backstage/plugin-events-node": "0.4.21-next.0",
86
+ "@backstage/plugin-catalog-node": "2.1.1-next.1",
87
+ "@backstage/plugin-events-node": "0.4.21-next.1",
88
88
  "@backstage/plugin-permission-common": "0.9.7",
89
- "@backstage/plugin-permission-node": "0.10.12-next.0",
89
+ "@backstage/plugin-permission-node": "0.10.12-next.1",
90
90
  "@backstage/plugin-scaffolder-common": "2.0.0",
91
- "@backstage/plugin-scaffolder-node": "0.13.1-next.0",
91
+ "@backstage/plugin-scaffolder-node": "0.13.1-next.1",
92
92
  "@backstage/types": "1.2.2",
93
93
  "@opentelemetry/api": "^1.9.0",
94
94
  "@types/luxon": "^3.0.0",
@@ -115,11 +115,11 @@
115
115
  "zod-to-json-schema": "^3.25.1"
116
116
  },
117
117
  "devDependencies": {
118
- "@backstage/backend-defaults": "0.16.1-next.0",
119
- "@backstage/backend-test-utils": "1.11.2-next.0",
120
- "@backstage/cli": "0.36.1-next.0",
121
- "@backstage/plugin-scaffolder-node-test-utils": "0.3.10-next.0",
122
- "@backstage/repo-tools": "0.17.1-next.0",
118
+ "@backstage/backend-defaults": "0.16.1-next.1",
119
+ "@backstage/backend-test-utils": "1.11.2-next.1",
120
+ "@backstage/cli": "0.36.1-next.1",
121
+ "@backstage/plugin-scaffolder-node-test-utils": "0.3.10-next.1",
122
+ "@backstage/repo-tools": "0.17.1-next.1",
123
123
  "@types/express": "^4.17.6",
124
124
  "@types/fs-extra": "^11.0.0",
125
125
  "@types/nunjucks": "^3.1.4",