@backstage/plugin-scaffolder-backend 0.15.23 → 0.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,88 @@
1
1
  # @backstage/plugin-scaffolder-backend
2
2
 
3
+ ## 0.16.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Fix for the previous release with missing type declarations.
8
+ - Updated dependencies
9
+ - @backstage/backend-common@0.10.9
10
+ - @backstage/catalog-client@0.7.1
11
+ - @backstage/catalog-model@0.10.1
12
+ - @backstage/config@0.1.15
13
+ - @backstage/errors@0.2.2
14
+ - @backstage/integration@0.7.4
15
+ - @backstage/types@0.1.3
16
+ - @backstage/plugin-catalog-backend@0.21.5
17
+ - @backstage/plugin-scaffolder-backend-module-cookiecutter@0.2.1
18
+ - @backstage/plugin-scaffolder-common@0.2.1
19
+
20
+ ## 0.16.0
21
+
22
+ ### Minor Changes
23
+
24
+ - 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.
25
+ - 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.
26
+ - 5a1594330e: **BREAKING** - Removed the `CatalogEntityClient` export. This is no longer provider by this package,
27
+ but you can implement one pretty simply yourself using the `CatalogApi` and applying filters to fetch templates.
28
+ - 7d3471db94: Remove the previously deprecated `scaffolder.provider` config for all providers.
29
+ This config is no longer used anywhere, and adopters should use [`integrations` config](https://backstage.io/docs/integrations) instead.
30
+
31
+ ### Patch Changes
32
+
33
+ - 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5
34
+ - 3e59f90b51: Fix error handling of the `runCommand` helper to return `Error`
35
+ instance.
36
+ - c77c5c7eb6: Added `backstage.role` to `package.json`
37
+ - 216725b434: Updated to use new names for `parseLocationRef` and `stringifyLocationRef`
38
+ - e72d371296: Use `TemplateEntityV1beta2` from `@backstage/plugin-scaffolder-common` instead
39
+ of `@backstage/catalog-model`.
40
+ - 1433045c08: Removed unused `helmet` dependency.
41
+ - 27eccab216: Replaces use of deprecated catalog-model constants.
42
+ - Updated dependencies
43
+ - @backstage/plugin-scaffolder-common@0.2.0
44
+ - @backstage/plugin-catalog-backend@0.21.4
45
+ - @backstage/backend-common@0.10.8
46
+ - @backstage/catalog-client@0.7.0
47
+ - @backstage/errors@0.2.1
48
+ - @backstage/integration@0.7.3
49
+ - @backstage/catalog-model@0.10.0
50
+ - @backstage/config@0.1.14
51
+ - @backstage/types@0.1.2
52
+ - @backstage/plugin-scaffolder-backend-module-cookiecutter@0.2.0
53
+
54
+ ## 0.15.24
55
+
56
+ ### Patch Changes
57
+
58
+ - 2441d1cf59: chore(deps): bump `knex` from 0.95.6 to 1.0.2
59
+
60
+ This also replaces `sqlite3` with `@vscode/sqlite3` 5.0.7
61
+
62
+ - 2bd5f24043: fix for the `gitlab:publish` action to use the `oauthToken` key when creating a
63
+ `Gitlab` client. This only happens if `ctx.input.token` is provided else the key `token` will be used.
64
+ - 898a56578c: Bump `vm2` to version 3.9.6
65
+ - Updated dependencies
66
+ - @backstage/catalog-client@0.6.0
67
+ - @backstage/backend-common@0.10.7
68
+ - @backstage/plugin-catalog-backend@0.21.3
69
+ - @backstage/plugin-scaffolder-backend-module-cookiecutter@0.1.11
70
+
71
+ ## 0.15.24-next.0
72
+
73
+ ### Patch Changes
74
+
75
+ - 2441d1cf59: chore(deps): bump `knex` from 0.95.6 to 1.0.2
76
+
77
+ This also replaces `sqlite3` with `@vscode/sqlite3` 5.0.7
78
+
79
+ - 2bd5f24043: fix for the `gitlab:publish` action to use the `oauthToken` key when creating a
80
+ `Gitlab` client. This only happens if `ctx.input.token` is provided else the key `token` will be used.
81
+ - Updated dependencies
82
+ - @backstage/backend-common@0.10.7-next.0
83
+ - @backstage/plugin-catalog-backend@0.21.3-next.0
84
+ - @backstage/plugin-scaffolder-backend-module-cookiecutter@0.1.11-next.0
85
+
3
86
  ## 0.15.23
4
87
 
5
88
  ### 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
  });
