@backstage/plugin-scaffolder-backend 1.6.0 → 1.7.0-next.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/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # @backstage/plugin-scaffolder-backend
2
2
 
3
+ ## 1.7.0-next.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 253453fa14: Added a new property called `additionalTemplateGlobals` which allows you to add global functions to the scaffolder nunjucks templates.
8
+ - 304305dd20: Add `allowAutoMerge` option for `publish:github` action
9
+ - 694bfe2d61: Add functionality to shutdown scaffolder tasks if they are stale
10
+
11
+ ### Patch Changes
12
+
13
+ - b681275e69: Ignore .git directories in Template Editor, increase upload limit for dry-runs to 10MB.
14
+ - Updated dependencies
15
+ - @backstage/catalog-model@1.1.2-next.0
16
+ - @backstage/backend-plugin-api@0.1.3-next.0
17
+ - @backstage/plugin-catalog-backend@1.4.1-next.0
18
+ - @backstage/catalog-client@1.1.1-next.0
19
+ - @backstage/plugin-catalog-node@1.1.1-next.0
20
+ - @backstage/plugin-scaffolder-common@1.2.1-next.0
21
+ - @backstage/backend-common@0.15.2-next.0
22
+ - @backstage/backend-tasks@0.3.6-next.0
23
+ - @backstage/plugin-auth-node@0.2.6-next.0
24
+ - @backstage/config@1.0.3-next.0
25
+ - @backstage/errors@1.1.2-next.0
26
+ - @backstage/integration@1.3.2-next.0
27
+ - @backstage/types@1.0.0
28
+
3
29
  ## 1.6.0
4
30
 
5
31
  ### Minor Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/plugin-scaffolder-backend",
3
- "version": "1.6.0",
3
+ "version": "1.7.0-next.0",
4
4
  "main": "../dist/index.cjs.js",
5
5
  "types": "../dist/index.alpha.d.ts"
6
6
  }
@@ -24,6 +24,7 @@ import { Logger } from 'winston';
24
24
  import { Observable } from '@backstage/types';
25
25
  import { Octokit } from 'octokit';
26
26
  import { PluginDatabaseManager } from '@backstage/backend-common';
27
+ import { PluginTaskScheduler } from '@backstage/backend-tasks';
27
28
  import { Schema } from 'jsonschema';
28
29
  import { ScmIntegrationRegistry } from '@backstage/integration';
29
30
  import { ScmIntegrations } from '@backstage/integration';
@@ -106,6 +107,7 @@ export declare interface CreateBuiltInActionsOptions {
106
107
  * Template Manifests and also template skeleton files when using `fetch:template`.
107
108
  */
108
109
  additionalTemplateFilters?: Record<string, TemplateFilter>;
110
+ additionalTemplateGlobals?: Record<string, TemplateGlobal>;
109
111
  }
110
112
 
