@backstage/plugin-scaffolder-backend 4.1.0-next.0 → 4.1.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.
Files changed (41) hide show
  1. package/CHANGELOG.md +23 -11
  2. package/README.md +0 -23
  3. package/config.schema.json +7 -63
  4. package/dist/ScaffolderPlugin.cjs.js +9 -2
  5. package/dist/ScaffolderPlugin.cjs.js.map +1 -1
  6. package/dist/actions/createDryRunTemplateAction.cjs.js +0 -2
  7. package/dist/actions/createDryRunTemplateAction.cjs.js.map +1 -1
  8. package/dist/index.d.ts +4 -0
  9. package/dist/scaffolder/actions/builtin/fetch/assertScmUserCredentials.cjs.js +34 -0
  10. package/dist/scaffolder/actions/builtin/fetch/assertScmUserCredentials.cjs.js.map +1 -0
  11. package/dist/scaffolder/actions/builtin/fetch/plain.cjs.js +9 -1
  12. package/dist/scaffolder/actions/builtin/fetch/plain.cjs.js.map +1 -1
  13. package/dist/scaffolder/actions/builtin/fetch/plainFile.cjs.js +9 -1
  14. package/dist/scaffolder/actions/builtin/fetch/plainFile.cjs.js.map +1 -1
  15. package/dist/scaffolder/actions/builtin/fetch/template.cjs.js +8 -0
  16. package/dist/scaffolder/actions/builtin/fetch/template.cjs.js.map +1 -1
  17. package/dist/scaffolder/actions/builtin/fetch/templateFile.cjs.js +8 -0
  18. package/dist/scaffolder/actions/builtin/fetch/templateFile.cjs.js.map +1 -1
  19. package/dist/scaffolder/tasks/DatabaseTaskStore.cjs.js +53 -78
  20. package/dist/scaffolder/tasks/DatabaseTaskStore.cjs.js.map +1 -1
  21. package/dist/scaffolder/tasks/DatabaseWorkspaceProvider.cjs.js +23 -0
  22. package/dist/scaffolder/tasks/DatabaseWorkspaceProvider.cjs.js.map +1 -0
  23. package/dist/scaffolder/tasks/NunjucksWorkflowRunner.cjs.js +130 -91
  24. package/dist/scaffolder/tasks/NunjucksWorkflowRunner.cjs.js.map +1 -1
  25. package/dist/scaffolder/tasks/StorageTaskBroker.cjs.js +29 -53
  26. package/dist/scaffolder/tasks/StorageTaskBroker.cjs.js.map +1 -1
  27. package/dist/scaffolder/tasks/WorkspaceService.cjs.js +18 -26
  28. package/dist/scaffolder/tasks/WorkspaceService.cjs.js.map +1 -1
  29. package/dist/scaffolder/tasks/logger.cjs.js +101 -7
  30. package/dist/scaffolder/tasks/logger.cjs.js.map +1 -1
  31. package/dist/scaffolder/tasks/taskRecoveryHelper.cjs.js +0 -4
  32. package/dist/scaffolder/tasks/taskRecoveryHelper.cjs.js.map +1 -1
  33. package/dist/schema/openapi/generated/router.cjs.js +6 -6
  34. package/dist/schema/openapi/generated/router.cjs.js.map +1 -1
  35. package/dist/service/router.cjs.js +22 -9
  36. package/dist/service/router.cjs.js.map +1 -1
  37. package/dist/service/rules.cjs.js +12 -0
  38. package/dist/service/rules.cjs.js.map +1 -1
  39. package/dist/util/checkPermissions.cjs.js +3 -0
  40. package/dist/util/checkPermissions.cjs.js.map +1 -1
  41. package/package.json +20 -20
package/CHANGELOG.md CHANGED
@@ -1,24 +1,36 @@
1
1
  # @backstage/plugin-scaffolder-backend
2
2
 
3
- ## 4.1.0-next.0
3
+ ## 4.1.0
4
4
 
5
5
  ### Minor Changes
6
6
 
7
- - 1a705ca: Applied `templateDryRunPermission` to inline Software Template dry runs and the corresponding backend action. Permission policies that deny unknown permissions must explicitly allow `scaffolder.template.dry-run` to retain existing dry-run access.
8
- - e95b649: Added task recovery feature with new `scaffolder.taskRecovery` config section. When enabled, tasks that crash or timeout are automatically recovered and resume from the last completed step, task secrets are retained until the task reaches a terminal state so recovery can continue, and completed step outputs are persisted. Enabling recovery applies to all scaffolder tasks, so actions used by those tasks should be idempotent or use checkpoints. When recovery is disabled (the default), the previous behavior is unchanged: secrets are cleared as soon as a task is claimed and retries re-run every step. The new config consolidates previous experimental flags (`EXPERIMENTAL_recoverTasks`, `EXPERIMENTAL_workspaceSerialization`, `EXPERIMENTAL_recoverTasksTimeout`) which remain supported as fallbacks. The legacy workspace provider setting continues to select a provider only when `EXPERIMENTAL_workspaceSerialization` is `true`.
7
+ - 6fb2a41: Added the `scaffolder.requireScmUserCredentials` configuration option to require user-provided credentials for supported SCM mutation and fetch actions.
9
8
 
10
- Workspace serialization for task recovery now requires installing a separate workspace provider module, including when you use the legacy configuration. For development, use `@backstage/plugin-scaffolder-backend-module-workspace-database` (50 MB limit, not recommended for production). On first startup, that module migrates existing database workspace snapshots from the legacy task storage. For production, use `@backstage/plugin-scaffolder-backend-module-gcp` or a similar external storage provider. The scaffolder rejects a configured provider that has not been installed and registered.
9
+ ### Patch Changes
10
+
11
+ - 0253c50: Respect task read permission decisions when listing scaffolder tasks.
12
+ - e673a86: Restrict task list ordering to supported fields.
13
+ - 66d2219: Exclude internal task data from task responses.
14
+ - 3eb3dc5: Improve denied scaffolder action error handling.
15
+ - 3f1e869: Ensure task failure details use the configured log redactions.
16
+ - dc30fae: Fixed log redaction for transformed secret values used to iterate Scaffolder steps.
17
+ - 9e86c95: Restrict task retries to terminal states.
18
+ - a91ed72: Fixed matching of action input values in scaffolder permission policies.
19
+ - Updated dependencies
20
+ - @backstage/plugin-scaffolder-common@2.2.3
21
+ - @backstage/integration@2.1.1
11
22
 
12
- Enabling crash recovery does not keep completed task event streams open; normal task completion remains terminal for event-stream clients.
23
+ ## 4.0.5
13
24
 
14
25
  ### Patch Changes
15
26
 
16
- - 2bf1392: Software template inline conditionals without an `else` branch now render an empty string when their condition is false, matching Nunjucks behavior.
17
- - beaa3db: Reject Scaffolder steps where `each` resolves to a primitive value instead of an array or object.
18
- - c1a30ef: Restored support for intrinsic string, number, array, `Map`, and `Set` methods in software templates.
19
- - Updated dependencies
20
- - @backstage/plugin-scaffolder-common@2.3.0-next.0
21
- - @backstage/plugin-scaffolder-node@0.13.7-next.0
27
+ - 640372d: Software template inline conditionals without an `else` branch now render an empty string when their condition is false, matching Nunjucks behavior.
28
+
29
+ ## 4.0.4
30
+
31
+ ### Patch Changes
32
+
33
+ - 913634d: Restored support for intrinsic string, number, array, `Map`, and `Set` methods in software templates.
22
34
 
