@backstage/plugin-scaffolder-backend 0.15.2 → 0.15.6

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,53 @@
1
1
  # @backstage/plugin-scaffolder-backend
2
2
 
3
+ ## 0.15.6
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies
8
+ - @backstage/integration@0.6.5
9
+ - @backstage/catalog-client@0.4.0
10
+ - @backstage/catalog-model@0.9.3
11
+ - @backstage/backend-common@0.9.4
12
+ - @backstage/config@0.1.10
13
+
14
+ ## 0.15.5
15
+
16
+ ### Patch Changes
17
+
18
+ - 618143c3c7: Action needed: If you are using the templates located at https://github.com/backstage/backstage/tree/master/ in your Backstage app directly using the URL via the `app-config.yaml`, you should copy over the templates inside your org and import from there. The templates have now been moved to https://github.com/backstage/software-templates. See https://github.com/backstage/backstage/issues/6415 for explanation.
19
+ - cfade02127: Change hardcoded branch `master` to \$defaultBranch in GitLab provider
20
+ - 96fef17a18: Upgrade git-parse-url to v11.6.0
21
+ - Updated dependencies
22
+ - @backstage/backend-common@0.9.3
23
+ - @backstage/integration@0.6.4
24
+
25
+ ## 0.15.4
26
+
27
+ ### Patch Changes
28
+
29
+ - 04aad2dab: Fix issue #7021 scaffolder action fetch:template preserves templates file permissions
30
+ - 21ccd4997: GitHub Webhook action in Scaffolder Backend has been improved to validate event names against Octokit Webhook event names list.
31
+ - Updated dependencies
32
+ - @backstage/catalog-client@0.3.19
33
+ - @backstage/catalog-model@0.9.2
34
+ - @backstage/errors@0.1.2
35
+ - @backstage/config@0.1.9
36
+ - @backstage/backend-common@0.9.2
37
+
38
+ ## 0.15.3
39
+
40
+ ### Patch Changes
41
+
42
+ - 3f9dd1759: GitHub create repository webhook action: `github:webhook` for Backstage plugin Scaffolder has been added.
43
+ - 774b08a5c: GitHubWebhook Action can be created with a default webhook secret. This allows getting secret from environment variable as an alternative to get it from context.
44
+ - 536f4d844: Updated dependencies
45
+ - 0b92a1e74: refactor: extract common Octokit related code and use it in actions: `publish:github`, `github:actions:dispatch`, `github:webhook`.
46
+ - Updated dependencies
47
+ - @backstage/integration@0.6.3
48
+ - @backstage/catalog-model@0.9.1
49
+ - @backstage/backend-common@0.9.1
50
+
3
51
  ## 0.15.2
4
52
 
5
53
  ### Patch Changes
package/dist/index.cjs.js CHANGED
@@ -21,6 +21,7 @@ var rest = require('@octokit/rest');
21
21
  var lodash = require('lodash');
22
22
  var octokitPluginCreatePullRequest = require('octokit-plugin-create-pull-request');
23
23
  var node = require('@gitbeaker/node');
24
+ var webhooks = require('@octokit/webhooks');
24
25
  var express = require('express');
25
26
  var Router = require('express-promise-router');
26
27
  var jsonschema = require('jsonschema');
@@ -418,9 +419,10 @@ function createFetchTemplateAction(options) {
418
419
  ctx.logger.info(`Copying binary file ${location} to template output path.`);
419
420
  await fs__default['default'].copy(inputFilePath, outputPath);
420
421
  } else {
421
- ctx.logger.info(`Writing file ${location} to template output path.`);
422
+ const statsObj = await fs__default['default'].stat(inputFilePath);
423
+ ctx.logger.info(`Writing file ${location} to template output path with mode ${statsObj.mode}.`);
422
424
  const inputFileContents = await fs__default['default'].readFile(inputFilePath, "utf-8");
423
- await fs__default['default'].outputFile(outputPath, renderContents ? templater.renderString(inputFileContents, context) : inputFileContents);
425
+ await fs__default['default'].outputFile(outputPath, renderContents ? templater.renderString(inputFileContents, context) : inputFileContents, {mode: statsObj.mode});
424
426
  }
425
427
  }
426
428
  }