111
113
  /**
@@ -172,6 +174,7 @@ export declare function createFetchTemplateAction(options: {
172
174
  reader: UrlReader;
173
175
  integrations: ScmIntegrations;
174
176
  additionalTemplateFilters?: Record<string, TemplateFilter>;
177
+ additionalTemplateGlobals?: Record<string, TemplateGlobal>;
175
178
  }): TemplateAction< {
176
179
  url: string;
177
180
  targetPath?: string | undefined;
@@ -287,6 +290,7 @@ gitAuthorEmail?: string | undefined;
287
290
  allowRebaseMerge?: boolean | undefined;
288
291
  allowSquashMerge?: boolean | undefined;
289
292
  allowMergeCommit?: boolean | undefined;
293
+ allowAutoMerge?: boolean | undefined;
290
294
  requireCodeOwnerReviews?: boolean | undefined;
291
295
  requiredStatusCheckContexts?: string[] | undefined;
292
296
  repoVisibility?: "internal" | "private" | "public" | undefined;
@@ -484,6 +488,7 @@ gitAuthorEmail?: string | undefined;
484
488
  allowRebaseMerge?: boolean | undefined;
485
489
  allowSquashMerge?: boolean | undefined;
486
490
  allowMergeCommit?: boolean | undefined;
491
+ allowAutoMerge?: boolean | undefined;
487
492
  sourcePath?: string | undefined;
488
493
  requireCodeOwnerReviews?: boolean | undefined;
489
494
  requiredStatusCheckContexts?: string[] | undefined;
@@ -586,6 +591,7 @@ export declare type CreateWorkerOptions = {
586
591
  workingDirectory: string;
587
592
  logger: Logger;
588
593
  additionalTemplateFilters?: Record<string, TemplateFilter>;
594
+ additionalTemplateGlobals?: Record<string, TemplateGlobal>;
589
595
  };
590
596
 
591
597
  /**
@@ -650,6 +656,7 @@ export declare class DatabaseTaskStore implements TaskStore {
650
656
  listEvents(options: TaskStoreListEventsOptions): Promise<{
651
657
  events: SerializedTaskEvent[];
652
658
  }>;
659
+ shutdownTask({ taskId }: TaskStoreShutDownTaskOptions): Promise<void>;
653
660
  }
654
661
 
655
662
  /**
@@ -703,10 +710,12 @@ export declare interface RouterOptions {
703
710
  reader: UrlReader;
704
711
  database: PluginDatabaseManager;
705
712
  catalogClient: CatalogApi;
713
+ scheduler?: PluginTaskScheduler;
706
714
  actions?: TemplateAction<any>[];
707
715
  taskWorkers?: number;
708
716
  taskBroker?: TaskBroker;
709
717
  additionalTemplateFilters?: Record<string, TemplateFilter>;
718
+ additionalTemplateGlobals?: Record<string, TemplateGlobal>;
710
719
  identity?: IdentityApi;
711
720
  }
712
721
 
@@ -751,6 +760,7 @@ export declare type ScaffolderPluginOptions = {
751
760
  taskWorkers?: number;
752
761
  taskBroker?: TaskBroker;
753
762
  additionalTemplateFilters?: Record<string, TemplateFilter>;
763
+ additionalTemplateGlobals?: Record<string, TemplateGlobal>;
754
764
  };
755
765
 
756
766
  /**
@@ -927,6 +937,7 @@ export declare interface TaskStore {
927
937
  listEvents({ taskId, after, }: TaskStoreListEventsOptions): Promise<{
928
938
  events: SerializedTaskEvent[];
929
939
  }>;
940
+ shutdownTask?({ taskId }: TaskStoreShutDownTaskOptions): Promise<void>;
930
941
  }
931
942
 
932
943
  /**
@@ -967,6 +978,15 @@ export declare type TaskStoreListEventsOptions = {
967
978
  after?: number | undefined;
968
979
  };
969
980
 
981
+ /**
982
+ * TaskStoreShutDownTaskOptions
983
+ *
984
+ * @public
985
+ */
986
+ export declare type TaskStoreShutDownTaskOptions = {
987
+ taskId: string;
988
+ };
989
+
970
990
  /**
971
991
  * TaskWorker
972
992
  *
@@ -1006,4 +1026,7 @@ export declare class TemplateActionRegistry {
1006
1026
  /** @public */
1007
1027
  export declare type TemplateFilter = (...args: JsonValue[]) => JsonValue | undefined;
1008
1028
 
1029
+ /** @public */
1030
+ export declare type TemplateGlobal = ((...args: JsonValue[]) => JsonValue | undefined) | JsonValue;
1031
+
1009
1032
  export { }
@@ -24,6 +24,7 @@ import { Logger } from 'winston';
24
24
  import { Observable } from '@backstage/types';
25
25
  import { Octokit } from 'octokit';
26
26
  import { PluginDatabaseManager } from '@backstage/backend-common';
27
+ import { PluginTaskScheduler } from '@backstage/backend-tasks';
27
28
  import { Schema } from 'jsonschema';
28
29
  import { ScmIntegrationRegistry } from '@backstage/integration';
29
30
  import { ScmIntegrations } from '@backstage/integration';
@@ -106,6 +107,7 @@ export declare interface CreateBuiltInActionsOptions {
106
107
  * Template Manifests and also template skeleton files when using `fetch:template`.
107
108
  */
108
109
  additionalTemplateFilters?: Record<string, TemplateFilter>;
110
+ additionalTemplateGlobals?: Record<string, TemplateGlobal>;
109
111
  }
110
112
 
