@backstage/plugin-scaffolder-backend 0.15.16 → 0.15.20

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,58 @@
1
1
  # @backstage/plugin-scaffolder-backend
2
2
 
3
+ ## 0.15.20
4
+
5
+ ### Patch Changes
6
+
7
+ - 9fbd3b90ae: fix: Register plugin to prioritise Component kind for entityRef
8
+ - 451ef0aa07: Fix token pass-through for software templates using beta 3 version
9
+ - 5333451def: Cleaned up API exports
10
+ - 3b4d8caff6: Allow a GitHubCredentialsProvider to be passed to the GitHub scaffolder tasks actions.
11
+ - Updated dependencies
12
+ - @backstage/config@0.1.12
13
+ - @backstage/integration@0.7.1
14
+ - @backstage/backend-common@0.10.3
15
+ - @backstage/plugin-catalog-backend@0.20.0
16
+ - @backstage/errors@0.2.0
17
+ - @backstage/catalog-client@0.5.4
18
+ - @backstage/catalog-model@0.9.9
19
+ - @backstage/plugin-scaffolder-backend-module-cookiecutter@0.1.8
20
+
21
+ ## 0.15.19
22
+
23
+ ### Patch Changes
24
+
25
+ - 7d4b4e937c: Uptake changes to the GitHub Credentials Provider interface.
26
+ - d078377f67: Support navigating back to pre-filled templates to update inputs of scaffolder tasks for resubmission
27
+ - 5f8ceba1b1: Support custom file name for `catalog:write` action
28
+ - Updated dependencies
29
+ - @backstage/backend-common@0.10.1
30
+ - @backstage/plugin-catalog-backend@0.19.4
31
+ - @backstage/plugin-scaffolder-common@0.1.2
32
+ - @backstage/integration@0.7.0
33
+ - @backstage/plugin-scaffolder-backend-module-cookiecutter@0.1.7
34
+
35
+ ## 0.15.18
36
+
37
+ ### Patch Changes
38
+
39
+ - Updated dependencies
40
+ - @backstage/backend-common@0.10.0
41
+ - @backstage/catalog-client@0.5.3
42
+ - @backstage/plugin-catalog-backend@0.19.3
43
+ - @backstage/plugin-scaffolder-backend-module-cookiecutter@0.1.6
44
+
45
+ ## 0.15.17
46
+
47
+ ### Patch Changes
48
+
49
+ - eec0750d8d: Makes cookiecutter a default, but optional action based on if a containerRunner argument is passed in to createRouter or createBuiltinActions
50
+ - ed52f74ab3: Adding changes to create GitLab Merge Request using custom action
51
+ - Updated dependencies
52
+ - @backstage/plugin-catalog-backend@0.19.2
53
+ - @backstage/backend-common@0.9.14
54
+ - @backstage/catalog-model@0.9.8
55
+
3
56
  ## 0.15.16
4
57
 
5
58
  ### Patch Changes
package/dist/index.cjs.js CHANGED
@@ -7,6 +7,7 @@ var catalogModel = require('@backstage/catalog-model');
7
7
  var fs = require('fs-extra');
8
8
  var yaml = require('yaml');
9
9
  var backendCommon = require('@backstage/backend-common');
10
+ var integration = require('@backstage/integration');
10
11
  var path = require('path');
11
12
  var globby = require('globby');
12
13
  var isbinaryfile = require('isbinaryfile');
@@ -16,7 +17,6 @@ var child_process = require('child_process');
16
17
  var stream = require('stream');
17
18
  var azureDevopsNodeApi = require('azure-devops-node-api');
18
19
  var fetch = require('node-fetch');
19
- var integration = require('@backstage/integration');
20
20
  var rest = require('@octokit/rest');
21
21
  var lodash = require('lodash');
22
22
  var octokitPluginCreatePullRequest = require('octokit-plugin-create-pull-request');
@@ -119,7 +119,6 @@ function createCatalogRegisterAction(options) {
119
119
  }
120
120
  },
