@backstage/plugin-scaffolder-backend 3.1.4 → 3.2.0-next.2

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,12 +1,70 @@
1
1
  # @backstage/plugin-scaffolder-backend
2
2
 
3
- ## 3.1.4
3
+ ## 3.2.0-next.2
4
+
5
+ ### Minor Changes
6
+
7
+ - e8736ea: Added secrets schema validation for task creation, retry, and dry-run endpoints. When a template defines `spec.secrets.schema`, the API validates provided secrets against the schema and returns a `400` error if validation fails.
8
+
9
+ ### Patch Changes
10
+
11
+ - 30ff981: Fixed a security vulnerability where secrets could bypass log redaction when transformed through Nunjucks filters in scaffolder templates.
12
+ - Updated dependencies
13
+ - @backstage/backend-plugin-api@1.8.0-next.1
14
+ - @backstage/integration@2.0.0-next.2
15
+ - @backstage/plugin-scaffolder-common@2.0.0-next.2
16
+ - @backstage/backend-openapi-utils@0.6.7-next.1
17
+ - @backstage/plugin-catalog-node@2.1.0-next.2
18
+ - @backstage/plugin-events-node@0.4.20-next.1
19
+ - @backstage/plugin-permission-node@0.10.11-next.1
20
+ - @backstage/plugin-scaffolder-node@0.13.0-next.2
21
+
22
+ ## 3.2.0-next.1
23
+
24
+ ### Minor Changes
25
+
26
+ - c9b11eb: Added a new `list-scaffolder-tasks` action that allows querying scaffolder tasks with optional ownership filtering and pagination support
27
+ - 0fbcf23: Migrated OpenAPI schemas to 3.1.
28
+ - 7695dd2: Added a new `list-scaffolder-actions` action that returns all installed scaffolder actions with their schemas and examples
29
+
30
+ ### Patch Changes
31
+
32
+ - e27bd4e: Removed `@backstage/plugin-scaffolder-backend-module-bitbucket` from `package.json` as the package itself has been deprecated and the code deleted.
33
+ - ccc20cf: create scaffolder MCP action to dry run a provided scaffolder template
34
+ - Updated dependencies
35
+ - @backstage/integration@2.0.0-next.1
36
+ - @backstage/plugin-scaffolder-common@2.0.0-next.1
37
+ - @backstage/plugin-scaffolder-node@0.13.0-next.1
38
+ - @backstage/plugin-catalog-node@2.1.0-next.1
39
+ - @backstage/backend-openapi-utils@0.6.7-next.0
40
+ - @backstage/backend-plugin-api@1.7.1-next.0
41
+ - @backstage/catalog-model@1.7.6
42
+ - @backstage/config@1.3.6
43
+ - @backstage/errors@1.2.7
44
+ - @backstage/types@1.2.2
45
+ - @backstage/plugin-events-node@0.4.20-next.0
46
+ - @backstage/plugin-permission-common@0.9.6
47
+ - @backstage/plugin-permission-node@0.10.11-next.0
48
+
49
+ ## 3.1.4-next.0
4
50
 
5
51
  ### Patch Changes
6
52
 
7
- - 3532fc2: Fixed a security vulnerability where secrets could bypass log redaction when transformed through Nunjucks filters in scaffolder templates.
53
+ - 4e39e63: Removed unused dependencies
8
54
  - Updated dependencies
9
- - @backstage/integration@1.20.1
55
+ - @backstage/integration@1.21.0-next.0
56
+ - @backstage/plugin-catalog-node@2.1.0-next.0
57
+ - @backstage/backend-plugin-api@1.7.1-next.0
58
+ - @backstage/backend-openapi-utils@0.6.7-next.0
59
+ - @backstage/catalog-model@1.7.6
60
+ - @backstage/config@1.3.6
61
+ - @backstage/errors@1.2.7
62
+ - @backstage/types@1.2.2
63
+ - @backstage/plugin-events-node@0.4.20-next.0
64
+ - @backstage/plugin-permission-common@0.9.6
65
+ - @backstage/plugin-permission-node@0.10.11-next.0
66
+ - @backstage/plugin-scaffolder-common@1.7.7-next.0
67
+ - @backstage/plugin-scaffolder-node@0.12.6-next.0
10
68
 
11
69
  ## 3.1.3
12
70
 
@@ -32,6 +32,7 @@ var router = require('./service/router.cjs.js');
32
32
  var loggerToWinstonLogger = require('./util/loggerToWinstonLogger.cjs.js');
33
33
  var templating = require('./util/templating.cjs.js');
34
34
  var alpha$1 = require('@backstage/backend-plugin-api/alpha');
35
+ var index = require('./actions/index.cjs.js');
35
36
 