23
35
  ## 4.0.3
24
36
 
package/README.md CHANGED
@@ -124,26 +124,3 @@ Default secrets are resolved from environment variables and accessible via `${{
124
124
  ```
125
125
 
126
126
  **Security Note:** Secrets are automatically masked in logs and are only available to backend actions, never exposed to the frontend.
127
-
128
- ### Task Recovery
129
-
130
- The scaffolder supports automatic task recovery when workers restart or crash. When enabled, tasks that were in a `processing` state will be recovered and can be resumed from where they left off.
131
-
132
- ```yaml
133
- scaffolder:
134
- taskRecovery:
135
- enabled: true
136
- staleTimeout: { seconds: 30 } # Optional: how long before a task is considered stale
137
- workspaceProvider: database # Optional: enables workspace serialization with specified provider
138
- ```
139
-
140
- When task recovery is enabled:
141
-
142
- - Tasks in `processing` state with stale heartbeats are automatically recovered to `open` state
143
- - Secrets are preserved until the task reaches a terminal state (completed/failed)
144
- - Completed steps are skipped on retry, resuming from the last incomplete step
145
- - Step outputs are restored so subsequent steps can access previous results
146
-
147
- **Note:** `workspaceProvider` is a separate option from `enabled`. Setting `enabled: true` activates task recovery (secrets preservation, step skipping), but workspace serialization only happens if you also set `workspaceProvider`. The `workspaceProvider` value specifies which storage backend to use (for example, `database` from `@backstage/plugin-scaffolder-backend-module-workspace-database`, or `gcpBucket` from `@backstage/plugin-scaffolder-backend-module-gcp`). Install and register the corresponding module before selecting a provider.
148
-
149
- This replaces the previous experimental flags (`EXPERIMENTAL_recoverTasks`, `EXPERIMENTAL_workspaceSerialization`, `EXPERIMENTAL_recoverTasksTimeout`) which are still supported as fallbacks. Legacy workspace serialization also requires a separately installed provider module.
@@ -30,61 +30,9 @@
30
30
  "type": "number",
31
31
  "description": "Sets the number of concurrent tasks that can be run at any given time on the TaskWorker.\n\nDefaults to 10.\n\nSet to 0 to disable task workers altogether."
32
32
  },
33
- "taskRecovery": {
34
- "type": "object",
35
- "properties": {
36
- "enabled": {
37
- "type": "boolean",
38
- "description": "Enable automatic task recovery. When enabled:\n- Secrets are preserved until task completion\n- Step state is saved after each step\n- Crashed tasks resume from last completed step",
39
- "visibility": "backend"
40
- },
41
- "staleTimeout": {
42
- "anyOf": [
43
- {
44
- "type": "object",
45
- "properties": {
46
- "years": {
47
- "type": "number"
48
- },
49
- "months": {
50
- "type": "number"
51
- },
52
- "weeks": {
53
- "type": "number"
54
- },
55
- "days": {
56
- "type": "number"
57
- },
58
- "hours": {
59
- "type": "number"
60
- },
61
- "minutes": {
62
- "type": "number"
63
- },
64
- "seconds": {
65
- "type": "number"
66
- },
67
- "milliseconds": {
68
- "type": "number"
69
- }
70
- },
71
- "description": "Human friendly durations object."
72
- },
73
- {
74
- "type": "string"
75
- }
76
- ],
77
- "description": "How long before a task is considered stale and eligible for recovery. Default: 30 seconds",
78
- "visibility": "backend"
79
- },
80
- "workspaceProvider": {
81
- "type": "string",
82
- "description": "The workspace provider to use for serializing and restoring workspaces. Setting this value enables workspace serialization. If not set, workspace serialization is disabled. Common values: 'database'",
83
- "visibility": "backend"
84
- }
85
- },
86
- "description": "Task recovery configuration",
87
- "visibility": "backend"
33
+ "requireScmUserCredentials": {
34
+ "type": "boolean",
35
+ "description": "Requires supported SCM actions to only operate with credentials explicitly provided by the signed-in user.\n\nDefaults to false."
88
36
  },
89
37
  "EXPERIMENTAL_gracefulShutdown": {
90
38
  "type": "boolean",
@@ -92,18 +40,15 @@
92
40
  },
93
41
  "EXPERIMENTAL_recoverTasks": {
94
42
  "type": "boolean",
95
- "description": "Sets the tasks recoverability on system start up.\n\nIf not specified, the default value is false.",
96
- "deprecated": "Use scaffolder.taskRecovery.enabled instead."
43
+ "description": "Sets the tasks recoverability on system start up.\n\nIf not specified, the default value is false."
97
44
  },
98
45
  "EXPERIMENTAL_workspaceSerialization": {
99
46
  "type": "boolean",
100
- "description": "Sets the serialization of the workspace to have an ability to rerun the failed task.",
101
- "deprecated": "Use scaffolder.taskRecovery.workspaceProvider instead."
47
+ "description": "Sets the serialization of the workspace to have an ability to rerun the failed task."
102
48
  },
103
49
  "EXPERIMENTAL_workspaceSerializationProvider": {
104
50
  "type": "string",
105
- "description": "Sets the provider for workspace serialization.\n\nDefaults to the database provider when workspace serialization is enabled.",
106
- "deprecated": "Use scaffolder.taskRecovery.workspaceProvider instead."
51
+ "description": "Sets the provider for workspace serialization.\n\nBy default, it is your database."
107
52
  },
108
53
  "EXPERIMENTAL_recoverTasksTimeout": {
109
54
  "anyOf": [
@@ -141,8 +86,7 @@
141
86
  "type": "string"
142
87
  }
143
88
  ],
144
- "description": "Every task which is in progress state and having a last heartbeat longer than a specified timeout is going to be attempted to recover.\n\nIf not specified, the default value is 30 seconds.",
145
- "deprecated": "Use scaffolder.taskRecovery.staleTimeout instead."
89
+ "description": "Every task which is in progress state and having a last heartbeat longer than a specified timeout is going to be attempted to recover.\n\nIf not specified, the default value is 5 seconds."
146
90
  },