121
121
  async handler(ctx) {
122
- var _a;
123
122
  const { input } = ctx;
124
123
  let catalogInfoUrl;
125
124
  if ("catalogInfoUrl" in input) {
@@ -148,7 +147,14 @@ function createCatalogRegisterAction(options) {
148
147
  }, ctx.token ? { token: ctx.token } : {});
149
148
  if (result.entities.length > 0) {
150
149
  const { entities } = result;
151
- const entity = (_a = entities.find((e) => !e.metadata.name.startsWith("generated-"))) != null ? _a : entities[0];
150
+ let entity;
151
+ entity = entities.find((e) => !e.metadata.name.startsWith("generated-") && e.kind === "Component");
152
+ if (!entity) {
153
+ entity = entities.find((e) => !e.metadata.name.startsWith("generated-"));
154
+ }
155
+ if (!entity) {
156
+ entity = entities[0];
157
+ }
152
158
  ctx.output("entityRef", catalogModel.stringifyEntityRef(entity));
153
159
  }
154
160
  } catch (e) {
@@ -169,6 +175,11 @@ function createCatalogWriteAction() {
169
175
  input: {
170
176
  type: "object",
171
177
  properties: {
178
+ filePath: {
179
+ title: "Catalog file path",
180
+ description: "Defaults to catalog-info.yaml",
181
+ type: "string"
182
+ },
172
183
  entity: {
173
184
  title: "Entity info to write catalog-info.yaml",
174
185
  description: "You can provide the same values used in the Entity schema.",
@@ -179,8 +190,9 @@ function createCatalogWriteAction() {
179
190
  },
180
191
  async handler(ctx) {
181
192
  ctx.logStream.write(`Writing catalog-info.yaml`);
182
- const { entity } = ctx.input;
183
- await fs__default["default"].writeFile(backendCommon.resolveSafeChildPath(ctx.workspacePath, "catalog-info.yaml"), yaml__namespace.stringify(entity));
193
+ const { filePath, entity } = ctx.input;
194
+ const path = filePath != null ? filePath : "catalog-info.yaml";
195
+ await fs__default["default"].writeFile(backendCommon.resolveSafeChildPath(ctx.workspacePath, path), yaml__namespace.stringify(entity));
184
196
  }
185
197
  });
186
198
  }
@@ -1144,12 +1156,9 @@ function createPublishFileAction() {
1144
1156
  }
1145
1157
 
1146
1158
  class OctokitProvider {
1147
- constructor(integrations) {
1159
+ constructor(integrations, githubCredentialsProvider) {
1148
1160
  this.integrations = integrations;
1149
- this.credentialsProviders = new Map(integrations.github.list().map((integration$1) => {
1150
- const provider = integration.GithubCredentialsProvider.create(integration$1.config);
1151
- return [integration$1.config.host, provider];
1152
- }));
1161
+ this.githubCredentialsProvider = githubCredentialsProvider || integration.DefaultGithubCredentialsProvider.fromIntegrations(this.integrations);
1153
1162
  }
1154
1163
  async getOctokit(repoUrl) {
1155
1164
  var _a;
@@ -1161,11 +1170,7 @@ class OctokitProvider {
1161
1170
  if (!integrationConfig) {
1162
1171
  throw new errors.InputError(`No integration for host ${host}`);
1163
1172
  }
1164
- const credentialsProvider = this.credentialsProviders.get(host);
1165
- if (!credentialsProvider) {
1166
- throw new errors.InputError(`No matching credentials for host ${host}, please check your integrations config`);
1167
- }
1168
- const { token } = await credentialsProvider.getCredentials({
1173
+ const { token } = await this.githubCredentialsProvider.getCredentials({
1169
1174
  url: `https://${host}/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}`
1170
1175
  });
1171
1176
  if (!token) {
@@ -1181,8 +1186,8 @@ class OctokitProvider {
1181
1186
  }
1182
1187
 
1183
1188
  function createPublishGithubAction(options) {
1184
- const { integrations, config } = options;
1185
- const octokitProvider = new OctokitProvider(integrations);
1189
+ const { integrations, config, githubCredentialsProvider } = options;
1190
+ const octokitProvider = new OctokitProvider(integrations, githubCredentialsProvider || integration.DefaultGithubCredentialsProvider.fromIntegrations(integrations));
1186
1191
  return createTemplateAction({
1187
1192
  id: "publish:github",
1188
1193
  description: "Initializes a git repository of contents in workspace and publishes it to GitHub.",
@@ -1382,6 +1387,7 @@ class GithubResponseError extends errors.CustomErrorBase {
1382
1387
  }
1383
1388
  const defaultClientFactory = async ({
1384
1389
  integrations,
1390
+ githubCredentialsProvider,
1385
1391
  owner,
1386
1392
  repo,
1387
1393
  host = "github.com"
@@ -1391,10 +1397,7 @@ const defaultClientFactory = async ({
1391
1397
  if (!integrationConfig) {
1392
1398
  throw new errors.InputError(`No integration for host ${host}`);
1393
1399
  }
1394
- const credentialsProvider = integration.GithubCredentialsProvider.create(integrationConfig);
1395
- if (!credentialsProvider) {
1396
- throw new errors.InputError(`No matching credentials for host ${host}, please check your integrations config`);
1397
- }
1400
+ const credentialsProvider = githubCredentialsProvider || integration.SingleInstanceGithubCredentialsProvider.create(integrationConfig);
1398
1401
  const { token } = await credentialsProvider.getCredentials({
1399
1402
  url: `https://${host}/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}`
1400
1403
  });
@@ -1409,6 +1412,7 @@ const defaultClientFactory = async ({
1409
1412
  };
1410
1413
  const createPublishGithubPullRequestAction = ({
1411
1414
  integrations,
1415
+ githubCredentialsProvider,
1412
1416
  clientFactory = defaultClientFactory
1413
1417
  }) => {
1414
1418
  return createTemplateAction({
@@ -1475,7 +1479,13 @@ const createPublishGithubPullRequestAction = ({
1475
1479
  if (!owner) {
1476
1480
  throw new errors.InputError(`No owner provided for host: ${host}, and repo ${repo}`);
1477
1481
  }
1478
- const client = await clientFactory({ integrations, host, owner, repo });
1482
+ const client = await clientFactory({
1483
+ integrations,
1484
+ githubCredentialsProvider,
1485
+ host,
1486
+ owner,
1487
+ repo
1488
+ });
1479
1489
  const fileRoot = sourcePath ? backendCommon.resolveSafeChildPath(ctx.workspacePath, sourcePath) : ctx.workspacePath;
1480
1490
  const localFilePaths = await globby__default["default"](["./**", "./**/.*", "!.git"], {
1481
1491
  cwd: fileRoot,
@@ -1622,9 +1632,123 @@ function createPublishGitlabAction(options) {
1622
1632
  });
1623
1633
  }
1624
1634
 
1625
- function createGithubActionsDispatchAction(options) {
1635
+ const createPublishGitlabMergeRequestAction = (options) => {
1626
1636
  const { integrations } = options;
1627
- const octokitProvider = new OctokitProvider(integrations);
1637
+ return createTemplateAction({
1638
+ id: "publish:gitlab:merge-request",
1639
+ schema: {
1640
+ input: {
1641
+ required: ["projectid", "repoUrl", "targetPath", "branchName"],
1642
+ type: "object",
1643
+ properties: {
1644
+ repoUrl: {
1645
+ type: "string",
1646
+ title: "Repository Location",
1647
+ description: `Accepts the format 'gitlab.com/group_name/project_name' where 'project_name' is the repository name and 'group_name' is a group or username`
1648
+ },
1649
+ projectid: {
1650
+ type: "string",
1651
+ title: "projectid",
1652
+ description: "Project ID/Name(slug) of the Gitlab Project"
1653
+ },
1654
+ title: {
1655
+ type: "string",
1656
+ title: "Merge Request Name",
1657
+ description: "The name for the merge request"
1658
+ },
1659
+ description: {
1660
+ type: "string",
1661
+ title: "Merge Request Description",
1662
+ description: "The description of the merge request"
1663
+ },
1664
+ branchName: {
1665
+ type: "string",
1666
+ title: "Destination Branch name",
1667
+ description: "The description of the merge request"
1668
+ },
1669
+ targetPath: {
1670
+ type: "string",
1671
+ title: "Repository Subdirectory",
1672
+ description: "Subdirectory of repository to apply changes to"
1673
+ }
1674
+ }
1675
+ },
1676
+ output: {
1677
+ type: "object",
1678
+ properties: {
1679
+ projectid: {
1680
+ title: "Gitlab Project id/Name(slug)",
1681
+ type: "string"
1682
+ },
1683
+ mergeRequestURL: {
1684
+ title: "MergeRequest(MR) URL",
1685
+ type: "string",
1686
+ description: "Link to the merge request in GitLab"
1687
+ }
1688
+ }
1689
+ }
1690
+ },
1691
+ async handler(ctx) {
1692
+ const repoUrl = ctx.input.repoUrl;
1693
+ const { host } = parseRepoUrl(repoUrl, integrations);
1694
+ const integrationConfig = integrations.gitlab.byHost(host);
1695
+ const actions = [];
1696
+ const destinationBranch = ctx.input.branchName;
1697
+ if (!integrationConfig) {
1698
+ throw new errors.InputError(`No matching integration configuration for host ${host}, please check your integrations config`);
1699
+ }
1700
+ if (!integrationConfig.config.token) {
1701
+ throw new errors.InputError(`No token available for host ${host}`);
1702
+ }
1703
+ const api = new node.Gitlab({
1704
+ host: integrationConfig.config.baseUrl,
1705
+ token: integrationConfig.config.token
1706
+ });
1707
+ const fileRoot = ctx.workspacePath;
1708
+ const localFilePaths = await globby__default["default"]([`${ctx.input.targetPath}/**`], {
1709
+ cwd: fileRoot,
1710
+ gitignore: true,
1711
+ dot: true
1712
+ });
1713
+ const fileContents = await Promise.all(localFilePaths.map((p) => fs.readFile(backendCommon.resolveSafeChildPath(fileRoot, p))));
1714
+ const repoFilePaths = localFilePaths.map((repoFilePath) => {
1715
+ return repoFilePath;
1716
+ });
1717
+ for (let i = 0; i < repoFilePaths.length; i++) {
1718
+ actions.push({
1719
+ action: "create",
1720
+ filePath: repoFilePaths[i],
1721
+ content: fileContents[i].toString()
1722
+ });
1723
+ }
1724
+ const projects = await api.Projects.show(ctx.input.projectid);
1725
+ const { default_branch: defaultBranch } = projects;
1726
+ try {
1727
+ await api.Branches.create(ctx.input.projectid, destinationBranch, String(defaultBranch));
1728
+ } catch (e) {
1729
+ throw new errors.InputError(`The branch creation failed ${e}`);
1730
+ }
1731
+ try {
1732
+ await api.Commits.create(ctx.input.projectid, destinationBranch, ctx.input.title, actions);
1733
+ } catch (e) {
1734
+ throw new errors.InputError(`Committing the changes to ${destinationBranch} failed ${e}`);
1735
+ }
1736
+ try {
1737
+ const mergeRequestUrl = await api.MergeRequests.create(ctx.input.projectid, destinationBranch, String(defaultBranch), ctx.input.title, { description: ctx.input.description }).then((mergeRequest) => {
1738
+ return mergeRequest.web_url;
1739
+ });
1740
+ ctx.output("projectid", ctx.input.projectid);
1741
+ ctx.output("mergeRequestUrl", mergeRequestUrl);
1742
+ } catch (e) {
1743
+ throw new errors.InputError(`Merge request creation failed${e}`);
1744
+ }
1745
+ }
1746
+ });
1747
+ };
1748
+
1749
+ function createGithubActionsDispatchAction(options) {
1750
+ const { integrations, githubCredentialsProvider } = options;
1751
+ const octokitProvider = new OctokitProvider(integrations, githubCredentialsProvider || integration.DefaultGithubCredentialsProvider.fromIntegrations(integrations));
1628
1752
  return createTemplateAction({
1629
1753
  id: "github:actions:dispatch",
1630
1754
  description: "Dispatches a GitHub Action workflow for a given branch or tag",
@@ -1667,8 +1791,8 @@ function createGithubActionsDispatchAction(options) {
1667
1791
  }
1668
1792
 
1669
1793
  function createGithubWebhookAction(options) {
1670
- const { integrations, defaultWebhookSecret } = options;
1671
- const octokitProvider = new OctokitProvider(integrations);
1794
+ const { integrations, defaultWebhookSecret, githubCredentialsProvider } = options;
1795
+ const octokitProvider = new OctokitProvider(integrations, githubCredentialsProvider != null ? githubCredentialsProvider : integration.DefaultGithubCredentialsProvider.fromIntegrations(integrations));
1672
1796
  const eventNames = webhooks.emitterEventNames.filter((event) => !event.includes("."));
1673
1797
  return createTemplateAction({
1674
1798
  id: "github:webhook",
@@ -1768,31 +1892,32 @@ function createGithubWebhookAction(options) {
1768
1892
 
1769
1893
  const createBuiltinActions = (options) => {
1770
1894
  const { reader, integrations, containerRunner, catalogClient, config } = options;
1771
- return [
1895
+ const githubCredentialsProvider = integration.DefaultGithubCredentialsProvider.fromIntegrations(integrations);
1896
+ const actions = [
1772
1897
  createFetchPlainAction({
1773
1898
  reader,
1774
1899
  integrations
1775
1900
  }),
1776
- pluginScaffolderBackendModuleCookiecutter.createFetchCookiecutterAction({
1777
- reader,
1778
- integrations,
1779
- containerRunner
1780
- }),
1781
1901
  createFetchTemplateAction({
1782
1902
  integrations,
1783
1903
  reader
1784
1904
  }),
1785
1905
  createPublishGithubAction({
1786
1906
  integrations,
1787
- config
1907
+ config,
1908
+ githubCredentialsProvider
1788
1909
  }),
1789
1910
  createPublishGithubPullRequestAction({
1790
- integrations
1911
+ integrations,
1912
+ githubCredentialsProvider
1791
1913
  }),
1792
1914
  createPublishGitlabAction({
1793
1915
  integrations,
1794
1916
  config
1795
1917
  }),
1918
+ createPublishGitlabMergeRequestAction({
1919
+ integrations
1920
+ }),
1796
1921
  createPublishBitbucketAction({
1797
1922
  integrations,
1798
1923
  config
@@ -1807,12 +1932,22 @@ const createBuiltinActions = (options) => {
1807
1932
  createFilesystemDeleteAction(),
1808
1933
  createFilesystemRenameAction(),
1809
1934
  createGithubActionsDispatchAction({
1810
- integrations
1935
+ integrations,
1936
+ githubCredentialsProvider
1811
1937
  }),
1812
1938
  createGithubWebhookAction({
1813
- integrations
1939
+ integrations,
1940
+ githubCredentialsProvider
1814
1941
  })
1815
1942
  ];
1943
+ if (containerRunner) {
1944
+ actions.push(pluginScaffolderBackendModuleCookiecutter.createFetchCookiecutterAction({
1945
+ reader,
1946
+ integrations,
1947
+ containerRunner
1948
+ }));
1949
+ }
1950
+ return actions;
1816
1951
  };
1817
1952
 
1818
1953
  class TemplateActionRegistry {
@@ -2395,7 +2530,7 @@ class NunjucksWorkflowRunner {
2395
2530
  });
2396
2531
  }
2397
2532
  async execute(task) {
2398
- var _a, _b;
2533
+ var _a, _b, _c;
2399
2534
  if (!isValidTaskSpec(task.spec)) {
2400
2535
  throw new errors.InputError("Wrong template version executed with the workflow engine");
2401
2536
  }
@@ -2444,6 +2579,7 @@ class NunjucksWorkflowRunner {
2444
2579
  await action.handler({
2445
2580
  baseUrl: task.spec.baseUrl,
2446
2581
  input,
2582
+ token: (_c = task.secrets) == null ? void 0 : _c.token,
2447
2583
  logger: taskLogger,
2448
2584
  logStream: streamLogger,
2449
2585
  workspacePath,
@@ -2875,6 +3011,7 @@ exports.createPublishFileAction = createPublishFileAction;
2875
3011
  exports.createPublishGithubAction = createPublishGithubAction;
2876
3012
  exports.createPublishGithubPullRequestAction = createPublishGithubPullRequestAction;
2877
3013
  exports.createPublishGitlabAction = createPublishGitlabAction;
3014
+ exports.createPublishGitlabMergeRequestAction = createPublishGitlabMergeRequestAction;
2878
3015
  exports.createRouter = createRouter;
2879
3016
  exports.createTemplateAction = createTemplateAction;
2880
3017
  exports.fetchContents = fetchContents;