36
37
  const scaffolderPlugin = backendPluginApi.createBackendPlugin({
37
38
  pluginId: "scaffolder",
@@ -98,7 +99,9 @@ const scaffolderPlugin = backendPluginApi.createBackendPlugin({
98
99
  auditor: backendPluginApi.coreServices.auditor,
99
100
  catalog: pluginCatalogNode.catalogServiceRef,
100
101
  events: pluginEventsNode.eventsServiceRef,
101
- actionsRegistry: alpha$1.actionsServiceRef
102
+ actionsRegistry: alpha$1.actionsServiceRef,
103
+ actionsRegistryService: alpha$1.actionsRegistryServiceRef,
104
+ scaffolderService: pluginScaffolderNode.scaffolderServiceRef
102
105
  },
103
106
  async init({
104
107
  logger,
@@ -113,7 +116,9 @@ const scaffolderPlugin = backendPluginApi.createBackendPlugin({
113
116
  permissions,
114
117
  events,
115
118
  auditor,
116
- actionsRegistry
119
+ actionsRegistry,
120
+ actionsRegistryService,
121
+ scaffolderService
117
122
  }) {
118
123
  const log$1 = loggerToWinstonLogger.loggerToWinstonLogger(logger);
119
124
  const integrations = integration.ScmIntegrations.fromConfig(config);
@@ -161,6 +166,11 @@ const scaffolderPlugin = backendPluginApi.createBackendPlugin({
161
166
  log$1.info(
162
167
  `Starting scaffolder with the following actions enabled ${actionIds}`
163
168
  );
169
+ index.createScaffolderActions({
170
+ actionsRegistry: actionsRegistryService,
171
+ scaffolderService,
172
+ auth
173
+ });
164
174
  const router$1 = await router.createRouter({
165
175
  logger,
166
176
  config,
@@ -1 +1 @@
1
- {"version":3,"file":"ScaffolderPlugin.cjs.js","sources":["../src/ScaffolderPlugin.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n coreServices,\n createBackendPlugin,\n} from '@backstage/backend-plugin-api';\nimport { ScmIntegrations } from '@backstage/integration';\nimport { catalogServiceRef } from '@backstage/plugin-catalog-node';\nimport { eventsServiceRef } from '@backstage/plugin-events-node';\nimport {\n scaffolderActionsExtensionPoint,\n TaskBroker,\n TemplateAction,\n} from '@backstage/plugin-scaffolder-node';\nimport {\n AutocompleteHandler,\n CreatedTemplateFilter,\n CreatedTemplateGlobal,\n createTemplateFilter,\n createTemplateGlobalFunction,\n createTemplateGlobalValue,\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';\nimport { loggerToWinstonLogger } from './util/loggerToWinstonLogger';\nimport {\n convertFiltersToRecord,\n convertGlobalsToRecord,\n} from './util/templating';\nimport { actionsServiceRef } from '@backstage/backend-plugin-api/alpha';\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: CreatedTemplateFilter<any, any>[] = [];\n const additionalTemplateGlobals: CreatedTemplateGlobal[] = [];\n\n env.registerExtensionPoint(scaffolderTemplatingExtensionPoint, {\n addTemplateFilters(newFilters) {\n additionalTemplateFilters.push(\n ...(Array.isArray(newFilters)\n ? newFilters\n : Object.entries(newFilters).map(([id, filter]) =>\n createTemplateFilter({\n id,\n filter,\n }),\n )),\n );\n },\n addTemplateGlobals(newGlobals) {\n additionalTemplateGlobals.push(\n ...(Array.isArray(newGlobals)\n ? newGlobals\n : Object.entries(newGlobals).map(([id, global]) =>\n typeof global === 'function'\n ? createTemplateGlobalFunction({ id, fn: global })\n : createTemplateGlobalValue({ id, value: global }),\n )),\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 httpRouter: coreServices.httpRouter,\n httpAuth: coreServices.httpAuth,\n auditor: coreServices.auditor,\n catalog: catalogServiceRef,\n events: eventsServiceRef,\n actionsRegistry: actionsServiceRef,\n },\n async init({\n logger,\n config,\n lifecycle,\n reader,\n database,\n auth,\n httpRouter,\n httpAuth,\n catalog,\n permissions,\n events,\n auditor,\n actionsRegistry,\n }) {\n const log = loggerToWinstonLogger(logger);\n const integrations = ScmIntegrations.fromConfig(config);\n\n const templateExtensions = {\n additionalTemplateFilters: convertFiltersToRecord(\n additionalTemplateFilters,\n ),\n additionalTemplateGlobals: convertGlobalsToRecord(\n additionalTemplateGlobals,\n ),\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 ...templateExtensions,\n }),\n createFetchTemplateFileAction({\n integrations,\n reader,\n ...templateExtensions,\n }),\n createDebugLogAction(),\n createWaitAction(),\n // todo(blam): maybe these should be a -catalog module?\n createCatalogRegisterAction({ catalog, integrations }),\n createFetchCatalogEntityAction({ catalog }),\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,\n config,\n database,\n catalog,\n lifecycle,\n actions,\n taskBroker,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n auth,\n httpAuth,\n permissions,\n autocompleteHandlers,\n additionalWorkspaceProviders,\n events,\n auditor,\n actionsRegistry,\n });\n httpRouter.use(router);\n },\n });\n },\n});\n"],"names":["createBackendPlugin","scaffolderActionsExtensionPoint","scaffolderTaskBrokerExtensionPoint","scaffolderTemplatingExtensionPoint","createTemplateFilter","createTemplateGlobalFunction","createTemplateGlobalValue","scaffolderAutocompleteExtensionPoint","scaffolderWorkspaceProviderExtensionPoint","coreServices","catalogServiceRef","eventsServiceRef","actionsServiceRef","log","loggerToWinstonLogger","ScmIntegrations","convertFiltersToRecord","convertGlobalsToRecord","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 {\n coreServices,\n createBackendPlugin,\n} from '@backstage/backend-plugin-api';\nimport { ScmIntegrations } from '@backstage/integration';\nimport { catalogServiceRef } from '@backstage/plugin-catalog-node';\nimport { eventsServiceRef } from '@backstage/plugin-events-node';\nimport {\n scaffolderActionsExtensionPoint,\n scaffolderServiceRef,\n TaskBroker,\n TemplateAction,\n} from '@backstage/plugin-scaffolder-node';\nimport {\n AutocompleteHandler,\n CreatedTemplateFilter,\n CreatedTemplateGlobal,\n createTemplateFilter,\n createTemplateGlobalFunction,\n createTemplateGlobalValue,\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';\nimport { loggerToWinstonLogger } from './util/loggerToWinstonLogger';\nimport {\n convertFiltersToRecord,\n convertGlobalsToRecord,\n} from './util/templating';\nimport {\n actionsServiceRef,\n actionsRegistryServiceRef,\n} from '@backstage/backend-plugin-api/alpha';\nimport { createScaffolderActions } from './actions';\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: CreatedTemplateFilter<any, any>[] = [];\n const additionalTemplateGlobals: CreatedTemplateGlobal[] = [];\n\n env.registerExtensionPoint(scaffolderTemplatingExtensionPoint, {\n addTemplateFilters(newFilters) {\n additionalTemplateFilters.push(\n ...(Array.isArray(newFilters)\n ? newFilters\n : Object.entries(newFilters).map(([id, filter]) =>\n createTemplateFilter({\n id,\n filter,\n }),\n )),\n );\n },\n addTemplateGlobals(newGlobals) {\n additionalTemplateGlobals.push(\n ...(Array.isArray(newGlobals)\n ? newGlobals\n : Object.entries(newGlobals).map(([id, global]) =>\n typeof global === 'function'\n ? createTemplateGlobalFunction({ id, fn: global })\n : createTemplateGlobalValue({ id, value: global }),\n )),\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 httpRouter: coreServices.httpRouter,\n httpAuth: coreServices.httpAuth,\n auditor: coreServices.auditor,\n catalog: catalogServiceRef,\n events: eventsServiceRef,\n actionsRegistry: actionsServiceRef,\n actionsRegistryService: actionsRegistryServiceRef,\n scaffolderService: scaffolderServiceRef,\n },\n async init({\n logger,\n config,\n lifecycle,\n reader,\n database,\n auth,\n httpRouter,\n httpAuth,\n catalog,\n permissions,\n events,\n auditor,\n actionsRegistry,\n actionsRegistryService,\n scaffolderService,\n }) {\n const log = loggerToWinstonLogger(logger);\n const integrations = ScmIntegrations.fromConfig(config);\n\n const templateExtensions = {\n additionalTemplateFilters: convertFiltersToRecord(\n additionalTemplateFilters,\n ),\n additionalTemplateGlobals: convertGlobalsToRecord(\n additionalTemplateGlobals,\n ),\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 ...templateExtensions,\n }),\n createFetchTemplateFileAction({\n integrations,\n reader,\n ...templateExtensions,\n }),\n createDebugLogAction(),\n createWaitAction(),\n // todo(blam): maybe these should be a -catalog module?\n createCatalogRegisterAction({ catalog, integrations }),\n createFetchCatalogEntityAction({ catalog }),\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 createScaffolderActions({\n actionsRegistry: actionsRegistryService,\n scaffolderService,\n auth,\n });\n\n const router = await createRouter({\n logger,\n config,\n database,\n catalog,\n lifecycle,\n actions,\n taskBroker,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n auth,\n httpAuth,\n permissions,\n autocompleteHandlers,\n additionalWorkspaceProviders,\n events,\n auditor,\n actionsRegistry,\n });\n httpRouter.use(router);\n },\n });\n },\n});\n"],"names":["createBackendPlugin","scaffolderActionsExtensionPoint","scaffolderTaskBrokerExtensionPoint","scaffolderTemplatingExtensionPoint","createTemplateFilter","createTemplateGlobalFunction","createTemplateGlobalValue","scaffolderAutocompleteExtensionPoint","scaffolderWorkspaceProviderExtensionPoint","coreServices","catalogServiceRef","eventsServiceRef","actionsServiceRef","actionsRegistryServiceRef","scaffolderServiceRef","log","loggerToWinstonLogger","ScmIntegrations","convertFiltersToRecord","convertGlobalsToRecord","createFetchPlainAction","createFetchPlainFileAction","createFetchTemplateAction","createFetchTemplateFileAction","createDebugLogAction","createWaitAction","createCatalogRegisterAction","createFetchCatalogEntityAction","createCatalogWriteAction","createFilesystemDeleteAction","createFilesystemRenameAction","createFilesystemReadDirAction","createScaffolderActions","router","createRouter"],"mappings":"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"}
@@ -0,0 +1,110 @@
1
+ 'use strict';
2
+
3
+ var yaml = require('yaml');
4
+
5
+ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
6
+
7
+ var yaml__default = /*#__PURE__*/_interopDefaultCompat(yaml);
8
+
9
+ const MAX_CONTENT_SIZE = 64 * 1024;
10
+ function base64EncodeContent(content) {
11
+ if (content.length > MAX_CONTENT_SIZE) {
12
+ return Buffer.from("<file too large>", "utf8").toString("base64");
13
+ }
14
+ return Buffer.from(content, "utf8").toString("base64");
15
+ }
16
+ const createDryRunTemplateAction = ({
17
+ actionsRegistry,
18
+ scaffolderService
19
+ }) => {
20
+ actionsRegistry.register({
21
+ name: "dry-run-template",
22
+ title: "Dry Run Scaffolder Template",
23
+ attributes: {
24
+ destructive: false,
25
+ readOnly: true,
26
+ idempotent: true
27
+ },
28
+ description: "Dry-runs a scaffolder template to validate it without making changes. Returns success with execution logs, or errors for validation failures.",
29
+ schema: {
30
+ input: (z) => z.object({
31
+ templateYaml: z.string().describe(
32
+ "The YAML content of the scaffolder template to validate"
33
+ ),
34
+ values: z.record(z.unknown()).optional().describe("Input values for template parameters"),
35
+ files: z.array(
36
+ z.object({
37
+ path: z.string().describe("File path relative to template root"),
38
+ content: z.string().describe("File content")
39
+ })
40
+ ).optional().describe("Files required for running the template")
41
+ }),
42
+ output: (z) => z.object({
43
+ valid: z.boolean().describe("Whether the template is valid"),
44
+ message: z.string().describe("Success message or validation error details"),
45
+ errors: z.array(z.string()).optional().describe("List of validation errors"),
46
+ log: z.array(
47
+ z.object({
48
+ message: z.string(),
49
+ stepId: z.string().optional(),
50
+ status: z.string().optional()
51
+ })
52
+ ).optional().describe("Execution log from dry-run"),
53
+ output: z.record(z.unknown()).optional().describe("Template output values"),
54
+ steps: z.array(
55
+ z.object({
56
+ id: z.string(),
57
+ name: z.string(),
58
+ action: z.string()
59
+ })
60
+ ).optional().describe("Parsed template steps")
61
+ })
62
+ },
63
+ action: async ({ input, credentials }) => {
64
+ const { templateYaml, values = {}, files = [] } = input;
65
+ let template;
66
+ try {
67
+ template = yaml__default.default.parse(templateYaml);
68
+ } catch (parseError) {
69
+ const yamlError = parseError;
70
+ return {
71
+ output: {
72
+ valid: false,
73
+ message: "Failed to parse YAML template",
74
+ errors: [
75
+ `YAML parsing error: ${yamlError.message}`,
76
+ yamlError.linePos ? `At line ${yamlError.linePos[0].line}, column ${yamlError.linePos[0].col}` : ""
77
+ ].filter(Boolean)
78
+ }
79
+ };
80
+ }
81
+ const result = await scaffolderService.dryRun(
82
+ {
83
+ template,
84
+ values,
85
+ directoryContents: files.map((file) => ({
86
+ path: file.path,
87
+ base64Content: base64EncodeContent(file.content)
88
+ }))
89
+ },
90
+ { credentials }
91
+ );
92
+ return {
93
+ output: {
94
+ valid: true,
95
+ message: "Template validation successful",
96
+ log: result.log?.map((entry) => ({
97
+ message: entry.body.message,
98
+ stepId: entry.body.stepId,
99
+ status: entry.body.status
100
+ })),
101
+ output: result.output,
102
+ steps: result.steps
103
+ }
104
+ };
105
+ }
106
+ });
107
+ };
108
+
109
+ exports.createDryRunTemplateAction = createDryRunTemplateAction;
110
+ //# sourceMappingURL=createDryRunTemplateAction.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createDryRunTemplateAction.cjs.js","sources":["../../src/actions/createDryRunTemplateAction.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 { JsonObject } from '@backstage/types';\nimport yaml from 'yaml';\n\nconst MAX_CONTENT_SIZE = 64 * 1024;\n\nfunction base64EncodeContent(content: string): string {\n if (content.length > MAX_CONTENT_SIZE) {\n return Buffer.from('<file too large>', 'utf8').toString('base64');\n }\n return Buffer.from(content, 'utf8').toString('base64');\n}\n\nexport const createDryRunTemplateAction = ({\n actionsRegistry,\n scaffolderService,\n}: {\n actionsRegistry: ActionsRegistryService;\n scaffolderService: ScaffolderService;\n}) => {\n actionsRegistry.register({\n name: 'dry-run-template',\n title: 'Dry Run Scaffolder Template',\n attributes: {\n destructive: false,\n readOnly: true,\n idempotent: true,\n },\n description:\n 'Dry-runs a scaffolder template to validate it without making changes. Returns success with execution logs, or errors for validation failures.',\n schema: {\n input: z =>\n z.object({\n templateYaml: z\n .string()\n .describe(\n 'The YAML content of the scaffolder template to validate',\n ),\n values: z\n .record(z.unknown())\n .optional()\n .describe('Input values for template parameters'),\n files: z\n .array(\n z.object({\n path: z\n .string()\n .describe('File path relative to template root'),\n content: z.string().describe('File content'),\n }),\n )\n .optional()\n .describe('Files required for running the template'),\n }),\n output: z =>\n z.object({\n valid: z.boolean().describe('Whether the template is valid'),\n message: z\n .string()\n .describe('Success message or validation error details'),\n errors: z\n .array(z.string())\n .optional()\n .describe('List of validation errors'),\n log: z\n .array(\n z.object({\n message: z.string(),\n stepId: z.string().optional(),\n status: z.string().optional(),\n }),\n )\n .optional()\n .describe('Execution log from dry-run'),\n output: z\n .record(z.unknown())\n .optional()\n .describe('Template output values'),\n steps: z\n .array(\n z.object({\n id: z.string(),\n name: z.string(),\n action: z.string(),\n }),\n )\n .optional()\n .describe('Parsed template steps'),\n }),\n },\n action: async ({ input, credentials }) => {\n const { templateYaml, values = {}, files = [] } = input;\n\n let template;\n try {\n template = yaml.parse(templateYaml);\n } catch (parseError) {\n const yamlError = parseError as yaml.YAMLParseError;\n return {\n output: {\n valid: false,\n message: 'Failed to parse YAML template',\n errors: [\n `YAML parsing error: ${yamlError.message}`,\n yamlError.linePos\n ? `At line ${yamlError.linePos[0].line}, column ${yamlError.linePos[0].col}`\n : '',\n ].filter(Boolean),\n },\n };\n }\n\n const result = await scaffolderService.dryRun(\n {\n template,\n values: values as JsonObject,\n directoryContents: files.map(file => ({\n path: file.path,\n base64Content: base64EncodeContent(file.content),\n })),\n },\n { credentials },\n );\n\n return {\n output: {\n valid: true,\n message: 'Template validation successful',\n log: result.log?.map(entry => ({\n message: entry.body.message,\n stepId: entry.body.stepId,\n status: entry.body.status,\n })),\n output: result.output,\n steps: result.steps,\n },\n };\n },\n });\n};\n"],"names":["yaml"],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ 'use strict';
2
+
3
+ const createListScaffolderActionsAction = ({
4
+ actionsRegistry,
5
+ scaffolderService
6
+ }) => {
7
+ actionsRegistry.register({
8
+ name: "list-scaffolder-actions",
9
+ title: "List Scaffolder Actions",
10
+ attributes: {
11
+ destructive: false,
12
+ readOnly: true,
13
+ idempotent: true
14
+ },
15
+ description: `Lists all installed Scaffolder actions.
16
+ Each action includes:
17
+ - id: The action identifier
18
+ - description: What the action does
19
+ - schema: Input and output JSON schemas
20
+ - examples: Usage examples when available`,
21
+ schema: {
22
+ input: (z) => z.object({}).describe("No input is required"),
23
+ output: (z) => z.object({
24
+ actions: z.array(
25
+ z.object({
26
+ id: z.string(),
27
+ description: z.string(),
28
+ schema: z.object({
29
+ input: z.object({}).passthrough().describe("JSON Schema for input of Action"),
30
+ output: z.object({}).passthrough().describe("JSON Schema for output of Action")
31
+ }),
32
+ examples: z.array(z.any()).optional()
33
+ })
34
+ )
35
+ })
36
+ },
37
+ action: async ({ credentials }) => {
38
+ const actions = await scaffolderService.listActions(void 0, {
39
+ credentials
40
+ });
41
+ const scaffolderActions = actions.map((action) => ({
42
+ id: action.id,
43
+ description: action.description ?? "",
44
+ schema: {
45
+ input: { ...action.schema?.input ?? {} },
46
+ output: { ...action.schema?.output ?? {} }
47
+ },
48
+ examples: action.examples ?? []
49
+ }));
50
+ return {
51
+ output: {
52
+ actions: scaffolderActions.sort((a, b) => a.id.localeCompare(b.id))
53
+ }
54
+ };
55
+ }
56
+ });
57
+ };
58
+
59
+ exports.createListScaffolderActionsAction = createListScaffolderActionsAction;
60
+ //# sourceMappingURL=createListScaffolderActionsAction.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createListScaffolderActionsAction.cjs.js","sources":["../../src/actions/createListScaffolderActionsAction.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';\n\nexport const createListScaffolderActionsAction = ({\n actionsRegistry,\n scaffolderService,\n}: {\n actionsRegistry: ActionsRegistryService;\n scaffolderService: ScaffolderService;\n}) => {\n actionsRegistry.register({\n name: 'list-scaffolder-actions',\n title: 'List Scaffolder Actions',\n attributes: {\n destructive: false,\n readOnly: true,\n idempotent: true,\n },\n description: `Lists all installed Scaffolder actions.\nEach action includes:\n- id: The action identifier\n- description: What the action does\n- schema: Input and output JSON schemas\n- examples: Usage examples when available`,\n schema: {\n input: z => z.object({}).describe('No input is required'),\n output: z =>\n z.object({\n actions: z.array(\n z.object({\n id: z.string(),\n description: z.string(),\n schema: z.object({\n input: z\n .object({})\n .passthrough()\n .describe('JSON Schema for input of Action'),\n output: z\n .object({})\n .passthrough()\n .describe('JSON Schema for output of Action'),\n }),\n examples: z.array(z.any()).optional(),\n }),\n ),\n }),\n },\n action: async ({ credentials }) => {\n const actions = await scaffolderService.listActions(undefined, {\n credentials,\n });\n const scaffolderActions = actions.map(action => ({\n id: action.id,\n description: action.description ?? '',\n schema: {\n input: { ...(action.schema?.input ?? {}) },\n output: { ...(action.schema?.output ?? {}) },\n },\n examples: action.examples ?? [],\n }));\n return {\n output: {\n actions: scaffolderActions.sort((a, b) => a.id.localeCompare(b.id)),\n },\n };\n },\n });\n};\n"],"names":[],"mappings":";;AAkBO,MAAM,oCAAoC,CAAC;AAAA,EAChD,eAAA;AAAA,EACA;AACF,CAAA,KAGM;AACJ,EAAA,eAAA,CAAgB,QAAA,CAAS;AAAA,IACvB,IAAA,EAAM,yBAAA;AAAA,IACN,KAAA,EAAO,yBAAA;AAAA,IACP,UAAA,EAAY;AAAA,MACV,WAAA,EAAa,KAAA;AAAA,MACb,QAAA,EAAU,IAAA;AAAA,MACV,UAAA,EAAY;AAAA,KACd;AAAA,IACA,WAAA,EAAa,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yCAAA,CAAA;AAAA,IAMb,MAAA,EAAQ;AAAA,MACN,KAAA,EAAO,OAAK,CAAA,CAAE,MAAA,CAAO,EAAE,CAAA,CAAE,SAAS,sBAAsB,CAAA;AAAA,MACxD,MAAA,EAAQ,CAAA,CAAA,KACN,CAAA,CAAE,MAAA,CAAO;AAAA,QACP,SAAS,CAAA,CAAE,KAAA;AAAA,UACT,EAAE,MAAA,CAAO;AAAA,YACP,EAAA,EAAI,EAAE,MAAA,EAAO;AAAA,YACb,WAAA,EAAa,EAAE,MAAA,EAAO;AAAA,YACtB,MAAA,EAAQ,EAAE,MAAA,CAAO;AAAA,cACf,KAAA,EAAO,EACJ,MAAA,CAAO,EAAE,CAAA,CACT,WAAA,EAAY,CACZ,QAAA,CAAS,iCAAiC,CAAA;AAAA,cAC7C,MAAA,EAAQ,EACL,MAAA,CAAO,EAAE,CAAA,CACT,WAAA,EAAY,CACZ,QAAA,CAAS,kCAAkC;AAAA,aAC/C,CAAA;AAAA,YACD,UAAU,CAAA,CAAE,KAAA,CAAM,EAAE,GAAA,EAAK,EAAE,QAAA;AAAS,WACrC;AAAA;AACH,OACD;AAAA,KACL;AAAA,IACA,MAAA,EAAQ,OAAO,EAAE,WAAA,EAAY,KAAM;AACjC,MAAA,MAAM,OAAA,GAAU,MAAM,iBAAA,CAAkB,WAAA,CAAY,MAAA,EAAW;AAAA,QAC7D;AAAA,OACD,CAAA;AACD,MAAA,MAAM,iBAAA,GAAoB,OAAA,CAAQ,GAAA,CAAI,CAAA,MAAA,MAAW;AAAA,QAC/C,IAAI,MAAA,CAAO,EAAA;AAAA,QACX,WAAA,EAAa,OAAO,WAAA,IAAe,EAAA;AAAA,QACnC,MAAA,EAAQ;AAAA,UACN,OAAO,EAAE,GAAI,OAAO,MAAA,EAAQ,KAAA,IAAS,EAAC,EAAG;AAAA,UACzC,QAAQ,EAAE,GAAI,OAAO,MAAA,EAAQ,MAAA,IAAU,EAAC;AAAG,SAC7C;AAAA,QACA,QAAA,EAAU,MAAA,CAAO,QAAA,IAAY;AAAC,OAChC,CAAE,CAAA;AACF,MAAA,OAAO;AAAA,QACL,MAAA,EAAQ;AAAA,UACN,OAAA,EAAS,iBAAA,CAAkB,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,CAAE,EAAA,CAAG,aAAA,CAAc,CAAA,CAAE,EAAE,CAAC;AAAA;AACpE,OACF;AAAA,IACF;AAAA,GACD,CAAA;AACH;;;;"}
@@ -0,0 +1,18 @@
1
+ 'use strict';
2
+
3
+ var listScaffolderTasksAction = require('./listScaffolderTasksAction.cjs.js');
4
+ var createDryRunTemplateAction = require('./createDryRunTemplateAction.cjs.js');
5
+ var createListScaffolderActionsAction = require('./createListScaffolderActionsAction.cjs.js');
6
+
7
+ const createScaffolderActions = (options) => {
8
+ listScaffolderTasksAction.createListScaffolderTasksAction({
9
+ actionsRegistry: options.actionsRegistry,
10
+ auth: options.auth,
11
+ scaffolderService: options.scaffolderService
12
+ });
13
+ createDryRunTemplateAction.createDryRunTemplateAction(options);
14
+ createListScaffolderActionsAction.createListScaffolderActionsAction(options);
15
+ };
16
+
17
+ exports.createScaffolderActions = createScaffolderActions;
18
+ //# sourceMappingURL=index.cjs.js.map
@@ -0,0 +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';\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};\n"],"names":["createListScaffolderTasksAction","createDryRunTemplateAction","createListScaffolderActionsAction"],"mappings":";;;;;;AAsBO,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;AAC3C;;;;"}
@@ -0,0 +1,80 @@
1
+ 'use strict';
2
+
3
+ var errors = require('@backstage/errors');
4
+
5
+ const createListScaffolderTasksAction = ({
6
+ actionsRegistry,
7
+ auth,
8
+ scaffolderService
9
+ }) => {
10
+ actionsRegistry.register({
11
+ name: "list-scaffolder-tasks",
12
+ title: "List Scaffolder Tasks",
13
+ attributes: {
14
+ destructive: false,
15
+ readOnly: true,
16
+ idempotent: true
17
+ },
18
+ description: `
19
+ This allows you to list scaffolder tasks that have been created.
20
+ Each task has a unique id, specification, and status (one of open, processing, completed, failed, cancelled, skipped).
21
+ Each task includes a timestamp for when it was created, and an optional last heartbeat timestamp indicating the most recent activity.
22
+ Set owned to true to return only tasks created by the current user; omit or set to false for all tasks the credentials can see.
23
+ Pagination is supported via limit and offset.
24
+ `,
25
+ schema: {
26
+ input: (z) => z.object({
27
+ owned: z.boolean().optional().default(false).describe(
28
+ "If true, return only tasks created by the current user. Requires a user identity."
29
+ ),
30
+ limit: z.number().int().min(1).max(1e3).describe("The maximum number of tasks to return for pagination").optional(),
31
+ offset: z.number().int().min(0).describe("The offset to start from for pagination").optional()
32
+ }),
33
+ output: (z) => z.object({
34
+ tasks: z.array(
35
+ z.object({
36
+ id: z.string().describe("The task identifier"),
37
+ spec: z.unknown().describe("The task specification"),
38
+ status: z.string().describe(
39
+ "Task status: open, processing, completed, failed, cancelled, or skipped"
40
+ ),
41
+ createdAt: z.string().describe("Timestamp when the task was created"),
42
+ lastHeartbeatAt: z.string().optional().describe("Timestamp of the last heartbeat")
43
+ })
44
+ ).describe("The list of scaffolder tasks"),
45
+ totalTasks: z.number().describe("Total number of tasks matching the filter")
46
+ }).describe("Object containing a tasks array and totalTasks count")
47
+ },
48
+ action: async ({ input, credentials }) => {
49
+ if (input.owned && !auth.isPrincipal(credentials, "user")) {
50
+ throw new errors.NotAllowedError(
51
+ "Filtering by owned tasks requires a user identity."
52
+ );
53
+ }
54
+ const createdBy = input.owned && auth.isPrincipal(credentials, "user") ? credentials.principal.userEntityRef : void 0;
55
+ const { items, totalItems } = await scaffolderService.listTasks(
56
+ {
57
+ createdBy,
58
+ limit: input.limit,
59
+ offset: input.offset
60
+ },
61
+ { credentials }
62
+ );
63
+ return {
64
+ output: {
65
+ tasks: items.map((task) => ({
66
+ id: task.id,
67
+ spec: task.spec,
68
+ status: task.status,
69
+ createdAt: task.createdAt,
70
+ lastHeartbeatAt: task.lastHeartbeatAt
71
+ })),
72
+ totalTasks: totalItems
73
+ }
74
+ };
75
+ }
76
+ });
77
+ };
78
+
79
+ exports.createListScaffolderTasksAction = createListScaffolderTasksAction;
80
+ //# sourceMappingURL=listScaffolderTasksAction.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"listScaffolderTasksAction.cjs.js","sources":["../../src/actions/listScaffolderTasksAction.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 { ActionsRegistryService } from '@backstage/backend-plugin-api/alpha';\nimport { AuthService } from '@backstage/backend-plugin-api';\nimport { NotAllowedError } from '@backstage/errors';\nimport { ScaffolderService } from '@backstage/plugin-scaffolder-node';\n\nexport const createListScaffolderTasksAction = ({\n actionsRegistry,\n auth,\n scaffolderService,\n}: {\n actionsRegistry: ActionsRegistryService;\n auth: AuthService;\n scaffolderService: ScaffolderService;\n}) => {\n actionsRegistry.register({\n name: 'list-scaffolder-tasks',\n title: 'List Scaffolder Tasks',\n attributes: {\n destructive: false,\n readOnly: true,\n idempotent: true,\n },\n description: `\nThis allows you to list scaffolder tasks that have been created.\nEach task has a unique id, specification, and status (one of open, processing, completed, failed, cancelled, skipped).\nEach task includes a timestamp for when it was created, and an optional last heartbeat timestamp indicating the most recent activity.\nSet owned to true to return only tasks created by the current user; omit or set to false for all tasks the credentials can see.\nPagination is supported via limit and offset.\n `,\n schema: {\n input: z =>\n z.object({\n owned: z\n .boolean()\n .optional()\n .default(false)\n .describe(\n 'If true, return only tasks created by the current user. Requires a user identity.',\n ),\n limit: z\n .number()\n .int()\n .min(1)\n .max(1000)\n .describe('The maximum number of tasks to return for pagination')\n .optional(),\n offset: z\n .number()\n .int()\n .min(0)\n .describe('The offset to start from for pagination')\n .optional(),\n }),\n output: z =>\n z\n .object({\n tasks: z\n .array(\n z.object({\n id: z.string().describe('The task identifier'),\n spec: z.unknown().describe('The task specification'),\n status: z\n .string()\n .describe(\n 'Task status: open, processing, completed, failed, cancelled, or skipped',\n ),\n createdAt: z\n .string()\n .describe('Timestamp when the task was created'),\n lastHeartbeatAt: z\n .string()\n .optional()\n .describe('Timestamp of the last heartbeat'),\n }),\n )\n .describe('The list of scaffolder tasks'),\n totalTasks: z\n .number()\n .describe('Total number of tasks matching the filter'),\n })\n .describe('Object containing a tasks array and totalTasks count'),\n },\n action: async ({ input, credentials }) => {\n if (input.owned && !auth.isPrincipal(credentials, 'user')) {\n throw new NotAllowedError(\n 'Filtering by owned tasks requires a user identity.',\n );\n }\n\n const createdBy =\n input.owned && auth.isPrincipal(credentials, 'user')\n ? credentials.principal.userEntityRef\n : undefined;\n\n const { items, totalItems } = await scaffolderService.listTasks(\n {\n createdBy,\n limit: input.limit,\n offset: input.offset,\n },\n { credentials },\n );\n\n return {\n output: {\n tasks: items.map(task => ({\n id: task.id,\n spec: task.spec,\n status: task.status,\n createdAt: task.createdAt,\n lastHeartbeatAt: task.lastHeartbeatAt,\n })),\n totalTasks: totalItems,\n },\n };\n },\n });\n};\n"],"names":["NotAllowedError"],"mappings":"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"}
@@ -3,7 +3,7 @@
3
3
  var backendOpenapiUtils = require('@backstage/backend-openapi-utils');
4
4
 
5
5
  const spec = {
6
- openapi: "3.0.3",
6
+ openapi: "3.1.0",
7
7
  info: {
8
8
  title: "scaffolder",
9
9
  version: "1",
@@ -50,7 +50,6 @@ const spec = {
50
50
  name: "kind",
51
51
  in: "path",
52
52
  required: true,
53
- allowReserved: true,
54
53
  schema: {
55
54
  type: "string"
56
55
  }
@@ -70,7 +69,6 @@ const spec = {
70
69
  name: "namespace",
71
70
  in: "path",
72
71
  required: true,
73
- allowReserved: true,
74
72
  schema: {
75
73
  type: "string"
76
74
  }
@@ -79,7 +77,6 @@ const spec = {
79
77
  name: "name",
80
78
  in: "path",
81
79
  required: true,
82
- allowReserved: true,
83
80
  schema: {
84
81
  type: "string"
85
82
  }
@@ -125,7 +122,6 @@ const spec = {
125
122
  name: "taskId",
126
123
  in: "path",
127
124
  required: true,
128
- allowReserved: true,
129
125
  schema: {
130
126
  type: "string"
131
127
  }
@@ -305,8 +301,7 @@ const spec = {
305
301
  type: "string"
306
302
  },
307
303
  {
308
- type: "object",
309
- nullable: true
304
+ type: "null"
310
305
  }
311
306
  ],
312
307
  description: "A type representing all allowed JSON primitive values."
@@ -580,8 +575,14 @@ const spec = {
580
575
  type: "string"
581
576
  },
582
577
  value: {
583
- type: "object",
584
- nullable: true
578
+ anyOf: [
579
+ {
580
+ type: "object"
581
+ },
582
+ {
583
+ type: "null"
584
+ }
585
+ ]
585
586
  }
586
587
  },
587
588
  required: ["value"],
@@ -990,6 +991,25 @@ const spec = {
990
991
  }
991
992
  }
992
993
  }
994
+ },
995
+ "400": {
996
+ description: "Validation errors.",
997
+ content: {
998
+ "application/json": {
999
+ schema: {
1000
+ type: "object",
1001
+ properties: {
1002
+ errors: {
1003
+ type: "array",
1004
+ items: {
1005
+ $ref: "#/components/schemas/ValidationError"
1006
+ }
1007
+ }
1008
+ },
1009
+ required: ["errors"]
1010
+ }
1011
+ }
1012
+ }
993
1013
  }
994
1014
  },
995
1015
  security: [
@@ -1240,7 +1260,6 @@ const spec = {
1240
1260
  in: "path",
1241
1261
  name: "provider",
1242
1262
  required: true,
1243
- allowReserved: true,
1244
1263
  schema: {
1245
1264
  type: "string"
1246
1265
  }
@@ -1249,7 +1268,6 @@ const spec = {
1249
1268
  in: "path",
1250
1269
  name: "resource",
1251
1270
  required: true,
1252
- allowReserved: true,
1253
1271
  schema: {
1254
1272
  type: "string"
1255
1273
  }