@backstage/plugin-scaffolder-backend 0.15.24 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,39 @@
1
1
  # @backstage/plugin-scaffolder-backend
2
2
 
3
+ ## 0.16.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 661594bf43: **BREAKING**: Updated `TemplateAction` and related types to have its type parameter extend `JsonObject` instead of `InputBase`. The `createTemplateAction` has also been updated to pass through the `TInput` type parameter to the return type, meaning the `TemplateAction` retains its type. This can lead to breakages during type checking especially within tests.
8
+ - 8db2b671c6: **BREAKING**: `ctx.token` is now `ctx.secrets.backstageToken` in Actions. Please update any of your Actions that might call out to Backstage API's with this token.
9
+ - 5a1594330e: **BREAKING** - Removed the `CatalogEntityClient` export. This is no longer provider by this package,
10
+ but you can implement one pretty simply yourself using the `CatalogApi` and applying filters to fetch templates.
11
+ - 7d3471db94: Remove the previously deprecated `scaffolder.provider` config for all providers.
12
+ This config is no longer used anywhere, and adopters should use [`integrations` config](https://backstage.io/docs/integrations) instead.
13
+
14
+ ### Patch Changes
15
+
16
+ - 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5
17
+ - 3e59f90b51: Fix error handling of the `runCommand` helper to return `Error`
18
+ instance.
19
+ - c77c5c7eb6: Added `backstage.role` to `package.json`
20
+ - 216725b434: Updated to use new names for `parseLocationRef` and `stringifyLocationRef`
21
+ - e72d371296: Use `TemplateEntityV1beta2` from `@backstage/plugin-scaffolder-common` instead
22
+ of `@backstage/catalog-model`.
23
+ - 1433045c08: Removed unused `helmet` dependency.
24
+ - 27eccab216: Replaces use of deprecated catalog-model constants.
25
+ - Updated dependencies
26
+ - @backstage/plugin-scaffolder-common@0.2.0
27
+ - @backstage/plugin-catalog-backend@0.21.4
28
+ - @backstage/backend-common@0.10.8
29
+ - @backstage/catalog-client@0.7.0
30
+ - @backstage/errors@0.2.1
31
+ - @backstage/integration@0.7.3
32
+ - @backstage/catalog-model@0.10.0
33
+ - @backstage/config@0.1.14
34
+ - @backstage/types@0.1.2
35
+ - @backstage/plugin-scaffolder-backend-module-cookiecutter@0.2.0
36
+
3
37
  ## 0.15.24
4
38
 
5
39
  ### Patch Changes
package/config.d.ts CHANGED
@@ -28,30 +28,5 @@ export interface Config {
28
28
  * The commit message used when new components are created.
29
29
  */
30
30
  defaultCommitMessage?: string;
31
- /**
32
- * @deprecated Replaced by parameters for the publish:github action
33
- */
34
- github?: {
35
- [key: string]: string;
36
- };
37
- /**
38
- * @deprecated Use the Gitlab integration instead
39
- */
40
- gitlab?: {
41
- api: { [key: string]: string };
42
- };
43
- /**
44
- * @deprecated Use the Azure integration instead
45
- */
46
- azure?: {
47
- baseUrl: string;
48
- api: { [key: string]: string };
49
- };
50
- /**
51
- * @deprecated Use the Bitbucket integration instead
52
- */
53
- bitbucket?: {
54
- api: { [key: string]: string };
55
- };
56
31
  };
57
32
  }
package/dist/index.cjs.js CHANGED
@@ -685,7 +685,7 @@ const runCommand = async ({
685
685
  });
686
686
  process.on("close", (code) => {
687
687
  if (code !== 0) {
688
- return reject(`Command ${command} failed, exit code: ${code}`);
688
+ return reject(new Error(`Command ${command} failed, exit code: ${code}`));
689
689
  }
690
690
  return resolve();
691
691
  });
@@ -2414,7 +2414,7 @@ class HandlebarsWorkflowRunner {
2414
2414
  this.handlebars.registerHelper("eq", (a, b) => a === b);
2415
2415
  }
