@backstage/plugin-scaffolder-backend 0.0.0-nightly-202202022734 → 0.0.0-nightly-20220206022752

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/dist/index.cjs.js CHANGED
@@ -17,7 +17,7 @@ var child_process = require('child_process');
17
17
  var stream = require('stream');
18
18
  var azureDevopsNodeApi = require('azure-devops-node-api');
19
19
  var fetch = require('node-fetch');
20
- var rest = require('@octokit/rest');
20
+ var octokit = require('octokit');
21
21
  var lodash = require('lodash');
22
22
  var octokitPluginCreatePullRequest = require('octokit-plugin-create-pull-request');
23
23
  var node = require('@gitbeaker/node');
@@ -119,6 +119,7 @@ function createCatalogRegisterAction(options) {
119
119
  }
120
120
  },
121
121
  async handler(ctx) {
122
+ var _a, _b;
122
123
  const { input } = ctx;
123
124
  let catalogInfoUrl;
124
125
  if ("catalogInfoUrl" in input) {
@@ -138,13 +139,13 @@ function createCatalogRegisterAction(options) {
138
139
  await catalogClient.addLocation({
139
140
  type: "url",
140
141
  target: catalogInfoUrl
141
- }, ctx.token ? { token: ctx.token } : {});
142
+ }, ((_a = ctx.secrets) == null ? void 0 : _a.backstageToken) ? { token: ctx.secrets.backstageToken } : {});
142
143
  try {
143
144
  const result = await catalogClient.addLocation({
144
145
  dryRun: true,
145
146
  type: "url",
146
147
  target: catalogInfoUrl
147
- }, ctx.token ? { token: ctx.token } : {});
148
+ }, ((_b = ctx.secrets) == null ? void 0 : _b.backstageToken) ? { token: ctx.secrets.backstageToken } : {});
148
149
  if (result.entities.length > 0) {
149
150
  const { entities } = result;
150
151
  let entity;
@@ -360,6 +361,12 @@ const { render, renderCompat } = (() => {
360
361
  });
361
362
  }
362
363
 
364
+ if (typeof additionalTemplateFilters !== 'undefined') {
365
+ for (const [filterName, filterFn] of Object.entries(additionalTemplateFilters)) {
366
+ env.addFilter(filterName, (...args) => JSON.parse(filterFn(...args)));
367
+ }
368
+ }
369
+
363
370
  let uninstallCompat = undefined;
364
371
 