@@ -1667,9 +1667,10 @@ function createPublishGitlabAction(options) {
1667
1667
  throw new errors.InputError(`No token available for host ${host}`);
1668
1668
  }
1669
1669
  const token = ctx.input.token || integrationConfig.config.token;
1670
+ const tokenType = ctx.input.token ? "oauthToken" : "token";
1670
1671
  const client = new node.Gitlab({
1671
1672
  host: integrationConfig.config.baseUrl,
1672
- token
1673
+ [tokenType]: token
1673
1674
  });
1674
1675
  let { id: targetNamespace } = await client.Namespaces.show(owner);
1675
1676
  if (!targetNamespace) {
@@ -1780,9 +1781,10 @@ const createPublishGitlabMergeRequestAction = (options) => {
1780
1781
  throw new errors.InputError(`No token available for host ${host}`);
1781
1782
  }
1782
1783
  const token = (_a = ctx.input.token) != null ? _a : integrationConfig.config.token;
1784
+ const tokenType = ctx.input.token ? "oauthToken" : "token";
1783
1785
  const api = new node.Gitlab({
1784
1786
  host: integrationConfig.config.baseUrl,
1785
- token
1787
+ [tokenType]: token
1786
1788
  });
1787
1789
  const fileRoot = ctx.workspacePath;
1788
1790
  const localFilePaths = await globby__default["default"]([`${ctx.input.targetPath}/**`], {
@@ -2412,7 +2414,7 @@ class HandlebarsWorkflowRunner {
2412
2414
  this.handlebars.registerHelper("eq", (a, b) => a === b);
2413
2415
  }
2414
2416
  async execute(task) {
2415
- var _a, _b, _c;
2417
+ var _a, _b;
2416
2418
  if (!isValidTaskSpec$1(task.spec)) {
2417
2419
  throw new errors.InputError(`Task spec is not a valid v1beta2 task spec`);
2418
2420
  }
@@ -2515,8 +2517,7 @@ class HandlebarsWorkflowRunner {
2515
2517
  logger: taskLogger,
2516
2518
  logStream: stream$1,
2517
2519
  input,
2518
- token: (_b = task.secrets) == null ? void 0 : _b.token,
2519
- secrets: (_c = task.secrets) != null ? _c : {},
2520
+ secrets: (_b = task.secrets) != null ? _b : {},
2520
2521
  workspacePath,
2521
2522
  async createTemporaryDirectory() {
2522
2523
  const tmpDir = await fs__default["default"].mkdtemp(`${workspacePath}_step-${step.id}-`);
@@ -2642,7 +2643,7 @@ class NunjucksWorkflowRunner {
2642
2643
  });
2643
2644
  }
2644
2645
  async execute(task) {
2645
- var _a, _b, _c, _d, _e;
2646
+ var _a, _b, _c, _d;
2646
2647
  if (!isValidTaskSpec(task.spec)) {
2647
2648
  throw new errors.InputError("Wrong template version executed with the workflow engine");
2648
2649
  }
@@ -2686,14 +2687,10 @@ class NunjucksWorkflowRunner {
2686
2687
  }
2687
2688
  const tmpDirs = new Array();
2688
2689
  const stepOutput = {};
2689
- if (!task.spec.metadata) {
2690
- console.warn("DEPRECATION NOTICE: metadata is undefined. metadata will be required in the future.");
2691
- }
2692
2690
  await action.handler({
2693
2691
  baseUrl: task.spec.baseUrl,
2694
2692
  input,
2695
- token: (_d = task.secrets) == null ? void 0 : _d.token,
2696
- secrets: (_e = task.secrets) != null ? _e : {},
2693
+ secrets: (_d = task.secrets) != null ? _d : {},
2697
2694
  logger: taskLogger,
2698
2695
  logStream: streamLogger,
2699
2696
  workspacePath,
@@ -2785,28 +2782,6 @@ class TaskWorker {
2785
2782
  }
2786
2783
  }
2787
2784
 
2788
- class CatalogEntityClient {
2789
- constructor(catalogClient) {
2790
- this.catalogClient = catalogClient;
2791
- }
2792
- async findTemplate(templateName, options) {
2793
- const { items: templates } = await this.catalogClient.getEntities({
2794
- filter: {
2795
- kind: "template",
2796
- "metadata.name": templateName
2797
- }
2798
- }, options);
2799
- if (templates.length !== 1) {
2800
- if (templates.length > 1) {
2801
- throw new errors.ConflictError("Templates lookup resulted in multiple matches");
2802
- } else {
2803
- throw new errors.NotFoundError("Template not found");
2804
- }
2805
- }
2806
- return templates[0];
2807
- }
2808
- }
2809
-
2810
2785
  async function getWorkingDirectory(config, logger) {
2811
2786
  if (!config.has("backend.workingDirectory")) {
2812
2787
  return os__default["default"].tmpdir();
@@ -2824,14 +2799,14 @@ async function getWorkingDirectory(config, logger) {
2824
2799
  }
2825
2800
  function getEntityBaseUrl(entity) {
2826
2801
  var _a, _b;
2827
- 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];
2828
2803
  if (!location) {
2829
- 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];
2830
2805
  }
2831
2806
  if (!location) {
2832
2807
  return void 0;
2833
2808
  }
2834
- const { type, target } = catalogModel.parseLocationReference(location);
2809
+ const { type, target } = catalogModel.parseLocationRef(location);
2835
2810
  if (type === "url") {
2836
2811
  return target;
2837
2812
  } else if (type === "file") {
@@ -2839,6 +2814,34 @@ function getEntityBaseUrl(entity) {
2839
2814
  }
2840
2815
  return void 0;
2841
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
+ }
2842
2845
 
2843
2846
  function isSupportedTemplate(entity) {
2844
2847
  return entity.apiVersion === "backstage.io/v1beta2" || entity.apiVersion === "scaffolder.backstage.io/v1beta3";
@@ -2859,7 +2862,6 @@ async function createRouter(options) {
2859
2862
  } = options;
2860
2863
  const logger = parentLogger.child({ plugin: "scaffolder" });
2861
2864
  const workingDirectory = await getWorkingDirectory(config, logger);
2862
- const entityClient = new CatalogEntityClient(catalogClient);
2863
2865
  const integrations = integration.ScmIntegrations.fromConfig(config);
2864
2866
  let taskBroker;
2865
2867
  if (!options.taskBroker) {
@@ -2902,7 +2904,9 @@ async function createRouter(options) {
2902
2904
  if (kind.toLowerCase() !== "template") {
2903
2905
  throw new errors.InputError(`Invalid kind, only 'Template' kind is supported`);
2904
2906
  }
2905
- const template = await entityClient.findTemplate(name, {
2907
+ const template = await findTemplate({
2908
+ catalogApi: catalogClient,
2909
+ entityRef: { kind, namespace, name },
2906
2910
  token: getBearerToken(req.headers.authorization)
2907
2911
  });
2908
2912
  if (isSupportedTemplate(template)) {
@@ -2934,11 +2938,18 @@ async function createRouter(options) {
2934
2938
  const templateName = req.body.templateName;
2935
2939
  const values = req.body.values;
2936
2940
  const token = getBearerToken(req.headers.authorization);
2937
- const template = await entityClient.findTemplate(templateName, {
2938
- token
2941
+ const template = await findTemplate({
2942
+ catalogApi: catalogClient,
2943
+ entityRef: {
2944
+ name: templateName
2945
+ },
2946
+ token: getBearerToken(req.headers.authorization)
2939
2947
  });
2940
2948
  let taskSpec;
2941
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
+ }
2942
2953
  for (const parameters of [(_a = template.spec.parameters) != null ? _a : []].flat()) {
2943
2954
  const result2 = jsonschema.validate(values, parameters);
2944
2955
  if (!result2.valid) {
@@ -3059,13 +3070,11 @@ function getBearerToken(header) {
3059
3070
 
3060
3071
  class ScaffolderEntitiesProcessor {
3061
3072
  constructor() {
3062
- this.validators = [
3063
- catalogModel.entityKindSchemaValidator(pluginScaffolderCommon.templateEntityV1beta3Schema)
3064
- ];
3073
+ this.validators = [pluginScaffolderCommon.templateEntityV1beta3Validator];
3065
3074
  }
3066
3075
  async validateEntityKind(entity) {
3067
3076
  for (const validator of this.validators) {
3068
- if (validator(entity)) {
3077
+ if (await validator.check(entity)) {
3069
3078
  return true;
3070
3079
  }
3071
3080
  }
@@ -3109,7 +3118,6 @@ Object.defineProperty(exports, 'createFetchCookiecutterAction', {
3109
3118
  enumerable: true,
3110
3119
  get: function () { return pluginScaffolderBackendModuleCookiecutter.createFetchCookiecutterAction; }
3111
3120
  });
3112
- exports.CatalogEntityClient = CatalogEntityClient;
3113
3121
  exports.DatabaseTaskStore = DatabaseTaskStore;
3114
3122
  exports.OctokitProvider = OctokitProvider;
3115
3123
  exports.ScaffolderEntitiesProcessor = ScaffolderEntitiesProcessor;