@backstage/plugin-scaffolder-backend 1.30.1-next.1 → 1.31.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.
@@ -10,6 +10,7 @@ var isbinaryfile = require('isbinaryfile');
10
10
  var SecureTemplater = require('../../../../lib/templating/SecureTemplater.cjs.js');
11
11
  var filters = require('../../../../lib/templating/filters.cjs.js');
12
12
  var template_examples = require('./template.examples.cjs.js');
13
+ var templating = require('../../../../util/templating.cjs.js');
13
14
 
14
15
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
15
16
 
@@ -23,7 +24,9 @@ function createFetchTemplateAction(options) {
23
24
  additionalTemplateFilters,
24
25
  additionalTemplateGlobals
25
26
  } = options;
26
- const defaultTemplateFilters = filters.createDefaultFilters({ integrations });
27
+ const defaultTemplateFilters = templating.convertFiltersToRecord(
28
+ filters.default({ integrations })
29
+ );
27
30
  return pluginScaffolderNode.createTemplateAction({
28
31
  id: "fetch:template",
29
32
  description: "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.",
@@ -165,7 +168,7 @@ function createFetchTemplateAction(options) {
165
168
  cookiecutterCompat: ctx.input.cookiecutterCompat,
166
169
  templateFilters: {
167
170
  ...defaultTemplateFilters,
168
- ...additionalTemplateFilters
171
+ ...additionalTemplateFilters ?? {}
169
172
  },
170
173
  templateGlobals: additionalTemplateGlobals,
171
174
  nunjucksConfigs: {
@@ -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 { extname } from 'path';\nimport { UrlReaderService } from '@backstage/backend-plugin-api';\nimport { resolveSafeChildPath } from '@backstage/backend-plugin-api';\nimport { InputError } from '@backstage/errors';\nimport { ScmIntegrations } from '@backstage/integration';\nimport {\n createTemplateAction,\n fetchContents,\n TemplateFilter,\n TemplateGlobal,\n} from '@backstage/plugin-scaffolder-node';\nimport globby from 'globby';\nimport fs from 'fs-extra';\nimport { isBinaryFile } from 'isbinaryfile';\nimport { SecureTemplater } from '../../../../lib/templating/SecureTemplater';\nimport { createDefaultFilters } from '../../../../lib/templating/filters';\nimport { examples } from './template.examples';\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 {\n reader,\n integrations,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n } = options;\n\n const defaultTemplateFilters = createDefaultFilters({ integrations });\n\n return createTemplateAction<{\n url: string;\n targetPath?: string;\n values: any;\n templateFileExtension?: string | boolean;\n\n // Cookiecutter compat options\n /**\n * @deprecated This field is deprecated in favor of copyWithoutTemplating.\n */\n copyWithoutRender?: string[];\n copyWithoutTemplating?: string[];\n cookiecutterCompat?: boolean;\n replace?: boolean;\n trimBlocks?: boolean;\n lstripBlocks?: boolean;\n token?: string;\n }>({\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 type: 'object',\n required: ['url'],\n properties: {\n url: {\n title: 'Fetch URL',\n description:\n 'Relative path or absolute URL pointing to the directory tree to fetch',\n type: 'string',\n },\n targetPath: {\n title: 'Target Path',\n description:\n 'Target path within the working directory to download the contents to. Defaults to the working directory root.',\n type: 'string',\n },\n values: {\n title: 'Template Values',\n description: 'Values to pass on to the templating engine',\n type: 'object',\n },\n copyWithoutRender: {\n title: '[Deprecated] Copy Without Render',\n description:\n 'An array of glob patterns. Any files or directories which match are copied without being processed as templates.',\n type: 'array',\n items: {\n type: 'string',\n },\n },\n copyWithoutTemplating: {\n title: 'Copy Without Templating',\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 type: 'array',\n items: {\n type: 'string',\n },\n },\n cookiecutterCompat: {\n title: 'Cookiecutter compatibility mode',\n description:\n 'Enable features to maximise compatibility with templates built for fetch:cookiecutter',\n type: 'boolean',\n },\n templateFileExtension: {\n title: 'Template File Extension',\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 type: ['string', 'boolean'],\n },\n replace: {\n title: 'Replace files',\n description:\n 'If set, replace files in targetPath instead of skipping existing ones.',\n type: 'boolean',\n },\n token: {\n title: 'Token',\n description:\n 'An optional token to use for authentication when reading the resources.',\n type: 'string',\n },\n },\n },\n },\n supportsDryRun: true,\n async handler(ctx) {\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 const targetPath = ctx.input.targetPath ?? './';\n const outputDir = resolveSafeChildPath(ctx.workspacePath, targetPath);\n if (ctx.input.copyWithoutRender && ctx.input.copyWithoutTemplating) {\n throw new InputError(\n 'Fetch action input copyWithoutRender and copyWithoutTemplating can not be used at the same time',\n );\n }\n\n let copyOnlyPatterns: string[] | undefined;\n let renderFilename: boolean;\n if (ctx.input.copyWithoutRender) {\n ctx.logger.warn(\n '[Deprecated] copyWithoutRender is deprecated Please use copyWithoutTemplating instead.',\n );\n copyOnlyPatterns = ctx.input.copyWithoutRender;\n renderFilename = false;\n } else {\n copyOnlyPatterns = ctx.input.copyWithoutTemplating;\n renderFilename = true;\n }\n\n if (copyOnlyPatterns && !Array.isArray(copyOnlyPatterns)) {\n throw new InputError(\n 'Fetch action input copyWithoutRender/copyWithoutTemplating must be an Array',\n );\n }\n\n if (\n ctx.input.templateFileExtension &&\n (copyOnlyPatterns || ctx.input.cookiecutterCompat)\n ) {\n throw new InputError(\n 'Fetch action input extension incompatible with copyWithoutRender/copyWithoutTemplating and cookiecutterCompat',\n );\n }\n\n let extension: string | false = false;\n if (ctx.input.templateFileExtension) {\n extension =\n ctx.input.templateFileExtension === true\n ? '.njk'\n : ctx.input.templateFileExtension;\n if (!extension.startsWith('.')) {\n extension = `.${extension}`;\n }\n }\n\n await fetchContents({\n reader,\n integrations,\n baseUrl: ctx.templateInfo?.baseUrl,\n fetchUrl: ctx.input.url,\n outputPath: templateDir,\n token: ctx.input.token,\n });\n\n ctx.logger.info('Listing files and directories in template');\n const allEntriesInTemplate = await globby(`**/*`, {\n cwd: templateDir,\n dot: true,\n onlyFiles: false,\n markDirectories: true,\n followSymbolicLinks: false,\n });\n\n const nonTemplatedEntries = new Set(\n await globby(copyOnlyPatterns || [], {\n cwd: templateDir,\n dot: true,\n onlyFiles: false,\n markDirectories: true,\n followSymbolicLinks: false,\n }),\n );\n\n // Cookiecutter prefixes all parameters in templates with\n // `cookiecutter.`. To replicate this, we wrap our parameters\n // in an object with a `cookiecutter` property when compat\n // mode is enabled.\n const { cookiecutterCompat, values } = ctx.input;\n const context = {\n [cookiecutterCompat ? 'cookiecutter' : 'values']: values,\n };\n\n ctx.logger.info(\n `Processing ${allEntriesInTemplate.length} template files/directories with input values`,\n ctx.input.values,\n );\n\n const renderTemplate = await SecureTemplater.loadRenderer({\n cookiecutterCompat: ctx.input.cookiecutterCompat,\n templateFilters: {\n ...defaultTemplateFilters,\n ...additionalTemplateFilters,\n },\n templateGlobals: additionalTemplateGlobals,\n nunjucksConfigs: {\n trimBlocks: ctx.input.trimBlocks,\n lstripBlocks: ctx.input.lstripBlocks,\n },\n });\n\n for (const location of allEntriesInTemplate) {\n let renderContents: boolean;\n\n let localOutputPath = location;\n if (extension) {\n renderContents = extname(localOutputPath) === extension;\n if (renderContents) {\n localOutputPath = localOutputPath.slice(0, -extension.length);\n }\n // extension is mutual exclusive with copyWithoutRender/copyWithoutTemplating,\n // therefore the output path is always rendered.\n localOutputPath = renderTemplate(localOutputPath, context);\n } else {\n renderContents = !nonTemplatedEntries.has(location);\n // The logic here is a bit tangled because it depends on two variables.\n // If renderFilename is true, which means copyWithoutTemplating is used,\n // then the path is always rendered.\n // If renderFilename is false, which means copyWithoutRender is used,\n // then matched file/directory won't be processed, same as before.\n if (renderFilename) {\n localOutputPath = renderTemplate(localOutputPath, context);\n } else {\n localOutputPath = renderContents\n ? renderTemplate(localOutputPath, context)\n : localOutputPath;\n }\n }\n\n if (containsSkippedContent(localOutputPath)) {\n continue;\n }\n\n const outputPath = resolveSafeChildPath(outputDir, localOutputPath);\n if (fs.existsSync(outputPath) && !ctx.input.replace) {\n continue;\n }\n\n if (!renderContents && !extension) {\n ctx.logger.info(\n `Copying file/directory ${location} without processing.`,\n );\n }\n\n if (location.endsWith('/')) {\n ctx.logger.info(\n `Writing directory ${location} to template output path.`,\n );\n await fs.ensureDir(outputPath);\n } else {\n const inputFilePath = resolveSafeChildPath(templateDir, location);\n const stats = await fs.promises.lstat(inputFilePath);\n\n if (stats.isSymbolicLink() || (await isBinaryFile(inputFilePath))) {\n ctx.logger.info(\n `Copying file binary or symbolic link at ${location}, to template output path.`,\n );\n await fs.copy(inputFilePath, outputPath);\n } else {\n const statsObj = await fs.stat(inputFilePath);\n ctx.logger.info(\n `Writing file ${location} to template output path with mode ${statsObj.mode}.`,\n );\n const inputFileContents = await fs.readFile(inputFilePath, 'utf-8');\n await fs.outputFile(\n outputPath,\n renderContents\n ? renderTemplate(inputFileContents, context)\n : inputFileContents,\n { mode: statsObj.mode },\n );\n }\n }\n }\n\n ctx.logger.info(`Template result written to ${outputDir}`);\n },\n });\n}\n\nfunction containsSkippedContent(localOutputPath: string): boolean {\n // if the path is empty means that there is a file skipped in the root\n // if the path starts with a separator it means that the root directory has been skipped\n // if the path includes // means that there is a subdirectory skipped\n // All paths returned are considered with / separator because of globby returning the linux separator for all os'.\n return (\n localOutputPath === '' ||\n localOutputPath.startsWith('/') ||\n localOutputPath.includes('//')\n );\n}\n"],"names":["createDefaultFilters","createTemplateAction","examples","resolveSafeChildPath","InputError","fetchContents","globby","SecureTemplater","extname","fs","isBinaryFile"],"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 { extname } from 'path';\nimport { UrlReaderService } from '@backstage/backend-plugin-api';\nimport { resolveSafeChildPath } from '@backstage/backend-plugin-api';\nimport { InputError } from '@backstage/errors';\nimport { ScmIntegrations } from '@backstage/integration';\nimport {\n createTemplateAction,\n fetchContents,\n TemplateFilter,\n TemplateGlobal,\n} from '@backstage/plugin-scaffolder-node';\nimport globby from 'globby';\nimport fs from 'fs-extra';\nimport { isBinaryFile } from 'isbinaryfile';\nimport { SecureTemplater } from '../../../../lib/templating/SecureTemplater';\nimport createDefaultFilters from '../../../../lib/templating/filters';\nimport { examples } from './template.examples';\nimport { convertFiltersToRecord } from '../../../../util/templating';\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 {\n reader,\n integrations,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n } = options;\n\n const defaultTemplateFilters = convertFiltersToRecord(\n createDefaultFilters({ integrations }),\n );\n\n return createTemplateAction<{\n url: string;\n targetPath?: string;\n values: any;\n templateFileExtension?: string | boolean;\n\n // Cookiecutter compat options\n /**\n * @deprecated This field is deprecated in favor of copyWithoutTemplating.\n */\n copyWithoutRender?: string[];\n copyWithoutTemplating?: string[];\n cookiecutterCompat?: boolean;\n replace?: boolean;\n trimBlocks?: boolean;\n lstripBlocks?: boolean;\n token?: string;\n }>({\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 type: 'object',\n required: ['url'],\n properties: {\n url: {\n title: 'Fetch URL',\n description:\n 'Relative path or absolute URL pointing to the directory tree to fetch',\n type: 'string',\n },\n targetPath: {\n title: 'Target Path',\n description:\n 'Target path within the working directory to download the contents to. Defaults to the working directory root.',\n type: 'string',\n },\n values: {\n title: 'Template Values',\n description: 'Values to pass on to the templating engine',\n type: 'object',\n },\n copyWithoutRender: {\n title: '[Deprecated] Copy Without Render',\n description:\n 'An array of glob patterns. Any files or directories which match are copied without being processed as templates.',\n type: 'array',\n items: {\n type: 'string',\n },\n },\n copyWithoutTemplating: {\n title: 'Copy Without Templating',\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 type: 'array',\n items: {\n type: 'string',\n },\n },\n cookiecutterCompat: {\n title: 'Cookiecutter compatibility mode',\n description:\n 'Enable features to maximise compatibility with templates built for fetch:cookiecutter',\n type: 'boolean',\n },\n templateFileExtension: {\n title: 'Template File Extension',\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 type: ['string', 'boolean'],\n },\n replace: {\n title: 'Replace files',\n description:\n 'If set, replace files in targetPath instead of skipping existing ones.',\n type: 'boolean',\n },\n token: {\n title: 'Token',\n description:\n 'An optional token to use for authentication when reading the resources.',\n type: 'string',\n },\n },\n },\n },\n supportsDryRun: true,\n async handler(ctx) {\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 const targetPath = ctx.input.targetPath ?? './';\n const outputDir = resolveSafeChildPath(ctx.workspacePath, targetPath);\n if (ctx.input.copyWithoutRender && ctx.input.copyWithoutTemplating) {\n throw new InputError(\n 'Fetch action input copyWithoutRender and copyWithoutTemplating can not be used at the same time',\n );\n }\n\n let copyOnlyPatterns: string[] | undefined;\n let renderFilename: boolean;\n if (ctx.input.copyWithoutRender) {\n ctx.logger.warn(\n '[Deprecated] copyWithoutRender is deprecated Please use copyWithoutTemplating instead.',\n );\n copyOnlyPatterns = ctx.input.copyWithoutRender;\n renderFilename = false;\n } else {\n copyOnlyPatterns = ctx.input.copyWithoutTemplating;\n renderFilename = true;\n }\n\n if (copyOnlyPatterns && !Array.isArray(copyOnlyPatterns)) {\n throw new InputError(\n 'Fetch action input copyWithoutRender/copyWithoutTemplating must be an Array',\n );\n }\n\n if (\n ctx.input.templateFileExtension &&\n (copyOnlyPatterns || ctx.input.cookiecutterCompat)\n ) {\n throw new InputError(\n 'Fetch action input extension incompatible with copyWithoutRender/copyWithoutTemplating and cookiecutterCompat',\n );\n }\n\n let extension: string | false = false;\n if (ctx.input.templateFileExtension) {\n extension =\n ctx.input.templateFileExtension === true\n ? '.njk'\n : ctx.input.templateFileExtension;\n if (!extension.startsWith('.')) {\n extension = `.${extension}`;\n }\n }\n\n await fetchContents({\n reader,\n integrations,\n baseUrl: ctx.templateInfo?.baseUrl,\n fetchUrl: ctx.input.url,\n outputPath: templateDir,\n token: ctx.input.token,\n });\n\n ctx.logger.info('Listing files and directories in template');\n const allEntriesInTemplate = await globby(`**/*`, {\n cwd: templateDir,\n dot: true,\n onlyFiles: false,\n markDirectories: true,\n followSymbolicLinks: false,\n });\n\n const nonTemplatedEntries = new Set(\n await globby(copyOnlyPatterns || [], {\n cwd: templateDir,\n dot: true,\n onlyFiles: false,\n markDirectories: true,\n followSymbolicLinks: false,\n }),\n );\n\n // Cookiecutter prefixes all parameters in templates with\n // `cookiecutter.`. To replicate this, we wrap our parameters\n // in an object with a `cookiecutter` property when compat\n // mode is enabled.\n const { cookiecutterCompat, values } = ctx.input;\n const context = {\n [cookiecutterCompat ? 'cookiecutter' : 'values']: values,\n };\n\n ctx.logger.info(\n `Processing ${allEntriesInTemplate.length} template files/directories with input values`,\n ctx.input.values,\n );\n\n const renderTemplate = await SecureTemplater.loadRenderer({\n cookiecutterCompat: ctx.input.cookiecutterCompat,\n templateFilters: {\n ...defaultTemplateFilters,\n ...(additionalTemplateFilters ?? {}),\n },\n templateGlobals: additionalTemplateGlobals,\n nunjucksConfigs: {\n trimBlocks: ctx.input.trimBlocks,\n lstripBlocks: ctx.input.lstripBlocks,\n },\n });\n\n for (const location of allEntriesInTemplate) {\n let renderContents: boolean;\n\n let localOutputPath = location;\n if (extension) {\n renderContents = extname(localOutputPath) === extension;\n if (renderContents) {\n localOutputPath = localOutputPath.slice(0, -extension.length);\n }\n // extension is mutual exclusive with copyWithoutRender/copyWithoutTemplating,\n // therefore the output path is always rendered.\n localOutputPath = renderTemplate(localOutputPath, context);\n } else {\n renderContents = !nonTemplatedEntries.has(location);\n // The logic here is a bit tangled because it depends on two variables.\n // If renderFilename is true, which means copyWithoutTemplating is used,\n // then the path is always rendered.\n // If renderFilename is false, which means copyWithoutRender is used,\n // then matched file/directory won't be processed, same as before.\n if (renderFilename) {\n localOutputPath = renderTemplate(localOutputPath, context);\n } else {\n localOutputPath = renderContents\n ? renderTemplate(localOutputPath, context)\n : localOutputPath;\n }\n }\n\n if (containsSkippedContent(localOutputPath)) {\n continue;\n }\n\n const outputPath = resolveSafeChildPath(outputDir, localOutputPath);\n if (fs.existsSync(outputPath) && !ctx.input.replace) {\n continue;\n }\n\n if (!renderContents && !extension) {\n ctx.logger.info(\n `Copying file/directory ${location} without processing.`,\n );\n }\n\n if (location.endsWith('/')) {\n ctx.logger.info(\n `Writing directory ${location} to template output path.`,\n );\n await fs.ensureDir(outputPath);\n } else {\n const inputFilePath = resolveSafeChildPath(templateDir, location);\n const stats = await fs.promises.lstat(inputFilePath);\n\n if (stats.isSymbolicLink() || (await isBinaryFile(inputFilePath))) {\n ctx.logger.info(\n `Copying file binary or symbolic link at ${location}, to template output path.`,\n );\n await fs.copy(inputFilePath, outputPath);\n } else {\n const statsObj = await fs.stat(inputFilePath);\n ctx.logger.info(\n `Writing file ${location} to template output path with mode ${statsObj.mode}.`,\n );\n const inputFileContents = await fs.readFile(inputFilePath, 'utf-8');\n await fs.outputFile(\n outputPath,\n renderContents\n ? renderTemplate(inputFileContents, context)\n : inputFileContents,\n { mode: statsObj.mode },\n );\n }\n }\n }\n\n ctx.logger.info(`Template result written to ${outputDir}`);\n },\n });\n}\n\nfunction containsSkippedContent(localOutputPath: string): boolean {\n // if the path is empty means that there is a file skipped in the root\n // if the path starts with a separator it means that the root directory has been skipped\n // if the path includes // means that there is a subdirectory skipped\n // All paths returned are considered with / separator because of globby returning the linux separator for all os'.\n return (\n localOutputPath === '' ||\n localOutputPath.startsWith('/') ||\n localOutputPath.includes('//')\n );\n}\n"],"names":["convertFiltersToRecord","createDefaultFilters","createTemplateAction","examples","resolveSafeChildPath","InputError","fetchContents","globby","SecureTemplater","extname","fs","isBinaryFile"],"mappings":"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"}
@@ -7,6 +7,7 @@ var SecureTemplater = require('../../../../lib/templating/SecureTemplater.cjs.js
7
7
  var filters = require('../../../../lib/templating/filters.cjs.js');
8
8
  var path = require('path');
9
9
  var fs = require('fs-extra');
10
+ var templating = require('../../../../util/templating.cjs.js');
10
11
 
11
12
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
12
13
 
@@ -20,7 +21,9 @@ function createFetchTemplateFileAction(options) {
20
21
  additionalTemplateFilters,
21
22
  additionalTemplateGlobals
22
23
  } = options;
23
- const defaultTemplateFilters = filters.createDefaultFilters({ integrations });
24
+ const defaultTemplateFilters = templating.convertFiltersToRecord(
25
+ filters.default({ integrations })
26
+ );
24
27
  return pluginScaffolderNode.createTemplateAction({
25
28
  id: "fetch:template:file",
26
29
  description: "Downloads single file and places it in the workspace.",
@@ -1 +1 @@
1
- {"version":3,"file":"templateFile.cjs.js","sources":["../../../../../src/scaffolder/actions/builtin/fetch/templateFile.ts"],"sourcesContent":["/*\n * Copyright 2024 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 { UrlReaderService } from '@backstage/backend-plugin-api';\nimport { resolveSafeChildPath } from '@backstage/backend-plugin-api';\nimport { ScmIntegrations } from '@backstage/integration';\nimport { examples } from './templateFile.examples';\nimport {\n createTemplateAction,\n fetchFile,\n TemplateFilter,\n TemplateGlobal,\n} from '@backstage/plugin-scaffolder-node';\nimport { SecureTemplater } from '../../../../lib/templating/SecureTemplater';\nimport { createDefaultFilters } from '../../../../lib/templating/filters';\nimport path from 'path';\nimport fs from 'fs-extra';\n\n/**\n * Downloads a single file and templates variables into file.\n * Then places the result in the workspace, or optionally in a subdirectory\n * specified by the 'targetPath' input option.\n * @public\n */\nexport function createFetchTemplateFileAction(options: {\n reader: UrlReaderService;\n integrations: ScmIntegrations;\n additionalTemplateFilters?: Record<string, TemplateFilter>;\n additionalTemplateGlobals?: Record<string, TemplateGlobal>;\n}) {\n const {\n reader,\n integrations,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n } = options;\n\n const defaultTemplateFilters = createDefaultFilters({ integrations });\n\n return createTemplateAction<{\n url: string;\n targetPath: string;\n values: any;\n cookiecutterCompat?: boolean;\n replace?: boolean;\n trimBlocks?: boolean;\n lstripBlocks?: boolean;\n token?: string;\n }>({\n id: 'fetch:template:file',\n description: 'Downloads single file and places it in the workspace.',\n examples,\n schema: {\n input: {\n type: 'object',\n required: ['url', 'targetPath'],\n properties: {\n url: {\n title: 'Fetch URL',\n description:\n 'Relative path or absolute URL pointing to the single file to fetch.',\n type: 'string',\n },\n targetPath: {\n title: 'Target Path',\n description:\n 'Target path within the working directory to download the file as.',\n type: 'string',\n },\n values: {\n title: 'Template Values',\n description: 'Values to pass on to the templating engine',\n type: 'object',\n },\n cookiecutterCompat: {\n title: 'Cookiecutter compatibility mode',\n description:\n 'Enable features to maximise compatibility with templates built for fetch:cookiecutter',\n type: 'boolean',\n },\n replace: {\n title: 'Replace file',\n description:\n 'If set, replace file in targetPath instead of overwriting existing one.',\n type: 'boolean',\n },\n token: {\n title: 'Token',\n description:\n 'An optional token to use for authentication when reading the resources.',\n type: 'string',\n },\n },\n },\n },\n supportsDryRun: true,\n async handler(ctx) {\n ctx.logger.info('Fetching template file content from remote URL');\n\n const workDir = await ctx.createTemporaryDirectory();\n // Write to a tmp file, render the template, then copy to workspace.\n const tmpFilePath = path.join(workDir, 'tmp');\n\n const outputPath = resolveSafeChildPath(\n ctx.workspacePath,\n ctx.input.targetPath,\n );\n\n if (fs.existsSync(outputPath) && !ctx.input.replace) {\n ctx.logger.info(\n `File ${ctx.input.targetPath} already exists in workspace, not replacing.`,\n );\n return;\n }\n\n await fetchFile({\n reader,\n integrations,\n baseUrl: ctx.templateInfo?.baseUrl,\n fetchUrl: ctx.input.url,\n outputPath: tmpFilePath,\n token: ctx.input.token,\n });\n\n const { cookiecutterCompat, values } = ctx.input;\n const context = {\n [cookiecutterCompat ? 'cookiecutter' : 'values']: values,\n };\n\n ctx.logger.info(\n `Processing template file with input values`,\n ctx.input.values,\n );\n\n const renderTemplate = await SecureTemplater.loadRenderer({\n cookiecutterCompat,\n templateFilters: {\n ...defaultTemplateFilters,\n ...additionalTemplateFilters,\n },\n templateGlobals: additionalTemplateGlobals,\n nunjucksConfigs: {\n trimBlocks: ctx.input.trimBlocks,\n lstripBlocks: ctx.input.lstripBlocks,\n },\n });\n\n const contents = await fs.readFile(tmpFilePath, 'utf-8');\n const result = renderTemplate(contents, context);\n await fs.ensureDir(path.dirname(outputPath));\n await fs.outputFile(outputPath, result);\n\n ctx.logger.info(`Template file has been written to ${outputPath}`);\n },\n });\n}\n"],"names":["createDefaultFilters","createTemplateAction","examples","path","resolveSafeChildPath","fs","fetchFile","SecureTemplater"],"mappings":"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"}
1
+ {"version":3,"file":"templateFile.cjs.js","sources":["../../../../../src/scaffolder/actions/builtin/fetch/templateFile.ts"],"sourcesContent":["/*\n * Copyright 2024 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 { UrlReaderService } from '@backstage/backend-plugin-api';\nimport { resolveSafeChildPath } from '@backstage/backend-plugin-api';\nimport { ScmIntegrations } from '@backstage/integration';\nimport { examples } from './templateFile.examples';\nimport {\n createTemplateAction,\n fetchFile,\n TemplateFilter,\n TemplateGlobal,\n} from '@backstage/plugin-scaffolder-node';\nimport { SecureTemplater } from '../../../../lib/templating/SecureTemplater';\nimport createDefaultFilters from '../../../../lib/templating/filters';\nimport path from 'path';\nimport fs from 'fs-extra';\nimport { convertFiltersToRecord } from '../../../../util/templating';\n\n/**\n * Downloads a single file and templates variables into file.\n * Then places the result in the workspace, or optionally in a subdirectory\n * specified by the 'targetPath' input option.\n * @public\n */\nexport function createFetchTemplateFileAction(options: {\n reader: UrlReaderService;\n integrations: ScmIntegrations;\n additionalTemplateFilters?: Record<string, TemplateFilter>;\n additionalTemplateGlobals?: Record<string, TemplateGlobal>;\n}) {\n const {\n reader,\n integrations,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n } = options;\n\n const defaultTemplateFilters = convertFiltersToRecord(\n createDefaultFilters({ integrations }),\n );\n\n return createTemplateAction<{\n url: string;\n targetPath: string;\n values: any;\n cookiecutterCompat?: boolean;\n replace?: boolean;\n trimBlocks?: boolean;\n lstripBlocks?: boolean;\n token?: string;\n }>({\n id: 'fetch:template:file',\n description: 'Downloads single file and places it in the workspace.',\n examples,\n schema: {\n input: {\n type: 'object',\n required: ['url', 'targetPath'],\n properties: {\n url: {\n title: 'Fetch URL',\n description:\n 'Relative path or absolute URL pointing to the single file to fetch.',\n type: 'string',\n },\n targetPath: {\n title: 'Target Path',\n description:\n 'Target path within the working directory to download the file as.',\n type: 'string',\n },\n values: {\n title: 'Template Values',\n description: 'Values to pass on to the templating engine',\n type: 'object',\n },\n cookiecutterCompat: {\n title: 'Cookiecutter compatibility mode',\n description:\n 'Enable features to maximise compatibility with templates built for fetch:cookiecutter',\n type: 'boolean',\n },\n replace: {\n title: 'Replace file',\n description:\n 'If set, replace file in targetPath instead of overwriting existing one.',\n type: 'boolean',\n },\n token: {\n title: 'Token',\n description:\n 'An optional token to use for authentication when reading the resources.',\n type: 'string',\n },\n },\n },\n },\n supportsDryRun: true,\n async handler(ctx) {\n ctx.logger.info('Fetching template file content from remote URL');\n\n const workDir = await ctx.createTemporaryDirectory();\n // Write to a tmp file, render the template, then copy to workspace.\n const tmpFilePath = path.join(workDir, 'tmp');\n\n const outputPath = resolveSafeChildPath(\n ctx.workspacePath,\n ctx.input.targetPath,\n );\n\n if (fs.existsSync(outputPath) && !ctx.input.replace) {\n ctx.logger.info(\n `File ${ctx.input.targetPath} already exists in workspace, not replacing.`,\n );\n return;\n }\n\n await fetchFile({\n reader,\n integrations,\n baseUrl: ctx.templateInfo?.baseUrl,\n fetchUrl: ctx.input.url,\n outputPath: tmpFilePath,\n token: ctx.input.token,\n });\n\n const { cookiecutterCompat, values } = ctx.input;\n const context = {\n [cookiecutterCompat ? 'cookiecutter' : 'values']: values,\n };\n\n ctx.logger.info(\n `Processing template file with input values`,\n ctx.input.values,\n );\n\n const renderTemplate = await SecureTemplater.loadRenderer({\n cookiecutterCompat,\n templateFilters: {\n ...defaultTemplateFilters,\n ...additionalTemplateFilters,\n },\n templateGlobals: additionalTemplateGlobals,\n nunjucksConfigs: {\n trimBlocks: ctx.input.trimBlocks,\n lstripBlocks: ctx.input.lstripBlocks,\n },\n });\n\n const contents = await fs.readFile(tmpFilePath, 'utf-8');\n const result = renderTemplate(contents, context);\n await fs.ensureDir(path.dirname(outputPath));\n await fs.outputFile(outputPath, result);\n\n ctx.logger.info(`Template file has been written to ${outputPath}`);\n },\n });\n}\n"],"names":["convertFiltersToRecord","createDefaultFilters","createTemplateAction","examples","path","resolveSafeChildPath","fs","fetchFile","SecureTemplater"],"mappings":"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"}
@@ -39,7 +39,10 @@ const createFilesystemDeleteAction = () => {
39
39
  throw new errors.InputError("files must be an Array");
40
40
  }
41
41
  for (const file of ctx.input.files) {
42
- const safeFilepath = backendPluginApi.resolveSafeChildPath(ctx.workspacePath, file);
42
+ const safeFilepath = backendPluginApi.resolveSafeChildPath(
43
+ ctx.workspacePath,
44
+ file
45
+ ).replace(/\\/g, "/");
43
46
  const resolvedPaths = await globby__default.default(safeFilepath, {
44
47
  cwd: ctx.workspacePath,
45
48
  absolute: true
@@ -1 +1 @@
1
- {"version":3,"file":"delete.cjs.js","sources":["../../../../../src/scaffolder/actions/builtin/filesystem/delete.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { createTemplateAction } from '@backstage/plugin-scaffolder-node';\nimport { InputError } from '@backstage/errors';\nimport { resolveSafeChildPath } from '@backstage/backend-plugin-api';\nimport fs from 'fs-extra';\nimport globby from 'globby';\nimport { examples } from './delete.examples';\n\n/**\n * Creates new action that enables deletion of files and directories in the workspace.\n * @public\n */\nexport const createFilesystemDeleteAction = () => {\n return createTemplateAction<{ files: string[] }>({\n id: 'fs:delete',\n description: 'Deletes files and directories from the workspace',\n examples,\n schema: {\n input: {\n required: ['files'],\n type: 'object',\n properties: {\n files: {\n title: 'Files',\n description: 'A list of files and directories that will be deleted',\n type: 'array',\n items: {\n type: 'string',\n },\n },\n },\n },\n },\n supportsDryRun: true,\n async handler(ctx) {\n if (!Array.isArray(ctx.input?.files)) {\n throw new InputError('files must be an Array');\n }\n\n for (const file of ctx.input.files) {\n const safeFilepath = resolveSafeChildPath(ctx.workspacePath, file);\n const resolvedPaths = await globby(safeFilepath, {\n cwd: ctx.workspacePath,\n absolute: true,\n });\n\n for (const filepath of resolvedPaths) {\n try {\n await fs.remove(filepath);\n ctx.logger.info(`File ${filepath} deleted successfully`);\n } catch (err) {\n ctx.logger.error(`Failed to delete file ${filepath}:`, err);\n throw err;\n }\n }\n }\n },\n });\n};\n"],"names":["createTemplateAction","examples","InputError","resolveSafeChildPath","globby","fs"],"mappings":";;;;;;;;;;;;;;AA2BO,MAAM,+BAA+B,MAAM;AAChD,EAAA,OAAOA,yCAA0C,CAAA;AAAA,IAC/C,EAAI,EAAA,WAAA;AAAA,IACJ,WAAa,EAAA,kDAAA;AAAA,cACbC,wBAAA;AAAA,IACA,MAAQ,EAAA;AAAA,MACN,KAAO,EAAA;AAAA,QACL,QAAA,EAAU,CAAC,OAAO,CAAA;AAAA,QAClB,IAAM,EAAA,QAAA;AAAA,QACN,UAAY,EAAA;AAAA,UACV,KAAO,EAAA;AAAA,YACL,KAAO,EAAA,OAAA;AAAA,YACP,WAAa,EAAA,sDAAA;AAAA,YACb,IAAM,EAAA,OAAA;AAAA,YACN,KAAO,EAAA;AAAA,cACL,IAAM,EAAA;AAAA;AACR;AACF;AACF;AACF,KACF;AAAA,IACA,cAAgB,EAAA,IAAA;AAAA,IAChB,MAAM,QAAQ,GAAK,EAAA;AACjB,MAAA,IAAI,CAAC,KAAM,CAAA,OAAA,CAAQ,GAAI,CAAA,KAAA,EAAO,KAAK,CAAG,EAAA;AACpC,QAAM,MAAA,IAAIC,kBAAW,wBAAwB,CAAA;AAAA;AAG/C,MAAW,KAAA,MAAA,IAAA,IAAQ,GAAI,CAAA,KAAA,CAAM,KAAO,EAAA;AAClC,QAAA,MAAM,YAAe,GAAAC,qCAAA,CAAqB,GAAI,CAAA,aAAA,EAAe,IAAI,CAAA;AACjE,QAAM,MAAA,aAAA,GAAgB,MAAMC,uBAAA,CAAO,YAAc,EAAA;AAAA,UAC/C,KAAK,GAAI,CAAA,aAAA;AAAA,UACT,QAAU,EAAA;AAAA,SACX,CAAA;AAED,QAAA,KAAA,MAAW,YAAY,aAAe,EAAA;AACpC,UAAI,IAAA;AACF,YAAM,MAAAC,mBAAA,CAAG,OAAO,QAAQ,CAAA;AACxB,YAAA,GAAA,CAAI,MAAO,CAAA,IAAA,CAAK,CAAQ,KAAA,EAAA,QAAQ,CAAuB,qBAAA,CAAA,CAAA;AAAA,mBAChD,GAAK,EAAA;AACZ,YAAA,GAAA,CAAI,MAAO,CAAA,KAAA,CAAM,CAAyB,sBAAA,EAAA,QAAQ,KAAK,GAAG,CAAA;AAC1D,YAAM,MAAA,GAAA;AAAA;AACR;AACF;AACF;AACF,GACD,CAAA;AACH;;;;"}
1
+ {"version":3,"file":"delete.cjs.js","sources":["../../../../../src/scaffolder/actions/builtin/filesystem/delete.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { createTemplateAction } from '@backstage/plugin-scaffolder-node';\nimport { InputError } from '@backstage/errors';\nimport { resolveSafeChildPath } from '@backstage/backend-plugin-api';\nimport fs from 'fs-extra';\nimport globby from 'globby';\nimport { examples } from './delete.examples';\n\n/**\n * Creates new action that enables deletion of files and directories in the workspace.\n * @public\n */\nexport const createFilesystemDeleteAction = () => {\n return createTemplateAction<{ files: string[] }>({\n id: 'fs:delete',\n description: 'Deletes files and directories from the workspace',\n examples,\n schema: {\n input: {\n required: ['files'],\n type: 'object',\n properties: {\n files: {\n title: 'Files',\n description: 'A list of files and directories that will be deleted',\n type: 'array',\n items: {\n type: 'string',\n },\n },\n },\n },\n },\n supportsDryRun: true,\n async handler(ctx) {\n if (!Array.isArray(ctx.input?.files)) {\n throw new InputError('files must be an Array');\n }\n\n for (const file of ctx.input.files) {\n // globby cannot handle backslash file separators\n const safeFilepath = resolveSafeChildPath(\n ctx.workspacePath,\n file,\n ).replace(/\\\\/g, '/');\n const resolvedPaths = await globby(safeFilepath, {\n cwd: ctx.workspacePath,\n absolute: true,\n });\n\n for (const filepath of resolvedPaths) {\n try {\n await fs.remove(filepath);\n ctx.logger.info(`File ${filepath} deleted successfully`);\n } catch (err) {\n ctx.logger.error(`Failed to delete file ${filepath}:`, err);\n throw err;\n }\n }\n }\n },\n });\n};\n"],"names":["createTemplateAction","examples","InputError","resolveSafeChildPath","globby","fs"],"mappings":";;;;;;;;;;;;;;AA2BO,MAAM,+BAA+B,MAAM;AAChD,EAAA,OAAOA,yCAA0C,CAAA;AAAA,IAC/C,EAAI,EAAA,WAAA;AAAA,IACJ,WAAa,EAAA,kDAAA;AAAA,cACbC,wBAAA;AAAA,IACA,MAAQ,EAAA;AAAA,MACN,KAAO,EAAA;AAAA,QACL,QAAA,EAAU,CAAC,OAAO,CAAA;AAAA,QAClB,IAAM,EAAA,QAAA;AAAA,QACN,UAAY,EAAA;AAAA,UACV,KAAO,EAAA;AAAA,YACL,KAAO,EAAA,OAAA;AAAA,YACP,WAAa,EAAA,sDAAA;AAAA,YACb,IAAM,EAAA,OAAA;AAAA,YACN,KAAO,EAAA;AAAA,cACL,IAAM,EAAA;AAAA;AACR;AACF;AACF;AACF,KACF;AAAA,IACA,cAAgB,EAAA,IAAA;AAAA,IAChB,MAAM,QAAQ,GAAK,EAAA;AACjB,MAAA,IAAI,CAAC,KAAM,CAAA,OAAA,CAAQ,GAAI,CAAA,KAAA,EAAO,KAAK,CAAG,EAAA;AACpC,QAAM,MAAA,IAAIC,kBAAW,wBAAwB,CAAA;AAAA;AAG/C,MAAW,KAAA,MAAA,IAAA,IAAQ,GAAI,CAAA,KAAA,CAAM,KAAO,EAAA;AAElC,QAAA,MAAM,YAAe,GAAAC,qCAAA;AAAA,UACnB,GAAI,CAAA,aAAA;AAAA,UACJ;AAAA,SACF,CAAE,OAAQ,CAAA,KAAA,EAAO,GAAG,CAAA;AACpB,QAAM,MAAA,aAAA,GAAgB,MAAMC,uBAAA,CAAO,YAAc,EAAA;AAAA,UAC/C,KAAK,GAAI,CAAA,aAAA;AAAA,UACT,QAAU,EAAA;AAAA,SACX,CAAA;AAED,QAAA,KAAA,MAAW,YAAY,aAAe,EAAA;AACpC,UAAI,IAAA;AACF,YAAM,MAAAC,mBAAA,CAAG,OAAO,QAAQ,CAAA;AACxB,YAAA,GAAA,CAAI,MAAO,CAAA,IAAA,CAAK,CAAQ,KAAA,EAAA,QAAQ,CAAuB,qBAAA,CAAA,CAAA;AAAA,mBAChD,GAAK,EAAA;AACZ,YAAA,GAAA,CAAI,MAAO,CAAA,KAAA,CAAM,CAAyB,sBAAA,EAAA,QAAQ,KAAK,GAAG,CAAA;AAC1D,YAAM,MAAA,GAAA;AAAA;AACR;AACF;AACF;AACF,GACD,CAAA;AACH;;;;"}
@@ -23,6 +23,7 @@ require('isbinaryfile');
23
23
  require('isolated-vm');
24
24
  require('lodash/get');
25
25
  require('../actions/builtin/fetch/template.examples.cjs.js');
26
+ require('zod-to-json-schema');
26
27
  require('../actions/builtin/fetch/templateFile.examples.cjs.js');
27
28
  require('../actions/builtin/filesystem/delete.examples.cjs.js');
28
29
  require('../actions/builtin/filesystem/rename.examples.cjs.js');
@@ -1 +1 @@
1
- {"version":3,"file":"DecoratedActionsRegistry.cjs.js","sources":["../../../src/scaffolder/dryrun/DecoratedActionsRegistry.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 { TemplateAction } from '@backstage/plugin-scaffolder-node';\nimport { TemplateActionRegistry } from '../actions';\n\n/** @internal */\nexport class DecoratedActionsRegistry extends TemplateActionRegistry {\n constructor(\n private readonly innerRegistry: TemplateActionRegistry,\n extraActions: Array<TemplateAction>,\n ) {\n super();\n for (const action of extraActions) {\n this.register(action);\n }\n }\n\n get(actionId: string): TemplateAction {\n try {\n return super.get(actionId);\n } catch {\n return this.innerRegistry.get(actionId);\n }\n }\n}\n"],"names":["TemplateActionRegistry"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoBO,MAAM,iCAAiCA,6CAAuB,CAAA;AAAA,EACnE,WAAA,CACmB,eACjB,YACA,EAAA;AACA,IAAM,KAAA,EAAA;AAHW,IAAA,IAAA,CAAA,aAAA,GAAA,aAAA;AAIjB,IAAA,KAAA,MAAW,UAAU,YAAc,EAAA;AACjC,MAAA,IAAA,CAAK,SAAS,MAAM,CAAA;AAAA;AACtB;AACF,EAEA,IAAI,QAAkC,EAAA;AACpC,IAAI,IAAA;AACF,MAAO,OAAA,KAAA,CAAM,IAAI,QAAQ,CAAA;AAAA,KACnB,CAAA,MAAA;AACN,MAAO,OAAA,IAAA,CAAK,aAAc,CAAA,GAAA,CAAI,QAAQ,CAAA;AAAA;AACxC;AAEJ;;;;"}
1
+ {"version":3,"file":"DecoratedActionsRegistry.cjs.js","sources":["../../../src/scaffolder/dryrun/DecoratedActionsRegistry.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 { TemplateAction } from '@backstage/plugin-scaffolder-node';\nimport { TemplateActionRegistry } from '../actions';\n\n/** @internal */\nexport class DecoratedActionsRegistry extends TemplateActionRegistry {\n constructor(\n private readonly innerRegistry: TemplateActionRegistry,\n extraActions: Array<TemplateAction>,\n ) {\n super();\n for (const action of extraActions) {\n this.register(action);\n }\n }\n\n get(actionId: string): TemplateAction {\n try {\n return super.get(actionId);\n } catch {\n return this.innerRegistry.get(actionId);\n }\n }\n}\n"],"names":["TemplateActionRegistry"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoBO,MAAM,iCAAiCA,6CAAuB,CAAA;AAAA,EACnE,WAAA,CACmB,eACjB,YACA,EAAA;AACA,IAAM,KAAA,EAAA;AAHW,IAAA,IAAA,CAAA,aAAA,GAAA,aAAA;AAIjB,IAAA,KAAA,MAAW,UAAU,YAAc,EAAA;AACjC,MAAA,IAAA,CAAK,SAAS,MAAM,CAAA;AAAA;AACtB;AACF,EAEA,IAAI,QAAkC,EAAA;AACpC,IAAI,IAAA;AACF,MAAO,OAAA,KAAA,CAAM,IAAI,QAAQ,CAAA;AAAA,KACnB,CAAA,MAAA;AACN,MAAO,OAAA,IAAA,CAAK,aAAc,CAAA,GAAA,CAAI,QAAQ,CAAA;AAAA;AACxC;AAEJ;;;;"}
@@ -18,6 +18,7 @@ var rules = require('../../service/rules.cjs.js');
18
18
  var metrics = require('../../util/metrics.cjs.js');
19
19
  var logger = require('./logger.cjs.js');
20
20
  var loggerToWinstonLogger = require('../../util/loggerToWinstonLogger.cjs.js');
21
+ var templating = require('../../util/templating.cjs.js');
21
22
 
22
23
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
23
24
 
@@ -76,9 +77,11 @@ const isActionAuthorized = pluginPermissionNode.createConditionAuthorizer(
76
77
  class NunjucksWorkflowRunner {
77
78
  constructor(options) {
78
79
  this.options = options;
79
- this.defaultTemplateFilters = filters.createDefaultFilters({
80
- integrations: this.options.integrations
81
- });
80
+ this.defaultTemplateFilters = templating.convertFiltersToRecord(
81
+ filters.default({
82
+ integrations: this.options.integrations
83
+ })
84
+ );
82
85
  }
83
86
  defaultTemplateFilters;
84
87
  tracker = scaffoldingTracker();
@@ -1 +1 @@
1
- {"version":3,"file":"NunjucksWorkflowRunner.cjs.js","sources":["../../../src/scaffolder/tasks/NunjucksWorkflowRunner.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 { InputError, NotAllowedError, stringifyError } from '@backstage/errors';\nimport { ScmIntegrations } from '@backstage/integration';\nimport {\n TaskRecovery,\n TaskSpec,\n TaskSpecV1beta3,\n TaskStep,\n} from '@backstage/plugin-scaffolder-common';\nimport { JsonArray, JsonObject, JsonValue } from '@backstage/types';\nimport { metrics } from '@opentelemetry/api';\nimport fs from 'fs-extra';\nimport { validate as validateJsonSchema } from 'jsonschema';\nimport nunjucks from 'nunjucks';\nimport path from 'path';\nimport { PassThrough } from 'stream';\nimport * as winston from 'winston';\nimport {\n SecureTemplater,\n SecureTemplateRenderer,\n} from '../../lib/templating/SecureTemplater';\nimport { TemplateActionRegistry } from '../actions';\nimport { generateExampleOutput, isTruthy } from './helper';\nimport { TaskTrackType, WorkflowResponse, WorkflowRunner } from './types';\n\nimport type {\n AuditorService,\n PermissionsService,\n} from '@backstage/backend-plugin-api';\nimport { UserEntity } from '@backstage/catalog-model';\nimport {\n AuthorizeResult,\n PolicyDecision,\n} from '@backstage/plugin-permission-common';\nimport { createConditionAuthorizer } from '@backstage/plugin-permission-node';\nimport { actionExecutePermission } from '@backstage/plugin-scaffolder-common/alpha';\nimport {\n TaskContext,\n TemplateAction,\n TemplateFilter,\n TemplateGlobal,\n} from '@backstage/plugin-scaffolder-node';\nimport { createDefaultFilters } from '../../lib/templating/filters';\nimport { scaffolderActionRules } from '../../service/rules';\nimport { createCounterMetric, createHistogramMetric } from '../../util/metrics';\nimport { BackstageLoggerTransport, WinstonLogger } from './logger';\nimport { loggerToWinstonLogger } from '../../util/loggerToWinstonLogger';\n\ntype NunjucksWorkflowRunnerOptions = {\n workingDirectory: string;\n actionRegistry: TemplateActionRegistry;\n integrations: ScmIntegrations;\n logger: winston.Logger;\n auditor?: AuditorService;\n additionalTemplateFilters?: Record<string, TemplateFilter>;\n additionalTemplateGlobals?: Record<string, TemplateGlobal>;\n permissions?: PermissionsService;\n};\n\ntype TemplateContext = {\n parameters: JsonObject;\n EXPERIMENTAL_recovery?: TaskRecovery;\n steps: {\n [stepName: string]: { output: { [outputName: string]: JsonValue } };\n };\n secrets?: Record<string, string>;\n user?: {\n entity?: UserEntity;\n ref?: string;\n };\n each?: JsonValue;\n context: {\n task: {\n id: string;\n };\n };\n};\n\ntype CheckpointState =\n | {\n status: 'failed';\n reason: string;\n }\n | {\n status: 'success';\n value: JsonValue;\n };\n\nconst isValidTaskSpec = (taskSpec: TaskSpec): taskSpec is TaskSpecV1beta3 => {\n return taskSpec.apiVersion === 'scaffolder.backstage.io/v1beta3';\n};\n\nconst createStepLogger = ({\n task,\n step,\n rootLogger,\n}: {\n task: TaskContext;\n step: TaskStep;\n rootLogger: winston.Logger;\n}) => {\n const taskLogger = WinstonLogger.create({\n level: process.env.LOG_LEVEL || 'info',\n format: winston.format.combine(\n winston.format.colorize(),\n winston.format.simple(),\n ),\n transports: [new BackstageLoggerTransport(rootLogger, task, step.id)],\n });\n\n taskLogger.addRedactions(Object.values(task.secrets ?? {}));\n\n // This stream logger should be deprecated. We're going to replace it with\n // just using the logger directly, as all those logs get written to step logs\n // using the stepLogStream above.\n // Initially this stream used to be the only way to write to the client logs, but that\n // has changed over time, there's not really a need for this anymore.\n // You can just create a simple wrapper like the below in your action to write to the main logger.\n // This way we also get redactions for free.\n const streamLogger = new PassThrough();\n streamLogger.on('data', async data => {\n const message = data.toString().trim();\n if (message?.length > 1) {\n taskLogger.info(message);\n }\n });\n\n return { taskLogger, streamLogger };\n};\n\nconst isActionAuthorized = createConditionAuthorizer(\n Object.values(scaffolderActionRules),\n);\n\nexport class NunjucksWorkflowRunner implements WorkflowRunner {\n private readonly defaultTemplateFilters: Record<string, TemplateFilter>;\n\n constructor(private readonly options: NunjucksWorkflowRunnerOptions) {\n this.defaultTemplateFilters = createDefaultFilters({\n integrations: this.options.integrations,\n });\n }\n\n private readonly tracker = scaffoldingTracker();\n\n private isSingleTemplateString(input: string) {\n const { parser, nodes } = nunjucks as unknown as {\n parser: {\n parse(\n template: string,\n ctx: object,\n options: nunjucks.ConfigureOptions,\n ): { children: { children?: unknown[] }[] };\n };\n nodes: { TemplateData: Function };\n };\n\n const parsed = parser.parse(\n input,\n {},\n {\n autoescape: false,\n tags: {\n variableStart: '${{',\n variableEnd: '}}',\n },\n },\n );\n\n return (\n parsed.children.length === 1 &&\n !(parsed.children[0]?.children?.[0] instanceof nodes.TemplateData)\n );\n }\n\n private render<T>(\n input: T,\n context: TemplateContext,\n renderTemplate: SecureTemplateRenderer,\n ): T {\n return JSON.parse(JSON.stringify(input), (_key, value) => {\n try {\n if (typeof value === 'string') {\n try {\n if (this.isSingleTemplateString(value)) {\n // Lets convert ${{ parameters.bob }} to ${{ (parameters.bob) | dump }} so we can keep the input type\n const wrappedDumped = value.replace(\n /\\${{(.+)}}/g,\n '${{ ( $1 ) | dump }}',\n );\n\n // Run the templating\n const templated = renderTemplate(wrappedDumped, context);\n\n // If there's an empty string returned, then it's undefined\n if (templated === '') {\n return undefined;\n }\n\n // Reparse the dumped string\n return JSON.parse(templated);\n }\n } catch (ex) {\n this.options.logger.error(\n `Failed to parse template string: ${value} with error ${ex.message}`,\n );\n }\n\n // Fallback to default behaviour\n const templated = renderTemplate(value, context);\n\n if (templated === '') {\n return undefined;\n }\n\n return templated;\n }\n } catch {\n return value;\n }\n return value;\n });\n }\n\n async executeStep(\n task: TaskContext,\n step: TaskStep,\n context: TemplateContext,\n renderTemplate: (template: string, values: unknown) => string,\n taskTrack: TaskTrackType,\n workspacePath: string,\n decision: PolicyDecision,\n ) {\n const stepTrack = await this.tracker.stepStart(task, step);\n\n if (task.cancelSignal.aborted) {\n throw new Error(\n `Step ${step.id} (${step.name}) of task ${task.taskId} has been cancelled.`,\n );\n }\n\n try {\n if (\n step.if === false ||\n (typeof step.if === 'string' &&\n !isTruthy(this.render(step.if, context, renderTemplate)))\n ) {\n await stepTrack.skipFalsy();\n return;\n }\n const action: TemplateAction<JsonObject> =\n this.options.actionRegistry.get(step.action);\n const { taskLogger, streamLogger } = createStepLogger({\n task,\n step,\n rootLogger: this.options.logger,\n });\n\n if (task.isDryRun) {\n const redactedSecrets = Object.fromEntries(\n Object.entries(task.secrets ?? {}).map(secret => [secret[0], '***']),\n );\n const debugInput =\n (step.input &&\n this.render(\n step.input,\n {\n ...context,\n secrets: redactedSecrets,\n },\n renderTemplate,\n )) ??\n {};\n taskLogger.info(\n `Running ${\n action.id\n } in dry-run mode with inputs (secrets redacted): ${JSON.stringify(\n debugInput,\n undefined,\n 2,\n )}`,\n );\n if (!action.supportsDryRun) {\n await taskTrack.skipDryRun(step, action);\n const outputSchema = action.schema?.output;\n if (outputSchema) {\n context.steps[step.id] = {\n output: generateExampleOutput(outputSchema) as {\n [name in string]: JsonValue;\n },\n };\n } else {\n context.steps[step.id] = { output: {} };\n }\n return;\n }\n }\n\n const resolvedEach =\n step.each && this.render(step.each, context, renderTemplate);\n\n if (step.each && !resolvedEach) {\n throw new InputError(\n `Invalid value on action ${action.id}.each parameter, \"${step.each}\" cannot be resolved to a value`,\n );\n }\n\n const iterations = (\n resolvedEach\n ? Object.entries(resolvedEach).map(([key, value]) => ({\n each: { key, value },\n }))\n : [{}]\n ).map(i => ({\n ...i,\n // Secrets are only passed when templating the input to actions for security reasons\n input: step.input\n ? this.render(\n step.input,\n { ...context, secrets: task.secrets ?? {}, ...i },\n renderTemplate,\n )\n : {},\n }));\n for (const iteration of iterations) {\n const actionId = `${action.id}${\n iteration.each ? `[${iteration.each.key}]` : ''\n }`;\n\n if (action.schema?.input) {\n const validateResult = validateJsonSchema(\n iteration.input,\n action.schema.input,\n );\n if (!validateResult.valid) {\n const errors = validateResult.errors.join(', ');\n throw new InputError(\n `Invalid input passed to action ${actionId}, ${errors}`,\n );\n }\n }\n if (\n !isActionAuthorized(decision, {\n action: action.id,\n input: iteration.input,\n })\n ) {\n throw new NotAllowedError(\n `Unauthorized action: ${actionId}. The action is not allowed. Input: ${JSON.stringify(\n iteration.input,\n null,\n 2,\n )}`,\n );\n }\n }\n const tmpDirs = new Array<string>();\n const stepOutput: { [outputName: string]: JsonValue } = {};\n const prevTaskState = await task.getTaskState?.();\n\n for (const iteration of iterations) {\n if (iteration.each) {\n taskLogger.info(\n `Running step each: ${JSON.stringify(\n iteration.each,\n (k, v) => (k ? v.toString() : v),\n 0,\n )}`,\n );\n }\n\n await action.handler({\n input: iteration.input,\n task: {\n id: await task.getWorkspaceName(),\n },\n secrets: task.secrets ?? {},\n // TODO(blam): move to LoggerService and away from Winston\n logger: loggerToWinstonLogger(taskLogger),\n logStream: streamLogger,\n workspacePath,\n async checkpoint<T extends JsonValue | void>(opts: {\n key?: string;\n fn: () => Promise<T> | T;\n }) {\n const { key: checkpointKey, fn } = opts;\n const key = `v1.task.checkpoint.${step.id}.${checkpointKey}`;\n\n try {\n let prevValue: T | undefined;\n\n if (prevTaskState) {\n const prevState = (\n prevTaskState.state?.checkpoints as {\n [key: string]: CheckpointState;\n }\n )?.[key];\n\n if (prevState && prevState.status === 'success') {\n prevValue = prevState.value as T;\n }\n }\n\n const value = prevValue ? prevValue : await fn();\n\n if (!prevValue) {\n task.updateCheckpoint?.({\n key,\n status: 'success',\n value: value ?? {},\n });\n }\n return value;\n } catch (err) {\n task.updateCheckpoint?.({\n key,\n status: 'failed',\n reason: stringifyError(err),\n });\n throw err;\n } finally {\n await task.serializeWorkspace?.({ path: workspacePath });\n }\n },\n createTemporaryDirectory: async () => {\n const tmpDir = await fs.mkdtemp(\n `${workspacePath}_step-${step.id}-`,\n );\n tmpDirs.push(tmpDir);\n return tmpDir;\n },\n output(name: string, value: JsonValue) {\n if (step.each) {\n stepOutput[name] = stepOutput[name] || [];\n (stepOutput[name] as JsonArray).push(value);\n } else {\n stepOutput[name] = value;\n }\n },\n templateInfo: task.spec.templateInfo,\n user: task.spec.user,\n isDryRun: task.isDryRun,\n signal: task.cancelSignal,\n getInitiatorCredentials: () => task.getInitiatorCredentials(),\n });\n }\n\n // Remove all temporary directories that were created when executing the action\n for (const tmpDir of tmpDirs) {\n await fs.remove(tmpDir);\n }\n\n context.steps[step.id] = { output: stepOutput };\n\n if (task.cancelSignal.aborted) {\n throw new Error(\n `Step ${step.id} (${step.name}) of task ${task.taskId} has been cancelled.`,\n );\n }\n\n await stepTrack.markSuccessful();\n } catch (err) {\n await taskTrack.markFailed(step, err);\n await stepTrack.markFailed();\n throw err;\n } finally {\n await task.serializeWorkspace?.({ path: workspacePath });\n }\n }\n\n async execute(task: TaskContext): Promise<WorkflowResponse> {\n if (!isValidTaskSpec(task.spec)) {\n throw new InputError(\n 'Wrong template version executed with the workflow engine',\n );\n }\n const taskId = await task.getWorkspaceName();\n\n const workspacePath = path.join(this.options.workingDirectory, taskId);\n\n const { additionalTemplateFilters, additionalTemplateGlobals } =\n this.options;\n\n const renderTemplate = await SecureTemplater.loadRenderer({\n templateFilters: {\n ...this.defaultTemplateFilters,\n ...additionalTemplateFilters,\n },\n templateGlobals: additionalTemplateGlobals,\n });\n\n try {\n await task.rehydrateWorkspace?.({ taskId, targetPath: workspacePath });\n\n const taskTrack = await this.tracker.taskStart(task);\n await fs.ensureDir(workspacePath);\n\n const context: TemplateContext = {\n parameters: task.spec.parameters,\n steps: {},\n user: task.spec.user,\n context: {\n task: {\n id: taskId,\n },\n },\n };\n\n const [decision]: PolicyDecision[] =\n this.options.permissions && task.spec.steps.length\n ? await this.options.permissions.authorizeConditional(\n [{ permission: actionExecutePermission }],\n { credentials: await task.getInitiatorCredentials() },\n )\n : [{ result: AuthorizeResult.ALLOW }];\n\n for (const step of task.spec.steps) {\n await this.executeStep(\n task,\n step,\n context,\n renderTemplate,\n taskTrack,\n workspacePath,\n decision,\n );\n }\n\n const output = this.render(task.spec.output, context, renderTemplate);\n await taskTrack.markSuccessful();\n await task.cleanWorkspace?.();\n\n return { output };\n } finally {\n if (workspacePath) {\n await fs.remove(workspacePath);\n }\n }\n }\n}\n\nfunction scaffoldingTracker() {\n // prom-client metrics are deprecated in favour of OpenTelemetry metrics.\n const promTaskCount = createCounterMetric({\n name: 'scaffolder_task_count',\n help: 'Count of task runs',\n labelNames: ['template', 'user', 'result'],\n });\n const promTaskDuration = createHistogramMetric({\n name: 'scaffolder_task_duration',\n help: 'Duration of a task run',\n labelNames: ['template', 'result'],\n });\n const promtStepCount = createCounterMetric({\n name: 'scaffolder_step_count',\n help: 'Count of step runs',\n labelNames: ['template', 'step', 'result'],\n });\n const promStepDuration = createHistogramMetric({\n name: 'scaffolder_step_duration',\n help: 'Duration of a step runs',\n labelNames: ['template', 'step', 'result'],\n });\n\n const meter = metrics.getMeter('default');\n const taskCount = meter.createCounter('scaffolder.task.count', {\n description: 'Count of task runs',\n });\n\n const taskDuration = meter.createHistogram('scaffolder.task.duration', {\n description: 'Duration of a task run',\n unit: 'seconds',\n });\n\n const stepCount = meter.createCounter('scaffolder.step.count', {\n description: 'Count of step runs',\n });\n\n const stepDuration = meter.createHistogram('scaffolder.step.duration', {\n description: 'Duration of a step runs',\n unit: 'seconds',\n });\n\n async function taskStart(task: TaskContext) {\n await task.emitLog(`Starting up task with ${task.spec.steps.length} steps`);\n const template = task.spec.templateInfo?.entityRef || '';\n const user = task.spec.user?.ref || '';\n\n const startTime = process.hrtime();\n const taskTimer = promTaskDuration.startTimer({\n template,\n });\n\n function endTime() {\n const delta = process.hrtime(startTime);\n return delta[0] + delta[1] / 1e9;\n }\n\n async function skipDryRun(\n step: TaskStep,\n action: TemplateAction<JsonObject>,\n ) {\n task.emitLog(`Skipping because ${action.id} does not support dry-run`, {\n stepId: step.id,\n status: 'skipped',\n });\n }\n\n async function markSuccessful() {\n promTaskCount.inc({\n template,\n user,\n result: 'ok',\n });\n taskTimer({ result: 'ok' });\n\n taskCount.add(1, { template, user, result: 'ok' });\n taskDuration.record(endTime(), {\n result: 'ok',\n });\n }\n\n async function markFailed(step: TaskStep, err: Error) {\n await task.emitLog(String(err.stack), {\n stepId: step.id,\n status: 'failed',\n });\n promTaskCount.inc({\n template,\n user,\n result: 'failed',\n });\n taskTimer({ result: 'failed' });\n\n taskCount.add(1, { template, user, result: 'failed' });\n taskDuration.record(endTime(), {\n result: 'failed',\n });\n }\n\n async function markCancelled(step: TaskStep) {\n await task.emitLog(`Step ${step.id} has been cancelled.`, {\n stepId: step.id,\n status: 'cancelled',\n });\n promTaskCount.inc({\n template,\n user,\n result: 'cancelled',\n });\n taskTimer({ result: 'cancelled' });\n\n taskCount.add(1, { template, user, result: 'cancelled' });\n taskDuration.record(endTime(), {\n result: 'cancelled',\n });\n }\n\n return {\n skipDryRun,\n markCancelled,\n markSuccessful,\n markFailed,\n };\n }\n\n async function stepStart(task: TaskContext, step: TaskStep) {\n await task.emitLog(`Beginning step ${step.name}`, {\n stepId: step.id,\n status: 'processing',\n });\n const template = task.spec.templateInfo?.entityRef || '';\n\n const startTime = process.hrtime();\n const stepTimer = promStepDuration.startTimer({\n template,\n step: step.name,\n });\n\n function endTime() {\n const delta = process.hrtime(startTime);\n return delta[0] + delta[1] / 1e9;\n }\n\n async function markSuccessful() {\n await task.emitLog(`Finished step ${step.name}`, {\n stepId: step.id,\n status: 'completed',\n });\n promtStepCount.inc({\n template,\n step: step.name,\n result: 'ok',\n });\n stepTimer({ result: 'ok' });\n\n stepCount.add(1, { template, step: step.name, result: 'ok' });\n stepDuration.record(endTime(), {\n result: 'ok',\n });\n }\n\n async function markCancelled() {\n promtStepCount.inc({\n template,\n step: step.name,\n result: 'cancelled',\n });\n stepTimer({ result: 'cancelled' });\n\n stepCount.add(1, { template, step: step.name, result: 'cancelled' });\n stepDuration.record(endTime(), {\n result: 'cancelled',\n });\n }\n\n async function markFailed() {\n promtStepCount.inc({\n template,\n step: step.name,\n result: 'failed',\n });\n stepTimer({ result: 'failed' });\n\n stepCount.add(1, { template, step: step.name, result: 'failed' });\n stepDuration.record(endTime(), {\n result: 'failed',\n });\n }\n\n async function skipFalsy() {\n await task.emitLog(\n `Skipping step ${step.id} because its if condition was false`,\n { stepId: step.id, status: 'skipped' },\n );\n stepTimer({ result: 'skipped' });\n\n stepCount.add(1, { template, step: step.name, result: 'skipped' });\n stepDuration.record(endTime(), {\n result: 'skipped',\n });\n }\n\n return {\n markCancelled,\n markFailed,\n markSuccessful,\n skipFalsy,\n };\n }\n\n return {\n taskStart,\n stepStart,\n };\n}\n"],"names":["WinstonLogger","winston","BackstageLoggerTransport","PassThrough","createConditionAuthorizer","scaffolderActionRules","createDefaultFilters","nunjucks","templated","isTruthy","generateExampleOutput","InputError","validateJsonSchema","errors","NotAllowedError","loggerToWinstonLogger","stringifyError","fs","path","SecureTemplater","actionExecutePermission","AuthorizeResult","createCounterMetric","createHistogramMetric","metrics"],"mappings":"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"}
1
+ {"version":3,"file":"NunjucksWorkflowRunner.cjs.js","sources":["../../../src/scaffolder/tasks/NunjucksWorkflowRunner.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 { InputError, NotAllowedError, stringifyError } from '@backstage/errors';\nimport { ScmIntegrations } from '@backstage/integration';\nimport {\n TaskRecovery,\n TaskSpec,\n TaskSpecV1beta3,\n TaskStep,\n} from '@backstage/plugin-scaffolder-common';\nimport { JsonArray, JsonObject, JsonValue } from '@backstage/types';\nimport { metrics } from '@opentelemetry/api';\nimport fs from 'fs-extra';\nimport { validate as validateJsonSchema } from 'jsonschema';\nimport nunjucks from 'nunjucks';\nimport path from 'path';\nimport { PassThrough } from 'stream';\nimport * as winston from 'winston';\nimport {\n SecureTemplater,\n SecureTemplateRenderer,\n} from '../../lib/templating/SecureTemplater';\nimport { TemplateActionRegistry } from '../actions';\nimport { generateExampleOutput, isTruthy } from './helper';\nimport { TaskTrackType, WorkflowResponse, WorkflowRunner } from './types';\n\nimport type {\n AuditorService,\n PermissionsService,\n} from '@backstage/backend-plugin-api';\nimport { UserEntity } from '@backstage/catalog-model';\nimport {\n AuthorizeResult,\n PolicyDecision,\n} from '@backstage/plugin-permission-common';\nimport { createConditionAuthorizer } from '@backstage/plugin-permission-node';\nimport { actionExecutePermission } from '@backstage/plugin-scaffolder-common/alpha';\nimport {\n TaskContext,\n TemplateAction,\n TemplateFilter,\n TemplateGlobal,\n} from '@backstage/plugin-scaffolder-node';\nimport createDefaultFilters from '../../lib/templating/filters';\nimport { scaffolderActionRules } from '../../service/rules';\nimport { createCounterMetric, createHistogramMetric } from '../../util/metrics';\nimport { BackstageLoggerTransport, WinstonLogger } from './logger';\nimport { loggerToWinstonLogger } from '../../util/loggerToWinstonLogger';\nimport { convertFiltersToRecord } from '../../util/templating';\n\ntype NunjucksWorkflowRunnerOptions = {\n workingDirectory: string;\n actionRegistry: TemplateActionRegistry;\n integrations: ScmIntegrations;\n logger: winston.Logger;\n auditor?: AuditorService;\n additionalTemplateFilters?: Record<string, TemplateFilter>;\n additionalTemplateGlobals?: Record<string, TemplateGlobal>;\n permissions?: PermissionsService;\n};\n\ntype TemplateContext = {\n parameters: JsonObject;\n EXPERIMENTAL_recovery?: TaskRecovery;\n steps: {\n [stepName: string]: { output: { [outputName: string]: JsonValue } };\n };\n secrets?: Record<string, string>;\n user?: {\n entity?: UserEntity;\n ref?: string;\n };\n each?: JsonValue;\n context: {\n task: {\n id: string;\n };\n };\n};\n\ntype CheckpointState =\n | {\n status: 'failed';\n reason: string;\n }\n | {\n status: 'success';\n value: JsonValue;\n };\n\nconst isValidTaskSpec = (taskSpec: TaskSpec): taskSpec is TaskSpecV1beta3 => {\n return taskSpec.apiVersion === 'scaffolder.backstage.io/v1beta3';\n};\n\nconst createStepLogger = ({\n task,\n step,\n rootLogger,\n}: {\n task: TaskContext;\n step: TaskStep;\n rootLogger: winston.Logger;\n}) => {\n const taskLogger = WinstonLogger.create({\n level: process.env.LOG_LEVEL || 'info',\n format: winston.format.combine(\n winston.format.colorize(),\n winston.format.simple(),\n ),\n transports: [new BackstageLoggerTransport(rootLogger, task, step.id)],\n });\n\n taskLogger.addRedactions(Object.values(task.secrets ?? {}));\n\n // This stream logger should be deprecated. We're going to replace it with\n // just using the logger directly, as all those logs get written to step logs\n // using the stepLogStream above.\n // Initially this stream used to be the only way to write to the client logs, but that\n // has changed over time, there's not really a need for this anymore.\n // You can just create a simple wrapper like the below in your action to write to the main logger.\n // This way we also get redactions for free.\n const streamLogger = new PassThrough();\n streamLogger.on('data', async data => {\n const message = data.toString().trim();\n if (message?.length > 1) {\n taskLogger.info(message);\n }\n });\n\n return { taskLogger, streamLogger };\n};\n\nconst isActionAuthorized = createConditionAuthorizer(\n Object.values(scaffolderActionRules),\n);\n\nexport class NunjucksWorkflowRunner implements WorkflowRunner {\n private readonly defaultTemplateFilters: Record<string, TemplateFilter>;\n\n constructor(private readonly options: NunjucksWorkflowRunnerOptions) {\n this.defaultTemplateFilters = convertFiltersToRecord(\n createDefaultFilters({\n integrations: this.options.integrations,\n }),\n );\n }\n\n private readonly tracker = scaffoldingTracker();\n\n private isSingleTemplateString(input: string) {\n const { parser, nodes } = nunjucks as unknown as {\n parser: {\n parse(\n template: string,\n ctx: object,\n options: nunjucks.ConfigureOptions,\n ): { children: { children?: unknown[] }[] };\n };\n nodes: { TemplateData: Function };\n };\n\n const parsed = parser.parse(\n input,\n {},\n {\n autoescape: false,\n tags: {\n variableStart: '${{',\n variableEnd: '}}',\n },\n },\n );\n\n return (\n parsed.children.length === 1 &&\n !(parsed.children[0]?.children?.[0] instanceof nodes.TemplateData)\n );\n }\n\n private render<T>(\n input: T,\n context: TemplateContext,\n renderTemplate: SecureTemplateRenderer,\n ): T {\n return JSON.parse(JSON.stringify(input), (_key, value) => {\n try {\n if (typeof value === 'string') {\n try {\n if (this.isSingleTemplateString(value)) {\n // Lets convert ${{ parameters.bob }} to ${{ (parameters.bob) | dump }} so we can keep the input type\n const wrappedDumped = value.replace(\n /\\${{(.+)}}/g,\n '${{ ( $1 ) | dump }}',\n );\n\n // Run the templating\n const templated = renderTemplate(wrappedDumped, context);\n\n // If there's an empty string returned, then it's undefined\n if (templated === '') {\n return undefined;\n }\n\n // Reparse the dumped string\n return JSON.parse(templated);\n }\n } catch (ex) {\n this.options.logger.error(\n `Failed to parse template string: ${value} with error ${ex.message}`,\n );\n }\n\n // Fallback to default behaviour\n const templated = renderTemplate(value, context);\n\n if (templated === '') {\n return undefined;\n }\n\n return templated;\n }\n } catch {\n return value;\n }\n return value;\n });\n }\n\n async executeStep(\n task: TaskContext,\n step: TaskStep,\n context: TemplateContext,\n renderTemplate: (template: string, values: unknown) => string,\n taskTrack: TaskTrackType,\n workspacePath: string,\n decision: PolicyDecision,\n ) {\n const stepTrack = await this.tracker.stepStart(task, step);\n\n if (task.cancelSignal.aborted) {\n throw new Error(\n `Step ${step.id} (${step.name}) of task ${task.taskId} has been cancelled.`,\n );\n }\n\n try {\n if (\n step.if === false ||\n (typeof step.if === 'string' &&\n !isTruthy(this.render(step.if, context, renderTemplate)))\n ) {\n await stepTrack.skipFalsy();\n return;\n }\n const action: TemplateAction<JsonObject> =\n this.options.actionRegistry.get(step.action);\n const { taskLogger, streamLogger } = createStepLogger({\n task,\n step,\n rootLogger: this.options.logger,\n });\n\n if (task.isDryRun) {\n const redactedSecrets = Object.fromEntries(\n Object.entries(task.secrets ?? {}).map(secret => [secret[0], '***']),\n );\n const debugInput =\n (step.input &&\n this.render(\n step.input,\n {\n ...context,\n secrets: redactedSecrets,\n },\n renderTemplate,\n )) ??\n {};\n taskLogger.info(\n `Running ${\n action.id\n } in dry-run mode with inputs (secrets redacted): ${JSON.stringify(\n debugInput,\n undefined,\n 2,\n )}`,\n );\n if (!action.supportsDryRun) {\n await taskTrack.skipDryRun(step, action);\n const outputSchema = action.schema?.output;\n if (outputSchema) {\n context.steps[step.id] = {\n output: generateExampleOutput(outputSchema) as {\n [name in string]: JsonValue;\n },\n };\n } else {\n context.steps[step.id] = { output: {} };\n }\n return;\n }\n }\n\n const resolvedEach =\n step.each && this.render(step.each, context, renderTemplate);\n\n if (step.each && !resolvedEach) {\n throw new InputError(\n `Invalid value on action ${action.id}.each parameter, \"${step.each}\" cannot be resolved to a value`,\n );\n }\n\n const iterations = (\n resolvedEach\n ? Object.entries(resolvedEach).map(([key, value]) => ({\n each: { key, value },\n }))\n : [{}]\n ).map(i => ({\n ...i,\n // Secrets are only passed when templating the input to actions for security reasons\n input: step.input\n ? this.render(\n step.input,\n { ...context, secrets: task.secrets ?? {}, ...i },\n renderTemplate,\n )\n : {},\n }));\n for (const iteration of iterations) {\n const actionId = `${action.id}${\n iteration.each ? `[${iteration.each.key}]` : ''\n }`;\n\n if (action.schema?.input) {\n const validateResult = validateJsonSchema(\n iteration.input,\n action.schema.input,\n );\n if (!validateResult.valid) {\n const errors = validateResult.errors.join(', ');\n throw new InputError(\n `Invalid input passed to action ${actionId}, ${errors}`,\n );\n }\n }\n if (\n !isActionAuthorized(decision, {\n action: action.id,\n input: iteration.input,\n })\n ) {\n throw new NotAllowedError(\n `Unauthorized action: ${actionId}. The action is not allowed. Input: ${JSON.stringify(\n iteration.input,\n null,\n 2,\n )}`,\n );\n }\n }\n const tmpDirs = new Array<string>();\n const stepOutput: { [outputName: string]: JsonValue } = {};\n const prevTaskState = await task.getTaskState?.();\n\n for (const iteration of iterations) {\n if (iteration.each) {\n taskLogger.info(\n `Running step each: ${JSON.stringify(\n iteration.each,\n (k, v) => (k ? v.toString() : v),\n 0,\n )}`,\n );\n }\n\n await action.handler({\n input: iteration.input,\n task: {\n id: await task.getWorkspaceName(),\n },\n secrets: task.secrets ?? {},\n // TODO(blam): move to LoggerService and away from Winston\n logger: loggerToWinstonLogger(taskLogger),\n logStream: streamLogger,\n workspacePath,\n async checkpoint<T extends JsonValue | void>(opts: {\n key?: string;\n fn: () => Promise<T> | T;\n }) {\n const { key: checkpointKey, fn } = opts;\n const key = `v1.task.checkpoint.${step.id}.${checkpointKey}`;\n\n try {\n let prevValue: T | undefined;\n\n if (prevTaskState) {\n const prevState = (\n prevTaskState.state?.checkpoints as {\n [key: string]: CheckpointState;\n }\n )?.[key];\n\n if (prevState && prevState.status === 'success') {\n prevValue = prevState.value as T;\n }\n }\n\n const value = prevValue ? prevValue : await fn();\n\n if (!prevValue) {\n task.updateCheckpoint?.({\n key,\n status: 'success',\n value: value ?? {},\n });\n }\n return value;\n } catch (err) {\n task.updateCheckpoint?.({\n key,\n status: 'failed',\n reason: stringifyError(err),\n });\n throw err;\n } finally {\n await task.serializeWorkspace?.({ path: workspacePath });\n }\n },\n createTemporaryDirectory: async () => {\n const tmpDir = await fs.mkdtemp(\n `${workspacePath}_step-${step.id}-`,\n );\n tmpDirs.push(tmpDir);\n return tmpDir;\n },\n output(name: string, value: JsonValue) {\n if (step.each) {\n stepOutput[name] = stepOutput[name] || [];\n (stepOutput[name] as JsonArray).push(value);\n } else {\n stepOutput[name] = value;\n }\n },\n templateInfo: task.spec.templateInfo,\n user: task.spec.user,\n isDryRun: task.isDryRun,\n signal: task.cancelSignal,\n getInitiatorCredentials: () => task.getInitiatorCredentials(),\n });\n }\n\n // Remove all temporary directories that were created when executing the action\n for (const tmpDir of tmpDirs) {\n await fs.remove(tmpDir);\n }\n\n context.steps[step.id] = { output: stepOutput };\n\n if (task.cancelSignal.aborted) {\n throw new Error(\n `Step ${step.id} (${step.name}) of task ${task.taskId} has been cancelled.`,\n );\n }\n\n await stepTrack.markSuccessful();\n } catch (err) {\n await taskTrack.markFailed(step, err);\n await stepTrack.markFailed();\n throw err;\n } finally {\n await task.serializeWorkspace?.({ path: workspacePath });\n }\n }\n\n async execute(task: TaskContext): Promise<WorkflowResponse> {\n if (!isValidTaskSpec(task.spec)) {\n throw new InputError(\n 'Wrong template version executed with the workflow engine',\n );\n }\n const taskId = await task.getWorkspaceName();\n\n const workspacePath = path.join(this.options.workingDirectory, taskId);\n\n const { additionalTemplateFilters, additionalTemplateGlobals } =\n this.options;\n\n const renderTemplate = await SecureTemplater.loadRenderer({\n templateFilters: {\n ...this.defaultTemplateFilters,\n ...additionalTemplateFilters,\n },\n templateGlobals: additionalTemplateGlobals,\n });\n\n try {\n await task.rehydrateWorkspace?.({ taskId, targetPath: workspacePath });\n\n const taskTrack = await this.tracker.taskStart(task);\n await fs.ensureDir(workspacePath);\n\n const context: TemplateContext = {\n parameters: task.spec.parameters,\n steps: {},\n user: task.spec.user,\n context: {\n task: {\n id: taskId,\n },\n },\n };\n\n const [decision]: PolicyDecision[] =\n this.options.permissions && task.spec.steps.length\n ? await this.options.permissions.authorizeConditional(\n [{ permission: actionExecutePermission }],\n { credentials: await task.getInitiatorCredentials() },\n )\n : [{ result: AuthorizeResult.ALLOW }];\n\n for (const step of task.spec.steps) {\n await this.executeStep(\n task,\n step,\n context,\n renderTemplate,\n taskTrack,\n workspacePath,\n decision,\n );\n }\n\n const output = this.render(task.spec.output, context, renderTemplate);\n await taskTrack.markSuccessful();\n await task.cleanWorkspace?.();\n\n return { output };\n } finally {\n if (workspacePath) {\n await fs.remove(workspacePath);\n }\n }\n }\n}\n\nfunction scaffoldingTracker() {\n // prom-client metrics are deprecated in favour of OpenTelemetry metrics.\n const promTaskCount = createCounterMetric({\n name: 'scaffolder_task_count',\n help: 'Count of task runs',\n labelNames: ['template', 'user', 'result'],\n });\n const promTaskDuration = createHistogramMetric({\n name: 'scaffolder_task_duration',\n help: 'Duration of a task run',\n labelNames: ['template', 'result'],\n });\n const promtStepCount = createCounterMetric({\n name: 'scaffolder_step_count',\n help: 'Count of step runs',\n labelNames: ['template', 'step', 'result'],\n });\n const promStepDuration = createHistogramMetric({\n name: 'scaffolder_step_duration',\n help: 'Duration of a step runs',\n labelNames: ['template', 'step', 'result'],\n });\n\n const meter = metrics.getMeter('default');\n const taskCount = meter.createCounter('scaffolder.task.count', {\n description: 'Count of task runs',\n });\n\n const taskDuration = meter.createHistogram('scaffolder.task.duration', {\n description: 'Duration of a task run',\n unit: 'seconds',\n });\n\n const stepCount = meter.createCounter('scaffolder.step.count', {\n description: 'Count of step runs',\n });\n\n const stepDuration = meter.createHistogram('scaffolder.step.duration', {\n description: 'Duration of a step runs',\n unit: 'seconds',\n });\n\n async function taskStart(task: TaskContext) {\n await task.emitLog(`Starting up task with ${task.spec.steps.length} steps`);\n const template = task.spec.templateInfo?.entityRef || '';\n const user = task.spec.user?.ref || '';\n\n const startTime = process.hrtime();\n const taskTimer = promTaskDuration.startTimer({\n template,\n });\n\n function endTime() {\n const delta = process.hrtime(startTime);\n return delta[0] + delta[1] / 1e9;\n }\n\n async function skipDryRun(\n step: TaskStep,\n action: TemplateAction<JsonObject>,\n ) {\n task.emitLog(`Skipping because ${action.id} does not support dry-run`, {\n stepId: step.id,\n status: 'skipped',\n });\n }\n\n async function markSuccessful() {\n promTaskCount.inc({\n template,\n user,\n result: 'ok',\n });\n taskTimer({ result: 'ok' });\n\n taskCount.add(1, { template, user, result: 'ok' });\n taskDuration.record(endTime(), {\n result: 'ok',\n });\n }\n\n async function markFailed(step: TaskStep, err: Error) {\n await task.emitLog(String(err.stack), {\n stepId: step.id,\n status: 'failed',\n });\n promTaskCount.inc({\n template,\n user,\n result: 'failed',\n });\n taskTimer({ result: 'failed' });\n\n taskCount.add(1, { template, user, result: 'failed' });\n taskDuration.record(endTime(), {\n result: 'failed',\n });\n }\n\n async function markCancelled(step: TaskStep) {\n await task.emitLog(`Step ${step.id} has been cancelled.`, {\n stepId: step.id,\n status: 'cancelled',\n });\n promTaskCount.inc({\n template,\n user,\n result: 'cancelled',\n });\n taskTimer({ result: 'cancelled' });\n\n taskCount.add(1, { template, user, result: 'cancelled' });\n taskDuration.record(endTime(), {\n result: 'cancelled',\n });\n }\n\n return {\n skipDryRun,\n markCancelled,\n markSuccessful,\n markFailed,\n };\n }\n\n async function stepStart(task: TaskContext, step: TaskStep) {\n await task.emitLog(`Beginning step ${step.name}`, {\n stepId: step.id,\n status: 'processing',\n });\n const template = task.spec.templateInfo?.entityRef || '';\n\n const startTime = process.hrtime();\n const stepTimer = promStepDuration.startTimer({\n template,\n step: step.name,\n });\n\n function endTime() {\n const delta = process.hrtime(startTime);\n return delta[0] + delta[1] / 1e9;\n }\n\n async function markSuccessful() {\n await task.emitLog(`Finished step ${step.name}`, {\n stepId: step.id,\n status: 'completed',\n });\n promtStepCount.inc({\n template,\n step: step.name,\n result: 'ok',\n });\n stepTimer({ result: 'ok' });\n\n stepCount.add(1, { template, step: step.name, result: 'ok' });\n stepDuration.record(endTime(), {\n result: 'ok',\n });\n }\n\n async function markCancelled() {\n promtStepCount.inc({\n template,\n step: step.name,\n result: 'cancelled',\n });\n stepTimer({ result: 'cancelled' });\n\n stepCount.add(1, { template, step: step.name, result: 'cancelled' });\n stepDuration.record(endTime(), {\n result: 'cancelled',\n });\n }\n\n async function markFailed() {\n promtStepCount.inc({\n template,\n step: step.name,\n result: 'failed',\n });\n stepTimer({ result: 'failed' });\n\n stepCount.add(1, { template, step: step.name, result: 'failed' });\n stepDuration.record(endTime(), {\n result: 'failed',\n });\n }\n\n async function skipFalsy() {\n await task.emitLog(\n `Skipping step ${step.id} because its if condition was false`,\n { stepId: step.id, status: 'skipped' },\n );\n stepTimer({ result: 'skipped' });\n\n stepCount.add(1, { template, step: step.name, result: 'skipped' });\n stepDuration.record(endTime(), {\n result: 'skipped',\n });\n }\n\n return {\n markCancelled,\n markFailed,\n markSuccessful,\n skipFalsy,\n };\n }\n\n return {\n taskStart,\n stepStart,\n };\n}\n"],"names":["WinstonLogger","winston","BackstageLoggerTransport","PassThrough","createConditionAuthorizer","scaffolderActionRules","convertFiltersToRecord","createDefaultFilters","nunjucks","templated","isTruthy","generateExampleOutput","InputError","validateJsonSchema","errors","NotAllowedError","loggerToWinstonLogger","stringifyError","fs","path","SecureTemplater","actionExecutePermission","AuthorizeResult","createCounterMetric","createHistogramMetric","metrics"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"helper.cjs.js","sources":["../../../src/scaffolder/tasks/helper.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 { Config, readDurationFromConfig } from '@backstage/config';\nimport { HumanDuration } from '@backstage/types';\n\nimport { isArray } from 'lodash';\nimport { Schema } from 'jsonschema';\n\n/**\n * Returns true if the input is not `false`, `undefined`, `null`, `\"\"`, `0`, or\n * `[]`. This behavior is based on the behavior of handlebars, see\n * https://handlebarsjs.com/guide/builtin-helpers.html#if\n */\nexport function isTruthy(value: any): boolean {\n return isArray(value) ? value.length > 0 : !!value;\n}\n\nexport function generateExampleOutput(schema: Schema): unknown {\n const { examples } = schema as { examples?: unknown };\n if (examples && Array.isArray(examples)) {\n return examples[0];\n }\n if (schema.type === 'object') {\n return Object.fromEntries(\n Object.entries(schema.properties ?? {}).map(([key, value]) => [\n key,\n generateExampleOutput(value),\n ]),\n );\n } else if (schema.type === 'array') {\n const [firstSchema] = [schema.items]?.flat();\n if (firstSchema) {\n return [generateExampleOutput(firstSchema)];\n }\n return [];\n } else if (schema.type === 'string') {\n return '<example>';\n } else if (schema.type === 'number') {\n return 0;\n } else if (schema.type === 'boolean') {\n return false;\n }\n return '<unknown>';\n}\n\nexport const readDuration = (\n config: Config | undefined,\n key: string,\n defaultValue: HumanDuration,\n) => {\n if (config?.has(key)) {\n return readDurationFromConfig(config, { key });\n }\n return defaultValue;\n};\n"],"names":["isArray","config","readDurationFromConfig"],"mappings":";;;;;AA2BO,SAAS,SAAS,KAAqB,EAAA;AAC5C,EAAA,OAAOA,eAAQ,KAAK,CAAA,GAAI,MAAM,MAAS,GAAA,CAAA,GAAI,CAAC,CAAC,KAAA;AAC/C;AAEO,SAAS,sBAAsB,MAAyB,EAAA;AAC7D,EAAM,MAAA,EAAE,UAAa,GAAA,MAAA;AACrB,EAAA,IAAI,QAAY,IAAA,KAAA,CAAM,OAAQ,CAAA,QAAQ,CAAG,EAAA;AACvC,IAAA,OAAO,SAAS,CAAC,CAAA;AAAA;AAEnB,EAAI,IAAA,MAAA,CAAO,SAAS,QAAU,EAAA;AAC5B,IAAA,OAAO,MAAO,CAAA,WAAA;AAAA,MACZ,MAAO,CAAA,OAAA,CAAQ,MAAO,CAAA,UAAA,IAAc,EAAE,CAAE,CAAA,GAAA,CAAI,CAAC,CAAC,GAAK,EAAA,KAAK,CAAM,KAAA;AAAA,QAC5D,GAAA;AAAA,QACA,sBAAsB,KAAK;AAAA,OAC5B;AAAA,KACH;AAAA,GACF,MAAA,IAAW,MAAO,CAAA,IAAA,KAAS,OAAS,EAAA;AAClC,IAAA,MAAM,CAAC,WAAW,CAAA,GAAI,CAAC,MAAO,CAAA,KAAK,GAAG,IAAK,EAAA;AAC3C,IAAA,IAAI,WAAa,EAAA;AACf,MAAO,OAAA,CAAC,qBAAsB,CAAA,WAAW,CAAC,CAAA;AAAA;AAE5C,IAAA,OAAO,EAAC;AAAA,GACV,MAAA,IAAW,MAAO,CAAA,IAAA,KAAS,QAAU,EAAA;AACnC,IAAO,OAAA,WAAA;AAAA,GACT,MAAA,IAAW,MAAO,CAAA,IAAA,KAAS,QAAU,EAAA;AACnC,IAAO,OAAA,CAAA;AAAA,GACT,MAAA,IAAW,MAAO,CAAA,IAAA,KAAS,SAAW,EAAA;AACpC,IAAO,OAAA,KAAA;AAAA;AAET,EAAO,OAAA,WAAA;AACT;AAEO,MAAM,YAAe,GAAA,CAC1BC,QACA,EAAA,GAAA,EACA,YACG,KAAA;AACH,EAAI,IAAAA,QAAA,EAAQ,GAAI,CAAA,GAAG,CAAG,EAAA;AACpB,IAAA,OAAOC,6BAAuB,CAAAD,QAAA,EAAQ,EAAE,GAAA,EAAK,CAAA;AAAA;AAE/C,EAAO,OAAA,YAAA;AACT;;;;;;"}
1
+ {"version":3,"file":"helper.cjs.js","sources":["../../../src/scaffolder/tasks/helper.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 { Config, readDurationFromConfig } from '@backstage/config';\nimport { HumanDuration } from '@backstage/types';\n\nimport { isArray } from 'lodash';\nimport { Schema } from 'jsonschema';\n\n/**\n * Returns true if the input is not `false`, `undefined`, `null`, `\"\"`, `0`, or\n * `[]`. This behavior is based on the behavior of handlebars, see\n * https://handlebarsjs.com/guide/builtin-helpers.html#if\n */\nexport function isTruthy(value: any): boolean {\n return isArray(value) ? value.length > 0 : !!value;\n}\n\nexport function generateExampleOutput(schema: Schema): unknown {\n const { examples } = schema as { examples?: unknown };\n if (examples && Array.isArray(examples)) {\n return examples[0];\n }\n if (schema.type === 'object') {\n return Object.fromEntries(\n Object.entries(schema.properties ?? {}).map(([key, value]) => [\n key,\n generateExampleOutput(value as Schema),\n ]),\n );\n } else if (schema.type === 'array') {\n const [firstSchema] = [schema.items]?.flat();\n if (firstSchema) {\n return [generateExampleOutput(firstSchema as Schema)];\n }\n return [];\n } else if (schema.type === 'string') {\n return '<example>';\n } else if (schema.type === 'number') {\n return 0;\n } else if (schema.type === 'boolean') {\n return false;\n }\n return '<unknown>';\n}\n\nexport const readDuration = (\n config: Config | undefined,\n key: string,\n defaultValue: HumanDuration,\n) => {\n if (config?.has(key)) {\n return readDurationFromConfig(config, { key });\n }\n return defaultValue;\n};\n"],"names":["isArray","config","readDurationFromConfig"],"mappings":";;;;;AA2BO,SAAS,SAAS,KAAqB,EAAA;AAC5C,EAAA,OAAOA,eAAQ,KAAK,CAAA,GAAI,MAAM,MAAS,GAAA,CAAA,GAAI,CAAC,CAAC,KAAA;AAC/C;AAEO,SAAS,sBAAsB,MAAyB,EAAA;AAC7D,EAAM,MAAA,EAAE,UAAa,GAAA,MAAA;AACrB,EAAA,IAAI,QAAY,IAAA,KAAA,CAAM,OAAQ,CAAA,QAAQ,CAAG,EAAA;AACvC,IAAA,OAAO,SAAS,CAAC,CAAA;AAAA;AAEnB,EAAI,IAAA,MAAA,CAAO,SAAS,QAAU,EAAA;AAC5B,IAAA,OAAO,MAAO,CAAA,WAAA;AAAA,MACZ,MAAO,CAAA,OAAA,CAAQ,MAAO,CAAA,UAAA,IAAc,EAAE,CAAE,CAAA,GAAA,CAAI,CAAC,CAAC,GAAK,EAAA,KAAK,CAAM,KAAA;AAAA,QAC5D,GAAA;AAAA,QACA,sBAAsB,KAAe;AAAA,OACtC;AAAA,KACH;AAAA,GACF,MAAA,IAAW,MAAO,CAAA,IAAA,KAAS,OAAS,EAAA;AAClC,IAAA,MAAM,CAAC,WAAW,CAAA,GAAI,CAAC,MAAO,CAAA,KAAK,GAAG,IAAK,EAAA;AAC3C,IAAA,IAAI,WAAa,EAAA;AACf,MAAO,OAAA,CAAC,qBAAsB,CAAA,WAAqB,CAAC,CAAA;AAAA;AAEtD,IAAA,OAAO,EAAC;AAAA,GACV,MAAA,IAAW,MAAO,CAAA,IAAA,KAAS,QAAU,EAAA;AACnC,IAAO,OAAA,WAAA;AAAA,GACT,MAAA,IAAW,MAAO,CAAA,IAAA,KAAS,QAAU,EAAA;AACnC,IAAO,OAAA,CAAA;AAAA,GACT,MAAA,IAAW,MAAO,CAAA,IAAA,KAAS,SAAW,EAAA;AACpC,IAAO,OAAA,KAAA;AAAA;AAET,EAAO,OAAA,WAAA;AACT;AAEO,MAAM,YAAe,GAAA,CAC1BC,QACA,EAAA,GAAA,EACA,YACG,KAAA;AACH,EAAI,IAAAA,QAAA,EAAQ,GAAI,CAAA,GAAG,CAAG,EAAA;AACpB,IAAA,OAAOC,6BAAuB,CAAAD,QAAA,EAAQ,EAAE,GAAA,EAAK,CAAA;AAAA;AAE/C,EAAO,OAAA,YAAA;AACT;;;;;;"}
@@ -34,6 +34,7 @@ require('isbinaryfile');
34
34
  require('isolated-vm');
35
35
  require('lodash/get');
36
36
  require('../scaffolder/actions/builtin/fetch/template.examples.cjs.js');
37
+ var templating = require('../util/templating.cjs.js');
37
38
  require('../scaffolder/actions/builtin/fetch/templateFile.examples.cjs.js');
38
39
  require('../scaffolder/actions/builtin/filesystem/delete.examples.cjs.js');
39
40
  require('../scaffolder/actions/builtin/filesystem/rename.examples.cjs.js');
@@ -195,18 +196,12 @@ async function createRouter(options) {
195
196
  }
196
197
  const actionRegistry = new TemplateActionRegistry.TemplateActionRegistry();
197
198
  const templateExtensions = {
198
- additionalTemplateFilters: Array.isArray(additionalTemplateFilters) ? Object.fromEntries(
199
- additionalTemplateFilters.map((f) => [
200
- f.id,
201
- f.filter
202
- ])
203
- ) : additionalTemplateFilters,
204
- additionalTemplateGlobals: Array.isArray(additionalTemplateGlobals) ? Object.fromEntries(
205
- additionalTemplateGlobals.map((g) => [
206
- g.id,
207
- "value" in g ? g.value : g.fn
208
- ])
209
- ) : additionalTemplateGlobals
199
+ additionalTemplateFilters: templating.convertFiltersToRecord(
200
+ additionalTemplateFilters
201
+ ),
202
+ additionalTemplateGlobals: templating.convertGlobalsToRecord(
203
+ additionalTemplateGlobals
204
+ )
210
205
  };
211
206
  const workers = [];
212
207
  if (concurrentTasksLimit !== 0) {