111
113
  /**
@@ -172,6 +174,7 @@ export declare function createFetchTemplateAction(options: {
172
174
  reader: UrlReader;
173
175
  integrations: ScmIntegrations;
174
176
  additionalTemplateFilters?: Record<string, TemplateFilter>;
177
+ additionalTemplateGlobals?: Record<string, TemplateGlobal>;
175
178
  }): TemplateAction< {
176
179
  url: string;
177
180
  targetPath?: string | undefined;
@@ -287,6 +290,7 @@ gitAuthorEmail?: string | undefined;
287
290
  allowRebaseMerge?: boolean | undefined;
288
291
  allowSquashMerge?: boolean | undefined;
289
292
  allowMergeCommit?: boolean | undefined;
293
+ allowAutoMerge?: boolean | undefined;
290
294
  requireCodeOwnerReviews?: boolean | undefined;
291
295
  requiredStatusCheckContexts?: string[] | undefined;
292
296
  repoVisibility?: "internal" | "private" | "public" | undefined;
@@ -484,6 +488,7 @@ gitAuthorEmail?: string | undefined;
484
488
  allowRebaseMerge?: boolean | undefined;
485
489
  allowSquashMerge?: boolean | undefined;
486
490
  allowMergeCommit?: boolean | undefined;
491
+ allowAutoMerge?: boolean | undefined;
487
492
  sourcePath?: string | undefined;
488
493
  requireCodeOwnerReviews?: boolean | undefined;
489
494
  requiredStatusCheckContexts?: string[] | undefined;
@@ -586,6 +591,7 @@ export declare type CreateWorkerOptions = {
586
591
  workingDirectory: string;
587
592
  logger: Logger;
588
593
  additionalTemplateFilters?: Record<string, TemplateFilter>;
594
+ additionalTemplateGlobals?: Record<string, TemplateGlobal>;
589
595
  };
590
596
 
591
597
  /**
@@ -650,6 +656,7 @@ export declare class DatabaseTaskStore implements TaskStore {
650
656
  listEvents(options: TaskStoreListEventsOptions): Promise<{
651
657
  events: SerializedTaskEvent[];
652
658
  }>;
659
+ shutdownTask({ taskId }: TaskStoreShutDownTaskOptions): Promise<void>;
653
660
  }
654
661
 
655
662
  /**
@@ -703,10 +710,12 @@ export declare interface RouterOptions {
703
710
  reader: UrlReader;
704
711
  database: PluginDatabaseManager;
705
712
  catalogClient: CatalogApi;
713
+ scheduler?: PluginTaskScheduler;
706
714
  actions?: TemplateAction<any>[];
707
715
  taskWorkers?: number;
708
716
  taskBroker?: TaskBroker;
709
717
  additionalTemplateFilters?: Record<string, TemplateFilter>;
718
+ additionalTemplateGlobals?: Record<string, TemplateGlobal>;
710
719
  identity?: IdentityApi;
711
720
  }
712
721
 
@@ -910,6 +919,7 @@ export declare interface TaskStore {
910
919
  listEvents({ taskId, after, }: TaskStoreListEventsOptions): Promise<{
911
920
  events: SerializedTaskEvent[];
912
921
  }>;
922
+ shutdownTask?({ taskId }: TaskStoreShutDownTaskOptions): Promise<void>;
913
923
  }
914
924
 
915
925
  /**
@@ -950,6 +960,15 @@ export declare type TaskStoreListEventsOptions = {
950
960
  after?: number | undefined;
951
961
  };
952
962
 
963
+ /**
964
+ * TaskStoreShutDownTaskOptions
965
+ *
966
+ * @public
967
+ */
968
+ export declare type TaskStoreShutDownTaskOptions = {
969
+ taskId: string;
970
+ };
971
+
953
972
  /**
954
973
  * TaskWorker
955
974
  *
@@ -989,4 +1008,7 @@ export declare class TemplateActionRegistry {
989
1008
  /** @public */
990
1009
  export declare type TemplateFilter = (...args: JsonValue[]) => JsonValue | undefined;
991
1010
 
1011
+ /** @public */
1012
+ export declare type TemplateGlobal = ((...args: JsonValue[]) => JsonValue | undefined) | JsonValue;
1013
+
992
1014
  export { }
package/dist/index.cjs.js CHANGED
@@ -403,6 +403,16 @@ const { render, renderCompat } = (() => {
403
403
  }
404
404
  }
405
405
 