@@ -1018,12 +1020,46 @@ function createPublishFileAction() {
1018
1020
  });
1019
1021
  }
1020
1022
 
1023
+ class OctokitProvider {
1024
+ constructor(integrations) {
1025
+ this.integrations = integrations;
1026
+ this.credentialsProviders = new Map(integrations.github.list().map((integration$1) => {
1027
+ const provider = integration.GithubCredentialsProvider.create(integration$1.config);
1028
+ return [integration$1.config.host, provider];
1029
+ }));
1030
+ }
1031
+ async getOctokit(repoUrl) {
1032
+ var _a;
1033
+ const {owner, repo, host} = parseRepoUrl(repoUrl, this.integrations);
1034
+ if (!owner) {
1035
+ throw new errors.InputError(`No owner provided for repo ${repoUrl}`);
1036
+ }
1037
+ const integrationConfig = (_a = this.integrations.github.byHost(host)) == null ? void 0 : _a.config;
1038
+ if (!integrationConfig) {
1039
+ throw new errors.InputError(`No integration for host ${host}`);
1040
+ }
1041
+ const credentialsProvider = this.credentialsProviders.get(host);
1042
+ if (!credentialsProvider) {
1043
+ throw new errors.InputError(`No matching credentials for host ${host}, please check your integrations config`);
1044
+ }
1045
+ const {token} = await credentialsProvider.getCredentials({
1046
+ url: `https://${host}/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}`
1047
+ });
1048
+ if (!token) {
1049
+ throw new errors.InputError(`No token available for host: ${host}, with owner ${owner}, and repo ${repo}`);
1050
+ }
1051
+ const client = new rest.Octokit({
1052
+ auth: token,
1053
+ baseUrl: integrationConfig.apiBaseUrl,
1054
+ previews: ["nebula-preview"]
1055
+ });
1056
+ return {client, token, owner, repo};
1057
+ }
1058
+ }
1059
+
1021
1060
  function createPublishGithubAction(options) {
1022
1061
  const {integrations, config} = options;
1023
- const credentialsProviders = new Map(integrations.github.list().map((integration$1) => {
1024
- const provider = integration.GithubCredentialsProvider.create(integration$1.config);
1025
- return [integration$1.config.host, provider];
1026
- }));
1062
+ const octokitProvider = new OctokitProvider(integrations);
1027
1063
  return createTemplateAction({
1028
1064
  id: "publish:github",
1029
1065
  description: "Initializes a git repository of contents in workspace and publishes it to GitHub.",
@@ -1118,26 +1154,7 @@ function createPublishGithubAction(options) {
1118
1154
  collaborators,
1119
1155
  topics
1120
1156
  } = ctx.input;
1121
- const {owner, repo, host} = parseRepoUrl(repoUrl, integrations);
1122
- if (!owner) {
1123
- throw new errors.InputError(`No owner provided for host: ${host}, and repo ${repo}`);
1124
- }
1125
- const credentialsProvider = credentialsProviders.get(host);
1126
- const integrationConfig = integrations.github.byHost(host);
1127
- if (!credentialsProvider || !integrationConfig) {
1128
- throw new errors.InputError(`No matching integration configuration for host ${host}, please check your integrations config`);
1129
- }
1130
- const {token} = await credentialsProvider.getCredentials({
1131
- url: `https://${host}/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}`
1132
- });
1133
- if (!token) {
1134
- throw new errors.InputError(`No token available for host: ${host}, with owner ${owner}, and repo ${repo}`);
1135
- }
1136
- const client = new rest.Octokit({
1137
- auth: token,
1138
- baseUrl: integrationConfig.config.apiBaseUrl,
1139
- previews: ["nebula-preview"]
1140
- });
1157
+ const {client, token, owner, repo} = await octokitProvider.getOctokit(repoUrl);
1141
1158
  const user = await client.users.getByUsername({
1142
1159
  username: owner
1143
1160
  });
@@ -1445,7 +1462,7 @@ function createPublishGitlabAction(options) {
1445
1462
  visibility: repoVisibility
1446
1463
  });
1447
1464
  const remoteUrl = http_url_to_repo.replace(/\.git$/, "");
1448
- const repoContentsUrl = `${remoteUrl}/-/blob/master`;
1465
+ const repoContentsUrl = `${remoteUrl}/-/blob/${defaultBranch}`;
1449
1466
  const gitAuthorInfo = {
1450
1467
  name: config.getOptionalString("scaffolder.defaultAuthor.name"),
1451
1468
  email: config.getOptionalString("scaffolder.defaultAuthor.email")
@@ -1470,10 +1487,7 @@ function createPublishGitlabAction(options) {
1470
1487
 
1471
1488
  function createGithubActionsDispatchAction(options) {
1472
1489
  const {integrations} = options;
1473
- const credentialsProviders = new Map(integrations.github.list().map((integration$1) => {
1474
- const provider = integration.GithubCredentialsProvider.create(integration$1.config);
1475
- return [integration$1.config.host, provider];
1476
- }));
1490
+ const octokitProvider = new OctokitProvider(integrations);
1477
1491
  return createTemplateAction({
1478
1492
  id: "github:actions:dispatch",
1479
1493
  description: "Dispatches a GitHub Action workflow for a given branch or tag",
@@ -1502,27 +1516,8 @@ function createGithubActionsDispatchAction(options) {
1502
1516
  },
1503
1517
  async handler(ctx) {
1504
1518
  const {repoUrl, workflowId, branchOrTagName} = ctx.input;
1505
- const {owner, repo, host} = parseRepoUrl(repoUrl, integrations);
1506
- if (!owner) {
1507
- throw new errors.InputError(`No owner provided for host: ${host}, and repo ${repo}`);
1508
- }
1509
1519
  ctx.logger.info(`Dispatching workflow ${workflowId} for repo ${repoUrl} on ${branchOrTagName}`);
1510
- const credentialsProvider = credentialsProviders.get(host);
1511
- const integrationConfig = integrations.github.byHost(host);
1512
- if (!credentialsProvider || !integrationConfig) {
1513
- throw new errors.InputError(`No matching integration configuration for host ${host}, please check your integrations config`);
1514
- }
1515
- const {token} = await credentialsProvider.getCredentials({
1516
- url: `https://${host}/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}`
1517
- });
1518
- if (!token) {
1519
- throw new errors.InputError(`No token available for host: ${host}, with owner ${owner}, and repo ${repo}`);
1520
- }
1521
- const client = new rest.Octokit({
1522
- auth: token,
1523
- baseUrl: integrationConfig.config.apiBaseUrl,
1524
- previews: ["nebula-preview"]
1525
- });
1520
+ const {client, owner, repo} = await octokitProvider.getOctokit(repoUrl);
1526
1521
  await client.rest.actions.createWorkflowDispatch({
1527
1522
  owner,
1528
1523
  repo,
@@ -1534,6 +1529,105 @@ function createGithubActionsDispatchAction(options) {
1534
1529
  });
1535
1530
  }
1536
1531
 
1532
+ function createGithubWebhookAction(options) {
1533
+ const {integrations, defaultWebhookSecret} = options;
1534
+ const octokitProvider = new OctokitProvider(integrations);
1535
+ const eventNames = webhooks.emitterEventNames.filter((event) => !event.includes("."));
1536
+ return createTemplateAction({
1537
+ id: "github:webhook",
1538
+ description: "Creates webhook for a repository on GitHub.",
1539
+ schema: {
1540
+ input: {
1541
+ type: "object",
1542
+ required: ["repoUrl", "webhookUrl"],
1543
+ properties: {
1544
+ repoUrl: {
1545
+ title: "Repository Location",
1546
+ description: `Accepts the format 'github.com?repo=reponame&owner=owner' where 'reponame' is the new repository name and 'owner' is an organization or username`,
1547
+ type: "string"
1548
+ },
1549
+ webhookUrl: {
1550
+ title: "Webhook URL",
1551
+ description: "The URL to which the payloads will be delivered",
1552
+ type: "string"
1553
+ },
1554
+ webhookSecret: {
1555
+ title: "Webhook Secret",
1556
+ description: "Webhook secret value. The default can be provided internally in action creation",
1557
+ type: "string"
1558
+ },
1559
+ events: {
1560
+ title: "Triggering Events",
1561
+ description: "Determines what events the hook is triggered for. Default: push",
1562
+ type: "array",
1563
+ oneOf: [
1564
+ {
1565
+ items: {
1566
+ type: "string",
1567
+ enum: eventNames
1568
+ }
1569
+ },
1570
+ {
1571
+ items: {
1572
+ type: "string",
1573
+ const: "*"
1574
+ }
1575
+ }
1576
+ ]
1577
+ },
1578
+ active: {
1579
+ title: "Active",
1580
+ type: "boolean",
1581
+ description: `Determines if notifications are sent when the webhook is triggered. Default: true`
1582
+ },
1583
+ contentType: {
1584
+ title: "Content Type",
1585
+ type: "string",
1586
+ enum: ["form", "json"],
1587
+ description: `The media type used to serialize the payloads. The default is 'form'`
1588
+ },
1589
+ insecureSsl: {
1590
+ title: "Insecure SSL",
1591
+ type: "boolean",
1592
+ description: `Determines whether the SSL certificate of the host for url will be verified when delivering payloads. Default 'false'`
1593
+ }
1594
+ }
1595
+ }
1596
+ },
1597
+ async handler(ctx) {
1598
+ const {
1599
+ repoUrl,
1600
+ webhookUrl,
1601
+ webhookSecret = defaultWebhookSecret,
1602
+ events = ["push"],
1603
+ active = true,
1604
+ contentType = "form",
1605
+ insecureSsl = false
1606
+ } = ctx.input;
1607
+ ctx.logger.info(`Creating webhook ${webhookUrl} for repo ${repoUrl}`);
1608
+ const {client, owner, repo} = await octokitProvider.getOctokit(repoUrl);
1609
+ try {
1610
+ const insecure_ssl = insecureSsl ? "1" : "0";
1611
+ await client.repos.createWebhook({
1612
+ owner,
1613
+ repo,
1614
+ config: {
1615
+ url: webhookUrl,
1616
+ content_type: contentType,
1617
+ secret: webhookSecret,
1618
+ insecure_ssl
1619
+ },
1620
+ events,
1621
+ active
1622
+ });
1623
+ ctx.logger.info(`Webhook '${webhookUrl}' created successfully`);
1624
+ } catch (e) {
1625
+ ctx.logger.warn(`Failed: create webhook '${webhookUrl}' on repo: '${repo}', ${e.message}`);
1626
+ }
1627
+ }
1628
+ });
1629
+ }
1630
+
1537
1631
  const createBuiltinActions = (options) => {
1538
1632
  const {reader, integrations, containerRunner, catalogClient, config} = options;
1539
1633
  return [
@@ -1576,6 +1670,9 @@ const createBuiltinActions = (options) => {
1576
1670
  createFilesystemRenameAction(),
1577
1671
  createGithubActionsDispatchAction({
1578
1672
  integrations
1673
+ }),
1674
+ createGithubWebhookAction({
1675
+ integrations
1579
1676
  })
1580
1677
  ];
1581
1678
  };
@@ -2324,6 +2421,7 @@ Object.defineProperty(exports, 'createFetchCookiecutterAction', {
2324
2421
  }
2325
2422
  });
2326
2423
  exports.CatalogEntityClient = CatalogEntityClient;
2424
+ exports.OctokitProvider = OctokitProvider;
2327
2425
  exports.TemplateActionRegistry = TemplateActionRegistry;
2328
2426
  exports.createBuiltinActions = createBuiltinActions;
2329
2427
  exports.createCatalogRegisterAction = createCatalogRegisterAction;
@@ -2334,6 +2432,7 @@ exports.createFetchTemplateAction = createFetchTemplateAction;
2334
2432
  exports.createFilesystemDeleteAction = createFilesystemDeleteAction;
2335
2433
  exports.createFilesystemRenameAction = createFilesystemRenameAction;
2336
2434
  exports.createGithubActionsDispatchAction = createGithubActionsDispatchAction;
2435
+ exports.createGithubWebhookAction = createGithubWebhookAction;
2337
2436
  exports.createPublishAzureAction = createPublishAzureAction;
2338
2437
  exports.createPublishBitbucketAction = createPublishBitbucketAction;
2339
2438
  exports.createPublishFileAction = createPublishFileAction;