365
372
  function render(str, values) {
@@ -392,12 +399,16 @@ const { render, renderCompat } = (() => {
392
399
  `;
393
400
  class SecureTemplater {
394
401
  static async loadRenderer(options = {}) {
395
- const { parseRepoUrl, cookiecutterCompat } = options;
396
- let sandbox = void 0;
402
+ const { parseRepoUrl, cookiecutterCompat, additionalTemplateFilters } = options;
403
+ const sandbox = {};
397
404
  if (parseRepoUrl) {
398
- sandbox = {
399
- parseRepoUrl: (url) => JSON.stringify(parseRepoUrl(url))
400
- };
405
+ sandbox.parseRepoUrl = (url) => JSON.stringify(parseRepoUrl(url));
406
+ }
407
+ if (additionalTemplateFilters) {
408
+ sandbox.additionalTemplateFilters = Object.fromEntries(Object.entries(additionalTemplateFilters).filter(([_, filterFunction]) => !!filterFunction).map(([filterName, filterFunction]) => [
409
+ filterName,
410
+ (...args) => JSON.stringify(filterFunction(...args))
411
+ ]));
401
412
  }
402
413
  const vm = new vm2.VM({ sandbox });
403
414
  const nunjucksSource = await fs__default["default"].readFile(backendCommon.resolvePackagePath("@backstage/plugin-scaffolder-backend", "assets/nunjucks.js.txt"), "utf-8");
@@ -418,7 +429,7 @@ class SecureTemplater {
418
429
  }
419
430
 
420
431
  function createFetchTemplateAction(options) {
421
- const { reader, integrations } = options;
432
+ const { reader, integrations, additionalTemplateFilters } = options;
422
433
  return createTemplateAction({
423
434
  id: "fetch:template",
424
435
  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.",
@@ -509,7 +520,8 @@ function createFetchTemplateAction(options) {
509
520
  };
510
521
  ctx.logger.info(`Processing ${allEntriesInTemplate.length} template files/directories with input values`, ctx.input.values);
511
522
  const renderTemplate = await SecureTemplater.loadRenderer({
512
- cookiecutterCompat: ctx.input.cookiecutterCompat
523
+ cookiecutterCompat: ctx.input.cookiecutterCompat,
524
+ additionalTemplateFilters
513
525
  });
514
526
  for (const location of allEntriesInTemplate) {
515
527
  let renderFilename;
@@ -729,7 +741,7 @@ const enableBranchProtectionOnDefaultRepoBranch = async ({
729
741
  }) => {
730
742
  const tryOnce = async () => {
731
743
  try {
732
- await client.repos.updateBranchProtection({
744
+ await client.rest.repos.updateBranchProtection({
733
745
  mediaType: {
734
746
  previews: ["luke-cage-preview"]
735
747
  },
@@ -842,8 +854,14 @@ function createPublishAzureAction(options) {
842
854
  description: `Sets the default branch on the repository. The default value is 'master'`
843
855
  },
844
856
  sourcePath: {
845
- title: "Path within the workspace that will be used as the repository root. If omitted, the entire workspace will be published as the repository.",
857
+ title: "Source Path",
858
+ description: "Path within the workspace that will be used as the repository root. If omitted, the entire workspace will be published as the repository.",
846
859
  type: "string"
860
+ },
861
+ token: {
862
+ title: "Authentication Token",
863
+ type: "string",
864
+ description: "The token to use for authorization to Azure"
847
865
  }
848
866
  }
849
867
  },
@@ -862,6 +880,7 @@ function createPublishAzureAction(options) {
862
880
  }
863
881
  },
864
882
  async handler(ctx) {
883
+ var _a;
865
884
  const { repoUrl, defaultBranch = "master" } = ctx.input;
866
885
  const { owner, repo, host, organization } = parseRepoUrl(repoUrl, integrations);
867
886
  if (!organization) {
@@ -871,10 +890,11 @@ function createPublishAzureAction(options) {
871
890
  if (!integrationConfig) {
872
891
  throw new errors.InputError(`No matching integration configuration for host ${host}, please check your integrations config`);
873
892
  }
874
- if (!integrationConfig.config.token) {
893
+ if (!integrationConfig.config.token && !ctx.input.token) {
875
894
  throw new errors.InputError(`No token provided for Azure Integration ${host}`);
876
895
  }
877
- const authHandler = azureDevopsNodeApi.getPersonalAccessTokenHandler(integrationConfig.config.token);
896
+ const token = (_a = ctx.input.token) != null ? _a : integrationConfig.config.token;
897
+ const authHandler = azureDevopsNodeApi.getPersonalAccessTokenHandler(token);
878
898
  const webApi = new azureDevopsNodeApi.WebApi(`https://${host}/${organization}`, authHandler);
879
899
  const client = await webApi.getGitApi();
880
900
  const createOptions = { name: repo };
@@ -898,7 +918,7 @@ function createPublishAzureAction(options) {
898
918
  defaultBranch,
899
919
  auth: {
900
920
  username: "notempty",
901
- password: integrationConfig.config.token
921
+ password: token
902
922
  },
903
923
  logger: ctx.logger,
904
924
  commitMessage: config.getOptionalString("scaffolder.defaultCommitMessage"),
@@ -1044,12 +1064,19 @@ function createPublishBitbucketAction(options) {
1044
1064
  description: `Sets the default branch on the repository. The default value is 'master'`
1045
1065
  },
1046
1066
  sourcePath: {
1047
- title: "Path within the workspace that will be used as the repository root. If omitted, the entire workspace will be published as the repository.",
1067
+ title: "Source Path",
1068
+ description: "Path within the workspace that will be used as the repository root. If omitted, the entire workspace will be published as the repository.",
1048
1069
  type: "string"
1049
1070
  },
1050
1071
  enableLFS: {
1051
- title: "Enable LFS for the repository. Only available for hosted Bitbucket.",
1072
+ title: "Enable LFS?",
1073
+ description: "Enable LFS for the repository. Only available for hosted Bitbucket.",
1052
1074
  type: "boolean"
1075
+ },
1076
+ token: {
1077
+ title: "Authentication Token",
1078
+ type: "string",
1079
+ description: "The token to use for authorization to BitBucket"
1053
1080
  }
1054
1081
  }
1055
1082
  },
@@ -1089,7 +1116,7 @@ function createPublishBitbucketAction(options) {
1089
1116
  if (!integrationConfig) {
1090
1117
  throw new errors.InputError(`No matching integration configuration for host ${host}, please check your integrations config`);
1091
1118
  }
1092
- const authorization = getAuthorizationHeader(integrationConfig.config);
1119
+ const authorization = getAuthorizationHeader(ctx.input.token ? { host: integrationConfig.config.host, token: ctx.input.token } : integrationConfig.config);
1093
1120
  const apiBaseUrl = integrationConfig.config.apiBaseUrl;
1094
1121
  const createMethod = host === "bitbucket.org" ? createBitbucketCloudRepository : createBitbucketServerRepository;
1095
1122
  const { remoteUrl, repoContentsUrl } = await createMethod({
@@ -1106,13 +1133,22 @@ function createPublishBitbucketAction(options) {
1106
1133
  name: config.getOptionalString("scaffolder.defaultAuthor.name"),
1107
1134
  email: config.getOptionalString("scaffolder.defaultAuthor.email")
1108
1135
  };
1136
+ let auth;
1137
+ if (ctx.input.token) {
1138
+ auth = {
1139
+ username: "x-token-auth",
1140
+ password: ctx.input.token
1141
+ };
1142
+ } else {
1143
+ auth = {
1144
+ username: integrationConfig.config.username ? integrationConfig.config.username : "x-token-auth",
1145
+ password: integrationConfig.config.appPassword ? integrationConfig.config.appPassword : (_a = integrationConfig.config.token) != null ? _a : ""
1146
+ };
1147
+ }
1109
1148
  await initRepoAndPush({
1110
1149
  dir: getRepoSourceDirectory(ctx.workspacePath, ctx.input.sourcePath),
1111
1150
  remoteUrl,
1112
- auth: {
1113
- username: integrationConfig.config.username ? integrationConfig.config.username : "x-token-auth",
1114
- password: integrationConfig.config.appPassword ? integrationConfig.config.appPassword : (_a = integrationConfig.config.token) != null ? _a : ""
1115
- },
1151
+ auth,
1116
1152
  defaultBranch,
1117
1153
  logger: ctx.logger,
1118
1154
  commitMessage: config.getOptionalString("scaffolder.defaultCommitMessage"),
@@ -1160,7 +1196,7 @@ class OctokitProvider {
1160
1196
  this.integrations = integrations;
1161
1197
  this.githubCredentialsProvider = githubCredentialsProvider || integration.DefaultGithubCredentialsProvider.fromIntegrations(this.integrations);
1162
1198
  }
1163
- async getOctokit(repoUrl) {
1199
+ async getOctokit(repoUrl, options) {
1164
1200
  var _a;
1165
1201
  const { owner, repo, host } = parseRepoUrl(repoUrl, this.integrations);
1166
1202
  if (!owner) {
@@ -1170,13 +1206,21 @@ class OctokitProvider {
1170
1206
  if (!integrationConfig) {
1171
1207
  throw new errors.InputError(`No integration for host ${host}`);
1172
1208
  }
1209
+ if (options == null ? void 0 : options.token) {
1210
+ const client2 = new octokit.Octokit({
1211
+ auth: options.token,
1212
+ baseUrl: integrationConfig.apiBaseUrl,
1213
+ previews: ["nebula-preview"]
1214
+ });
1215
+ return { client: client2, token: options.token, owner, repo };
1216
+ }
1173
1217
  const { token } = await this.githubCredentialsProvider.getCredentials({
1174
1218
  url: `https://${host}/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}`
1175
1219
  });
1176
1220
  if (!token) {
1177
1221
  throw new errors.InputError(`No token available for host: ${host}, with owner ${owner}, and repo ${repo}`);
1178
1222
  }
1179
- const client = new rest.Octokit({
1223
+ const client = new octokit.Octokit({
1180
1224
  auth: token,
1181
1225
  baseUrl: integrationConfig.apiBaseUrl,
1182
1226
  previews: ["nebula-preview"]
@@ -1211,7 +1255,8 @@ function createPublishGithubAction(options) {
1211
1255
  type: "string"
1212
1256
  },
1213
1257
  requireCodeOwnerReviews: {
1214
- title: "Require an approved review in PR including files with a designated Code Owner",
1258
+ title: "Require CODEOWNER Reviews?",
1259
+ description: "Require an approved review in PR including files with a designated Code Owner",
1215
1260
  type: "boolean"
1216
1261
  },
1217
1262
  repoVisibility: {
@@ -1225,7 +1270,8 @@ function createPublishGithubAction(options) {
1225
1270
  description: `Sets the default branch on the repository. The default value is 'master'`
1226
1271
  },
1227
1272
  sourcePath: {
1228
- title: "Path within the workspace that will be used as the repository root. If omitted, the entire workspace will be published as the repository.",
1273
+ title: "Source Path",
1274
+ description: "Path within the workspace that will be used as the repository root. If omitted, the entire workspace will be published as the repository.",
1229
1275
  type: "string"
1230
1276
  },
1231
1277
  collaborators: {
@@ -1248,6 +1294,11 @@ function createPublishGithubAction(options) {
1248
1294
  }
1249
1295
  }
1250
1296
  },
1297
+ token: {
1298
+ title: "Authentication Token",
1299
+ type: "string",
1300
+ description: "The token to use for authorization to GitHub"
1301
+ },
1251
1302
  topics: {
1252
1303
  title: "Topics",
1253
1304
  type: "array",
@@ -1280,19 +1331,20 @@ function createPublishGithubAction(options) {
1280
1331
  repoVisibility = "private",
1281
1332
  defaultBranch = "master",
1282
1333
  collaborators,
1283
- topics
1334
+ topics,
1335
+ token: providedToken
1284
1336
  } = ctx.input;
1285
- const { client, token, owner, repo } = await octokitProvider.getOctokit(repoUrl);
1286
- const user = await client.users.getByUsername({
1337
+ const { client, token, owner, repo } = await octokitProvider.getOctokit(repoUrl, { token: providedToken });
1338
+ const user = await client.rest.users.getByUsername({
1287
1339
  username: owner
1288
1340
  });
1289
- const repoCreationPromise = user.data.type === "Organization" ? client.repos.createInOrg({
1341
+ const repoCreationPromise = user.data.type === "Organization" ? client.rest.repos.createInOrg({
1290
1342
  name: repo,
1291
1343
  org: owner,
1292
1344
  private: repoVisibility === "private",
1293
1345
  visibility: repoVisibility,
1294
1346
  description
1295
- }) : client.repos.createForAuthenticatedUser({
1347
+ }) : client.rest.repos.createForAuthenticatedUser({
1296
1348
  name: repo,
1297
1349
  private: repoVisibility === "private",
1298
1350
  description
@@ -1300,7 +1352,7 @@ function createPublishGithubAction(options) {
1300
1352
  const { data: newRepo } = await repoCreationPromise;
1301
1353
  if (access == null ? void 0 : access.startsWith(`${owner}/`)) {
1302
1354
  const [, team] = access.split("/");
1303
- await client.teams.addOrUpdateRepoPermissionsInOrg({
1355
+ await client.rest.teams.addOrUpdateRepoPermissionsInOrg({
1304
1356
  org: owner,
1305
1357
  team_slug: team,
1306
1358
  owner,
@@ -1308,7 +1360,7 @@ function createPublishGithubAction(options) {
1308
1360
  permission: "admin"
1309
1361
  });
1310
1362
  } else if (access && access !== owner) {
1311
- await client.repos.addCollaborator({
1363
+ await client.rest.repos.addCollaborator({
1312
1364
  owner,
1313
1365
  repo,
1314
1366
  username: access,
@@ -1321,7 +1373,7 @@ function createPublishGithubAction(options) {
1321
1373
  username: team_slug
1322
1374
  } of collaborators) {
1323
1375
  try {
1324
- await client.teams.addOrUpdateRepoPermissionsInOrg({
1376
+ await client.rest.teams.addOrUpdateRepoPermissionsInOrg({
1325
1377
  org: owner,
1326
1378
  team_slug,
1327
1379
  owner,
@@ -1336,7 +1388,7 @@ function createPublishGithubAction(options) {
1336
1388
  }
1337
1389
  if (topics) {
1338
1390
  try {
1339
- await client.repos.replaceAllTopics({
1391
+ await client.rest.repos.replaceAllTopics({
1340
1392
  owner,
1341
1393
  repo,
1342
1394
  names: topics.map((t) => t.toLowerCase())
@@ -1390,13 +1442,21 @@ const defaultClientFactory = async ({
1390
1442
  githubCredentialsProvider,
1391
1443
  owner,
1392
1444
  repo,
1393
- host = "github.com"
1445
+ host = "github.com",
1446
+ token: providedToken
1394
1447
  }) => {
1395
1448
  var _a;
1396
1449
  const integrationConfig = (_a = integrations.github.byHost(host)) == null ? void 0 : _a.config;
1450
+ const OctokitPR = octokit.Octokit.plugin(octokitPluginCreatePullRequest.createPullRequest);
1397
1451
  if (!integrationConfig) {
1398
1452
  throw new errors.InputError(`No integration for host ${host}`);
1399
1453
  }
1454
+ if (providedToken) {
1455
+ return new OctokitPR({
1456
+ auth: providedToken,
1457
+ baseUrl: integrationConfig.apiBaseUrl
1458
+ });
1459
+ }
1400
1460
  const credentialsProvider = githubCredentialsProvider || integration.SingleInstanceGithubCredentialsProvider.create(integrationConfig);
1401
1461
  const { token } = await credentialsProvider.getCredentials({
1402
1462
  url: `https://${host}/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}`
@@ -1404,7 +1464,6 @@ const defaultClientFactory = async ({
1404
1464
  if (!token) {
1405
1465
  throw new errors.InputError(`No token available for host: ${host}, with owner ${owner}, and repo ${repo}`);
1406
1466
  }
1407
- const OctokitPR = rest.Octokit.plugin(octokitPluginCreatePullRequest.createPullRequest);
1408
1467
  return new OctokitPR({
1409
1468
  auth: token,
1410
1469
  baseUrl: integrationConfig.apiBaseUrl
@@ -1451,6 +1510,11 @@ const createPublishGithubPullRequestAction = ({
1451
1510
  type: "string",
1452
1511
  title: "Repository Subdirectory",
1453
1512
  description: "Subdirectory of repository to apply changes to"
1513
+ },
1514
+ token: {
1515
+ title: "Authentication Token",
1516
+ type: "string",
1517
+ description: "The token to use for authorization to GitHub"
1454
1518
  }
1455
1519
  }
1456
1520
  },
@@ -1473,7 +1537,8 @@ const createPublishGithubPullRequestAction = ({
1473
1537
  title,
1474
1538
  description,
1475
1539
  targetPath,
1476
- sourcePath
1540
+ sourcePath,
1541
+ token: providedToken
1477
1542
  } = ctx.input;
1478
1543
  const { owner, repo, host } = parseRepoUrl(repoUrl, integrations);
1479
1544
  if (!owner) {
@@ -1484,7 +1549,8 @@ const createPublishGithubPullRequestAction = ({
1484
1549
  githubCredentialsProvider,
1485
1550
  host,
1486
1551
  owner,
1487
- repo
1552
+ repo,
1553
+ token: providedToken
1488
1554
  });
1489
1555
  const fileRoot = sourcePath ? backendCommon.resolveSafeChildPath(ctx.workspacePath, sourcePath) : ctx.workspacePath;
1490
1556
  const localFilePaths = await globby__default["default"](["./**", "./**/.*", "!.git"], {
@@ -1558,8 +1624,14 @@ function createPublishGitlabAction(options) {
1558
1624
  description: `Sets the default branch on the repository. The default value is 'master'`
1559
1625
  },
1560
1626
  sourcePath: {
1561
- title: "Path within the workspace that will be used as the repository root. If omitted, the entire workspace will be published as the repository.",
1627
+ title: "Source Path",
1628
+ description: "Path within the workspace that will be used as the repository root. If omitted, the entire workspace will be published as the repository.",
1562
1629
  type: "string"
1630
+ },
1631
+ token: {
1632
+ title: "Authentication Token",
1633
+ type: "string",
1634
+ description: "The token to use for authorization to GitLab"
1563
1635
  }
1564
1636
  }
1565
1637
  },
@@ -1591,12 +1663,14 @@ function createPublishGitlabAction(options) {
1591
1663
  if (!integrationConfig) {
1592
1664
  throw new errors.InputError(`No matching integration configuration for host ${host}, please check your integrations config`);
1593
1665
  }
1594
- if (!integrationConfig.config.token) {
1666
+ if (!integrationConfig.config.token && !ctx.input.token) {
1595
1667
  throw new errors.InputError(`No token available for host ${host}`);
1596
1668
  }
1669
+ const token = ctx.input.token || integrationConfig.config.token;
1670
+ const tokenType = ctx.input.token ? "oauthToken" : "token";
1597
1671
  const client = new node.Gitlab({
1598
1672
  host: integrationConfig.config.baseUrl,
1599
- token: integrationConfig.config.token
1673
+ [tokenType]: token
1600
1674
  });
1601
1675
  let { id: targetNamespace } = await client.Namespaces.show(owner);
1602
1676
  if (!targetNamespace) {
@@ -1620,7 +1694,7 @@ function createPublishGitlabAction(options) {
1620
1694
  defaultBranch,
1621
1695
  auth: {
1622
1696
  username: "oauth2",
1623
- password: integrationConfig.config.token
1697
+ password: token
1624
1698
  },
1625
1699
  logger: ctx.logger,
1626
1700
  commitMessage: config.getOptionalString("scaffolder.defaultCommitMessage"),
@@ -1670,6 +1744,11 @@ const createPublishGitlabMergeRequestAction = (options) => {
1670
1744
  type: "string",
1671
1745
  title: "Repository Subdirectory",
1672
1746
  description: "Subdirectory of repository to apply changes to"
1747
+ },
1748
+ token: {
1749
+ title: "Authentication Token",
1750
+ type: "string",
1751
+ description: "The token to use for authorization to GitLab"
1673
1752
  }
1674
1753
  }
1675
1754
  },
@@ -1689,6 +1768,7 @@ const createPublishGitlabMergeRequestAction = (options) => {
1689
1768
  }
1690
1769
  },
1691
1770
  async handler(ctx) {
1771
+ var _a;
1692
1772
  const repoUrl = ctx.input.repoUrl;
1693
1773
  const { host } = parseRepoUrl(repoUrl, integrations);
1694
1774
  const integrationConfig = integrations.gitlab.byHost(host);
@@ -1697,12 +1777,14 @@ const createPublishGitlabMergeRequestAction = (options) => {
1697
1777
  if (!integrationConfig) {
1698
1778
  throw new errors.InputError(`No matching integration configuration for host ${host}, please check your integrations config`);
1699
1779
  }
1700
- if (!integrationConfig.config.token) {
1780
+ if (!integrationConfig.config.token && !ctx.input.token) {
1701
1781
  throw new errors.InputError(`No token available for host ${host}`);
1702
1782
  }
1783
+ const token = (_a = ctx.input.token) != null ? _a : integrationConfig.config.token;
1784
+ const tokenType = ctx.input.token ? "oauthToken" : "token";
1703
1785
  const api = new node.Gitlab({
1704
1786
  host: integrationConfig.config.baseUrl,
1705
- token: integrationConfig.config.token
1787
+ [tokenType]: token
1706
1788
  });
1707
1789
  const fileRoot = ctx.workspacePath;
1708
1790
  const localFilePaths = await globby__default["default"]([`${ctx.input.targetPath}/**`], {
@@ -1771,19 +1853,36 @@ function createGithubActionsDispatchAction(options) {
1771
1853
  title: "Branch or Tag name",
1772
1854
  description: "The git branch or tag name used to dispatch the workflow",
1773
1855
  type: "string"
1856
+ },
1857
+ workflowInputs: {
1858
+ title: "Workflow Inputs",
1859
+ description: "Inputs keys and values to send to GitHub Action configured on the workflow file. The maximum number of properties is 10. ",
1860
+ type: "object"
1861
+ },
1862
+ token: {
1863
+ title: "Authentication Token",
1864
+ type: "string",
1865
+ description: "The GITHUB_TOKEN to use for authorization to GitHub"
1774
1866
  }
1775
1867
  }
1776
1868
  }
1777
1869
  },
1778
1870
  async handler(ctx) {
1779
- const { repoUrl, workflowId, branchOrTagName } = ctx.input;
1871
+ const {
1872
+ repoUrl,
1873
+ workflowId,
1874
+ branchOrTagName,
1875
+ workflowInputs,
1876
+ token: providedToken
1877
+ } = ctx.input;
1780
1878
  ctx.logger.info(`Dispatching workflow ${workflowId} for repo ${repoUrl} on ${branchOrTagName}`);
1781
- const { client, owner, repo } = await octokitProvider.getOctokit(repoUrl);
1879
+ const { client, owner, repo } = await octokitProvider.getOctokit(repoUrl, { token: providedToken });
1782
1880
  await client.rest.actions.createWorkflowDispatch({
1783
1881
  owner,
1784
1882
  repo,
1785
1883
  workflow_id: workflowId,
1786
- ref: branchOrTagName
1884
+ ref: branchOrTagName,
1885
+ inputs: workflowInputs
1787
1886
  });
1788
1887
  ctx.logger.info(`Workflow ${workflowId} dispatched successfully`);
1789
1888
  }
@@ -1851,6 +1950,11 @@ function createGithubWebhookAction(options) {
1851
1950
  title: "Insecure SSL",
1852
1951
  type: "boolean",
1853
1952
  description: `Determines whether the SSL certificate of the host for url will be verified when delivering payloads. Default 'false'`
1953
+ },
1954
+ token: {
1955
+ title: "Authentication Token",
1956
+ type: "string",
1957
+ description: "The GITHUB_TOKEN to use for authorization to GitHub"
1854
1958
  }
1855
1959
  }
1856
1960
  }
@@ -1863,13 +1967,14 @@ function createGithubWebhookAction(options) {
1863
1967
  events = ["push"],
1864
1968
  active = true,
1865
1969
  contentType = "form",
1866
- insecureSsl = false
1970
+ insecureSsl = false,
1971
+ token: providedToken
1867
1972
  } = ctx.input;
1868
1973
  ctx.logger.info(`Creating webhook ${webhookUrl} for repo ${repoUrl}`);
1869
- const { client, owner, repo } = await octokitProvider.getOctokit(repoUrl);
1974
+ const { client, owner, repo } = await octokitProvider.getOctokit(repoUrl, { token: providedToken });
1870
1975
  try {
1871
1976
  const insecure_ssl = insecureSsl ? "1" : "0";
1872
- await client.repos.createWebhook({
1977
+ await client.rest.repos.createWebhook({
1873
1978
  owner,
1874
1979
  repo,
1875
1980
  config: {
@@ -1891,7 +1996,14 @@ function createGithubWebhookAction(options) {
1891
1996
  }
1892
1997
 
1893
1998
  const createBuiltinActions = (options) => {
1894
- const { reader, integrations, containerRunner, catalogClient, config } = options;
1999
+ const {
2000
+ reader,
2001
+ integrations,
2002
+ containerRunner,
2003
+ catalogClient,
2004
+ config,
2005
+ additionalTemplateFilters
2006
+ } = options;
1895
2007
  const githubCredentialsProvider = integration.DefaultGithubCredentialsProvider.fromIntegrations(integrations);
1896
2008
  const actions = [
1897
2009
  createFetchPlainAction({
@@ -1900,7 +2012,8 @@ const createBuiltinActions = (options) => {
1900
2012
  }),
1901
2013
  createFetchTemplateAction({
1902
2014
  integrations,
1903
- reader
2015
+ reader,
2016
+ additionalTemplateFilters
1904
2017
  }),
1905
2018
  createPublishGithubAction({
1906
2019
  integrations,
@@ -2023,7 +2136,8 @@ class DatabaseTaskStore {
2023
2136
  }
2024
2137
  const updateCount = await tx("tasks").where({ id: task.id, status: "open" }).update({
2025
2138
  status: "processing",
2026
- last_heartbeat_at: this.db.fn.now()
2139
+ last_heartbeat_at: this.db.fn.now(),
2140
+ secrets: null
2027
2141
  });
2028
2142
  if (updateCount < 1) {
2029
2143
  return void 0;
@@ -2087,8 +2201,7 @@ class DatabaseTaskStore {
2087
2201
  id: taskId,
2088
2202
  status: oldStatus
2089
2203
  }).update({
2090
- status,
2091
- secrets: null
2204
+ status
2092
2205
  });
2093
2206
  if (updateCount !== 1) {
2094
2207
  throw new errors.ConflictError(`Failed to update status to '${status}' for taskId ${taskId}`);
@@ -2301,7 +2414,7 @@ class HandlebarsWorkflowRunner {
2301
2414
  this.handlebars.registerHelper("eq", (a, b) => a === b);
2302
2415
  }
2303
2416
  async execute(task) {
2304
- var _a, _b;
2417
+ var _a, _b, _c;
2305
2418
  if (!isValidTaskSpec$1(task.spec)) {
2306
2419
  throw new errors.InputError(`Task spec is not a valid v1beta2 task spec`);
2307
2420
  }
@@ -2405,6 +2518,7 @@ class HandlebarsWorkflowRunner {
2405
2518
  logStream: stream$1,
2406
2519
  input,
2407
2520
  token: (_b = task.secrets) == null ? void 0 : _b.token,
2521
+ secrets: (_c = task.secrets) != null ? _c : {},
2408
2522
  workspacePath,
2409
2523
  async createTemporaryDirectory() {
2410
2524
  const tmpDir = await fs__default["default"].mkdtemp(`${workspacePath}_step-${step.id}-`);
@@ -2530,7 +2644,7 @@ class NunjucksWorkflowRunner {
2530
2644
  });
2531
2645
  }
2532
2646
  async execute(task) {
2533
- var _a, _b, _c;
2647
+ var _a, _b, _c, _d, _e;
2534
2648
  if (!isValidTaskSpec(task.spec)) {
2535
2649
  throw new errors.InputError("Wrong template version executed with the workflow engine");
2536
2650
  }
@@ -2539,7 +2653,8 @@ class NunjucksWorkflowRunner {
2539
2653
  const renderTemplate = await SecureTemplater.loadRenderer({
2540
2654
  parseRepoUrl(url) {
2541
2655
  return parseRepoUrl(url, integrations);
2542
- }
2656
+ },
2657
+ additionalTemplateFilters: this.options.additionalTemplateFilters
2543
2658
  });
2544
2659
  try {
2545
2660
  await fs__default["default"].ensureDir(workspacePath);
@@ -2563,8 +2678,8 @@ class NunjucksWorkflowRunner {
2563
2678
  });
2564
2679
  const action = this.options.actionRegistry.get(step.action);
2565
2680
  const { taskLogger, streamLogger } = createStepLogger({ task, step });
2566
- const input = (_a = step.input && this.render(step.input, context, renderTemplate)) != null ? _a : {};
2567
- if ((_b = action.schema) == null ? void 0 : _b.input) {
2681
+ const input = (_b = step.input && this.render(step.input, { ...context, secrets: (_a = task.secrets) != null ? _a : {} }, renderTemplate)) != null ? _b : {};
2682
+ if ((_c = action.schema) == null ? void 0 : _c.input) {
2568
2683
  const validateResult = jsonschema.validate(input, action.schema.input);
2569
2684
  if (!validateResult.valid) {
2570
2685
  const errors$1 = validateResult.errors.join(", ");
@@ -2579,7 +2694,8 @@ class NunjucksWorkflowRunner {
2579
2694
  await action.handler({
2580
2695
  baseUrl: task.spec.baseUrl,
2581
2696
  input,
2582
- token: (_c = task.secrets) == null ? void 0 : _c.token,
2697
+ token: (_d = task.secrets) == null ? void 0 : _d.token,
2698
+ secrets: (_e = task.secrets) != null ? _e : {},
2583
2699
  logger: taskLogger,
2584
2700
  logStream: streamLogger,
2585
2701
  workspacePath,
@@ -2629,7 +2745,8 @@ class TaskWorker {
2629
2745
  logger,
2630
2746
  actionRegistry,
2631
2747
  integrations,
2632
- workingDirectory
2748
+ workingDirectory,
2749
+ additionalTemplateFilters
2633
2750
  } = options;
2634
2751
  const legacyWorkflowRunner = new HandlebarsWorkflowRunner({
2635
2752
  logger,
@@ -2641,7 +2758,8 @@ class TaskWorker {
2641
2758
  actionRegistry,
2642
2759
  integrations,
2643
2760
  logger,
2644
- workingDirectory
2761
+ workingDirectory,
2762
+ additionalTemplateFilters
2645
2763
  });
2646
2764
  return new TaskWorker({
2647
2765
  taskBroker,
@@ -2738,7 +2856,8 @@ async function createRouter(options) {
2738
2856
  catalogClient,
2739
2857
  actions,
2740
2858
  containerRunner,
2741
- taskWorkers
2859
+ taskWorkers,
2860
+ additionalTemplateFilters
2742
2861
  } = options;
2743
2862
  const logger = parentLogger.child({ plugin: "scaffolder" });
2744
2863
  const workingDirectory = await getWorkingDirectory(config, logger);
@@ -2761,7 +2880,8 @@ async function createRouter(options) {
2761
2880
  actionRegistry,
2762
2881
  integrations,
2763
2882
  logger,
2764
- workingDirectory
2883
+ workingDirectory,
2884
+ additionalTemplateFilters
2765
2885
  });
2766
2886
  workers.push(worker);
2767
2887
  }
@@ -2770,7 +2890,8 @@ async function createRouter(options) {
2770
2890
  catalogClient,
2771
2891
  containerRunner,
2772
2892
  reader,
2773
- config
2893
+ config,
2894
+ additionalTemplateFilters
2774
2895
  });
2775
2896
  actionsToRegister.forEach((action) => actionRegistry.register(action));
2776
2897
  workers.forEach((worker) => worker.start());
@@ -2861,6 +2982,8 @@ async function createRouter(options) {
2861
2982
  throw new errors.InputError(`Unsupported apiVersion field in schema entity, ${template.apiVersion}`);
2862
2983
  }
2863
2984
  const result = await taskBroker.dispatch(taskSpec, {
2985
+ ...req.body.secrets,
2986
+ backstageToken: token,
2864
2987
  token
2865
2988
  });
2866
2989
  res.status(201).json({ id: result.taskId });