147
91
  "taskTimeoutJanitorFrequency": {
148
92
  "anyOf": [
@@ -128,6 +128,9 @@ const scaffolderPlugin = backendPluginApi.createBackendPlugin({
128
128
  }) {
129
129
  const log$1 = loggerToWinstonLogger.loggerToWinstonLogger(logger);
130
130
  const integrations = integration.ScmIntegrations.fromConfig(config);
131
+ const requireScmUserCredentials = config.getOptionalBoolean(
132
+ "scaffolder.requireScmUserCredentials"
133
+ );
131
134
  const templateExtensions = {
132
135
  additionalTemplateFilters: templating.convertFiltersToRecord(
133
136
  additionalTemplateFilters
@@ -142,20 +145,24 @@ const scaffolderPlugin = backendPluginApi.createBackendPlugin({
142
145
  // built-in actions for the scaffolder
143
146
  plain.createFetchPlainAction({
144
147
  reader,
145
- integrations
148
+ integrations,
149
+ requireScmUserCredentials
146
150
  }),
147
151
  plainFile.createFetchPlainFileAction({
148
152
  reader,
149
- integrations
153
+ integrations,
154
+ requireScmUserCredentials
150
155
  }),
151
156
  template.createFetchTemplateAction({
152
157
  integrations,
153
158
  reader,
159
+ requireScmUserCredentials,
154
160
  ...templateExtensions
155
161
  }),
156
162
  templateFile.createFetchTemplateFileAction({
157
163
  integrations,
158
164
  reader,
165
+ requireScmUserCredentials,
159
166
  ...templateExtensions
160
167
  }),
161
168
  log.createDebugLogAction(),
@@ -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 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 metricsServiceRef,\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 permissionsRegistry: coreServices.permissionsRegistry,\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 scheduler: coreServices.scheduler,\n metrics: metricsServiceRef,\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 permissionsRegistry,\n events,\n auditor,\n actionsRegistry,\n actionsRegistryService,\n scaffolderService,\n scheduler,\n metrics,\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 permissionsRegistry,\n autocompleteHandlers,\n additionalWorkspaceProviders,\n events,\n auditor,\n actionsRegistry,\n scheduler,\n metrics,\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","metricsServiceRef","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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"}
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 metricsServiceRef,\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 permissionsRegistry: coreServices.permissionsRegistry,\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 scheduler: coreServices.scheduler,\n metrics: metricsServiceRef,\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 permissionsRegistry,\n events,\n auditor,\n actionsRegistry,\n actionsRegistryService,\n scaffolderService,\n scheduler,\n metrics,\n }) {\n const log = loggerToWinstonLogger(logger);\n const integrations = ScmIntegrations.fromConfig(config);\n const requireScmUserCredentials = config.getOptionalBoolean(\n 'scaffolder.requireScmUserCredentials',\n );\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 requireScmUserCredentials,\n }),\n createFetchPlainFileAction({\n reader,\n integrations,\n requireScmUserCredentials,\n }),\n createFetchTemplateAction({\n integrations,\n reader,\n requireScmUserCredentials,\n ...templateExtensions,\n }),\n createFetchTemplateFileAction({\n integrations,\n reader,\n requireScmUserCredentials,\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 permissionsRegistry,\n autocompleteHandlers,\n additionalWorkspaceProviders,\n events,\n auditor,\n actionsRegistry,\n scheduler,\n metrics,\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","metricsServiceRef","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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"}
@@ -1,6 +1,5 @@
1
1
  'use strict';
2
2
 
3
- var alpha = require('@backstage/plugin-scaffolder-common/alpha');
4
3
  var yaml = require('yaml');
5
4
 
6
5
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
@@ -27,7 +26,6 @@ const createDryRunTemplateAction = ({
27
26
  idempotent: true
28
27
  },
29
28
  description: "Dry-runs a scaffolder template to validate it without making changes. Returns success with execution logs, or errors for validation failures.",
30
- visibilityPermission: alpha.templateDryRunPermission,
31
29
  schema: {
32
30
  input: (z) => z.object({
33
31
  templateYaml: z.string().describe(
@@ -1 +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 { templateDryRunPermission } from '@backstage/plugin-scaffolder-common/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 visibilityPermission: templateDryRunPermission,\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":["templateDryRunPermission","yaml"],"mappings":"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"}
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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"}
package/dist/index.d.ts CHANGED
@@ -117,6 +117,7 @@ declare function createWaitAction(options?: {
117
117
  declare function createFetchPlainAction(options: {
118
118
  reader: UrlReaderService;
119
119
  integrations: ScmIntegrations;
120
+ requireScmUserCredentials?: boolean;
120
121
  }): _backstage_plugin_scaffolder_node.TemplateAction<{
121
122
  url: string;
122
123
  targetPath?: string | undefined;
@@ -132,6 +133,7 @@ declare function createFetchPlainAction(options: {
132
133
  declare function createFetchPlainFileAction(options: {
133
134
  reader: UrlReaderService;
134
135
  integrations: ScmIntegrations;
136
+ requireScmUserCredentials?: boolean;
135
137
  }): _backstage_plugin_scaffolder_node.TemplateAction<{
136
138
  url: string;
137
139
  targetPath: string;
@@ -150,6 +152,7 @@ declare function createFetchPlainFileAction(options: {
150
152
  declare function createFetchTemplateAction(options: {
151
153
  reader: UrlReaderService;
152
154
  integrations: ScmIntegrations;
155
+ requireScmUserCredentials?: boolean;
153
156
  additionalTemplateFilters?: Record<string, TemplateFilter>;
154
157
  additionalTemplateGlobals?: Record<string, TemplateGlobal>;
155
158
  }): _backstage_plugin_scaffolder_node.TemplateAction<{
@@ -177,6 +180,7 @@ declare function createFetchTemplateAction(options: {
177
180
  declare function createFetchTemplateFileAction(options: {
178
181
  reader: UrlReaderService;
179
182
  integrations: ScmIntegrations;
183
+ requireScmUserCredentials?: boolean;
180
184
  additionalTemplateFilters?: Record<string, TemplateFilter>;
181
185
  additionalTemplateGlobals?: Record<string, TemplateGlobal>;
182
186
  }): _backstage_plugin_scaffolder_node.TemplateAction<{
@@ -0,0 +1,34 @@
1
+ 'use strict';
2
+
3
+ var errors = require('@backstage/errors');
4
+
5
+ const USER_TOKEN_SUPPORTED_INTEGRATION_TYPES = /* @__PURE__ */ new Set(["github", "gitlab"]);
6
+ function assertScmUserCredentials(options) {
7
+ const { integrations, requireScmUserCredentials, url, baseUrl, token } = options;
8
+ if (!requireScmUserCredentials || token) {
9
+ return;
10
+ }
11
+ let sourceUrl;
12
+ try {
13
+ sourceUrl = new URL(url);
14
+ } catch {
15
+ if (baseUrl) {
16
+ try {
17
+ sourceUrl = new URL(baseUrl);
18
+ } catch {
19
+ }
20
+ }
21
+ }
22
+ if (!sourceUrl) {
23
+ return;
24
+ }
25
+ const integration = integrations.byUrl(sourceUrl);
26
+ if (integration && USER_TOKEN_SUPPORTED_INTEGRATION_TYPES.has(integration.type)) {
27
+ throw new errors.InputError(
28
+ `No user credentials provided for host ${sourceUrl.host}, but scaffolder.requireScmUserCredentials is enabled`
29
+ );
30
+ }
31
+ }
32
+
33
+ exports.assertScmUserCredentials = assertScmUserCredentials;
34
+ //# sourceMappingURL=assertScmUserCredentials.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assertScmUserCredentials.cjs.js","sources":["../../../../../src/scaffolder/actions/builtin/fetch/assertScmUserCredentials.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 */\n\nimport { InputError } from '@backstage/errors';\nimport { ScmIntegrations } from '@backstage/integration';\n\nconst USER_TOKEN_SUPPORTED_INTEGRATION_TYPES = new Set(['github', 'gitlab']);\n\nexport function assertScmUserCredentials(options: {\n integrations: ScmIntegrations;\n requireScmUserCredentials?: boolean;\n url: string;\n baseUrl?: string;\n token?: string;\n}) {\n const { integrations, requireScmUserCredentials, url, baseUrl, token } =\n options;\n\n if (!requireScmUserCredentials || token) {\n return;\n }\n\n let sourceUrl: URL | undefined;\n try {\n sourceUrl = new URL(url);\n } catch {\n if (baseUrl) {\n try {\n sourceUrl = new URL(baseUrl);\n } catch {\n // Invalid URLs are reported by the fetch helpers.\n }\n }\n }\n\n if (!sourceUrl) {\n return;\n }\n\n const integration = integrations.byUrl(sourceUrl);\n if (\n integration &&\n USER_TOKEN_SUPPORTED_INTEGRATION_TYPES.has(integration.type)\n ) {\n throw new InputError(\n `No user credentials provided for host ${sourceUrl.host}, but scaffolder.requireScmUserCredentials is enabled`,\n );\n }\n}\n"],"names":["InputError"],"mappings":";;;;AAmBA,MAAM,yDAAyC,IAAI,GAAA,CAAI,CAAC,QAAA,EAAU,QAAQ,CAAC,CAAA;AAEpE,SAAS,yBAAyB,OAAA,EAMtC;AACD,EAAA,MAAM,EAAE,YAAA,EAAc,yBAAA,EAA2B,GAAA,EAAK,OAAA,EAAS,OAAM,GACnE,OAAA;AAEF,EAAA,IAAI,CAAC,6BAA6B,KAAA,EAAO;AACvC,IAAA;AAAA,EACF;AAEA,EAAA,IAAI,SAAA;AACJ,EAAA,IAAI;AACF,IAAA,SAAA,GAAY,IAAI,IAAI,GAAG,CAAA;AAAA,EACzB,CAAA,CAAA,MAAQ;AACN,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,IAAI;AACF,QAAA,SAAA,GAAY,IAAI,IAAI,OAAO,CAAA;AAAA,MAC7B,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAEA,EAAA,IAAI,CAAC,SAAA,EAAW;AACd,IAAA;AAAA,EACF;AAEA,EAAA,MAAM,WAAA,GAAc,YAAA,CAAa,KAAA,CAAM,SAAS,CAAA;AAChD,EAAA,IACE,WAAA,IACA,sCAAA,CAAuC,GAAA,CAAI,WAAA,CAAY,IAAI,CAAA,EAC3D;AACA,IAAA,MAAM,IAAIA,iBAAA;AAAA,MACR,CAAA,sCAAA,EAAyC,UAAU,IAAI,CAAA,qDAAA;AAAA,KACzD;AAAA,EACF;AACF;;;;"}
@@ -2,11 +2,12 @@
2
2
 
3
3
  var backendPluginApi = require('@backstage/backend-plugin-api');
4
4
  var plain_examples = require('./plain.examples.cjs.js');
5
+ var assertScmUserCredentials = require('./assertScmUserCredentials.cjs.js');
5
6
  var pluginScaffolderNode = require('@backstage/plugin-scaffolder-node');
6
7
 
7
8
  const ACTION_ID = "fetch:plain";
8
9
  function createFetchPlainAction(options) {
9
- const { reader, integrations } = options;
10
+ const { reader, integrations, requireScmUserCredentials } = options;
10
11
  return pluginScaffolderNode.createTemplateAction({
11
12
  id: ACTION_ID,
12
13
  examples: plain_examples.examples,
@@ -29,6 +30,13 @@ function createFetchPlainAction(options) {
29
30
  ctx.logger.info("Fetching plain content from remote URL");
30
31
  const targetPath = ctx.input.targetPath ?? "./";
31
32
  const outputPath = backendPluginApi.resolveSafeChildPath(ctx.workspacePath, targetPath);
33
+ assertScmUserCredentials.assertScmUserCredentials({
34
+ integrations,
35
+ requireScmUserCredentials,
36
+ url: ctx.input.url,
37
+ baseUrl: ctx.templateInfo?.baseUrl,
38
+ token: ctx.input.token
39
+ });
32
40
  await pluginScaffolderNode.fetchContents({
33
41
  reader,
34
42
  integrations,
@@ -1 +1 @@
1
- {"version":3,"file":"plain.cjs.js","sources":["../../../../../src/scaffolder/actions/builtin/fetch/plain.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 {\n resolveSafeChildPath,\n UrlReaderService,\n} from '@backstage/backend-plugin-api';\nimport { ScmIntegrations } from '@backstage/integration';\nimport { examples } from './plain.examples';\n\nimport {\n createTemplateAction,\n fetchContents,\n} from '@backstage/plugin-scaffolder-node';\n\nexport const ACTION_ID = 'fetch:plain';\n\n/**\n * Downloads content and places it in the workspace, or optionally\n * in a subdirectory specified by the 'targetPath' input option.\n * @public\n */\nexport function createFetchPlainAction(options: {\n reader: UrlReaderService;\n integrations: ScmIntegrations;\n}) {\n const { reader, integrations } = options;\n\n return createTemplateAction({\n id: ACTION_ID,\n examples,\n description:\n 'Downloads content and places it in the workspace, or optionally in a subdirectory specified by the `targetPath` input option.',\n schema: {\n input: {\n url: z =>\n z.string({\n description:\n 'Relative path or absolute URL pointing to the directory tree to fetch',\n }),\n targetPath: z =>\n z\n .string({\n description:\n 'Target path within the working directory to download the contents to.',\n })\n .optional(),\n token: z =>\n z\n .string({\n description:\n 'An optional token to use for authentication when reading the resources.',\n })\n .optional(),\n },\n },\n supportsDryRun: true,\n async handler(ctx) {\n ctx.logger.info('Fetching plain content from remote URL');\n\n // Finally move the template result into the task workspace\n const targetPath = ctx.input.targetPath ?? './';\n const outputPath = resolveSafeChildPath(ctx.workspacePath, targetPath);\n\n await fetchContents({\n reader,\n integrations,\n baseUrl: ctx.templateInfo?.baseUrl,\n fetchUrl: ctx.input.url,\n outputPath,\n token: ctx.input.token,\n });\n },\n });\n}\n"],"names":["createTemplateAction","examples","resolveSafeChildPath","fetchContents"],"mappings":";;;;;;AA4BO,MAAM,SAAA,GAAY;AAOlB,SAAS,uBAAuB,OAAA,EAGpC;AACD,EAAA,MAAM,EAAE,MAAA,EAAQ,YAAA,EAAa,GAAI,OAAA;AAEjC,EAAA,OAAOA,yCAAA,CAAqB;AAAA,IAC1B,EAAA,EAAI,SAAA;AAAA,cACJC,uBAAA;AAAA,IACA,WAAA,EACE,+HAAA;AAAA,IACF,MAAA,EAAQ;AAAA,MACN,KAAA,EAAO;AAAA,QACL,GAAA,EAAK,CAAA,CAAA,KACH,CAAA,CAAE,MAAA,CAAO;AAAA,UACP,WAAA,EACE;AAAA,SACH,CAAA;AAAA,QACH,UAAA,EAAY,CAAA,CAAA,KACV,CAAA,CACG,MAAA,CAAO;AAAA,UACN,WAAA,EACE;AAAA,SACH,EACA,QAAA,EAAS;AAAA,QACd,KAAA,EAAO,CAAA,CAAA,KACL,CAAA,CACG,MAAA,CAAO;AAAA,UACN,WAAA,EACE;AAAA,SACH,EACA,QAAA;AAAS;AAChB,KACF;AAAA,IACA,cAAA,EAAgB,IAAA;AAAA,IAChB,MAAM,QAAQ,GAAA,EAAK;AACjB,MAAA,GAAA,CAAI,MAAA,CAAO,KAAK,wCAAwC,CAAA;AAGxD,MAAA,MAAM,UAAA,GAAa,GAAA,CAAI,KAAA,CAAM,UAAA,IAAc,IAAA;AAC3C,MAAA,MAAM,UAAA,GAAaC,qCAAA,CAAqB,GAAA,CAAI,aAAA,EAAe,UAAU,CAAA;AAErE,MAAA,MAAMC,kCAAA,CAAc;AAAA,QAClB,MAAA;AAAA,QACA,YAAA;AAAA,QACA,OAAA,EAAS,IAAI,YAAA,EAAc,OAAA;AAAA,QAC3B,QAAA,EAAU,IAAI,KAAA,CAAM,GAAA;AAAA,QACpB,UAAA;AAAA,QACA,KAAA,EAAO,IAAI,KAAA,CAAM;AAAA,OAClB,CAAA;AAAA,IACH;AAAA,GACD,CAAA;AACH;;;;;"}
1
+ {"version":3,"file":"plain.cjs.js","sources":["../../../../../src/scaffolder/actions/builtin/fetch/plain.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 {\n resolveSafeChildPath,\n UrlReaderService,\n} from '@backstage/backend-plugin-api';\nimport { ScmIntegrations } from '@backstage/integration';\nimport { examples } from './plain.examples';\nimport { assertScmUserCredentials } from './assertScmUserCredentials';\n\nimport {\n createTemplateAction,\n fetchContents,\n} from '@backstage/plugin-scaffolder-node';\n\nexport const ACTION_ID = 'fetch:plain';\n\n/**\n * Downloads content and places it in the workspace, or optionally\n * in a subdirectory specified by the 'targetPath' input option.\n * @public\n */\nexport function createFetchPlainAction(options: {\n reader: UrlReaderService;\n integrations: ScmIntegrations;\n requireScmUserCredentials?: boolean;\n}) {\n const { reader, integrations, requireScmUserCredentials } = options;\n\n return createTemplateAction({\n id: ACTION_ID,\n examples,\n description:\n 'Downloads content and places it in the workspace, or optionally in a subdirectory specified by the `targetPath` input option.',\n schema: {\n input: {\n url: z =>\n z.string({\n description:\n 'Relative path or absolute URL pointing to the directory tree to fetch',\n }),\n targetPath: z =>\n z\n .string({\n description:\n 'Target path within the working directory to download the contents to.',\n })\n .optional(),\n token: z =>\n z\n .string({\n description:\n 'An optional token to use for authentication when reading the resources.',\n })\n .optional(),\n },\n },\n supportsDryRun: true,\n async handler(ctx) {\n ctx.logger.info('Fetching plain content from remote URL');\n\n // Finally move the template result into the task workspace\n const targetPath = ctx.input.targetPath ?? './';\n const outputPath = resolveSafeChildPath(ctx.workspacePath, targetPath);\n\n assertScmUserCredentials({\n integrations,\n requireScmUserCredentials,\n url: ctx.input.url,\n baseUrl: ctx.templateInfo?.baseUrl,\n token: ctx.input.token,\n });\n\n await fetchContents({\n reader,\n integrations,\n baseUrl: ctx.templateInfo?.baseUrl,\n fetchUrl: ctx.input.url,\n outputPath,\n token: ctx.input.token,\n });\n },\n });\n}\n"],"names":["createTemplateAction","examples","resolveSafeChildPath","assertScmUserCredentials","fetchContents"],"mappings":";;;;;;;AA6BO,MAAM,SAAA,GAAY;AAOlB,SAAS,uBAAuB,OAAA,EAIpC;AACD,EAAA,MAAM,EAAE,MAAA,EAAQ,YAAA,EAAc,yBAAA,EAA0B,GAAI,OAAA;AAE5D,EAAA,OAAOA,yCAAA,CAAqB;AAAA,IAC1B,EAAA,EAAI,SAAA;AAAA,cACJC,uBAAA;AAAA,IACA,WAAA,EACE,+HAAA;AAAA,IACF,MAAA,EAAQ;AAAA,MACN,KAAA,EAAO;AAAA,QACL,GAAA,EAAK,CAAA,CAAA,KACH,CAAA,CAAE,MAAA,CAAO;AAAA,UACP,WAAA,EACE;AAAA,SACH,CAAA;AAAA,QACH,UAAA,EAAY,CAAA,CAAA,KACV,CAAA,CACG,MAAA,CAAO;AAAA,UACN,WAAA,EACE;AAAA,SACH,EACA,QAAA,EAAS;AAAA,QACd,KAAA,EAAO,CAAA,CAAA,KACL,CAAA,CACG,MAAA,CAAO;AAAA,UACN,WAAA,EACE;AAAA,SACH,EACA,QAAA;AAAS;AAChB,KACF;AAAA,IACA,cAAA,EAAgB,IAAA;AAAA,IAChB,MAAM,QAAQ,GAAA,EAAK;AACjB,MAAA,GAAA,CAAI,MAAA,CAAO,KAAK,wCAAwC,CAAA;AAGxD,MAAA,MAAM,UAAA,GAAa,GAAA,CAAI,KAAA,CAAM,UAAA,IAAc,IAAA;AAC3C,MAAA,MAAM,UAAA,GAAaC,qCAAA,CAAqB,GAAA,CAAI,aAAA,EAAe,UAAU,CAAA;AAErE,MAAAC,iDAAA,CAAyB;AAAA,QACvB,YAAA;AAAA,QACA,yBAAA;AAAA,QACA,GAAA,EAAK,IAAI,KAAA,CAAM,GAAA;AAAA,QACf,OAAA,EAAS,IAAI,YAAA,EAAc,OAAA;AAAA,QAC3B,KAAA,EAAO,IAAI,KAAA,CAAM;AAAA,OAClB,CAAA;AAED,MAAA,MAAMC,kCAAA,CAAc;AAAA,QAClB,MAAA;AAAA,QACA,YAAA;AAAA,QACA,OAAA,EAAS,IAAI,YAAA,EAAc,OAAA;AAAA,QAC3B,QAAA,EAAU,IAAI,KAAA,CAAM,GAAA;AAAA,QACpB,UAAA;AAAA,QACA,KAAA,EAAO,IAAI,KAAA,CAAM;AAAA,OAClB,CAAA;AAAA,IACH;AAAA,GACD,CAAA;AACH;;;;;"}
@@ -2,10 +2,11 @@
2
2
 
3
3
  var backendPluginApi = require('@backstage/backend-plugin-api');
4
4
  var plainFile_examples = require('./plainFile.examples.cjs.js');
5
+ var assertScmUserCredentials = require('./assertScmUserCredentials.cjs.js');
5
6
  var pluginScaffolderNode = require('@backstage/plugin-scaffolder-node');
6
7
 
7
8
  function createFetchPlainFileAction(options) {
8
- const { reader, integrations } = options;
9
+ const { reader, integrations, requireScmUserCredentials } = options;
9
10
  return pluginScaffolderNode.createTemplateAction({
10
11
  id: "fetch:plain:file",
11
12
  description: "Downloads single file and places it in the workspace.",
@@ -30,6 +31,13 @@ function createFetchPlainFileAction(options) {
30
31
  ctx.workspacePath,
31
32
  ctx.input.targetPath
32
33
  );
34
+ assertScmUserCredentials.assertScmUserCredentials({
35
+ integrations,
36
+ requireScmUserCredentials,
37
+ url: ctx.input.url,
38
+ baseUrl: ctx.templateInfo?.baseUrl,
39
+ token: ctx.input.token
40
+ });
33
41
  await pluginScaffolderNode.fetchFile({
34
42
  reader,
35
43
  integrations,
@@ -1 +1 @@
1
- {"version":3,"file":"plainFile.cjs.js","sources":["../../../../../src/scaffolder/actions/builtin/fetch/plainFile.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 {\n resolveSafeChildPath,\n UrlReaderService,\n} from '@backstage/backend-plugin-api';\nimport { ScmIntegrations } from '@backstage/integration';\nimport { examples } from './plainFile.examples';\n\nimport {\n createTemplateAction,\n fetchFile,\n} from '@backstage/plugin-scaffolder-node';\n\n/**\n * Downloads a single file and places it in the workspace.\n * @public\n */\nexport function createFetchPlainFileAction(options: {\n reader: UrlReaderService;\n integrations: ScmIntegrations;\n}) {\n const { reader, integrations } = options;\n\n return createTemplateAction({\n id: 'fetch:plain:file',\n description: 'Downloads single file and places it in the workspace.',\n examples,\n schema: {\n input: {\n url: z =>\n z.string({\n description:\n 'Relative path or absolute URL pointing to the single file to fetch.',\n }),\n targetPath: z =>\n z.string({\n description:\n 'Target path within the working directory to download the file as.',\n }),\n token: z =>\n z\n .string({\n description:\n 'An optional token to use for authentication when reading the resources.',\n })\n .optional(),\n },\n },\n supportsDryRun: true,\n async handler(ctx) {\n ctx.logger.info('Fetching plain content from remote URL');\n\n // Finally move the template result into the task workspace\n const outputPath = resolveSafeChildPath(\n ctx.workspacePath,\n ctx.input.targetPath,\n );\n\n await fetchFile({\n reader,\n integrations,\n baseUrl: ctx.templateInfo?.baseUrl,\n fetchUrl: ctx.input.url,\n outputPath,\n token: ctx.input.token,\n });\n },\n });\n}\n"],"names":["createTemplateAction","examples","resolveSafeChildPath","fetchFile"],"mappings":";;;;;;AAgCO,SAAS,2BAA2B,OAAA,EAGxC;AACD,EAAA,MAAM,EAAE,MAAA,EAAQ,YAAA,EAAa,GAAI,OAAA;AAEjC,EAAA,OAAOA,yCAAA,CAAqB;AAAA,IAC1B,EAAA,EAAI,kBAAA;AAAA,IACJ,WAAA,EAAa,uDAAA;AAAA,cACbC,2BAAA;AAAA,IACA,MAAA,EAAQ;AAAA,MACN,KAAA,EAAO;AAAA,QACL,GAAA,EAAK,CAAA,CAAA,KACH,CAAA,CAAE,MAAA,CAAO;AAAA,UACP,WAAA,EACE;AAAA,SACH,CAAA;AAAA,QACH,UAAA,EAAY,CAAA,CAAA,KACV,CAAA,CAAE,MAAA,CAAO;AAAA,UACP,WAAA,EACE;AAAA,SACH,CAAA;AAAA,QACH,KAAA,EAAO,CAAA,CAAA,KACL,CAAA,CACG,MAAA,CAAO;AAAA,UACN,WAAA,EACE;AAAA,SACH,EACA,QAAA;AAAS;AAChB,KACF;AAAA,IACA,cAAA,EAAgB,IAAA;AAAA,IAChB,MAAM,QAAQ,GAAA,EAAK;AACjB,MAAA,GAAA,CAAI,MAAA,CAAO,KAAK,wCAAwC,CAAA;AAGxD,MAAA,MAAM,UAAA,GAAaC,qCAAA;AAAA,QACjB,GAAA,CAAI,aAAA;AAAA,QACJ,IAAI,KAAA,CAAM;AAAA,OACZ;AAEA,MAAA,MAAMC,8BAAA,CAAU;AAAA,QACd,MAAA;AAAA,QACA,YAAA;AAAA,QACA,OAAA,EAAS,IAAI,YAAA,EAAc,OAAA;AAAA,QAC3B,QAAA,EAAU,IAAI,KAAA,CAAM,GAAA;AAAA,QACpB,UAAA;AAAA,QACA,KAAA,EAAO,IAAI,KAAA,CAAM;AAAA,OAClB,CAAA;AAAA,IACH;AAAA,GACD,CAAA;AACH;;;;"}
1
+ {"version":3,"file":"plainFile.cjs.js","sources":["../../../../../src/scaffolder/actions/builtin/fetch/plainFile.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 {\n resolveSafeChildPath,\n UrlReaderService,\n} from '@backstage/backend-plugin-api';\nimport { ScmIntegrations } from '@backstage/integration';\nimport { examples } from './plainFile.examples';\nimport { assertScmUserCredentials } from './assertScmUserCredentials';\n\nimport {\n createTemplateAction,\n fetchFile,\n} from '@backstage/plugin-scaffolder-node';\n\n/**\n * Downloads a single file and places it in the workspace.\n * @public\n */\nexport function createFetchPlainFileAction(options: {\n reader: UrlReaderService;\n integrations: ScmIntegrations;\n requireScmUserCredentials?: boolean;\n}) {\n const { reader, integrations, requireScmUserCredentials } = options;\n\n return createTemplateAction({\n id: 'fetch:plain:file',\n description: 'Downloads single file and places it in the workspace.',\n examples,\n schema: {\n input: {\n url: z =>\n z.string({\n description:\n 'Relative path or absolute URL pointing to the single file to fetch.',\n }),\n targetPath: z =>\n z.string({\n description:\n 'Target path within the working directory to download the file as.',\n }),\n token: z =>\n z\n .string({\n description:\n 'An optional token to use for authentication when reading the resources.',\n })\n .optional(),\n },\n },\n supportsDryRun: true,\n async handler(ctx) {\n ctx.logger.info('Fetching plain content from remote URL');\n\n // Finally move the template result into the task workspace\n const outputPath = resolveSafeChildPath(\n ctx.workspacePath,\n ctx.input.targetPath,\n );\n\n assertScmUserCredentials({\n integrations,\n requireScmUserCredentials,\n url: ctx.input.url,\n baseUrl: ctx.templateInfo?.baseUrl,\n token: ctx.input.token,\n });\n\n await fetchFile({\n reader,\n integrations,\n baseUrl: ctx.templateInfo?.baseUrl,\n fetchUrl: ctx.input.url,\n outputPath,\n token: ctx.input.token,\n });\n },\n });\n}\n"],"names":["createTemplateAction","examples","resolveSafeChildPath","assertScmUserCredentials","fetchFile"],"mappings":";;;;;;;AAiCO,SAAS,2BAA2B,OAAA,EAIxC;AACD,EAAA,MAAM,EAAE,MAAA,EAAQ,YAAA,EAAc,yBAAA,EAA0B,GAAI,OAAA;AAE5D,EAAA,OAAOA,yCAAA,CAAqB;AAAA,IAC1B,EAAA,EAAI,kBAAA;AAAA,IACJ,WAAA,EAAa,uDAAA;AAAA,cACbC,2BAAA;AAAA,IACA,MAAA,EAAQ;AAAA,MACN,KAAA,EAAO;AAAA,QACL,GAAA,EAAK,CAAA,CAAA,KACH,CAAA,CAAE,MAAA,CAAO;AAAA,UACP,WAAA,EACE;AAAA,SACH,CAAA;AAAA,QACH,UAAA,EAAY,CAAA,CAAA,KACV,CAAA,CAAE,MAAA,CAAO;AAAA,UACP,WAAA,EACE;AAAA,SACH,CAAA;AAAA,QACH,KAAA,EAAO,CAAA,CAAA,KACL,CAAA,CACG,MAAA,CAAO;AAAA,UACN,WAAA,EACE;AAAA,SACH,EACA,QAAA;AAAS;AAChB,KACF;AAAA,IACA,cAAA,EAAgB,IAAA;AAAA,IAChB,MAAM,QAAQ,GAAA,EAAK;AACjB,MAAA,GAAA,CAAI,MAAA,CAAO,KAAK,wCAAwC,CAAA;AAGxD,MAAA,MAAM,UAAA,GAAaC,qCAAA;AAAA,QACjB,GAAA,CAAI,aAAA;AAAA,QACJ,IAAI,KAAA,CAAM;AAAA,OACZ;AAEA,MAAAC,iDAAA,CAAyB;AAAA,QACvB,YAAA;AAAA,QACA,yBAAA;AAAA,QACA,GAAA,EAAK,IAAI,KAAA,CAAM,GAAA;AAAA,QACf,OAAA,EAAS,IAAI,YAAA,EAAc,OAAA;AAAA,QAC3B,KAAA,EAAO,IAAI,KAAA,CAAM;AAAA,OAClB,CAAA;AAED,MAAA,MAAMC,8BAAA,CAAU;AAAA,QACd,MAAA;AAAA,QACA,YAAA;AAAA,QACA,OAAA,EAAS,IAAI,YAAA,EAAc,OAAA;AAAA,QAC3B,QAAA,EAAU,IAAI,KAAA,CAAM,GAAA;AAAA,QACpB,UAAA;AAAA,QACA,KAAA,EAAO,IAAI,KAAA,CAAM;AAAA,OAClB,CAAA;AAAA,IACH;AAAA,GACD,CAAA;AACH;;;;"}
@@ -3,6 +3,7 @@
3
3
  var backendPluginApi = require('@backstage/backend-plugin-api');
4
4
  var pluginScaffolderNode = require('@backstage/plugin-scaffolder-node');
5
5
  var template_examples = require('./template.examples.cjs.js');
6
+ var assertScmUserCredentials = require('./assertScmUserCredentials.cjs.js');
6
7
  var templateActionHandler = require('./templateActionHandler.cjs.js');
7
8
 
8
9
  function createFetchTemplateAction(options) {
@@ -53,6 +54,13 @@ function createFetchTemplateAction(options) {
53
54
  ctx,
54
55
  resolveTemplate: async () => {
55
56
  ctx.logger.info("Fetching template content from remote URL");
57
+ assertScmUserCredentials.assertScmUserCredentials({
58
+ integrations: options.integrations,
59
+ requireScmUserCredentials: options.requireScmUserCredentials,
60
+ url: ctx.input.url,
61
+ baseUrl: ctx.templateInfo?.baseUrl,
62
+ token: ctx.input.token
63
+ });
56
64
  const workDir = await ctx.createTemporaryDirectory();
57
65
  const templateDir = backendPluginApi.resolveSafeChildPath(workDir, "template");
58
66
  await pluginScaffolderNode.fetchContents({
@@ -1 +1 @@
1
- {"version":3,"file":"template.cjs.js","sources":["../../../../../src/scaffolder/actions/builtin/fetch/template.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 {\n resolveSafeChildPath,\n UrlReaderService,\n} from '@backstage/backend-plugin-api';\nimport { ScmIntegrations } from '@backstage/integration';\nimport {\n createTemplateAction,\n fetchContents,\n TemplateFilter,\n TemplateGlobal,\n} from '@backstage/plugin-scaffolder-node';\nimport { examples } from './template.examples';\nimport {\n collectActionTemplateCapabilities,\n createTemplateActionHandler,\n} from './templateActionHandler';\n\n/**\n * Downloads a skeleton, templates variables into file and directory names and content.\n * Then places the result in the workspace, or optionally in a subdirectory\n * specified by the 'targetPath' input option.\n *\n * @public\n */\nexport function createFetchTemplateAction(options: {\n reader: UrlReaderService;\n integrations: ScmIntegrations;\n additionalTemplateFilters?: Record<string, TemplateFilter>;\n additionalTemplateGlobals?: Record<string, TemplateGlobal>;\n}) {\n const templateCapabilities = collectActionTemplateCapabilities(options);\n\n return createTemplateAction({\n id: 'fetch:template',\n description:\n 'Downloads a skeleton, templates variables into file and directory names and content, and places the result in the workspace, or optionally in a subdirectory specified by the `targetPath` input option.',\n examples,\n schema: {\n input: {\n url: z =>\n z.string({\n description:\n 'Relative path or absolute URL pointing to the directory tree to fetch',\n }),\n targetPath: z =>\n z\n .string({\n description:\n 'Target path within the working directory to download the contents to. Defaults to the working directory root.',\n })\n .optional(),\n values: z =>\n z\n .record(z.any(), {\n description: 'Values to pass on to the templating engine',\n })\n .optional(),\n copyWithoutRender: z =>\n z\n .array(z.string(), {\n description:\n 'An array of glob patterns. Any files or directories which match are copied without being processed as templates.',\n })\n .optional(),\n copyWithoutTemplating: z =>\n z\n .array(z.string(), {\n description:\n 'An array of glob patterns. Contents of matched files or directories are copied without being processed, but paths are subject to rendering.',\n })\n .optional(),\n cookiecutterCompat: z =>\n z\n .boolean({\n description:\n 'Enable features to maximise compatibility with templates built for fetch:cookiecutter',\n })\n .optional(),\n templateFileExtension: z =>\n z\n .union([z.string(), z.boolean()], {\n description:\n 'If set, only files with the given extension will be templated. If set to `true`, the default extension `.njk` is used.',\n })\n .optional(),\n replace: z =>\n z\n .boolean({\n description:\n 'If set, replace files in targetPath instead of skipping existing ones.',\n })\n .optional(),\n trimBlocks: z =>\n z\n .boolean({\n description:\n 'If set, the first newline after a block is removed (block, not variable tag).',\n })\n .optional(),\n lstripBlocks: z =>\n z\n .boolean({\n description:\n 'If set, leading spaces and tabs are stripped from the start of a line to a block.',\n })\n .optional(),\n token: z =>\n z\n .string({\n description:\n 'An optional token to use for authentication when reading the resources.',\n })\n .optional(),\n },\n },\n supportsDryRun: true,\n handler: ctx =>\n createTemplateActionHandler({\n ctx,\n resolveTemplate: async () => {\n ctx.logger.info('Fetching template content from remote URL');\n\n const workDir = await ctx.createTemporaryDirectory();\n const templateDir = resolveSafeChildPath(workDir, 'template');\n\n await fetchContents({\n baseUrl: ctx.templateInfo?.baseUrl,\n fetchUrl: ctx.input.url,\n outputPath: templateDir,\n token: ctx.input.token,\n ...options,\n });\n\n return templateDir;\n },\n ...options,\n templateCapabilities,\n }),\n });\n}\n"],"names":["collectActionTemplateCapabilities","createTemplateAction","examples","createTemplateActionHandler","resolveSafeChildPath","fetchContents"],"mappings":"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"}
1
+ {"version":3,"file":"template.cjs.js","sources":["../../../../../src/scaffolder/actions/builtin/fetch/template.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 {\n resolveSafeChildPath,\n UrlReaderService,\n} from '@backstage/backend-plugin-api';\nimport { ScmIntegrations } from '@backstage/integration';\nimport {\n createTemplateAction,\n fetchContents,\n TemplateFilter,\n TemplateGlobal,\n} from '@backstage/plugin-scaffolder-node';\nimport { examples } from './template.examples';\nimport { assertScmUserCredentials } from './assertScmUserCredentials';\nimport {\n collectActionTemplateCapabilities,\n createTemplateActionHandler,\n} from './templateActionHandler';\n\n/**\n * Downloads a skeleton, templates variables into file and directory names and content.\n * Then places the result in the workspace, or optionally in a subdirectory\n * specified by the 'targetPath' input option.\n *\n * @public\n */\nexport function createFetchTemplateAction(options: {\n reader: UrlReaderService;\n integrations: ScmIntegrations;\n requireScmUserCredentials?: boolean;\n additionalTemplateFilters?: Record<string, TemplateFilter>;\n additionalTemplateGlobals?: Record<string, TemplateGlobal>;\n}) {\n const templateCapabilities = collectActionTemplateCapabilities(options);\n\n return createTemplateAction({\n id: 'fetch:template',\n description:\n 'Downloads a skeleton, templates variables into file and directory names and content, and places the result in the workspace, or optionally in a subdirectory specified by the `targetPath` input option.',\n examples,\n schema: {\n input: {\n url: z =>\n z.string({\n description:\n 'Relative path or absolute URL pointing to the directory tree to fetch',\n }),\n targetPath: z =>\n z\n .string({\n description:\n 'Target path within the working directory to download the contents to. Defaults to the working directory root.',\n })\n .optional(),\n values: z =>\n z\n .record(z.any(), {\n description: 'Values to pass on to the templating engine',\n })\n .optional(),\n copyWithoutRender: z =>\n z\n .array(z.string(), {\n description:\n 'An array of glob patterns. Any files or directories which match are copied without being processed as templates.',\n })\n .optional(),\n copyWithoutTemplating: z =>\n z\n .array(z.string(), {\n description:\n 'An array of glob patterns. Contents of matched files or directories are copied without being processed, but paths are subject to rendering.',\n })\n .optional(),\n cookiecutterCompat: z =>\n z\n .boolean({\n description:\n 'Enable features to maximise compatibility with templates built for fetch:cookiecutter',\n })\n .optional(),\n templateFileExtension: z =>\n z\n .union([z.string(), z.boolean()], {\n description:\n 'If set, only files with the given extension will be templated. If set to `true`, the default extension `.njk` is used.',\n })\n .optional(),\n replace: z =>\n z\n .boolean({\n description:\n 'If set, replace files in targetPath instead of skipping existing ones.',\n })\n .optional(),\n trimBlocks: z =>\n z\n .boolean({\n description:\n 'If set, the first newline after a block is removed (block, not variable tag).',\n })\n .optional(),\n lstripBlocks: z =>\n z\n .boolean({\n description:\n 'If set, leading spaces and tabs are stripped from the start of a line to a block.',\n })\n .optional(),\n token: z =>\n z\n .string({\n description:\n 'An optional token to use for authentication when reading the resources.',\n })\n .optional(),\n },\n },\n supportsDryRun: true,\n handler: ctx =>\n createTemplateActionHandler({\n ctx,\n resolveTemplate: async () => {\n ctx.logger.info('Fetching template content from remote URL');\n\n assertScmUserCredentials({\n integrations: options.integrations,\n requireScmUserCredentials: options.requireScmUserCredentials,\n url: ctx.input.url,\n baseUrl: ctx.templateInfo?.baseUrl,\n token: ctx.input.token,\n });\n\n const workDir = await ctx.createTemporaryDirectory();\n const templateDir = resolveSafeChildPath(workDir, 'template');\n\n await fetchContents({\n baseUrl: ctx.templateInfo?.baseUrl,\n fetchUrl: ctx.input.url,\n outputPath: templateDir,\n token: ctx.input.token,\n ...options,\n });\n\n return templateDir;\n },\n ...options,\n templateCapabilities,\n }),\n });\n}\n"],"names":["collectActionTemplateCapabilities","createTemplateAction","examples","createTemplateActionHandler","assertScmUserCredentials","resolveSafeChildPath","fetchContents"],"mappings":"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"}
@@ -3,6 +3,7 @@
3
3
  var pluginScaffolderNode = require('@backstage/plugin-scaffolder-node');
4
4
  var path = require('node:path');
5
5
  var templateFile_examples = require('./templateFile.examples.cjs.js');
6
+ var assertScmUserCredentials = require('./assertScmUserCredentials.cjs.js');
6
7
  var templateFileActionHandler = require('./templateFileActionHandler.cjs.js');
7
8
  var templateActionHandler = require('./templateActionHandler.cjs.js');
8
9
 
@@ -49,6 +50,13 @@ function createFetchTemplateFileAction(options) {
49
50
  ctx,
50
51
  resolveTemplateFile: async () => {
51
52
  ctx.logger.info("Fetching template file content from remote URL");
53
+ assertScmUserCredentials.assertScmUserCredentials({
54
+ integrations: options.integrations,
55
+ requireScmUserCredentials: options.requireScmUserCredentials,
56
+ url: ctx.input.url,
57
+ baseUrl: ctx.templateInfo?.baseUrl,
58
+ token: ctx.input.token
59
+ });
52
60
  const workDir = await ctx.createTemporaryDirectory();
53
61
  const tmpFilePath = path__default.default.join(workDir, "tmp");
54
62
  await pluginScaffolderNode.fetchFile({