@backstage/plugin-scaffolder-backend 1.10.0-next.1 → 1.10.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/dist/index.cjs.js CHANGED
@@ -4,8 +4,8 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var errors = require('@backstage/errors');
6
6
  var catalogModel = require('@backstage/catalog-model');
7
- var fs = require('fs-extra');
8
7
  var yaml = require('yaml');
8
+ var fs = require('fs-extra');
9
9
  var backendCommon = require('@backstage/backend-common');
10
10
  var integration = require('@backstage/integration');
11
11
  var path = require('path');
@@ -62,8 +62,9 @@ function _interopNamespace(e) {
62
62
  return Object.freeze(n);
63
63
  }
64
64
 
65
- var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
65
+ var yaml__default = /*#__PURE__*/_interopDefaultLegacy(yaml);
66
66
  var yaml__namespace = /*#__PURE__*/_interopNamespace(yaml);
67
+ var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
67
68
  var path__default = /*#__PURE__*/_interopDefaultLegacy(path);
68
69
  var globby__default = /*#__PURE__*/_interopDefaultLegacy(globby);
69
70
  var fetch__default = /*#__PURE__*/_interopDefaultLegacy(fetch);
@@ -81,11 +82,30 @@ const createTemplateAction = (templateAction) => {
81
82
  return templateAction;
82
83
  };
83
84
 