406
+ if (typeof additionalTemplateGlobals !== 'undefined') {
407
+ for (const [globalName, global] of Object.entries(additionalTemplateGlobals)) {
408
+ if (typeof global === 'function') {
409
+ env.addGlobal(globalName, (...args) => JSON.parse(global(...args)));
410
+ } else {
411
+ env.addGlobal(globalName, JSON.parse(global));
412
+ }
413
+ }
414
+ }
415
+
406
416
  let uninstallCompat = undefined;
407
417
 
408
418
  function render(str, values) {
@@ -435,7 +445,12 @@ const { render, renderCompat } = (() => {
435
445
  `;
436
446
  class SecureTemplater {
437
447
  static async loadRenderer(options = {}) {
438
- const { parseRepoUrl, cookiecutterCompat, additionalTemplateFilters } = options;
448
+ const {
449
+ parseRepoUrl,
450
+ cookiecutterCompat,
451
+ additionalTemplateFilters,
452
+ additionalTemplateGlobals
453
+ } = options;
439
454
  const sandbox = {};
440
455
  if (parseRepoUrl) {
441
456
  sandbox.parseRepoUrl = (url) => JSON.stringify(parseRepoUrl(url));
@@ -448,6 +463,19 @@ class SecureTemplater {
448
463
  ])
449
464
  );
450
465
  }
466
+ if (additionalTemplateGlobals) {
467
+ sandbox.additionalTemplateGlobals = Object.fromEntries(
468
+ Object.entries(additionalTemplateGlobals).filter(([_, global]) => !!global).map(([globalName, global]) => {
469
+ if (typeof global === "function") {
470
+ return [
471
+ globalName,
472
+ (...args) => JSON.stringify(global(...args))
473
+ ];
474
+ }
475
+ return [globalName, JSON.stringify(global)];
476
+ })
477
+ );
478
+ }
451
479
  const vm = new vm2.VM({ sandbox });
452
480
  const nunjucksSource = await fs__default["default"].readFile(
453
481
  backendCommon.resolvePackagePath(
@@ -473,7 +501,12 @@ class SecureTemplater {
473
501
  }
474
502
 
475
503
  function createFetchTemplateAction(options) {
476
- const { reader, integrations, additionalTemplateFilters } = options;
504
+ const {
505
+ reader,
506
+ integrations,
507
+ additionalTemplateFilters,
508
+ additionalTemplateGlobals
509
+ } = options;
477
510
  return createTemplateAction({
478
511
  id: "fetch:template",
479
512
  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.",
@@ -606,7 +639,8 @@ function createFetchTemplateAction(options) {
606
639
  );
607
640
  const renderTemplate = await SecureTemplater.loadRenderer({
608
641
  cookiecutterCompat: ctx.input.cookiecutterCompat,
609
- additionalTemplateFilters
642
+ additionalTemplateFilters,
643
+ additionalTemplateGlobals
610
644
  });
611
645
  for (const location of allEntriesInTemplate) {
612
646
  let renderContents;
@@ -1039,7 +1073,7 @@ async function getOctokitOptions(options) {
1039
1073
  previews: ["nebula-preview"]
1040
1074
  };
1041
1075
  }
1042
- async function createGithubRepoWithCollaboratorsAndTopics(client, repo, owner, repoVisibility, description, homepage, deleteBranchOnMerge, allowMergeCommit, allowSquashMerge, allowRebaseMerge, access, collaborators, topics, logger) {
1076
+ async function createGithubRepoWithCollaboratorsAndTopics(client, repo, owner, repoVisibility, description, homepage, deleteBranchOnMerge, allowMergeCommit, allowSquashMerge, allowRebaseMerge, allowAutoMerge, access, collaborators, topics, logger) {
1043
1077
  const user = await client.rest.users.getByUsername({
1044
1078
  username: owner
1045
1079
  });
@@ -1053,6 +1087,7 @@ async function createGithubRepoWithCollaboratorsAndTopics(client, repo, owner, r
1053
1087
  allow_merge_commit: allowMergeCommit,
1054
1088
  allow_squash_merge: allowSquashMerge,
1055
1089
  allow_rebase_merge: allowRebaseMerge,
1090
+ allow_auto_merge: allowAutoMerge,
1056
1091
  homepage
1057
1092
  }) : client.rest.repos.createForAuthenticatedUser({
1058
1093
  name: repo,
@@ -1062,6 +1097,7 @@ async function createGithubRepoWithCollaboratorsAndTopics(client, repo, owner, r
1062
1097
  allow_merge_commit: allowMergeCommit,
1063
1098
  allow_squash_merge: allowSquashMerge,
1064
1099
  allow_rebase_merge: allowRebaseMerge,
1100
+ allow_auto_merge: allowAutoMerge,
1065
1101
  homepage
1066
1102
  });
1067
1103
  let newRepo;
@@ -1390,6 +1426,11 @@ const allowRebaseMerge = {
1390
1426
  type: "boolean",
1391
1427
  description: `Allow rebase merges. The default value is 'true'`
1392
1428
  };
1429
+ const allowAutoMerge = {
1430
+ title: "Allow Auto Merges",
1431
+ type: "boolean",
1432
+ description: `Allow individual PRs to merge automatically when all merge requirements are met. The default value is 'false'`
1433
+ };
1393
1434
  const collaborators = {
1394
1435
  title: "Collaborators",
1395
1436
  description: "Provide additional users or teams with permissions",
@@ -1484,6 +1525,7 @@ function createGithubRepoCreateAction(options) {
1484
1525
  allowMergeCommit: allowMergeCommit,
1485
1526
  allowSquashMerge: allowSquashMerge,
1486
1527
  allowRebaseMerge: allowRebaseMerge,
1528
+ allowAutoMerge: allowAutoMerge,
1487
1529
  collaborators: collaborators,
1488
1530
  token: token,
1489
1531
  topics: topics
@@ -1508,6 +1550,7 @@ function createGithubRepoCreateAction(options) {
1508
1550
  allowMergeCommit = true,
1509
1551
  allowSquashMerge = true,
1510
1552
  allowRebaseMerge = true,
1553
+ allowAutoMerge = false,
1511
1554
  collaborators,
1512
1555
  topics,
1513
1556
  token: providedToken
@@ -1534,6 +1577,7 @@ function createGithubRepoCreateAction(options) {
1534
1577
  allowMergeCommit,
1535
1578
  allowSquashMerge,
1536
1579
  allowRebaseMerge,
1580
+ allowAutoMerge,
1537
1581
  access,
1538
1582
  collaborators,
1539
1583
  topics,
@@ -2841,6 +2885,7 @@ function createPublishGithubAction(options) {
2841
2885
  allowMergeCommit: allowMergeCommit,
2842
2886
  allowSquashMerge: allowSquashMerge,
2843
2887
  allowRebaseMerge: allowRebaseMerge,
2888
+ allowAutoMerge: allowAutoMerge,
2844
2889
  sourcePath: sourcePath,
2845
2890
  collaborators: collaborators,
2846
2891
  token: token,
@@ -2874,6 +2919,7 @@ function createPublishGithubAction(options) {
2874
2919
  allowMergeCommit = true,
2875
2920
  allowSquashMerge = true,
2876
2921
  allowRebaseMerge = true,
2922
+ allowAutoMerge = false,
2877
2923
  collaborators,
2878
2924
  topics,
2879
2925
  token: providedToken
@@ -2900,6 +2946,7 @@ function createPublishGithubAction(options) {
2900
2946
  allowMergeCommit,
2901
2947
  allowSquashMerge,
2902
2948
  allowRebaseMerge,
2949
+ allowAutoMerge,
2903
2950
  access,
2904
2951
  collaborators,
2905
2952
  topics,
@@ -3551,7 +3598,8 @@ const createBuiltinActions = (options) => {
3551
3598
  integrations,
3552
3599
  catalogClient,
3553
3600
  config,
3554
- additionalTemplateFilters
3601
+ additionalTemplateFilters,
3602
+ additionalTemplateGlobals
3555
3603
  } = options;
3556
3604
  const githubCredentialsProvider = integration.DefaultGithubCredentialsProvider.fromIntegrations(integrations);
3557
3605
  const actions = [
@@ -3562,7 +3610,8 @@ const createBuiltinActions = (options) => {
3562
3610
  createFetchTemplateAction({
3563
3611
  integrations,
3564
3612
  reader,
3565
- additionalTemplateFilters
3613
+ additionalTemplateFilters,
3614
+ additionalTemplateGlobals
3566
3615
  }),
3567
3616
  createPublishGerritAction({
3568
3617
  integrations,
@@ -3805,8 +3854,7 @@ class DatabaseTaskStore {
3805
3854
  const rawRows = await this.db("tasks").where("status", "processing").andWhere(
3806
3855
  "last_heartbeat_at",
3807
3856
  "<=",
3808
- this.db.client.config.client.includes("sqlite3") ? this.db.raw(`datetime('now', ?)`, [`-${timeoutS} seconds`]) : this.db.raw(`dateadd('second', ?, ?)`, [
3809
- `-${timeoutS}`,
3857
+ this.db.client.config.client.includes("sqlite3") ? this.db.raw(`datetime('now', ?)`, [`-${timeoutS} seconds`]) : this.db.raw(`? - interval '${timeoutS} seconds'`, [
3810
3858
  this.db.fn.now()
3811
3859
  ])
3812
3860
  );
@@ -3891,6 +3939,33 @@ class DatabaseTaskStore {
3891
3939
  });
3892
3940
  return { events };
3893
3941
  }
3942
+ async shutdownTask({ taskId }) {
3943
+ const message = `This task was marked as stale as it exceeded its timeout`;
3944
+ const statusStepEvents = (await this.listEvents({ taskId })).events.filter(
3945
+ ({ body }) => body == null ? void 0 : body.stepId
3946
+ );
3947
+ const completedSteps = statusStepEvents.filter(
3948
+ ({ body: { status } }) => status === "failed" || status === "completed"
3949
+ ).map((step) => step.body.stepId);
3950
+ const hungProcessingSteps = statusStepEvents.filter(({ body: { status } }) => status === "processing").map((event) => event.body.stepId).filter((step) => !completedSteps.includes(step));
3951
+ for (const step of hungProcessingSteps) {
3952
+ await this.emitLogEvent({
3953
+ taskId,
3954
+ body: {
3955
+ message,
3956
+ stepId: step,
3957
+ status: "failed"
3958
+ }
3959
+ });
3960
+ }
3961
+ await this.completeTask({
3962
+ taskId,
3963
+ status: "failed",
3964
+ eventBody: {
3965
+ message
3966
+ }
3967
+ });
3968
+ }
3894
3969
  }
3895
3970
 
3896
3971
  class TaskManager {
@@ -4181,7 +4256,8 @@ class NunjucksWorkflowRunner {
4181
4256
  parseRepoUrl(url) {
4182
4257
  return parseRepoUrl(url, integrations);
4183
4258
  },
4184
- additionalTemplateFilters: this.options.additionalTemplateFilters
4259
+ additionalTemplateFilters: this.options.additionalTemplateFilters,
4260
+ additionalTemplateGlobals: this.options.additionalTemplateGlobals
4185
4261
  });
4186
4262
  try {
4187
4263
  await fs__default["default"].ensureDir(workspacePath);
@@ -4332,14 +4408,16 @@ class TaskWorker {
4332
4408
  actionRegistry,
4333
4409
  integrations,
4334
4410
  workingDirectory,
4335
- additionalTemplateFilters
4411
+ additionalTemplateFilters,
4412
+ additionalTemplateGlobals
4336
4413
  } = options;
4337
4414
  const workflowRunner = new NunjucksWorkflowRunner({
4338
4415
  actionRegistry,
4339
4416
  integrations,
4340
4417
  logger,
4341
4418
  workingDirectory,
4342
- additionalTemplateFilters
4419
+ additionalTemplateFilters,
4420
+ additionalTemplateGlobals
4343
4421
  });
4344
4422
  return new TaskWorker({
4345
4423
  taskBroker,
@@ -4563,7 +4641,7 @@ function buildDefaultIdentityClient({
4563
4641
  }
4564
4642
  async function createRouter(options) {
4565
4643
  const router = Router__default["default"]();
4566
- router.use(express__default["default"].json());
4644
+ router.use(express__default["default"].json({ limit: "10MB" }));
4567
4645
  const {
4568
4646
  logger: parentLogger,
4569
4647
  config,
@@ -4572,7 +4650,9 @@ async function createRouter(options) {
4572
4650
  catalogClient,
4573
4651
  actions,
4574
4652
  taskWorkers,
4575
- additionalTemplateFilters
4653
+ scheduler,
4654
+ additionalTemplateFilters,
4655
+ additionalTemplateGlobals
4576
4656
  } = options;
4577
4657
  const logger = parentLogger.child({ plugin: "scaffolder" });
4578
4658
  const identity = options.identity || buildDefaultIdentityClient({ logger });
@@ -4582,6 +4662,22 @@ async function createRouter(options) {
4582
4662
  if (!options.taskBroker) {
4583
4663
  const databaseTaskStore = await DatabaseTaskStore.create({ database });
4584
4664
  taskBroker = new StorageTaskBroker(databaseTaskStore, logger);
4665
+ if (scheduler && databaseTaskStore.listStaleTasks) {
4666
+ await scheduler.scheduleTask({
4667
+ id: "close_stale_tasks",
4668
+ frequency: { cron: "*/5 * * * *" },
4669
+ timeout: { minutes: 15 },
4670
+ fn: async () => {
4671
+ const { tasks } = await databaseTaskStore.listStaleTasks({
4672
+ timeoutS: 86400
4673
+ });
4674
+ for (const task of tasks) {
4675
+ await databaseTaskStore.shutdownTask(task);
4676
+ logger.info(`Successfully closed stale task ${task.taskId}`);
4677
+ }
4678
+ }
4679
+ });
4680
+ }
4585
4681
  } else {
4586
4682
  taskBroker = options.taskBroker;
4587
4683
  }
@@ -4594,7 +4690,8 @@ async function createRouter(options) {
4594
4690
  integrations,
4595
4691
  logger,
4596
4692
  workingDirectory,
4597
- additionalTemplateFilters
4693
+ additionalTemplateFilters,
4694
+ additionalTemplateGlobals
4598
4695
  });
4599
4696
  workers.push(worker);
4600
4697
  }
@@ -4603,7 +4700,8 @@ async function createRouter(options) {
4603
4700
  catalogClient,
4604
4701
  reader,
4605
4702
  config,
4606
- additionalTemplateFilters
4703
+ additionalTemplateFilters,
4704
+ additionalTemplateGlobals
4607
4705
  });
4608
4706
  actionsToRegister.forEach((action) => actionRegistry.register(action));
4609
4707
  workers.forEach((worker) => worker.start());
@@ -4612,7 +4710,8 @@ async function createRouter(options) {
4612
4710
  integrations,
4613
4711
  logger,
4614
4712
  workingDirectory,
4615
- additionalTemplateFilters
4713
+ additionalTemplateFilters,
4714
+ additionalTemplateGlobals
4616
4715
  });
4617
4716
  router.get(
4618
4717
  "/v2/templates/:namespace/:kind/:name/parameter-schema",
@@ -5005,7 +5104,12 @@ const scaffolderPlugin = backendPluginApi.createBackendPlugin({
5005
5104
  httpRouter,
5006
5105
  catalogClient
5007
5106
  }) {
5008
- const { additionalTemplateFilters, taskBroker, taskWorkers } = options;
5107
+ const {
5108
+ additionalTemplateFilters,
5109
+ taskBroker,
5110
+ taskWorkers,
5111
+ additionalTemplateGlobals
5112
+ } = options;
5009
5113
  const log = backendPluginApi.loggerToWinstonLogger(logger);
5010
5114
  const actions = options.actions || [
5011
5115
  ...actionsExtensions.actions,
@@ -5014,7 +5118,8 @@ const scaffolderPlugin = backendPluginApi.createBackendPlugin({
5014
5118
  catalogClient,
5015
5119
  reader,
5016
5120
  config,
5017
- additionalTemplateFilters
5121
+ additionalTemplateFilters,
5122
+ additionalTemplateGlobals
5018
5123
  })
5019
5124
  ];
5020
5125
  const actionIds = actions.map((action) => action.id).join(", ");
@@ -5030,7 +5135,8 @@ const scaffolderPlugin = backendPluginApi.createBackendPlugin({
5030
5135
  actions,
5031
5136
  taskBroker,
5032
5137
  taskWorkers,
5033
- additionalTemplateFilters
5138
+ additionalTemplateFilters,
5139
+ additionalTemplateGlobals
5034
5140
  });
5035
5141
  httpRouter.use(router);
5036
5142
  }