2416
2416
  async execute(task) {
2417
- var _a, _b, _c;
2417
+ var _a, _b;
2418
2418
  if (!isValidTaskSpec$1(task.spec)) {
2419
2419
  throw new errors.InputError(`Task spec is not a valid v1beta2 task spec`);
2420
2420
  }
@@ -2517,8 +2517,7 @@ class HandlebarsWorkflowRunner {
2517
2517
  logger: taskLogger,
2518
2518
  logStream: stream$1,
2519
2519
  input,
2520
- token: (_b = task.secrets) == null ? void 0 : _b.token,
2521
- secrets: (_c = task.secrets) != null ? _c : {},
2520
+ secrets: (_b = task.secrets) != null ? _b : {},
2522
2521
  workspacePath,
2523
2522
  async createTemporaryDirectory() {
2524
2523
  const tmpDir = await fs__default["default"].mkdtemp(`${workspacePath}_step-${step.id}-`);
@@ -2644,7 +2643,7 @@ class NunjucksWorkflowRunner {
2644
2643
  });
2645
2644
  }
2646
2645
  async execute(task) {
2647
- var _a, _b, _c, _d, _e;
2646
+ var _a, _b, _c, _d;
2648
2647
  if (!isValidTaskSpec(task.spec)) {
2649
2648
  throw new errors.InputError("Wrong template version executed with the workflow engine");
2650
2649
  }
@@ -2688,14 +2687,10 @@ class NunjucksWorkflowRunner {
2688
2687
  }
2689
2688
  const tmpDirs = new Array();
2690
2689
  const stepOutput = {};
2691
- if (!task.spec.metadata) {
2692
- console.warn("DEPRECATION NOTICE: metadata is undefined. metadata will be required in the future.");
2693
- }
2694
2690
  await action.handler({
2695
2691
  baseUrl: task.spec.baseUrl,
2696
2692
  input,
2697
- token: (_d = task.secrets) == null ? void 0 : _d.token,
2698
- secrets: (_e = task.secrets) != null ? _e : {},
2693
+ secrets: (_d = task.secrets) != null ? _d : {},
2699
2694
  logger: taskLogger,
2700
2695
  logStream: streamLogger,
2701
2696
  workspacePath,
@@ -2787,28 +2782,6 @@ class TaskWorker {
2787
2782
  }
2788
2783
  }
2789
2784
 
2790
- class CatalogEntityClient {
2791
- constructor(catalogClient) {
2792
- this.catalogClient = catalogClient;
2793
- }
2794
- async findTemplate(templateName, options) {
2795
- const { items: templates } = await this.catalogClient.getEntities({
2796
- filter: {
2797
- kind: "template",
2798
- "metadata.name": templateName
2799
- }
2800
- }, options);
2801
- if (templates.length !== 1) {
2802
- if (templates.length > 1) {
2803
- throw new errors.ConflictError("Templates lookup resulted in multiple matches");
2804
- } else {
2805
- throw new errors.NotFoundError("Template not found");
2806
- }
2807
- }
2808
- return templates[0];
2809
- }
2810
- }
2811
-
2812
2785
  async function getWorkingDirectory(config, logger) {
2813
2786
  if (!config.has("backend.workingDirectory")) {
2814
2787
  return os__default["default"].tmpdir();
@@ -2826,14 +2799,14 @@ async function getWorkingDirectory(config, logger) {
2826
2799
  }
2827
2800
  function getEntityBaseUrl(entity) {
2828
2801
  var _a, _b;
2829
- let location = (_a = entity.metadata.annotations) == null ? void 0 : _a[catalogModel.SOURCE_LOCATION_ANNOTATION];
2802
+ let location = (_a = entity.metadata.annotations) == null ? void 0 : _a[catalogModel.ANNOTATION_SOURCE_LOCATION];
2830
2803
  if (!location) {
2831
- location = (_b = entity.metadata.annotations) == null ? void 0 : _b[catalogModel.LOCATION_ANNOTATION];
2804
+ location = (_b = entity.metadata.annotations) == null ? void 0 : _b[catalogModel.ANNOTATION_LOCATION];
2832
2805
  }
2833
2806
  if (!location) {
2834
2807
  return void 0;
2835
2808
  }
2836
- const { type, target } = catalogModel.parseLocationReference(location);
2809
+ const { type, target } = catalogModel.parseLocationRef(location);
2837
2810
  if (type === "url") {
2838
2811
  return target;
2839
2812
  } else if (type === "file") {
@@ -2841,6 +2814,34 @@ function getEntityBaseUrl(entity) {
2841
2814
  }
2842
2815
  return void 0;
2843
2816
  }
2817
+ async function findTemplate({
2818
+ entityRef,
2819
+ token,
2820
+ catalogApi
2821
+ }) {
2822
+ const parsedEntityRef = catalogModel.parseEntityRef(entityRef, {
2823
+ defaultKind: "template",
2824
+ defaultNamespace: "default"
2825
+ });
2826
+ const { items } = await catalogApi.getEntities({
2827
+ filter: {
2828
+ kind: "template",
2829
+ "metadata.name": parsedEntityRef.name,
2830
+ "metadata.namespace": parsedEntityRef.namespace
2831
+ }
2832
+ }, {
2833
+ token
2834
+ });
2835
+ const templates = items.filter((entity) => entity.kind === "Template");
2836
+ if (templates.length !== 1) {
2837
+ if (templates.length > 1) {
2838
+ throw new errors.ConflictError("Templates lookup resulted in multiple matches");
2839
+ } else {
2840
+ throw new errors.NotFoundError("Template not found");
2841
+ }
2842
+ }
2843
+ return templates[0];
2844
+ }
2844
2845
 
2845
2846
  function isSupportedTemplate(entity) {
2846
2847
  return entity.apiVersion === "backstage.io/v1beta2" || entity.apiVersion === "scaffolder.backstage.io/v1beta3";
@@ -2861,7 +2862,6 @@ async function createRouter(options) {
2861
2862
  } = options;
2862
2863
  const logger = parentLogger.child({ plugin: "scaffolder" });
2863
2864
  const workingDirectory = await getWorkingDirectory(config, logger);
2864
- const entityClient = new CatalogEntityClient(catalogClient);
2865
2865
  const integrations = integration.ScmIntegrations.fromConfig(config);
2866
2866
  let taskBroker;
2867
2867
  if (!options.taskBroker) {
@@ -2904,7 +2904,9 @@ async function createRouter(options) {
2904
2904
  if (kind.toLowerCase() !== "template") {
2905
2905
  throw new errors.InputError(`Invalid kind, only 'Template' kind is supported`);
2906
2906
  }
2907
- const template = await entityClient.findTemplate(name, {
2907
+ const template = await findTemplate({
2908
+ catalogApi: catalogClient,
2909
+ entityRef: { kind, namespace, name },
2908
2910
  token: getBearerToken(req.headers.authorization)
2909
2911
  });
2910
2912
  if (isSupportedTemplate(template)) {
@@ -2936,11 +2938,18 @@ async function createRouter(options) {
2936
2938
  const templateName = req.body.templateName;
2937
2939
  const values = req.body.values;
2938
2940
  const token = getBearerToken(req.headers.authorization);
2939
- const template = await entityClient.findTemplate(templateName, {
2940
- token
2941
+ const template = await findTemplate({
2942
+ catalogApi: catalogClient,
2943
+ entityRef: {
2944
+ name: templateName
2945
+ },
2946
+ token: getBearerToken(req.headers.authorization)
2941
2947
  });
2942
2948
  let taskSpec;
2943
2949
  if (isSupportedTemplate(template)) {
2950
+ if (template.apiVersion === "backstage.io/v1beta2") {
2951
+ logger.warn(`Scaffolding ${catalogModel.stringifyEntityRef(template)} with deprecated apiVersion ${template.apiVersion}. Please migrate the template to backstage.io/v1beta3. https://backstage.io/docs/features/software-templates/migrating-from-v1beta2-to-v1beta3`);
2952
+ }
2944
2953
  for (const parameters of [(_a = template.spec.parameters) != null ? _a : []].flat()) {
2945
2954
  const result2 = jsonschema.validate(values, parameters);
2946
2955
  if (!result2.valid) {
@@ -3061,13 +3070,11 @@ function getBearerToken(header) {
3061
3070
 
3062
3071
  class ScaffolderEntitiesProcessor {
3063
3072
  constructor() {
3064
- this.validators = [
3065
- catalogModel.entityKindSchemaValidator(pluginScaffolderCommon.templateEntityV1beta3Schema)
3066
- ];
3073
+ this.validators = [pluginScaffolderCommon.templateEntityV1beta3Validator];
3067
3074
  }
3068
3075
  async validateEntityKind(entity) {
3069
3076
  for (const validator of this.validators) {
3070
- if (validator(entity)) {
3077
+ if (await validator.check(entity)) {
3071
3078
  return true;
3072
3079
  }
3073
3080
  }
@@ -3111,7 +3118,6 @@ Object.defineProperty(exports, 'createFetchCookiecutterAction', {
3111
3118
  enumerable: true,
3112
3119
  get: function () { return pluginScaffolderBackendModuleCookiecutter.createFetchCookiecutterAction; }
3113
3120
  });
3114
- exports.CatalogEntityClient = CatalogEntityClient;
3115
3121
  exports.DatabaseTaskStore = DatabaseTaskStore;
3116
3122
  exports.OctokitProvider = OctokitProvider;
3117
3123
  exports.ScaffolderEntitiesProcessor = ScaffolderEntitiesProcessor;