85
+ const id$3 = "catalog:register";
86
+ const examples$3 = [
87
+ {
88
+ description: "Register with the catalog",
89
+ example: yaml__default["default"].stringify({
90
+ steps: [
91
+ {
92
+ action: id$3,
93
+ id: "register-with-catalog",
94
+ name: "Register with the catalog",
95
+ input: {
96
+ catalogInfoUrl: "http://github.com/backstage/backstage/blob/master/catalog-info.yaml"
97
+ }
98
+ }
99
+ ]
100
+ })
101
+ }
102
+ ];
84
103
  function createCatalogRegisterAction(options) {
85
104
  const { catalogClient, integrations } = options;
86
105
  return createTemplateAction({
87
- id: "catalog:register",
106
+ id: id$3,
88
107
  description: "Registers entities from a catalog descriptor file in the workspace into the software catalog.",
108
+ examples: examples$3,
89
109
  schema: {
90
110
  input: {
91
111
  oneOf: [
@@ -203,10 +223,41 @@ function createCatalogRegisterAction(options) {
203
223
  });
204
224
  }
205
225
 
226
+ const id$2 = "catalog:write";
227
+ const examples$2 = [
228
+ {
229
+ description: "Write a catalog yaml file",
230
+ example: yaml__namespace.stringify({
231
+ steps: [
232
+ {
233
+ action: id$2,
234
+ id: "create-catalog-info-file",
235
+ name: "Create catalog file",
236
+ input: {
237
+ entity: {
238
+ apiVersion: "backstage.io/v1alpha1",
239
+ kind: "Component",
240
+ metadata: {
241
+ name: "test",
242
+ annotations: {}
243
+ },
244
+ spec: {
245
+ type: "service",
246
+ lifecycle: "production",
247
+ owner: "default/owner"
248
+ }
249
+ }
250
+ }
251
+ }
252
+ ]
253
+ })
254
+ }
255
+ ];
206
256
  function createCatalogWriteAction() {
207
257
  return createTemplateAction({
208
- id: "catalog:write",
258
+ id: id$2,
209
259
  description: "Writes the catalog-info.yaml for your template",
260
+ examples: examples$2,
210
261
  schema: {
211
262
  input: {
212
263
  type: "object",
@@ -237,10 +288,114 @@ function createCatalogWriteAction() {
237
288
  });
238
289
  }
239
290
 
291
+ const id$1 = "catalog:fetch";
292
+ const examples$1 = [
293
+ {
294
+ description: "Fetch entity by reference",
295
+ example: yaml__default["default"].stringify({
296
+ steps: [
297
+ {
298
+ action: id$1,
299
+ id: "fetch",
300
+ name: "Fetch catalog entity",
301
+ input: {
302
+ entityRef: "component:default/name"
303
+ }
304
+ }
305
+ ]
306
+ })
307
+ }
308
+ ];
309
+ function createFetchCatalogEntityAction(options) {
310
+ const { catalogClient } = options;
311
+ return createTemplateAction({
312
+ id: id$1,
313
+ description: "Returns entity from the catalog by entity reference",
314
+ examples: examples$1,
315
+ schema: {
316
+ input: {
317
+ required: ["entityRef"],
318
+ type: "object",
319
+ properties: {
320
+ entityRef: {
321
+ type: "string",
322
+ title: "Entity reference",
323
+ description: "Entity reference of the entity to get"
324
+ },
325
+ optional: {
326
+ title: "Optional",
327
+ description: "Permit the entity to optionally exist. Default: false",
328
+ type: "boolean"
329
+ }
330
+ }
331
+ },
332
+ output: {
333
+ type: "object",
334
+ properties: {
335
+ entity: {
336
+ title: "Entity found by the entity reference",
337
+ type: "object",
338
+ description: "Object containing same values used in the Entity schema."
339
+ }
340
+ }
341
+ }
342
+ },
343
+ async handler(ctx) {
344
+ var _a;
345
+ const { entityRef, optional } = ctx.input;
346
+ let entity;
347
+ try {
348
+ entity = await catalogClient.getEntityByRef(entityRef, {
349
+ token: (_a = ctx.secrets) == null ? void 0 : _a.backstageToken
350
+ });
351
+ } catch (e) {
352
+ if (!optional) {
353
+ throw e;
354
+ }
355
+ }
356
+ ctx.output("entity", entity != null ? entity : null);
357
+ }
358
+ });
359
+ }
360
+
361
+ const id = "debug:log";
362
+ const examples = [
363
+ {
364
+ description: "Write a debug message",
365
+ example: yaml__default["default"].stringify({
366
+ steps: [
367
+ {
368
+ action: id,
369
+ id: "write-debug-line",
370
+ name: 'Write "Hello Backstage!" log line',
371
+ input: {
372
+ message: "Hello Backstage!"
373
+ }
374
+ }
375
+ ]
376
+ })
377
+ },
378
+ {
379
+ description: "List the workspace directory",
380
+ example: yaml__default["default"].stringify({
381
+ steps: [
382
+ {
383
+ action: id,
384
+ id: "write-workspace-directory",
385
+ name: "List the workspace directory",
386
+ input: {
387
+ listWorkspace: true
388
+ }
389
+ }
390
+ ]
391
+ })
392
+ }
393
+ ];
240
394
  function createDebugLogAction() {
241
395
  return createTemplateAction({
242
- id: "debug:log",
396
+ id,
243
397
  description: "Writes a message into the log or lists all files in the workspace.",
398
+ examples,
244
399
  schema: {
245
400
  input: {
246
401
  type: "object",
@@ -327,7 +482,7 @@ function createFetchPlainAction(options) {
327
482
  const { reader, integrations } = options;
328
483
  return createTemplateAction({
329
484
  id: "fetch:plain",
330
- description: "Downloads content and places it in the workspace, or optionally in a subdirectory specified by the 'targetPath' input option.",
485
+ description: "Downloads content and places it in the workspace, or optionally in a subdirectory specified by the `targetPath` input option.",
331
486
  schema: {
332
487
  input: {
333
488
  type: "object",
@@ -512,7 +667,7 @@ function createFetchTemplateAction(options) {
512
667
  } = options;
513
668
  return createTemplateAction({
514
669
  id: "fetch:template",
515
- 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.",
670
+ 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.",
516
671
  schema: {
517
672
  input: {
518
673
  type: "object",
@@ -996,17 +1151,27 @@ const enableBranchProtectionOnDefaultRepoBranch = async ({
996
1151
  logger,
997
1152
  requireCodeOwnerReviews,
998
1153
  bypassPullRequestAllowances,
1154
+ requiredApprovingReviewCount,
1155
+ restrictions,
999
1156
  requiredStatusCheckContexts = [],
1000
1157
  requireBranchesToBeUpToDate = true,
1001
1158
  requiredConversationResolution = false,
1002
1159
  defaultBranch = "master",
1003
1160
  enforceAdmins = true,
1004
- dismissStaleReviews = false
1161
+ dismissStaleReviews = false,
1162
+ requiredCommitSigning = false
1005
1163
  }) => {
1006
1164
  const tryOnce = async () => {
1007
1165
  try {
1008
1166
  await client.rest.repos.updateBranchProtection({
1009
1167
  mediaType: {
1168
+ /**
1169
+ * 👇 we need this preview because allowing a custom
1170
+ * reviewer count on branch protection is a preview
1171
+ * feature
1172
+ *
1173
+ * More here: https://docs.github.com/en/rest/overview/api-previews#require-multiple-approving-reviews
1174
+ */
1010
1175
  previews: ["luke-cage-preview"]
1011
1176
  },
1012
1177
  owner,
@@ -1016,16 +1181,23 @@ const enableBranchProtectionOnDefaultRepoBranch = async ({
1016
1181
  strict: requireBranchesToBeUpToDate,
1017
1182
  contexts: requiredStatusCheckContexts
1018
1183
  },
1019
- restrictions: null,
1184
+ restrictions: restrictions != null ? restrictions : null,
1020
1185
  enforce_admins: enforceAdmins,
1021
1186
  required_pull_request_reviews: {
1022
- required_approving_review_count: 1,
1187
+ required_approving_review_count: requiredApprovingReviewCount,
1023
1188
  require_code_owner_reviews: requireCodeOwnerReviews,
1024
1189
  bypass_pull_request_allowances: bypassPullRequestAllowances,
1025
1190
  dismiss_stale_reviews: dismissStaleReviews
1026
1191
  },
1027
1192
  required_conversation_resolution: requiredConversationResolution
1028
1193
  });
1194
+ if (requiredCommitSigning) {
1195
+ await client.rest.repos.createCommitSignatureProtection({
1196
+ owner,
1197
+ repo: repoName,
1198
+ branch: defaultBranch
1199
+ });
1200
+ }
1029
1201
  } catch (e) {
1030
1202
  errors.assertError(e);
1031
1203
  if (e.message.includes(
@@ -1056,6 +1228,7 @@ async function getOctokitOptions(options) {
1056
1228
  const { integrations, credentialsProvider, repoUrl, token } = options;
1057
1229
  const { owner, repo, host } = parseRepoUrl(repoUrl, integrations);
1058
1230
  const requestOptions = {
1231
+ // set timeout to 60 seconds
1059
1232
  timeout: DEFAULT_TIMEOUT_MS
1060
1233
  };
1061
1234
  if (!owner) {
@@ -1200,7 +1373,7 @@ async function createGithubRepoWithCollaboratorsAndTopics(client, repo, owner, r
1200
1373
  }
1201
1374
  return newRepo;
1202
1375
  }
1203
- async function initRepoPushAndProtect(remoteUrl, password, workspacePath, sourcePath, defaultBranch, protectDefaultBranch, protectEnforceAdmins, owner, client, repo, requireCodeOwnerReviews, bypassPullRequestAllowances, requiredStatusCheckContexts, requireBranchesToBeUpToDate, requiredConversationResolution, config, logger, gitCommitMessage, gitAuthorName, gitAuthorEmail, dismissStaleReviews) {
1376
+ async function initRepoPushAndProtect(remoteUrl, password, workspacePath, sourcePath, defaultBranch, protectDefaultBranch, protectEnforceAdmins, owner, client, repo, requireCodeOwnerReviews, bypassPullRequestAllowances, requiredApprovingReviewCount, restrictions, requiredStatusCheckContexts, requireBranchesToBeUpToDate, requiredConversationResolution, config, logger, gitCommitMessage, gitAuthorName, gitAuthorEmail, dismissStaleReviews, requiredCommitSigning) {
1204
1377
  const gitAuthorInfo = {
1205
1378
  name: gitAuthorName ? gitAuthorName : config.getOptionalString("scaffolder.defaultAuthor.name"),
1206
1379
  email: gitAuthorEmail ? gitAuthorEmail : config.getOptionalString("scaffolder.defaultAuthor.email")
@@ -1227,12 +1400,15 @@ async function initRepoPushAndProtect(remoteUrl, password, workspacePath, source
1227
1400
  logger,
1228
1401
  defaultBranch,
1229
1402
  bypassPullRequestAllowances,
1403
+ requiredApprovingReviewCount,
1404
+ restrictions,
1230
1405
  requireCodeOwnerReviews,
1231
1406
  requiredStatusCheckContexts,
1232
1407
  requireBranchesToBeUpToDate,
1233
1408
  requiredConversationResolution,
1234
1409
  enforceAdmins: protectEnforceAdmins,
1235
- dismissStaleReviews
1410
+ dismissStaleReviews,
1411
+ requiredCommitSigning
1236
1412
  });
1237
1413
  } catch (e) {
1238
1414
  errors.assertError(e);
@@ -1590,6 +1766,42 @@ const sourcePath = {
1590
1766
  description: "Path within the workspace that will be used as the repository root. If omitted, the entire workspace will be published as the repository.",
1591
1767
  type: "string"
1592
1768
  };
1769
+ const requiredApprovingReviewCount = {
1770
+ title: "Required approving review count",
1771
+ type: "number",
1772
+ description: `Specify the number of reviewers required to approve pull requests. Use a number between 1 and 6 or 0 to not require reviewers. Defaults to 1.`
1773
+ };
1774
+ const restrictions = {
1775
+ title: "Restrict who can push to the protected branch",
1776
+ description: "Restrict who can push to the protected branch. User, app, and team restrictions are only available for organization-owned repositories.",
1777
+ type: "object",
1778
+ additionalProperties: false,
1779
+ properties: {
1780
+ apps: {
1781
+ type: "array",
1782
+ items: {
1783
+ type: "string"
1784
+ }
1785
+ },
1786
+ users: {
1787
+ type: "array",
1788
+ items: {
1789
+ type: "string"
1790
+ }
1791
+ },
1792
+ teams: {
1793
+ type: "array",
1794
+ items: {
1795
+ type: "string"
1796
+ }
1797
+ }
1798
+ }
1799
+ };
1800
+ const requiredCommitSigning = {
1801
+ title: "Require commit signing",
1802
+ type: "boolean",
1803
+ description: `Require commit signing so that you must sign commits on this branch.`
1804
+ };
1593
1805
 
1594
1806
  const remoteUrl = {
1595
1807
  title: "A URL to the repository with the provider",
@@ -1616,6 +1828,8 @@ function createGithubRepoCreateAction(options) {
1616
1828
  access: access,
1617
1829
  requireCodeOwnerReviews: requireCodeOwnerReviews,
1618
1830
  bypassPullRequestAllowances: bypassPullRequestAllowances,
1831
+ requiredApprovingReviewCount: requiredApprovingReviewCount,
1832
+ restrictions: restrictions,
1619
1833
  requiredStatusCheckContexts: requiredStatusCheckContexts,
1620
1834
  requireBranchesToBeUpToDate: requireBranchesToBeUpToDate,
1621
1835
  requiredConversationResolution: requiredConversationResolution,
@@ -1632,7 +1846,8 @@ function createGithubRepoCreateAction(options) {
1632
1846
  hasWiki: hasWiki,
1633
1847
  hasIssues: hasIssues,
1634
1848
  token: token,
1635
- topics: topics
1849
+ topics: topics,
1850
+ requiredCommitSigning: requiredCommitSigning
1636
1851
  }
1637
1852
  },
1638
1853
  output: {
@@ -1717,6 +1932,8 @@ function createGithubRepoPushAction(options) {
1717
1932
  dismissStaleReviews: dismissStaleReviews,
1718
1933
  requiredStatusCheckContexts: requiredStatusCheckContexts,
1719
1934
  bypassPullRequestAllowances: bypassPullRequestAllowances,
1935
+ requiredApprovingReviewCount: requiredApprovingReviewCount,
1936
+ restrictions: restrictions,
1720
1937
  requireBranchesToBeUpToDate: requireBranchesToBeUpToDate,
1721
1938
  requiredConversationResolution: requiredConversationResolution,
1722
1939
  defaultBranch: defaultBranch,
@@ -1726,7 +1943,8 @@ function createGithubRepoPushAction(options) {
1726
1943
  gitAuthorName: gitAuthorName,
1727
1944
  gitAuthorEmail: gitAuthorEmail,
1728
1945
  sourcePath: sourcePath,
1729
- token: token
1946
+ token: token,
1947
+ requiredCommitSigning: requiredCommitSigning
1730
1948
  }
1731
1949
  },
1732
1950
  output: {
@@ -1749,10 +1967,13 @@ function createGithubRepoPushAction(options) {
1749
1967
  requireCodeOwnerReviews = false,
1750
1968
  dismissStaleReviews = false,
1751
1969
  bypassPullRequestAllowances,
1970
+ requiredApprovingReviewCount = 1,
1971
+ restrictions,
1752
1972
  requiredStatusCheckContexts = [],
1753
1973
  requireBranchesToBeUpToDate = true,
1754
1974
  requiredConversationResolution = false,
1755
- token: providedToken
1975
+ token: providedToken,
1976
+ requiredCommitSigning = false
1756
1977
  } = ctx.input;
1757
1978
  const { owner, repo } = parseRepoUrl(repoUrl, integrations);
1758
1979
  if (!owner) {
@@ -1781,6 +2002,8 @@ function createGithubRepoPushAction(options) {
1781
2002
  repo,
1782
2003
  requireCodeOwnerReviews,
1783
2004
  bypassPullRequestAllowances,
2005
+ requiredApprovingReviewCount,
2006
+ restrictions,
1784
2007
  requiredStatusCheckContexts,
1785
2008
  requireBranchesToBeUpToDate,
1786
2009
  requiredConversationResolution,
@@ -1789,7 +2012,8 @@ function createGithubRepoPushAction(options) {
1789
2012
  gitCommitMessage,
1790
2013
  gitAuthorName,
1791
2014
  gitAuthorEmail,
1792
- dismissStaleReviews
2015
+ dismissStaleReviews,
2016
+ requiredCommitSigning
1793
2017
  );
1794
2018
  ctx.output("remoteUrl", remoteUrl);
1795
2019
  ctx.output("repoContentsUrl", repoContentsUrl);
@@ -2641,6 +2865,21 @@ function createPublishBitbucketServerAction(options) {
2641
2865
  title: "Authentication Token",
2642
2866
  type: "string",
2643
2867
  description: "The token to use for authorization to BitBucket Server"
2868
+ },
2869
+ gitCommitMessage: {
2870
+ title: "Git Commit Message",
2871
+ type: "string",
2872
+ description: `Sets the commit message on the repository. The default value is 'initial commit'`
2873
+ },
2874
+ gitAuthorName: {
2875
+ title: "Author Name",
2876
+ type: "string",
2877
+ description: `Sets the author name for the commit. The default value is 'Scaffolder'`
2878
+ },
2879
+ gitAuthorEmail: {
2880
+ title: "Author Email",
2881
+ type: "string",
2882
+ description: `Sets the author email for the commit.`
2644
2883
  }
2645
2884
  }
2646
2885
  },
@@ -2665,7 +2904,10 @@ function createPublishBitbucketServerAction(options) {
2665
2904
  description,
2666
2905
  defaultBranch = "master",
2667
2906
  repoVisibility = "private",
2668
- enableLFS = false
2907
+ enableLFS = false,
2908
+ gitCommitMessage = "initial commit",
2909
+ gitAuthorName,
2910
+ gitAuthorEmail
2669
2911
  } = ctx.input;
2670
2912
  const { project, repo, host } = parseRepoUrl(repoUrl, integrations);
2671
2913
  if (!project) {
@@ -2702,8 +2944,8 @@ function createPublishBitbucketServerAction(options) {
2702
2944
  apiBaseUrl
2703
2945
  });
2704
2946
  const gitAuthorInfo = {
2705
- name: config.getOptionalString("scaffolder.defaultAuthor.name"),
2706
- email: config.getOptionalString("scaffolder.defaultAuthor.email")
2947
+ name: gitAuthorName ? gitAuthorName : config.getOptionalString("scaffolder.defaultAuthor.name"),
2948
+ email: gitAuthorEmail ? gitAuthorEmail : config.getOptionalString("scaffolder.defaultAuthor.email")
2707
2949
  };
2708
2950
  const auth = authConfig.token ? {
2709
2951
  token
@@ -2717,9 +2959,7 @@ function createPublishBitbucketServerAction(options) {
2717
2959
  auth,
2718
2960
  defaultBranch,
2719
2961
  logger: ctx.logger,
2720
- commitMessage: config.getOptionalString(
2721
- "scaffolder.defaultCommitMessage"
2722
- ),
2962
+ commitMessage: gitCommitMessage ? gitCommitMessage : config.getOptionalString("scaffolder.defaultCommitMessage"),
2723
2963
  gitAuthorInfo
2724
2964
  });
2725
2965
  if (enableLFS) {
@@ -3002,6 +3242,8 @@ function createPublishGithubAction(options) {
3002
3242
  homepage: homepage,
3003
3243
  access: access,
3004
3244
  bypassPullRequestAllowances: bypassPullRequestAllowances,
3245
+ requiredApprovingReviewCount: requiredApprovingReviewCount,
3246
+ restrictions: restrictions,
3005
3247
  requireCodeOwnerReviews: requireCodeOwnerReviews,
3006
3248
  dismissStaleReviews: dismissStaleReviews,
3007
3249
  requiredStatusCheckContexts: requiredStatusCheckContexts,
@@ -3027,7 +3269,8 @@ function createPublishGithubAction(options) {
3027
3269
  hasWiki: hasWiki,
3028
3270
  hasIssues: hasIssues,
3029
3271
  token: token,
3030
- topics: topics
3272
+ topics: topics,
3273
+ requiredCommitSigning: requiredCommitSigning
3031
3274
  }
3032
3275
  },
3033
3276
  output: {
@@ -3047,6 +3290,8 @@ function createPublishGithubAction(options) {
3047
3290
  requireCodeOwnerReviews = false,
3048
3291
  dismissStaleReviews = false,
3049
3292
  bypassPullRequestAllowances,
3293
+ requiredApprovingReviewCount = 1,
3294
+ restrictions,
3050
3295
  requiredStatusCheckContexts = [],
3051
3296
  requireBranchesToBeUpToDate = true,
3052
3297
  requiredConversationResolution = false,
@@ -3069,7 +3314,8 @@ function createPublishGithubAction(options) {
3069
3314
  hasWiki = void 0,
3070
3315
  hasIssues = void 0,
3071
3316
  topics,
3072
- token: providedToken
3317
+ token: providedToken,
3318
+ requiredCommitSigning = false
3073
3319
  } = ctx.input;
3074
3320
  const octokitOptions = await getOctokitOptions({
3075
3321
  integrations,
@@ -3119,6 +3365,8 @@ function createPublishGithubAction(options) {
3119
3365
  repo,
3120
3366
  requireCodeOwnerReviews,
3121
3367
  bypassPullRequestAllowances,
3368
+ requiredApprovingReviewCount,
3369
+ restrictions,
3122
3370
  requiredStatusCheckContexts,
3123
3371
  requireBranchesToBeUpToDate,
3124
3372
  requiredConversationResolution,
@@ -3127,7 +3375,8 @@ function createPublishGithubAction(options) {
3127
3375
  gitCommitMessage,
3128
3376
  gitAuthorName,
3129
3377
  gitAuthorEmail,
3130
- dismissStaleReviews
3378
+ dismissStaleReviews,
3379
+ requiredCommitSigning
3131
3380
  );
3132
3381
  ctx.output("remoteUrl", remoteUrl);
3133
3382
  ctx.output("repoContentsUrl", repoContentsUrl);
@@ -3155,6 +3404,8 @@ async function serializeDirectoryContents(sourcePath, options) {
3155
3404
  dot: true,
3156
3405
  gitignore: options == null ? void 0 : options.gitignore,
3157
3406
  followSymbolicLinks: false,
3407
+ // In order to pick up 'broken' symlinks, we oxymoronically request files AND folders yet we filter out folders
3408
+ // This is because broken symlinks aren't classed as files so we need to glob everything
3158
3409
  onlyFiles: false,
3159
3410
  objectMode: true,
3160
3411
  stats: true
@@ -3352,7 +3603,16 @@ const createPublishGithubPullRequestAction = ({
3352
3603
  directoryContents.map((file) => [
3353
3604
  targetPath ? path__default["default"].posix.join(targetPath, file.path) : file.path,
3354
3605
  {
3606
+ // See the properties of tree items
3607
+ // in https://docs.github.com/en/rest/reference/git#trees
3355
3608
  mode: determineFileMode(file),
3609
+ // Always use base64 encoding where possible to avoid doubling a binary file in size
3610
+ // due to interpreting a binary file as utf-8 and sending github
3611
+ // the utf-8 encoded content. Symlinks are kept as utf-8 to avoid them
3612
+ // being formatted as a series of scrambled characters
3613
+ //
3614
+ // For example, the original gradle-wrapper.jar is 57.8k in https://github.com/kennethzfeng/pull-request-test/pull/5/files.
3615
+ // Its size could be doubled to 98.3K (See https://github.com/kennethzfeng/pull-request-test/pull/4/files)
3356
3616
  encoding: determineFileEncoding(file),
3357
3617
  content: file.content.toString(determineFileEncoding(file))
3358
3618
  }
@@ -3589,6 +3849,7 @@ const createPublishGitlabMergeRequestAction = (options) => {
3589
3849
  title: "Repository Location",
3590
3850
  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`
3591
3851
  },
3852
+ /** @deprecated projectID is passed as query parameters in the repoUrl */
3592
3853
  projectid: {
3593
3854
  type: "string",
3594
3855
  title: "projectid",
@@ -3826,6 +4087,7 @@ const createBuiltinActions = (options) => {
3826
4087
  }),
3827
4088
  createDebugLogAction(),
3828
4089
  createCatalogRegisterAction({ catalogClient, integrations }),
4090
+ createFetchCatalogEntityAction({ catalogClient }),
3829
4091
  createCatalogWriteAction(),
3830
4092
  createFilesystemDeleteAction(),
3831
4093
  createFilesystemRenameAction(),
@@ -3990,6 +4252,7 @@ class DatabaseTaskStore {
3990
4252
  const updateCount = await tx("tasks").where({ id: task.id, status: "open" }).update({
3991
4253
  status: "processing",
3992
4254
  last_heartbeat_at: this.db.fn.now(),
4255
+ // remove the secrets when moving moving to processing state.
3993
4256
  secrets: null
3994
4257
  });
3995
4258
  if (updateCount < 1) {
@@ -4140,6 +4403,7 @@ class DatabaseTaskStore {
4140
4403
  }
4141
4404
 
4142
4405
  class TaskManager {
4406
+ // Runs heartbeat internally
4143
4407
  constructor(task, storage, logger) {
4144
4408
  this.task = task;
4145
4409
  this.storage = storage;
@@ -4223,6 +4487,9 @@ class StorageTaskBroker {
4223
4487
  }
4224
4488
  return await this.storage.list({ createdBy: options == null ? void 0 : options.createdBy });
4225
4489
  }
4490
+ /**
4491
+ * {@inheritdoc TaskBroker.claim}
4492
+ */
4226
4493
  async claim() {
4227
4494
  for (; ; ) {
4228
4495
  const pendingTask = await this.storage.claimTask();
@@ -4241,6 +4508,9 @@ class StorageTaskBroker {
4241
4508
  await this.waitForDispatch();
4242
4509
  }
4243
4510
  }
4511
+ /**
4512
+ * {@inheritdoc TaskBroker.dispatch}
4513
+ */
4244
4514
  async dispatch(options) {
4245
4515
  const taskRow = await this.storage.createTask(options);
4246
4516
  this.signalDispatch();
@@ -4248,9 +4518,15 @@ class StorageTaskBroker {
4248
4518
  taskId: taskRow.taskId
4249
4519
  };
4250
4520
  }
4521
+ /**
4522
+ * {@inheritdoc TaskBroker.get}
4523
+ */
4251
4524
  async get(taskId) {
4252
4525
  return this.storage.getTask(taskId);
4253
4526
  }
4527
+ /**
4528
+ * {@inheritdoc TaskBroker.event$}
4529
+ */
4254
4530
  event$(options) {
4255
4531
  return new ObservableImpl__default["default"]((observer) => {
4256
4532
  const { taskId } = options;
@@ -4272,6 +4548,9 @@ class StorageTaskBroker {
4272
4548
  };
4273
4549
  });
4274
4550
  }
4551
+ /**
4552
+ * {@inheritdoc TaskBroker.vacuumTasks}
4553
+ */
4275
4554
  async vacuumTasks(options) {
4276
4555
  const { tasks } = await this.storage.listStaleTasks(options);
4277
4556
  await Promise.all(
@@ -4441,6 +4720,10 @@ class NunjucksWorkflowRunner {
4441
4720
  );
4442
4721
  const { integrations } = this.options;
4443
4722
  const renderTemplate = await SecureTemplater.loadRenderer({
4723
+ // TODO(blam): let's work out how we can deprecate this.
4724
+ // We shouldn't really need to be exposing these now we can deal with
4725
+ // objects in the params block.
4726
+ // Maybe we can expose a new RepoUrlPicker with secrets for V3 that provides an object already.
4444
4727
  parseRepoUrl(url) {
4445
4728
  return parseRepoUrl(url, integrations);
4446
4729
  },
@@ -4693,6 +4976,7 @@ class TaskWorker {
4693
4976
  workingDirectory,
4694
4977
  additionalTemplateFilters,
4695
4978
  concurrentTasksLimit = 10,
4979
+ // from 1 to Infinity
4696
4980
  additionalTemplateGlobals
4697
4981
  } = options;
4698
4982
  const workflowRunner = new NunjucksWorkflowRunner({
@@ -4809,6 +5093,7 @@ function createDryRunner(options) {
4809
5093
  }
4810
5094
  },
4811
5095
  secrets: input.secrets,
5096
+ // No need to update this at the end of the run, so just hard-code it
4812
5097
  done: false,
4813
5098
  isDryRun: true,
4814
5099
  getWorkspaceName: async () => `dry-run-${dryRunId}`,
@@ -4963,6 +5248,7 @@ async function createRouter(options) {
4963
5248
  await scheduler.scheduleTask({
4964
5249
  id: "close_stale_tasks",
4965
5250
  frequency: { cron: "*/5 * * * *" },
5251
+ // every 5 minutes, also supports Duration
4966
5252
  timeout: { minutes: 15 },
4967
5253
  fn: async () => {
4968
5254
  const { tasks } = await databaseTaskStore.listStaleTasks({
@@ -5051,6 +5337,7 @@ async function createRouter(options) {
5051
5337
  return {
5052
5338
  id: action.id,
5053
5339
  description: action.description,
5340
+ examples: action.examples,
5054
5341
  schema: action.schema
5055
5342
  };
5056
5343
  });
@@ -5377,71 +5664,73 @@ _actions = new WeakMap();
5377
5664
  const scaffolderActionsExtensionPoint = backendPluginApi.createExtensionPoint({
5378
5665
  id: "scaffolder.actions"
5379
5666
  });
5380
- const scaffolderPlugin = backendPluginApi.createBackendPlugin({
5381
- id: "scaffolder",
5382
- register(env, options) {
5383
- const actionsExtensions = new ScaffolderActionsExtensionPointImpl();
5384
- env.registerExtensionPoint(
5385
- scaffolderActionsExtensionPoint,
5386
- actionsExtensions
5387
- );
5388
- env.registerInit({
5389
- deps: {
5390
- logger: backendPluginApi.coreServices.logger,
5391
- config: backendPluginApi.coreServices.config,
5392
- reader: backendPluginApi.coreServices.urlReader,
5393
- permissions: backendPluginApi.coreServices.permissions,
5394
- database: backendPluginApi.coreServices.database,
5395
- httpRouter: backendPluginApi.coreServices.httpRouter,
5396
- catalogClient: pluginCatalogNode.catalogServiceRef
5397
- },
5398
- async init({
5399
- logger,
5400
- config,
5401
- reader,
5402
- database,
5403
- httpRouter,
5404
- catalogClient
5405
- }) {
5406
- const {
5407
- additionalTemplateFilters,
5408
- taskBroker,
5409
- taskWorkers,
5410
- additionalTemplateGlobals
5411
- } = options;
5412
- const log = backendPluginApi.loggerToWinstonLogger(logger);
5413
- const actions = options.actions || [
5414
- ...actionsExtensions.actions,
5415
- ...createBuiltinActions({
5416
- integrations: integration.ScmIntegrations.fromConfig(config),
5667
+ const scaffolderPlugin = backendPluginApi.createBackendPlugin(
5668
+ (options) => ({
5669
+ id: "scaffolder",
5670
+ register(env) {
5671
+ const actionsExtensions = new ScaffolderActionsExtensionPointImpl();
5672
+ env.registerExtensionPoint(
5673
+ scaffolderActionsExtensionPoint,
5674
+ actionsExtensions
5675
+ );
5676
+ env.registerInit({
5677
+ deps: {
5678
+ logger: backendPluginApi.coreServices.logger,
5679
+ config: backendPluginApi.coreServices.config,
5680
+ reader: backendPluginApi.coreServices.urlReader,
5681
+ permissions: backendPluginApi.coreServices.permissions,
5682
+ database: backendPluginApi.coreServices.database,
5683
+ httpRouter: backendPluginApi.coreServices.httpRouter,
5684
+ catalogClient: pluginCatalogNode.catalogServiceRef
5685
+ },
5686
+ async init({
5687
+ logger,
5688
+ config,
5689
+ reader,
5690
+ database,
5691
+ httpRouter,
5692
+ catalogClient
5693
+ }) {
5694
+ const {
5695
+ additionalTemplateFilters,
5696
+ taskBroker,
5697
+ taskWorkers,
5698
+ additionalTemplateGlobals
5699
+ } = options;
5700
+ const log = backendCommon.loggerToWinstonLogger(logger);
5701
+ const actions = options.actions || [
5702
+ ...actionsExtensions.actions,
5703
+ ...createBuiltinActions({
5704
+ integrations: integration.ScmIntegrations.fromConfig(config),
5705
+ catalogClient,
5706
+ reader,
5707
+ config,
5708
+ additionalTemplateFilters,
5709
+ additionalTemplateGlobals
5710
+ })
5711
+ ];
5712
+ const actionIds = actions.map((action) => action.id).join(", ");
5713
+ log.info(
5714
+ `Starting scaffolder with the following actions enabled ${actionIds}`
5715
+ );
5716
+ const router = await createRouter({
5717
+ logger: log,
5718
+ config,
5719
+ database,
5417
5720
  catalogClient,
5418
5721
  reader,
5419
- config,
5722
+ actions,
5723
+ taskBroker,
5724
+ taskWorkers,
5420
5725
  additionalTemplateFilters,
5421
5726
  additionalTemplateGlobals
5422
- })
5423
- ];
5424
- const actionIds = actions.map((action) => action.id).join(", ");
5425
- log.info(
5426
- `Starting scaffolder with the following actions enabled ${actionIds}`
5427
- );
5428
- const router = await createRouter({
5429
- logger: log,
5430
- config,
5431
- database,
5432
- catalogClient,
5433
- reader,
5434
- actions,
5435
- taskBroker,
5436
- taskWorkers,
5437
- additionalTemplateFilters,
5438
- additionalTemplateGlobals
5439
- });
5440
- httpRouter.use(router);
5441
- }
5442
- });
5443
- }
5444
- });
5727
+ });
5728
+ httpRouter.use(router);
5729
+ }
5730
+ });
5731
+ }
5732
+ })
5733
+ );
5445
5734
 
5446
5735
  exports.DatabaseTaskStore = DatabaseTaskStore;
5447
5736
  exports.ScaffolderEntitiesProcessor = ScaffolderEntitiesProcessor;
@@ -5452,6 +5741,7 @@ exports.createBuiltinActions = createBuiltinActions;
5452
5741
  exports.createCatalogRegisterAction = createCatalogRegisterAction;
5453
5742
  exports.createCatalogWriteAction = createCatalogWriteAction;
5454
5743
  exports.createDebugLogAction = createDebugLogAction;
5744
+ exports.createFetchCatalogEntityAction = createFetchCatalogEntityAction;
5455
5745
  exports.createFetchPlainAction = createFetchPlainAction;
5456
5746
  exports.createFetchTemplateAction = createFetchTemplateAction;
5457
5747
  exports.createFilesystemDeleteAction = createFilesystemDeleteAction;