@backstage/plugin-scaffolder-backend 1.22.8 → 1.22.9
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 +158 -6
- package/alpha/package.json +1 -1
- package/dist/alpha.cjs.js +1 -1
- package/dist/alpha.d.ts +1 -1
- package/dist/cjs/{router-Bj9ovbjU.cjs.js → router-BtUx0eIt.cjs.js} +212 -272
- package/dist/cjs/router-BtUx0eIt.cjs.js.map +1 -0
- package/dist/index.cjs.js +1 -1
- package/dist/index.d.ts +1 -0
- package/package.json +33 -24
- package/dist/cjs/router-Bj9ovbjU.cjs.js.map +0 -1
|
@@ -164,7 +164,6 @@ function createCatalogRegisterAction(options) {
|
|
|
164
164
|
}
|
|
165
165
|
},
|
|
166
166
|
async handler(ctx) {
|
|
167
|
-
var _a, _b;
|
|
168
167
|
const { input } = ctx;
|
|
169
168
|
let catalogInfoUrl;
|
|
170
169
|
if ("catalogInfoUrl" in input) {
|
|
@@ -183,10 +182,10 @@ function createCatalogRegisterAction(options) {
|
|
|
183
182
|
});
|
|
184
183
|
}
|
|
185
184
|
ctx.logger.info(`Registering ${catalogInfoUrl} in the catalog`);
|
|
186
|
-
const { token } =
|
|
185
|
+
const { token } = await auth?.getPluginRequestToken({
|
|
187
186
|
onBehalfOf: await ctx.getInitiatorCredentials(),
|
|
188
187
|
targetPluginId: "catalog"
|
|
189
|
-
})
|
|
188
|
+
}) ?? { token: ctx.secrets?.backstageToken };
|
|
190
189
|
try {
|
|
191
190
|
await catalogClient.addLocation(
|
|
192
191
|
{
|
|
@@ -282,11 +281,10 @@ function createCatalogWriteAction() {
|
|
|
282
281
|
examples: examples$8,
|
|
283
282
|
supportsDryRun: true,
|
|
284
283
|
async handler(ctx) {
|
|
285
|
-
var _a;
|
|
286
284
|
ctx.logger.info(`Writing catalog-info.yaml`);
|
|
287
285
|
const { filePath, entity } = ctx.input;
|
|
288
|
-
const entityRef =
|
|
289
|
-
const path = filePath
|
|
286
|
+
const entityRef = ctx.templateInfo?.entityRef;
|
|
287
|
+
const path = filePath ?? "catalog-info.yaml";
|
|
290
288
|
await fs__default.default.writeFile(
|
|
291
289
|
backendPluginApi.resolveSafeChildPath(ctx.workspacePath, path),
|
|
292
290
|
yaml__namespace.stringify({
|
|
@@ -373,7 +371,6 @@ function createFetchCatalogEntityAction(options) {
|
|
|
373
371
|
})
|
|
374
372
|
},
|
|
375
373
|
async handler(ctx) {
|
|
376
|
-
var _a, _b;
|
|
377
374
|
const { entityRef, entityRefs, optional, defaultKind, defaultNamespace } = ctx.input;
|
|
378
375
|
if (!entityRef && !entityRefs) {
|
|
379
376
|
if (optional) {
|
|
@@ -381,10 +378,10 @@ function createFetchCatalogEntityAction(options) {
|
|
|
381
378
|
}
|
|
382
379
|
throw new Error("Missing entity reference or references");
|
|
383
380
|
}
|
|
384
|
-
const { token } =
|
|
381
|
+
const { token } = await auth?.getPluginRequestToken({
|
|
385
382
|
onBehalfOf: await ctx.getInitiatorCredentials(),
|
|
386
383
|
targetPluginId: "catalog"
|
|
387
|
-
})
|
|
384
|
+
}) ?? { token: ctx.secrets?.backstageToken };
|
|
388
385
|
if (entityRef) {
|
|
389
386
|
const entity = await catalogClient.getEntityByRef(
|
|
390
387
|
catalogModel.stringifyEntityRef(
|
|
@@ -397,7 +394,7 @@ function createFetchCatalogEntityAction(options) {
|
|
|
397
394
|
if (!entity && !optional) {
|
|
398
395
|
throw new Error(`Entity ${entityRef} not found`);
|
|
399
396
|
}
|
|
400
|
-
ctx.output("entity", entity
|
|
397
|
+
ctx.output("entity", entity ?? null);
|
|
401
398
|
}
|
|
402
399
|
if (entityRefs) {
|
|
403
400
|
const entities = await catalogClient.getEntitiesByRefs(
|
|
@@ -416,7 +413,7 @@ function createFetchCatalogEntityAction(options) {
|
|
|
416
413
|
if (!e && !optional) {
|
|
417
414
|
throw new Error(`Entity ${entityRefs[i]} not found`);
|
|
418
415
|
}
|
|
419
|
-
return e
|
|
416
|
+
return e ?? null;
|
|
420
417
|
});
|
|
421
418
|
ctx.output("entities", finalEntities);
|
|
422
419
|
}
|
|
@@ -483,12 +480,11 @@ function createDebugLogAction() {
|
|
|
483
480
|
},
|
|
484
481
|
supportsDryRun: true,
|
|
485
482
|
async handler(ctx) {
|
|
486
|
-
var _a, _b;
|
|
487
483
|
ctx.logger.info(JSON.stringify(ctx.input, null, 2));
|
|
488
|
-
if (
|
|
484
|
+
if (ctx.input?.message) {
|
|
489
485
|
ctx.logger.info(ctx.input.message);
|
|
490
486
|
}
|
|
491
|
-
if (
|
|
487
|
+
if (ctx.input?.listWorkspace) {
|
|
492
488
|
const files = await recursiveReadDir(ctx.workspacePath);
|
|
493
489
|
ctx.logger.info(
|
|
494
490
|
`Workspace:
|
|
@@ -558,7 +554,7 @@ const examples$5 = [
|
|
|
558
554
|
];
|
|
559
555
|
|
|
560
556
|
const id = "debug:wait";
|
|
561
|
-
const MAX_WAIT_TIME_IN_ISO = "T00:00
|
|
557
|
+
const MAX_WAIT_TIME_IN_ISO = "T00:10:00";
|
|
562
558
|
function createWaitAction(options) {
|
|
563
559
|
const toDuration = (maxWaitTime) => {
|
|
564
560
|
if (maxWaitTime) {
|
|
@@ -594,20 +590,18 @@ function createWaitAction(options) {
|
|
|
594
590
|
},
|
|
595
591
|
async handler(ctx) {
|
|
596
592
|
const delayTime = luxon.Duration.fromObject(ctx.input);
|
|
597
|
-
const maxWait = toDuration(options
|
|
593
|
+
const maxWait = toDuration(options?.maxWaitTime);
|
|
598
594
|
if (delayTime.minus(maxWait).toMillis() > 0) {
|
|
599
595
|
throw new Error(
|
|
600
596
|
`Waiting duration is longer than the maximum threshold of ${maxWait.toHuman()}`
|
|
601
597
|
);
|
|
602
598
|
}
|
|
603
599
|
await new Promise((resolve) => {
|
|
604
|
-
var _a;
|
|
605
600
|
const controller = new AbortController();
|
|
606
601
|
const timeoutHandle = setTimeout(abort, delayTime.toMillis());
|
|
607
|
-
|
|
602
|
+
ctx.signal?.addEventListener("abort", abort);
|
|
608
603
|
function abort() {
|
|
609
|
-
|
|
610
|
-
(_a2 = ctx.signal) == null ? void 0 : _a2.removeEventListener("abort", abort);
|
|
604
|
+
ctx.signal?.removeEventListener("abort", abort);
|
|
611
605
|
clearTimeout(timeoutHandle);
|
|
612
606
|
controller.abort();
|
|
613
607
|
resolve("finished");
|
|
@@ -683,14 +677,13 @@ function createFetchPlainAction(options) {
|
|
|
683
677
|
},
|
|
684
678
|
supportsDryRun: true,
|
|
685
679
|
async handler(ctx) {
|
|
686
|
-
var _a, _b;
|
|
687
680
|
ctx.logger.info("Fetching plain content from remote URL");
|
|
688
|
-
const targetPath =
|
|
681
|
+
const targetPath = ctx.input.targetPath ?? "./";
|
|
689
682
|
const outputPath = backendPluginApi.resolveSafeChildPath(ctx.workspacePath, targetPath);
|
|
690
683
|
await pluginScaffolderNode.fetchContents({
|
|
691
684
|
reader,
|
|
692
685
|
integrations,
|
|
693
|
-
baseUrl:
|
|
686
|
+
baseUrl: ctx.templateInfo?.baseUrl,
|
|
694
687
|
fetchUrl: ctx.input.url,
|
|
695
688
|
outputPath,
|
|
696
689
|
token: ctx.input.token
|
|
@@ -749,7 +742,6 @@ function createFetchPlainFileAction(options) {
|
|
|
749
742
|
},
|
|
750
743
|
supportsDryRun: true,
|
|
751
744
|
async handler(ctx) {
|
|
752
|
-
var _a;
|
|
753
745
|
ctx.logger.info("Fetching plain content from remote URL");
|
|
754
746
|
const outputPath = backendPluginApi.resolveSafeChildPath(
|
|
755
747
|
ctx.workspacePath,
|
|
@@ -758,7 +750,7 @@ function createFetchPlainFileAction(options) {
|
|
|
758
750
|
await pluginScaffolderNode.fetchFile({
|
|
759
751
|
reader,
|
|
760
752
|
integrations,
|
|
761
|
-
baseUrl:
|
|
753
|
+
baseUrl: ctx.templateInfo?.baseUrl,
|
|
762
754
|
fetchUrl: ctx.input.url,
|
|
763
755
|
outputPath,
|
|
764
756
|
token: ctx.input.token
|
|
@@ -768,8 +760,7 @@ function createFetchPlainFileAction(options) {
|
|
|
768
760
|
}
|
|
769
761
|
|
|
770
762
|
function isNoNodeSnapshotOptionProvided() {
|
|
771
|
-
|
|
772
|
-
return ((_a = process.env.NODE_OPTIONS) == null ? void 0 : _a.includes("--no-node-snapshot")) || process.argv.includes("--no-node-snapshot");
|
|
763
|
+
return process.env.NODE_OPTIONS?.includes("--no-node-snapshot") || process.argv.includes("--no-node-snapshot");
|
|
773
764
|
}
|
|
774
765
|
function getMajorNodeVersion() {
|
|
775
766
|
const version = process.versions.node;
|
|
@@ -1044,11 +1035,10 @@ function createFetchTemplateAction(options) {
|
|
|
1044
1035
|
},
|
|
1045
1036
|
supportsDryRun: true,
|
|
1046
1037
|
async handler(ctx) {
|
|
1047
|
-
var _a, _b;
|
|
1048
1038
|
ctx.logger.info("Fetching template content from remote URL");
|
|
1049
1039
|
const workDir = await ctx.createTemporaryDirectory();
|
|
1050
1040
|
const templateDir = backendPluginApi.resolveSafeChildPath(workDir, "template");
|
|
1051
|
-
const targetPath =
|
|
1041
|
+
const targetPath = ctx.input.targetPath ?? "./";
|
|
1052
1042
|
const outputDir = backendPluginApi.resolveSafeChildPath(ctx.workspacePath, targetPath);
|
|
1053
1043
|
if (ctx.input.copyWithoutRender && ctx.input.copyWithoutTemplating) {
|
|
1054
1044
|
throw new errors.InputError(
|
|
@@ -1087,7 +1077,7 @@ function createFetchTemplateAction(options) {
|
|
|
1087
1077
|
await pluginScaffolderNode.fetchContents({
|
|
1088
1078
|
reader,
|
|
1089
1079
|
integrations,
|
|
1090
|
-
baseUrl:
|
|
1080
|
+
baseUrl: ctx.templateInfo?.baseUrl,
|
|
1091
1081
|
fetchUrl: ctx.input.url,
|
|
1092
1082
|
outputPath: templateDir,
|
|
1093
1083
|
token: ctx.input.token
|
|
@@ -1234,8 +1224,7 @@ const createFilesystemDeleteAction = () => {
|
|
|
1234
1224
|
},
|
|
1235
1225
|
supportsDryRun: true,
|
|
1236
1226
|
async handler(ctx) {
|
|
1237
|
-
|
|
1238
|
-
if (!Array.isArray((_a = ctx.input) == null ? void 0 : _a.files)) {
|
|
1227
|
+
if (!Array.isArray(ctx.input?.files)) {
|
|
1239
1228
|
throw new errors.InputError("files must be an Array");
|
|
1240
1229
|
}
|
|
1241
1230
|
for (const file of ctx.input.files) {
|
|
@@ -1312,8 +1301,7 @@ const createFilesystemRenameAction = () => {
|
|
|
1312
1301
|
},
|
|
1313
1302
|
supportsDryRun: true,
|
|
1314
1303
|
async handler(ctx) {
|
|
1315
|
-
|
|
1316
|
-
if (!Array.isArray((_a = ctx.input) == null ? void 0 : _a.files)) {
|
|
1304
|
+
if (!Array.isArray(ctx.input?.files)) {
|
|
1317
1305
|
throw new errors.InputError("files must be an Array");
|
|
1318
1306
|
}
|
|
1319
1307
|
for (const file of ctx.input.files) {
|
|
@@ -1327,7 +1315,7 @@ const createFilesystemRenameAction = () => {
|
|
|
1327
1315
|
const destFilepath = backendPluginApi.resolveSafeChildPath(ctx.workspacePath, file.to);
|
|
1328
1316
|
try {
|
|
1329
1317
|
await fs__default.default.move(sourceFilepath, destFilepath, {
|
|
1330
|
-
overwrite:
|
|
1318
|
+
overwrite: file.overwrite ?? false
|
|
1331
1319
|
});
|
|
1332
1320
|
ctx.logger.info(
|
|
1333
1321
|
`File ${sourceFilepath} renamed to ${destFilepath} successfully`
|
|
@@ -1467,16 +1455,8 @@ const createBuiltinActions = (options) => {
|
|
|
1467
1455
|
return actions;
|
|
1468
1456
|
};
|
|
1469
1457
|
|
|
1470
|
-
var __defProp$4 = Object.defineProperty;
|
|
1471
|
-
var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1472
|
-
var __publicField$4 = (obj, key, value) => {
|
|
1473
|
-
__defNormalProp$4(obj, key + "" , value);
|
|
1474
|
-
return value;
|
|
1475
|
-
};
|
|
1476
1458
|
class TemplateActionRegistry {
|
|
1477
|
-
|
|
1478
|
-
__publicField$4(this, "actions", /* @__PURE__ */ new Map());
|
|
1479
|
-
}
|
|
1459
|
+
actions = /* @__PURE__ */ new Map();
|
|
1480
1460
|
register(action) {
|
|
1481
1461
|
if (this.actions.has(action.id)) {
|
|
1482
1462
|
throw new errors.ConflictError(
|
|
@@ -1546,12 +1526,6 @@ const restoreWorkspace = async (path, buffer) => {
|
|
|
1546
1526
|
}
|
|
1547
1527
|
};
|
|
1548
1528
|
|
|
1549
|
-
var __defProp$3 = Object.defineProperty;
|
|
1550
|
-
var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1551
|
-
var __publicField$3 = (obj, key, value) => {
|
|
1552
|
-
__defNormalProp$3(obj, key + "" , value);
|
|
1553
|
-
return value;
|
|
1554
|
-
};
|
|
1555
1529
|
const migrationsDir = backendPluginApi.resolvePackagePath(
|
|
1556
1530
|
"@backstage/plugin-scaffolder-backend",
|
|
1557
1531
|
"migrations"
|
|
@@ -1572,10 +1546,7 @@ const parseSqlDateToIsoString = (input) => {
|
|
|
1572
1546
|
return input;
|
|
1573
1547
|
};
|
|
1574
1548
|
class DatabaseTaskStore {
|
|
1575
|
-
|
|
1576
|
-
__publicField$3(this, "db");
|
|
1577
|
-
this.db = client;
|
|
1578
|
-
}
|
|
1549
|
+
db;
|
|
1579
1550
|
static async create(options) {
|
|
1580
1551
|
const { database } = options;
|
|
1581
1552
|
const client = await this.getClient(database);
|
|
@@ -1583,9 +1554,8 @@ class DatabaseTaskStore {
|
|
|
1583
1554
|
return new DatabaseTaskStore(client);
|
|
1584
1555
|
}
|
|
1585
1556
|
isRecoverableTask(spec) {
|
|
1586
|
-
var _a, _b;
|
|
1587
1557
|
return ["startOver"].includes(
|
|
1588
|
-
|
|
1558
|
+
spec.EXPERIMENTAL_recovery?.EXPERIMENTAL_strategy ?? "none"
|
|
1589
1559
|
);
|
|
1590
1560
|
}
|
|
1591
1561
|
parseSpec({ spec, id }) {
|
|
@@ -1611,19 +1581,21 @@ class DatabaseTaskStore {
|
|
|
1611
1581
|
return database;
|
|
1612
1582
|
}
|
|
1613
1583
|
static async runMigrations(database, client) {
|
|
1614
|
-
var _a;
|
|
1615
1584
|
if (!isPluginDatabaseManager(database)) {
|
|
1616
1585
|
await client.migrate.latest({
|
|
1617
1586
|
directory: migrationsDir
|
|
1618
1587
|
});
|
|
1619
1588
|
return;
|
|
1620
1589
|
}
|
|
1621
|
-
if (!
|
|
1590
|
+
if (!database.migrations?.skip) {
|
|
1622
1591
|
await client.migrate.latest({
|
|
1623
1592
|
directory: migrationsDir
|
|
1624
1593
|
});
|
|
1625
1594
|
}
|
|
1626
1595
|
}
|
|
1596
|
+
constructor(client) {
|
|
1597
|
+
this.db = client;
|
|
1598
|
+
}
|
|
1627
1599
|
async list(options) {
|
|
1628
1600
|
const queryBuilder = this.db("tasks");
|
|
1629
1601
|
if (options.createdBy) {
|
|
@@ -1632,21 +1604,17 @@ class DatabaseTaskStore {
|
|
|
1632
1604
|
});
|
|
1633
1605
|
}
|
|
1634
1606
|
const results = await queryBuilder.orderBy("created_at", "desc").select();
|
|
1635
|
-
const tasks = results.map((result) => {
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
createdAt: parseSqlDateToIsoString(result.created_at)
|
|
1644
|
-
};
|
|
1645
|
-
});
|
|
1607
|
+
const tasks = results.map((result) => ({
|
|
1608
|
+
id: result.id,
|
|
1609
|
+
spec: JSON.parse(result.spec),
|
|
1610
|
+
status: result.status,
|
|
1611
|
+
createdBy: result.created_by ?? void 0,
|
|
1612
|
+
lastHeartbeatAt: parseSqlDateToIsoString(result.last_heartbeat_at),
|
|
1613
|
+
createdAt: parseSqlDateToIsoString(result.created_at)
|
|
1614
|
+
}));
|
|
1646
1615
|
return { tasks };
|
|
1647
1616
|
}
|
|
1648
1617
|
async getTask(taskId) {
|
|
1649
|
-
var _a;
|
|
1650
1618
|
const [result] = await this.db("tasks").where({ id: taskId }).select();
|
|
1651
1619
|
if (!result) {
|
|
1652
1620
|
throw new errors.NotFoundError(`No task with id '${taskId}' found`);
|
|
@@ -1661,7 +1629,7 @@ class DatabaseTaskStore {
|
|
|
1661
1629
|
status: result.status,
|
|
1662
1630
|
lastHeartbeatAt: parseSqlDateToIsoString(result.last_heartbeat_at),
|
|
1663
1631
|
createdAt: parseSqlDateToIsoString(result.created_at),
|
|
1664
|
-
createdBy:
|
|
1632
|
+
createdBy: result.created_by ?? void 0,
|
|
1665
1633
|
secrets,
|
|
1666
1634
|
state
|
|
1667
1635
|
};
|
|
@@ -1670,20 +1638,18 @@ class DatabaseTaskStore {
|
|
|
1670
1638
|
}
|
|
1671
1639
|
}
|
|
1672
1640
|
async createTask(options) {
|
|
1673
|
-
var _a;
|
|
1674
1641
|
const taskId = uuid.v4();
|
|
1675
1642
|
await this.db("tasks").insert({
|
|
1676
1643
|
id: taskId,
|
|
1677
1644
|
spec: JSON.stringify(options.spec),
|
|
1678
1645
|
secrets: options.secrets ? JSON.stringify(options.secrets) : void 0,
|
|
1679
|
-
created_by:
|
|
1646
|
+
created_by: options.createdBy ?? null,
|
|
1680
1647
|
status: "open"
|
|
1681
1648
|
});
|
|
1682
1649
|
return { taskId };
|
|
1683
1650
|
}
|
|
1684
1651
|
async claimTask() {
|
|
1685
1652
|
return this.db.transaction(async (tx) => {
|
|
1686
|
-
var _a;
|
|
1687
1653
|
const [task] = await tx("tasks").where({
|
|
1688
1654
|
status: "open"
|
|
1689
1655
|
}).limit(1).select();
|
|
@@ -1716,7 +1682,7 @@ class DatabaseTaskStore {
|
|
|
1716
1682
|
status: "processing",
|
|
1717
1683
|
lastHeartbeatAt: task.last_heartbeat_at,
|
|
1718
1684
|
createdAt: task.created_at,
|
|
1719
|
-
createdBy:
|
|
1685
|
+
createdBy: task.created_by ?? void 0,
|
|
1720
1686
|
secrets,
|
|
1721
1687
|
state: getState()
|
|
1722
1688
|
};
|
|
@@ -1845,7 +1811,7 @@ class DatabaseTaskStore {
|
|
|
1845
1811
|
const { taskId } = options;
|
|
1846
1812
|
const message = `This task was marked as stale as it exceeded its timeout`;
|
|
1847
1813
|
const statusStepEvents = (await this.listEvents({ taskId })).events.filter(
|
|
1848
|
-
({ body }) => body
|
|
1814
|
+
({ body }) => body?.stepId
|
|
1849
1815
|
);
|
|
1850
1816
|
const completedSteps = statusStepEvents.filter(
|
|
1851
1817
|
({ body: { status } }) => status === "failed" || status === "completed"
|
|
@@ -1898,7 +1864,6 @@ class DatabaseTaskStore {
|
|
|
1898
1864
|
const taskIdsToRecover = [];
|
|
1899
1865
|
const timeoutS = luxon.Duration.fromObject(options.timeout).as("seconds");
|
|
1900
1866
|
await this.db.transaction(async (tx) => {
|
|
1901
|
-
var _a, _b;
|
|
1902
1867
|
const heartbeatInterval = intervalFromNowTill(timeoutS, this.db);
|
|
1903
1868
|
const result = await tx("tasks").where("status", "processing").andWhere("last_heartbeat_at", "<=", heartbeatInterval).update(
|
|
1904
1869
|
{
|
|
@@ -1914,7 +1879,7 @@ class DatabaseTaskStore {
|
|
|
1914
1879
|
task_id: id,
|
|
1915
1880
|
event_type: "recovered",
|
|
1916
1881
|
body: JSON.stringify({
|
|
1917
|
-
recoverStrategy:
|
|
1882
|
+
recoverStrategy: taskSpec.EXPERIMENTAL_recovery?.EXPERIMENTAL_strategy ?? "none"
|
|
1918
1883
|
})
|
|
1919
1884
|
});
|
|
1920
1885
|
}
|
|
@@ -1927,20 +1892,19 @@ function isTruthy(value) {
|
|
|
1927
1892
|
return lodash.isArray(value) ? value.length > 0 : !!value;
|
|
1928
1893
|
}
|
|
1929
1894
|
function generateExampleOutput(schema) {
|
|
1930
|
-
var _a, _b;
|
|
1931
1895
|
const { examples } = schema;
|
|
1932
1896
|
if (examples && Array.isArray(examples)) {
|
|
1933
1897
|
return examples[0];
|
|
1934
1898
|
}
|
|
1935
1899
|
if (schema.type === "object") {
|
|
1936
1900
|
return Object.fromEntries(
|
|
1937
|
-
Object.entries(
|
|
1901
|
+
Object.entries(schema.properties ?? {}).map(([key, value]) => [
|
|
1938
1902
|
key,
|
|
1939
1903
|
generateExampleOutput(value)
|
|
1940
1904
|
])
|
|
1941
1905
|
);
|
|
1942
1906
|
} else if (schema.type === "array") {
|
|
1943
|
-
const [firstSchema] =
|
|
1907
|
+
const [firstSchema] = [schema.items]?.flat();
|
|
1944
1908
|
if (firstSchema) {
|
|
1945
1909
|
return [generateExampleOutput(firstSchema)];
|
|
1946
1910
|
}
|
|
@@ -1955,18 +1919,12 @@ function generateExampleOutput(schema) {
|
|
|
1955
1919
|
return "<unknown>";
|
|
1956
1920
|
}
|
|
1957
1921
|
const readDuration$1 = (config$1, key, defaultValue) => {
|
|
1958
|
-
if (config$1
|
|
1922
|
+
if (config$1?.has(key)) {
|
|
1959
1923
|
return config.readDurationFromConfig(config$1, { key });
|
|
1960
1924
|
}
|
|
1961
1925
|
return defaultValue;
|
|
1962
1926
|
};
|
|
1963
1927
|
|
|
1964
|
-
var __defProp$2 = Object.defineProperty;
|
|
1965
|
-
var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1966
|
-
var __publicField$2 = (obj, key, value) => {
|
|
1967
|
-
__defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1968
|
-
return value;
|
|
1969
|
-
};
|
|
1970
1928
|
class TaskManager {
|
|
1971
1929
|
// Runs heartbeat internally
|
|
1972
1930
|
constructor(task, storage, signal, logger, auth, config) {
|
|
@@ -1976,9 +1934,9 @@ class TaskManager {
|
|
|
1976
1934
|
this.logger = logger;
|
|
1977
1935
|
this.auth = auth;
|
|
1978
1936
|
this.config = config;
|
|
1979
|
-
__publicField$2(this, "isDone", false);
|
|
1980
|
-
__publicField$2(this, "heartbeatTimeoutId");
|
|
1981
1937
|
}
|
|
1938
|
+
isDone = false;
|
|
1939
|
+
heartbeatTimeoutId;
|
|
1982
1940
|
static create(task, storage, abortSignal, logger, auth, config) {
|
|
1983
1941
|
const agent = new TaskManager(
|
|
1984
1942
|
task,
|
|
@@ -2007,9 +1965,8 @@ class TaskManager {
|
|
|
2007
1965
|
return this.task.taskId;
|
|
2008
1966
|
}
|
|
2009
1967
|
async rehydrateWorkspace(options) {
|
|
2010
|
-
var _a, _b;
|
|
2011
1968
|
if (this.isWorkspaceSerializationEnabled()) {
|
|
2012
|
-
|
|
1969
|
+
this.storage.rehydrateWorkspace?.(options);
|
|
2013
1970
|
}
|
|
2014
1971
|
}
|
|
2015
1972
|
get done() {
|
|
@@ -2022,35 +1979,31 @@ class TaskManager {
|
|
|
2022
1979
|
});
|
|
2023
1980
|
}
|
|
2024
1981
|
async getTaskState() {
|
|
2025
|
-
|
|
2026
|
-
return (_b = (_a = this.storage).getTaskState) == null ? void 0 : _b.call(_a, { taskId: this.task.taskId });
|
|
1982
|
+
return this.storage.getTaskState?.({ taskId: this.task.taskId });
|
|
2027
1983
|
}
|
|
2028
1984
|
async updateCheckpoint(options) {
|
|
2029
|
-
var _a, _b;
|
|
2030
1985
|
const { key, ...value } = options;
|
|
2031
1986
|
if (this.task.state) {
|
|
2032
1987
|
this.task.state.checkpoints[key] = value;
|
|
2033
1988
|
} else {
|
|
2034
1989
|
this.task.state = { checkpoints: { [key]: value } };
|
|
2035
1990
|
}
|
|
2036
|
-
await
|
|
1991
|
+
await this.storage.saveTaskState?.({
|
|
2037
1992
|
taskId: this.task.taskId,
|
|
2038
1993
|
state: this.task.state
|
|
2039
|
-
})
|
|
1994
|
+
});
|
|
2040
1995
|
}
|
|
2041
1996
|
async serializeWorkspace(options) {
|
|
2042
|
-
var _a, _b;
|
|
2043
1997
|
if (this.isWorkspaceSerializationEnabled()) {
|
|
2044
|
-
await
|
|
1998
|
+
await this.storage.serializeWorkspace?.({
|
|
2045
1999
|
path: options.path,
|
|
2046
2000
|
taskId: this.task.taskId
|
|
2047
|
-
})
|
|
2001
|
+
});
|
|
2048
2002
|
}
|
|
2049
2003
|
}
|
|
2050
2004
|
async cleanWorkspace() {
|
|
2051
|
-
var _a, _b;
|
|
2052
2005
|
if (this.isWorkspaceSerializationEnabled()) {
|
|
2053
|
-
await
|
|
2006
|
+
await this.storage.cleanWorkspace?.({ taskId: this.task.taskId });
|
|
2054
2007
|
}
|
|
2055
2008
|
}
|
|
2056
2009
|
async complete(result, metadata) {
|
|
@@ -2082,10 +2035,9 @@ class TaskManager {
|
|
|
2082
2035
|
}, 1e3);
|
|
2083
2036
|
}
|
|
2084
2037
|
isWorkspaceSerializationEnabled() {
|
|
2085
|
-
|
|
2086
|
-
return (_b = (_a = this.config) == null ? void 0 : _a.getOptionalBoolean(
|
|
2038
|
+
return this.config?.getOptionalBoolean(
|
|
2087
2039
|
"scaffolder.EXPERIMENTAL_workspaceSerialization"
|
|
2088
|
-
)
|
|
2040
|
+
) ?? false;
|
|
2089
2041
|
}
|
|
2090
2042
|
async getInitiatorCredentials() {
|
|
2091
2043
|
const secrets = this.task.secrets;
|
|
@@ -2114,7 +2066,6 @@ class StorageTaskBroker {
|
|
|
2114
2066
|
this.logger = logger;
|
|
2115
2067
|
this.config = config;
|
|
2116
2068
|
this.auth = auth;
|
|
2117
|
-
__publicField$2(this, "deferredDispatch", defer());
|
|
2118
2069
|
}
|
|
2119
2070
|
async list(options) {
|
|
2120
2071
|
if (!this.storage.list) {
|
|
@@ -2122,8 +2073,9 @@ class StorageTaskBroker {
|
|
|
2122
2073
|
"TaskStore does not implement the list method. Please implement the list method to be able to list tasks"
|
|
2123
2074
|
);
|
|
2124
2075
|
}
|
|
2125
|
-
return await this.storage.list({ createdBy: options
|
|
2076
|
+
return await this.storage.list({ createdBy: options?.createdBy });
|
|
2126
2077
|
}
|
|
2078
|
+
deferredDispatch = defer();
|
|
2127
2079
|
async registerCancellable(taskId, abortController) {
|
|
2128
2080
|
let shouldUnsubscribe = false;
|
|
2129
2081
|
const subscription = this.event$({ taskId, after: void 0 }).subscribe({
|
|
@@ -2147,10 +2099,9 @@ class StorageTaskBroker {
|
|
|
2147
2099
|
});
|
|
2148
2100
|
}
|
|
2149
2101
|
async recoverTasks() {
|
|
2150
|
-
|
|
2151
|
-
const enabled = (_a = this.config && this.config.getOptionalBoolean(
|
|
2102
|
+
const enabled = (this.config && this.config.getOptionalBoolean(
|
|
2152
2103
|
"scaffolder.EXPERIMENTAL_recoverTasks"
|
|
2153
|
-
))
|
|
2104
|
+
)) ?? false;
|
|
2154
2105
|
if (enabled) {
|
|
2155
2106
|
const defaultTimeout = { seconds: 30 };
|
|
2156
2107
|
const timeout = readDuration$1(
|
|
@@ -2158,9 +2109,9 @@ class StorageTaskBroker {
|
|
|
2158
2109
|
"scaffolder.EXPERIMENTAL_recoverTasksTimeout",
|
|
2159
2110
|
defaultTimeout
|
|
2160
2111
|
);
|
|
2161
|
-
const { ids: recoveredTaskIds } =
|
|
2112
|
+
const { ids: recoveredTaskIds } = await this.storage.recoverTasks?.({
|
|
2162
2113
|
timeout
|
|
2163
|
-
})
|
|
2114
|
+
}) ?? { ids: [] };
|
|
2164
2115
|
if (recoveredTaskIds.length > 0) {
|
|
2165
2116
|
this.signalDispatch();
|
|
2166
2117
|
}
|
|
@@ -2262,17 +2213,16 @@ class StorageTaskBroker {
|
|
|
2262
2213
|
this.deferredDispatch = defer();
|
|
2263
2214
|
}
|
|
2264
2215
|
async cancel(taskId) {
|
|
2265
|
-
var _a, _b;
|
|
2266
2216
|
const { events } = await this.storage.listEvents({ taskId });
|
|
2267
|
-
const currentStepId = events.length > 0 ? events.filter(({ body }) => body
|
|
2268
|
-
await
|
|
2217
|
+
const currentStepId = events.length > 0 ? events.filter(({ body }) => body?.stepId).reduce((prev, curr) => prev.id > curr.id ? prev : curr).body.stepId : 0;
|
|
2218
|
+
await this.storage.cancelTask?.({
|
|
2269
2219
|
taskId,
|
|
2270
2220
|
body: {
|
|
2271
2221
|
message: `Step ${currentStepId} has been cancelled.`,
|
|
2272
2222
|
stepId: currentStepId,
|
|
2273
2223
|
status: "cancelled"
|
|
2274
2224
|
}
|
|
2275
|
-
})
|
|
2225
|
+
});
|
|
2276
2226
|
}
|
|
2277
2227
|
}
|
|
2278
2228
|
|
|
@@ -2302,8 +2252,7 @@ const hasTag = createTemplatePermissionRule({
|
|
|
2302
2252
|
tag: zod.z.string().describe("Name of the tag to match on")
|
|
2303
2253
|
}),
|
|
2304
2254
|
apply: (resource, { tag }) => {
|
|
2305
|
-
|
|
2306
|
-
return (_c = (_b = (_a = resource["backstage:permissions"]) == null ? void 0 : _a.tags) == null ? void 0 : _b.includes(tag)) != null ? _c : false;
|
|
2255
|
+
return resource["backstage:permissions"]?.tags?.includes(tag) ?? false;
|
|
2307
2256
|
},
|
|
2308
2257
|
toQuery: () => ({})
|
|
2309
2258
|
});
|
|
@@ -2374,25 +2323,6 @@ const scaffolderActionRules = {
|
|
|
2374
2323
|
hasStringProperty
|
|
2375
2324
|
};
|
|
2376
2325
|
|
|
2377
|
-
var __accessCheck = (obj, member, msg) => {
|
|
2378
|
-
if (!member.has(obj))
|
|
2379
|
-
throw TypeError("Cannot " + msg);
|
|
2380
|
-
};
|
|
2381
|
-
var __privateGet = (obj, member, getter) => {
|
|
2382
|
-
__accessCheck(obj, member, "read from private field");
|
|
2383
|
-
return member.get(obj);
|
|
2384
|
-
};
|
|
2385
|
-
var __privateAdd = (obj, member, value) => {
|
|
2386
|
-
if (member.has(obj))
|
|
2387
|
-
throw TypeError("Cannot add the same private member more than once");
|
|
2388
|
-
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
2389
|
-
};
|
|
2390
|
-
var __privateSet = (obj, member, value, setter) => {
|
|
2391
|
-
__accessCheck(obj, member, "write to private field");
|
|
2392
|
-
member.set(obj, value);
|
|
2393
|
-
return value;
|
|
2394
|
-
};
|
|
2395
|
-
var _winston, _addRedactions;
|
|
2396
2326
|
const escapeRegExp = (text) => {
|
|
2397
2327
|
return text.replace(/[.*+?^${}(\)|[\]\\]/g, "\\$&");
|
|
2398
2328
|
};
|
|
@@ -2431,28 +2361,23 @@ class BackstageLoggerTransport extends Transport__default.default {
|
|
|
2431
2361
|
callback();
|
|
2432
2362
|
}
|
|
2433
2363
|
}
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
__privateAdd(this, _addRedactions, void 0);
|
|
2438
|
-
__privateSet(this, _winston, winston);
|
|
2439
|
-
__privateSet(this, _addRedactions, addRedactions);
|
|
2440
|
-
}
|
|
2364
|
+
class WinstonLogger {
|
|
2365
|
+
#winston;
|
|
2366
|
+
#addRedactions;
|
|
2441
2367
|
/**
|
|
2442
2368
|
* Creates a {@link WinstonLogger} instance.
|
|
2443
2369
|
*/
|
|
2444
2370
|
static create(options) {
|
|
2445
|
-
|
|
2446
|
-
const redacter = _WinstonLogger.redacter();
|
|
2371
|
+
const redacter = WinstonLogger.redacter();
|
|
2447
2372
|
let logger = winston.createLogger({
|
|
2448
2373
|
level: options.level,
|
|
2449
2374
|
format: winston.format.combine(options.format, redacter.format),
|
|
2450
|
-
transports:
|
|
2375
|
+
transports: options.transports ?? new winston.transports.Console()
|
|
2451
2376
|
});
|
|
2452
2377
|
if (options.meta) {
|
|
2453
2378
|
logger = logger.child(options.meta);
|
|
2454
2379
|
}
|
|
2455
|
-
return new
|
|
2380
|
+
return new WinstonLogger(logger, redacter.add);
|
|
2456
2381
|
}
|
|
2457
2382
|
/**
|
|
2458
2383
|
* Creates a winston log formatter for redacting secrets.
|
|
@@ -2462,11 +2387,10 @@ const _WinstonLogger = class _WinstonLogger {
|
|
|
2462
2387
|
let redactionPattern = void 0;
|
|
2463
2388
|
return {
|
|
2464
2389
|
format: winston.format((obj) => {
|
|
2465
|
-
var _a, _b;
|
|
2466
2390
|
if (!redactionPattern || !obj) {
|
|
2467
2391
|
return obj;
|
|
2468
2392
|
}
|
|
2469
|
-
obj[tripleBeam.MESSAGE] =
|
|
2393
|
+
obj[tripleBeam.MESSAGE] = obj[tripleBeam.MESSAGE]?.replace?.(redactionPattern, "***");
|
|
2470
2394
|
return obj;
|
|
2471
2395
|
})(),
|
|
2472
2396
|
add(newRedactions) {
|
|
@@ -2518,36 +2442,30 @@ const _WinstonLogger = class _WinstonLogger {
|
|
|
2518
2442
|
})
|
|
2519
2443
|
);
|
|
2520
2444
|
}
|
|
2445
|
+
constructor(winston, addRedactions) {
|
|
2446
|
+
this.#winston = winston;
|
|
2447
|
+
this.#addRedactions = addRedactions;
|
|
2448
|
+
}
|
|
2521
2449
|
error(message, meta) {
|
|
2522
|
-
|
|
2450
|
+
this.#winston.error(message, meta);
|
|
2523
2451
|
}
|
|
2524
2452
|
warn(message, meta) {
|
|
2525
|
-
|
|
2453
|
+
this.#winston.warn(message, meta);
|
|
2526
2454
|
}
|
|
2527
2455
|
info(message, meta) {
|
|
2528
|
-
|
|
2456
|
+
this.#winston.info(message, meta);
|
|
2529
2457
|
}
|
|
2530
2458
|
debug(message, meta) {
|
|
2531
|
-
|
|
2459
|
+
this.#winston.debug(message, meta);
|
|
2532
2460
|
}
|
|
2533
2461
|
child(meta) {
|
|
2534
|
-
return new
|
|
2462
|
+
return new WinstonLogger(this.#winston.child(meta));
|
|
2535
2463
|
}
|
|
2536
2464
|
addRedactions(redactions) {
|
|
2537
|
-
|
|
2538
|
-
(_a = __privateGet(this, _addRedactions)) == null ? void 0 : _a.call(this, redactions);
|
|
2465
|
+
this.#addRedactions?.(redactions);
|
|
2539
2466
|
}
|
|
2540
|
-
}
|
|
2541
|
-
_winston = new WeakMap();
|
|
2542
|
-
_addRedactions = new WeakMap();
|
|
2543
|
-
let WinstonLogger = _WinstonLogger;
|
|
2467
|
+
}
|
|
2544
2468
|
|
|
2545
|
-
var __defProp$1 = Object.defineProperty;
|
|
2546
|
-
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
2547
|
-
var __publicField$1 = (obj, key, value) => {
|
|
2548
|
-
__defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
2549
|
-
return value;
|
|
2550
|
-
};
|
|
2551
2469
|
const isValidTaskSpec = (taskSpec) => {
|
|
2552
2470
|
return taskSpec.apiVersion === "scaffolder.backstage.io/v1beta3";
|
|
2553
2471
|
};
|
|
@@ -2556,7 +2474,6 @@ const createStepLogger = ({
|
|
|
2556
2474
|
step,
|
|
2557
2475
|
rootLogger
|
|
2558
2476
|
}) => {
|
|
2559
|
-
var _a;
|
|
2560
2477
|
const taskLogger = WinstonLogger.create({
|
|
2561
2478
|
level: process.env.LOG_LEVEL || "info",
|
|
2562
2479
|
format: winston__namespace.format.combine(
|
|
@@ -2565,11 +2482,11 @@ const createStepLogger = ({
|
|
|
2565
2482
|
),
|
|
2566
2483
|
transports: [new BackstageLoggerTransport(rootLogger, task, step.id)]
|
|
2567
2484
|
});
|
|
2568
|
-
taskLogger.addRedactions(Object.values(
|
|
2485
|
+
taskLogger.addRedactions(Object.values(task.secrets ?? {}));
|
|
2569
2486
|
const streamLogger = new stream.PassThrough();
|
|
2570
2487
|
streamLogger.on("data", async (data) => {
|
|
2571
2488
|
const message = data.toString().trim();
|
|
2572
|
-
if (
|
|
2489
|
+
if (message?.length > 1) {
|
|
2573
2490
|
taskLogger.info(message);
|
|
2574
2491
|
}
|
|
2575
2492
|
});
|
|
@@ -2581,14 +2498,13 @@ const isActionAuthorized = pluginPermissionNode.createConditionAuthorizer(
|
|
|
2581
2498
|
class NunjucksWorkflowRunner {
|
|
2582
2499
|
constructor(options) {
|
|
2583
2500
|
this.options = options;
|
|
2584
|
-
__publicField$1(this, "defaultTemplateFilters");
|
|
2585
|
-
__publicField$1(this, "tracker", scaffoldingTracker());
|
|
2586
2501
|
this.defaultTemplateFilters = createDefaultFilters({
|
|
2587
2502
|
integrations: this.options.integrations
|
|
2588
2503
|
});
|
|
2589
2504
|
}
|
|
2505
|
+
defaultTemplateFilters;
|
|
2506
|
+
tracker = scaffoldingTracker();
|
|
2590
2507
|
isSingleTemplateString(input) {
|
|
2591
|
-
var _a, _b;
|
|
2592
2508
|
const { parser, nodes } = nunjucks__default.default;
|
|
2593
2509
|
const parsed = parser.parse(
|
|
2594
2510
|
input,
|
|
@@ -2601,7 +2517,7 @@ class NunjucksWorkflowRunner {
|
|
|
2601
2517
|
}
|
|
2602
2518
|
}
|
|
2603
2519
|
);
|
|
2604
|
-
return parsed.children.length === 1 && !(
|
|
2520
|
+
return parsed.children.length === 1 && !(parsed.children[0]?.children?.[0] instanceof nodes.TemplateData);
|
|
2605
2521
|
}
|
|
2606
2522
|
render(input, context, renderTemplate) {
|
|
2607
2523
|
return JSON.parse(JSON.stringify(input), (_key, value) => {
|
|
@@ -2637,7 +2553,6 @@ class NunjucksWorkflowRunner {
|
|
|
2637
2553
|
});
|
|
2638
2554
|
}
|
|
2639
2555
|
async executeStep(task, step, context, renderTemplate, taskTrack, workspacePath, decision) {
|
|
2640
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
2641
2556
|
const stepTrack = await this.tracker.stepStart(task, step);
|
|
2642
2557
|
if (task.cancelSignal.aborted) {
|
|
2643
2558
|
throw new Error(`Step ${step.name} has been cancelled.`);
|
|
@@ -2658,19 +2573,16 @@ class NunjucksWorkflowRunner {
|
|
|
2658
2573
|
});
|
|
2659
2574
|
if (task.isDryRun) {
|
|
2660
2575
|
const redactedSecrets = Object.fromEntries(
|
|
2661
|
-
Object.entries(
|
|
2662
|
-
secret[0],
|
|
2663
|
-
"[REDACTED]"
|
|
2664
|
-
])
|
|
2576
|
+
Object.entries(task.secrets ?? {}).map((secret) => [secret[0], "***"])
|
|
2665
2577
|
);
|
|
2666
|
-
const debugInput = (
|
|
2578
|
+
const debugInput = (step.input && this.render(
|
|
2667
2579
|
step.input,
|
|
2668
2580
|
{
|
|
2669
2581
|
...context,
|
|
2670
2582
|
secrets: redactedSecrets
|
|
2671
2583
|
},
|
|
2672
2584
|
renderTemplate
|
|
2673
|
-
))
|
|
2585
|
+
)) ?? {};
|
|
2674
2586
|
taskLogger.info(
|
|
2675
2587
|
`Running ${action.id} in dry-run mode with inputs (secrets redacted): ${JSON.stringify(
|
|
2676
2588
|
debugInput,
|
|
@@ -2680,7 +2592,7 @@ class NunjucksWorkflowRunner {
|
|
|
2680
2592
|
);
|
|
2681
2593
|
if (!action.supportsDryRun) {
|
|
2682
2594
|
await taskTrack.skipDryRun(step, action);
|
|
2683
|
-
const outputSchema =
|
|
2595
|
+
const outputSchema = action.schema?.output;
|
|
2684
2596
|
if (outputSchema) {
|
|
2685
2597
|
context.steps[step.id] = {
|
|
2686
2598
|
output: generateExampleOutput(outputSchema)
|
|
@@ -2695,21 +2607,18 @@ class NunjucksWorkflowRunner {
|
|
|
2695
2607
|
([key, value]) => ({
|
|
2696
2608
|
each: { key, value }
|
|
2697
2609
|
})
|
|
2698
|
-
) : [{}]).map((i) => {
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
) : {}
|
|
2708
|
-
};
|
|
2709
|
-
});
|
|
2610
|
+
) : [{}]).map((i) => ({
|
|
2611
|
+
...i,
|
|
2612
|
+
// Secrets are only passed when templating the input to actions for security reasons
|
|
2613
|
+
input: step.input ? this.render(
|
|
2614
|
+
step.input,
|
|
2615
|
+
{ ...context, secrets: task.secrets ?? {}, ...i },
|
|
2616
|
+
renderTemplate
|
|
2617
|
+
) : {}
|
|
2618
|
+
}));
|
|
2710
2619
|
for (const iteration of iterations) {
|
|
2711
2620
|
const actionId = `${action.id}${iteration.each ? `[${iteration.each.key}]` : ""}`;
|
|
2712
|
-
if (
|
|
2621
|
+
if (action.schema?.input) {
|
|
2713
2622
|
const validateResult = jsonschema.validate(
|
|
2714
2623
|
iteration.input,
|
|
2715
2624
|
action.schema.input
|
|
@@ -2736,7 +2645,7 @@ class NunjucksWorkflowRunner {
|
|
|
2736
2645
|
}
|
|
2737
2646
|
const tmpDirs = new Array();
|
|
2738
2647
|
const stepOutput = {};
|
|
2739
|
-
const prevTaskState = await
|
|
2648
|
+
const prevTaskState = await task.getTaskState?.();
|
|
2740
2649
|
for (const iteration of iterations) {
|
|
2741
2650
|
if (iteration.each) {
|
|
2742
2651
|
taskLogger.info(
|
|
@@ -2749,25 +2658,24 @@ class NunjucksWorkflowRunner {
|
|
|
2749
2658
|
}
|
|
2750
2659
|
await action.handler({
|
|
2751
2660
|
input: iteration.input,
|
|
2752
|
-
secrets:
|
|
2661
|
+
secrets: task.secrets ?? {},
|
|
2753
2662
|
// TODO(blam): move to LoggerService and away from Winston
|
|
2754
2663
|
logger: backendCommon.loggerToWinstonLogger(taskLogger),
|
|
2755
2664
|
logStream: streamLogger,
|
|
2756
2665
|
workspacePath,
|
|
2757
2666
|
async checkpoint(keySuffix, fn) {
|
|
2758
|
-
var _a2, _b2, _c2, _d2, _e2;
|
|
2759
2667
|
const key = `v1.task.checkpoint.${keySuffix}`;
|
|
2760
2668
|
try {
|
|
2761
2669
|
let prevValue;
|
|
2762
2670
|
if (prevTaskState) {
|
|
2763
|
-
const prevState =
|
|
2671
|
+
const prevState = prevTaskState.state?.checkpoints?.[key];
|
|
2764
2672
|
if (prevState && prevState.status === "success") {
|
|
2765
2673
|
prevValue = prevState.value;
|
|
2766
2674
|
}
|
|
2767
2675
|
}
|
|
2768
2676
|
const value = prevValue ? prevValue : await fn();
|
|
2769
2677
|
if (!prevValue) {
|
|
2770
|
-
|
|
2678
|
+
task.updateCheckpoint?.({
|
|
2771
2679
|
key,
|
|
2772
2680
|
status: "success",
|
|
2773
2681
|
value
|
|
@@ -2775,14 +2683,14 @@ class NunjucksWorkflowRunner {
|
|
|
2775
2683
|
}
|
|
2776
2684
|
return value;
|
|
2777
2685
|
} catch (err) {
|
|
2778
|
-
|
|
2686
|
+
task.updateCheckpoint?.({
|
|
2779
2687
|
key,
|
|
2780
2688
|
status: "failed",
|
|
2781
2689
|
reason: errors.stringifyError(err)
|
|
2782
2690
|
});
|
|
2783
2691
|
throw err;
|
|
2784
2692
|
} finally {
|
|
2785
|
-
await
|
|
2693
|
+
await task.serializeWorkspace?.({ path: workspacePath });
|
|
2786
2694
|
}
|
|
2787
2695
|
},
|
|
2788
2696
|
createTemporaryDirectory: async () => {
|
|
@@ -2814,18 +2722,17 @@ class NunjucksWorkflowRunner {
|
|
|
2814
2722
|
if (task.cancelSignal.aborted) {
|
|
2815
2723
|
throw new Error(`Step ${step.name} has been cancelled.`);
|
|
2816
2724
|
}
|
|
2817
|
-
await
|
|
2725
|
+
await task.cleanWorkspace?.();
|
|
2818
2726
|
await stepTrack.markSuccessful();
|
|
2819
2727
|
} catch (err) {
|
|
2820
2728
|
await taskTrack.markFailed(step, err);
|
|
2821
2729
|
await stepTrack.markFailed();
|
|
2822
2730
|
throw err;
|
|
2823
2731
|
} finally {
|
|
2824
|
-
await
|
|
2732
|
+
await task.serializeWorkspace?.({ path: workspacePath });
|
|
2825
2733
|
}
|
|
2826
2734
|
}
|
|
2827
2735
|
async execute(task) {
|
|
2828
|
-
var _a;
|
|
2829
2736
|
if (!isValidTaskSpec(task.spec)) {
|
|
2830
2737
|
throw new errors.InputError(
|
|
2831
2738
|
"Wrong template version executed with the workflow engine"
|
|
@@ -2842,7 +2749,7 @@ class NunjucksWorkflowRunner {
|
|
|
2842
2749
|
templateGlobals: additionalTemplateGlobals
|
|
2843
2750
|
});
|
|
2844
2751
|
try {
|
|
2845
|
-
await
|
|
2752
|
+
await task.rehydrateWorkspace?.({ taskId, targetPath: workspacePath });
|
|
2846
2753
|
const taskTrack = await this.tracker.taskStart(task);
|
|
2847
2754
|
await fs__default.default.ensureDir(workspacePath);
|
|
2848
2755
|
const context = {
|
|
@@ -2897,10 +2804,9 @@ function scaffoldingTracker() {
|
|
|
2897
2804
|
labelNames: ["template", "step", "result"]
|
|
2898
2805
|
});
|
|
2899
2806
|
async function taskStart(task) {
|
|
2900
|
-
var _a, _b;
|
|
2901
2807
|
await task.emitLog(`Starting up task with ${task.spec.steps.length} steps`);
|
|
2902
|
-
const template =
|
|
2903
|
-
const user =
|
|
2808
|
+
const template = task.spec.templateInfo?.entityRef || "";
|
|
2809
|
+
const user = task.spec.user?.ref || "";
|
|
2904
2810
|
const taskTimer = taskDuration.startTimer({
|
|
2905
2811
|
template
|
|
2906
2812
|
});
|
|
@@ -2950,12 +2856,11 @@ function scaffoldingTracker() {
|
|
|
2950
2856
|
};
|
|
2951
2857
|
}
|
|
2952
2858
|
async function stepStart(task, step) {
|
|
2953
|
-
var _a;
|
|
2954
2859
|
await task.emitLog(`Beginning step ${step.name}`, {
|
|
2955
2860
|
stepId: step.id,
|
|
2956
2861
|
status: "processing"
|
|
2957
2862
|
});
|
|
2958
|
-
const template =
|
|
2863
|
+
const template = task.spec.templateInfo?.entityRef || "";
|
|
2959
2864
|
const stepTimer = stepDuration.startTimer({
|
|
2960
2865
|
template,
|
|
2961
2866
|
step: step.name
|
|
@@ -3008,24 +2913,18 @@ function scaffoldingTracker() {
|
|
|
3008
2913
|
};
|
|
3009
2914
|
}
|
|
3010
2915
|
|
|
3011
|
-
var __defProp = Object.defineProperty;
|
|
3012
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3013
|
-
var __publicField = (obj, key, value) => {
|
|
3014
|
-
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
3015
|
-
return value;
|
|
3016
|
-
};
|
|
3017
2916
|
class TaskWorker {
|
|
3018
2917
|
constructor(options) {
|
|
3019
2918
|
this.options = options;
|
|
3020
|
-
__publicField(this, "taskQueue");
|
|
3021
|
-
__publicField(this, "logger");
|
|
3022
|
-
__publicField(this, "stopWorkers");
|
|
3023
2919
|
this.stopWorkers = false;
|
|
3024
2920
|
this.logger = options.logger;
|
|
3025
2921
|
this.taskQueue = new PQueue__default.default({
|
|
3026
2922
|
concurrency: options.concurrentTasksLimit
|
|
3027
2923
|
});
|
|
3028
2924
|
}
|
|
2925
|
+
taskQueue;
|
|
2926
|
+
logger;
|
|
2927
|
+
stopWorkers;
|
|
3029
2928
|
static async create(options) {
|
|
3030
2929
|
const {
|
|
3031
2930
|
taskBroker,
|
|
@@ -3056,11 +2955,10 @@ class TaskWorker {
|
|
|
3056
2955
|
});
|
|
3057
2956
|
}
|
|
3058
2957
|
async recoverTasks() {
|
|
3059
|
-
var _a, _b, _c;
|
|
3060
2958
|
try {
|
|
3061
|
-
await
|
|
2959
|
+
await this.options.taskBroker.recoverTasks?.();
|
|
3062
2960
|
} catch (err) {
|
|
3063
|
-
|
|
2961
|
+
this.logger?.error(errors.stringifyError(err));
|
|
3064
2962
|
}
|
|
3065
2963
|
}
|
|
3066
2964
|
start() {
|
|
@@ -3182,7 +3080,7 @@ function createDryRunner(options) {
|
|
|
3182
3080
|
getWorkspaceName: async () => `dry-run-${dryRunId}`,
|
|
3183
3081
|
cancelSignal: abortSignal,
|
|
3184
3082
|
async emitLog(message, logMetadata) {
|
|
3185
|
-
if (
|
|
3083
|
+
if (logMetadata?.stepId === dryRunId) {
|
|
3186
3084
|
return;
|
|
3187
3085
|
}
|
|
3188
3086
|
log.push({
|
|
@@ -3229,10 +3127,9 @@ async function getWorkingDirectory(config, logger) {
|
|
|
3229
3127
|
return workingDirectory;
|
|
3230
3128
|
}
|
|
3231
3129
|
function getEntityBaseUrl(entity) {
|
|
3232
|
-
|
|
3233
|
-
let location = (_a = entity.metadata.annotations) == null ? void 0 : _a[catalogModel.ANNOTATION_SOURCE_LOCATION];
|
|
3130
|
+
let location = entity.metadata.annotations?.[catalogModel.ANNOTATION_SOURCE_LOCATION];
|
|
3234
3131
|
if (!location) {
|
|
3235
|
-
location =
|
|
3132
|
+
location = entity.metadata.annotations?.[catalogModel.ANNOTATION_LOCATION];
|
|
3236
3133
|
}
|
|
3237
3134
|
if (!location) {
|
|
3238
3135
|
return void 0;
|
|
@@ -3259,6 +3156,24 @@ async function findTemplate(options) {
|
|
|
3259
3156
|
return template;
|
|
3260
3157
|
}
|
|
3261
3158
|
|
|
3159
|
+
async function checkPermission(options) {
|
|
3160
|
+
const { permissions, permissionService, credentials } = options;
|
|
3161
|
+
if (permissionService) {
|
|
3162
|
+
const permissionRequest = permissions.map((permission) => ({
|
|
3163
|
+
permission
|
|
3164
|
+
}));
|
|
3165
|
+
const authorizationResponses = await permissionService.authorize(
|
|
3166
|
+
permissionRequest,
|
|
3167
|
+
{ credentials }
|
|
3168
|
+
);
|
|
3169
|
+
for (const response of authorizationResponses) {
|
|
3170
|
+
if (response.result === pluginPermissionCommon.AuthorizeResult.DENY) {
|
|
3171
|
+
throw new errors.NotAllowedError();
|
|
3172
|
+
}
|
|
3173
|
+
}
|
|
3174
|
+
}
|
|
3175
|
+
}
|
|
3176
|
+
|
|
3262
3177
|
function isTemplatePermissionRuleInput(permissionRule) {
|
|
3263
3178
|
return permissionRule.resourceType === alpha.RESOURCE_TYPE_SCAFFOLDER_TEMPLATE;
|
|
3264
3179
|
}
|
|
@@ -3271,14 +3186,13 @@ function isSupportedTemplate(entity) {
|
|
|
3271
3186
|
function buildDefaultIdentityClient(options) {
|
|
3272
3187
|
return {
|
|
3273
3188
|
getIdentity: async ({ request }) => {
|
|
3274
|
-
var _a;
|
|
3275
3189
|
const header = request.headers.authorization;
|
|
3276
3190
|
const { logger } = options;
|
|
3277
3191
|
if (!header) {
|
|
3278
3192
|
return void 0;
|
|
3279
3193
|
}
|
|
3280
3194
|
try {
|
|
3281
|
-
const token =
|
|
3195
|
+
const token = header.match(/^Bearer\s(\S+\.\S+\.\S+)$/i)?.[1];
|
|
3282
3196
|
if (!token) {
|
|
3283
3197
|
throw new TypeError("Expected Bearer with JWT");
|
|
3284
3198
|
}
|
|
@@ -3319,7 +3233,6 @@ const readDuration = (config$1, key, defaultValue) => {
|
|
|
3319
3233
|
return defaultValue;
|
|
3320
3234
|
};
|
|
3321
3235
|
async function createRouter(options) {
|
|
3322
|
-
var _a;
|
|
3323
3236
|
const router = Router__default.default();
|
|
3324
3237
|
router.use(express__default.default.json({ limit: "10MB" }));
|
|
3325
3238
|
const {
|
|
@@ -3343,7 +3256,7 @@ async function createRouter(options) {
|
|
|
3343
3256
|
identity,
|
|
3344
3257
|
discovery
|
|
3345
3258
|
});
|
|
3346
|
-
const concurrentTasksLimit =
|
|
3259
|
+
const concurrentTasksLimit = options.concurrentTasksLimit ?? options.config.getOptionalNumber("scaffolder.concurrentTasksLimit");
|
|
3347
3260
|
const logger = parentLogger.child({ plugin: "scaffolder" });
|
|
3348
3261
|
const workingDirectory = await getWorkingDirectory(config, logger);
|
|
3349
3262
|
const integrations = integration.ScmIntegrations.fromConfig(config);
|
|
@@ -3452,13 +3365,13 @@ async function createRouter(options) {
|
|
|
3452
3365
|
permissions: alpha.scaffolderActionPermissions,
|
|
3453
3366
|
rules: actionRules
|
|
3454
3367
|
}
|
|
3455
|
-
]
|
|
3368
|
+
],
|
|
3369
|
+
permissions: alpha.scaffolderTaskPermissions
|
|
3456
3370
|
});
|
|
3457
3371
|
router.use(permissionIntegrationRouter);
|
|
3458
3372
|
router.get(
|
|
3459
3373
|
"/v2/templates/:namespace/:kind/:name/parameter-schema",
|
|
3460
3374
|
async (req, res) => {
|
|
3461
|
-
var _a2, _b;
|
|
3462
3375
|
const credentials = await httpAuth.credentials(req);
|
|
3463
3376
|
const { token } = await auth.getPluginRequestToken({
|
|
3464
3377
|
onBehalfOf: credentials,
|
|
@@ -3469,21 +3382,18 @@ async function createRouter(options) {
|
|
|
3469
3382
|
token,
|
|
3470
3383
|
credentials
|
|
3471
3384
|
);
|
|
3472
|
-
const parameters = [
|
|
3385
|
+
const parameters = [template.spec.parameters ?? []].flat();
|
|
3473
3386
|
const presentation = template.spec.presentation;
|
|
3474
3387
|
res.json({
|
|
3475
|
-
title:
|
|
3388
|
+
title: template.metadata.title ?? template.metadata.name,
|
|
3476
3389
|
...presentation ? { presentation } : {},
|
|
3477
3390
|
description: template.metadata.description,
|
|
3478
3391
|
"ui:options": template.metadata["ui:options"],
|
|
3479
|
-
steps: parameters.map((schema) => {
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
schema
|
|
3485
|
-
};
|
|
3486
|
-
})
|
|
3392
|
+
steps: parameters.map((schema) => ({
|
|
3393
|
+
title: schema.title ?? "Please enter the following information",
|
|
3394
|
+
description: schema.description,
|
|
3395
|
+
schema
|
|
3396
|
+
}))
|
|
3487
3397
|
});
|
|
3488
3398
|
}
|
|
3489
3399
|
).get("/v2/actions", async (_req, res) => {
|
|
@@ -3497,12 +3407,16 @@ async function createRouter(options) {
|
|
|
3497
3407
|
});
|
|
3498
3408
|
res.json(actionsList);
|
|
3499
3409
|
}).post("/v2/tasks", async (req, res) => {
|
|
3500
|
-
var _a2, _b;
|
|
3501
3410
|
const templateRef = req.body.templateRef;
|
|
3502
3411
|
const { kind, namespace, name } = catalogModel.parseEntityRef(templateRef, {
|
|
3503
3412
|
defaultKind: "template"
|
|
3504
3413
|
});
|
|
3505
3414
|
const credentials = await httpAuth.credentials(req);
|
|
3415
|
+
await checkPermission({
|
|
3416
|
+
credentials,
|
|
3417
|
+
permissions: [alpha.taskCreatePermission],
|
|
3418
|
+
permissionService: permissions
|
|
3419
|
+
});
|
|
3506
3420
|
const { token } = await auth.getPluginRequestToken({
|
|
3507
3421
|
onBehalfOf: credentials,
|
|
3508
3422
|
targetPluginId: "catalog"
|
|
@@ -3520,7 +3434,7 @@ async function createRouter(options) {
|
|
|
3520
3434
|
token,
|
|
3521
3435
|
credentials
|
|
3522
3436
|
);
|
|
3523
|
-
for (const parameters of [
|
|
3437
|
+
for (const parameters of [template.spec.parameters ?? []].flat()) {
|
|
3524
3438
|
const result2 = jsonschema.validate(values, parameters);
|
|
3525
3439
|
if (!result2.valid) {
|
|
3526
3440
|
res.status(400).json({ errors: result2.errors });
|
|
@@ -3530,16 +3444,13 @@ async function createRouter(options) {
|
|
|
3530
3444
|
const baseUrl = getEntityBaseUrl(template);
|
|
3531
3445
|
const taskSpec = {
|
|
3532
3446
|
apiVersion: template.apiVersion,
|
|
3533
|
-
steps: template.spec.steps.map((step, index) => {
|
|
3534
|
-
|
|
3535
|
-
|
|
3536
|
-
|
|
3537
|
-
|
|
3538
|
-
name: (_b2 = step.name) != null ? _b2 : step.action
|
|
3539
|
-
};
|
|
3540
|
-
}),
|
|
3447
|
+
steps: template.spec.steps.map((step, index) => ({
|
|
3448
|
+
...step,
|
|
3449
|
+
id: step.id ?? `step-${index + 1}`,
|
|
3450
|
+
name: step.name ?? step.action
|
|
3451
|
+
})),
|
|
3541
3452
|
EXPERIMENTAL_recovery: template.spec.EXPERIMENTAL_recovery,
|
|
3542
|
-
output:
|
|
3453
|
+
output: template.spec.output ?? {},
|
|
3543
3454
|
parameters: values,
|
|
3544
3455
|
user: {
|
|
3545
3456
|
entity: userEntity,
|
|
@@ -3565,6 +3476,12 @@ async function createRouter(options) {
|
|
|
3565
3476
|
});
|
|
3566
3477
|
res.status(201).json({ id: result.taskId });
|
|
3567
3478
|
}).get("/v2/tasks", async (req, res) => {
|
|
3479
|
+
const credentials = await httpAuth.credentials(req);
|
|
3480
|
+
await checkPermission({
|
|
3481
|
+
credentials,
|
|
3482
|
+
permissions: [alpha.taskReadPermission],
|
|
3483
|
+
permissionService: permissions
|
|
3484
|
+
});
|
|
3568
3485
|
const [userEntityRef] = [req.query.createdBy].flat();
|
|
3569
3486
|
if (typeof userEntityRef !== "string" && typeof userEntityRef !== "undefined") {
|
|
3570
3487
|
throw new errors.InputError("createdBy query parameter must be a string");
|
|
@@ -3579,6 +3496,12 @@ async function createRouter(options) {
|
|
|
3579
3496
|
});
|
|
3580
3497
|
res.status(200).json(tasks);
|
|
3581
3498
|
}).get("/v2/tasks/:taskId", async (req, res) => {
|
|
3499
|
+
const credentials = await httpAuth.credentials(req);
|
|
3500
|
+
await checkPermission({
|
|
3501
|
+
credentials,
|
|
3502
|
+
permissions: [alpha.taskReadPermission],
|
|
3503
|
+
permissionService: permissions
|
|
3504
|
+
});
|
|
3582
3505
|
const { taskId } = req.params;
|
|
3583
3506
|
const task = await taskBroker.get(taskId);
|
|
3584
3507
|
if (!task) {
|
|
@@ -3587,11 +3510,22 @@ async function createRouter(options) {
|
|
|
3587
3510
|
delete task.secrets;
|
|
3588
3511
|
res.status(200).json(task);
|
|
3589
3512
|
}).post("/v2/tasks/:taskId/cancel", async (req, res) => {
|
|
3590
|
-
|
|
3513
|
+
const credentials = await httpAuth.credentials(req);
|
|
3514
|
+
await checkPermission({
|
|
3515
|
+
credentials,
|
|
3516
|
+
permissions: [alpha.taskCancelPermission, alpha.taskReadPermission],
|
|
3517
|
+
permissionService: permissions
|
|
3518
|
+
});
|
|
3591
3519
|
const { taskId } = req.params;
|
|
3592
|
-
await
|
|
3520
|
+
await taskBroker.cancel?.(taskId);
|
|
3593
3521
|
res.status(200).json({ status: "cancelled" });
|
|
3594
3522
|
}).get("/v2/tasks/:taskId/eventstream", async (req, res) => {
|
|
3523
|
+
const credentials = await httpAuth.credentials(req);
|
|
3524
|
+
await checkPermission({
|
|
3525
|
+
credentials,
|
|
3526
|
+
permissions: [alpha.taskReadPermission],
|
|
3527
|
+
permissionService: permissions
|
|
3528
|
+
});
|
|
3595
3529
|
const { taskId } = req.params;
|
|
3596
3530
|
const after = req.query.after !== void 0 ? Number(req.query.after) : void 0;
|
|
3597
3531
|
logger.debug(`Event stream observing taskId '${taskId}' opened`);
|
|
@@ -3608,7 +3542,6 @@ async function createRouter(options) {
|
|
|
3608
3542
|
res.end();
|
|
3609
3543
|
},
|
|
3610
3544
|
next: ({ events }) => {
|
|
3611
|
-
var _a2;
|
|
3612
3545
|
let shouldUnsubscribe = false;
|
|
3613
3546
|
for (const event of events) {
|
|
3614
3547
|
res.write(
|
|
@@ -3621,7 +3554,7 @@ data: ${JSON.stringify(event)}
|
|
|
3621
3554
|
shouldUnsubscribe = true;
|
|
3622
3555
|
}
|
|
3623
3556
|
}
|
|
3624
|
-
|
|
3557
|
+
res.flush?.();
|
|
3625
3558
|
if (shouldUnsubscribe) {
|
|
3626
3559
|
subscription.unsubscribe();
|
|
3627
3560
|
res.end();
|
|
@@ -3633,6 +3566,12 @@ data: ${JSON.stringify(event)}
|
|
|
3633
3566
|
logger.debug(`Event stream observing taskId '${taskId}' closed`);
|
|
3634
3567
|
});
|
|
3635
3568
|
}).get("/v2/tasks/:taskId/events", async (req, res) => {
|
|
3569
|
+
const credentials = await httpAuth.credentials(req);
|
|
3570
|
+
await checkPermission({
|
|
3571
|
+
credentials,
|
|
3572
|
+
permissions: [alpha.taskReadPermission],
|
|
3573
|
+
permissionService: permissions
|
|
3574
|
+
});
|
|
3636
3575
|
const { taskId } = req.params;
|
|
3637
3576
|
const after = Number(req.query.after) || void 0;
|
|
3638
3577
|
const timeout = setTimeout(() => {
|
|
@@ -3655,7 +3594,12 @@ data: ${JSON.stringify(event)}
|
|
|
3655
3594
|
clearTimeout(timeout);
|
|
3656
3595
|
});
|
|
3657
3596
|
}).post("/v2/dry-run", async (req, res) => {
|
|
3658
|
-
|
|
3597
|
+
const credentials = await httpAuth.credentials(req);
|
|
3598
|
+
await checkPermission({
|
|
3599
|
+
credentials,
|
|
3600
|
+
permissions: [alpha.taskCreatePermission],
|
|
3601
|
+
permissionService: permissions
|
|
3602
|
+
});
|
|
3659
3603
|
const bodySchema = zod.z.object({
|
|
3660
3604
|
template: zod.z.unknown(),
|
|
3661
3605
|
values: zod.z.record(zod.z.unknown()),
|
|
@@ -3671,34 +3615,30 @@ data: ${JSON.stringify(event)}
|
|
|
3671
3615
|
if (!await pluginScaffolderCommon.templateEntityV1beta3Validator.check(template)) {
|
|
3672
3616
|
throw new errors.InputError("Input template is not a template");
|
|
3673
3617
|
}
|
|
3674
|
-
const credentials = await httpAuth.credentials(req);
|
|
3675
3618
|
const { token } = await auth.getPluginRequestToken({
|
|
3676
3619
|
onBehalfOf: credentials,
|
|
3677
3620
|
targetPluginId: "catalog"
|
|
3678
3621
|
});
|
|
3679
|
-
for (const parameters of [
|
|
3622
|
+
for (const parameters of [template.spec.parameters ?? []].flat()) {
|
|
3680
3623
|
const result2 = jsonschema.validate(body.values, parameters);
|
|
3681
3624
|
if (!result2.valid) {
|
|
3682
3625
|
res.status(400).json({ errors: result2.errors });
|
|
3683
3626
|
return;
|
|
3684
3627
|
}
|
|
3685
3628
|
}
|
|
3686
|
-
const steps = template.spec.steps.map((step, index) => {
|
|
3687
|
-
|
|
3688
|
-
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
name: (_b2 = step.name) != null ? _b2 : step.action
|
|
3692
|
-
};
|
|
3693
|
-
});
|
|
3629
|
+
const steps = template.spec.steps.map((step, index) => ({
|
|
3630
|
+
...step,
|
|
3631
|
+
id: step.id ?? `step-${index + 1}`,
|
|
3632
|
+
name: step.name ?? step.action
|
|
3633
|
+
}));
|
|
3694
3634
|
const result = await dryRunner({
|
|
3695
3635
|
spec: {
|
|
3696
3636
|
apiVersion: template.apiVersion,
|
|
3697
3637
|
steps,
|
|
3698
|
-
output:
|
|
3638
|
+
output: template.spec.output ?? {},
|
|
3699
3639
|
parameters: body.values
|
|
3700
3640
|
},
|
|
3701
|
-
directoryContents: (
|
|
3641
|
+
directoryContents: (body.directoryContents ?? []).map((file) => ({
|
|
3702
3642
|
path: file.path,
|
|
3703
3643
|
content: Buffer.from(file.base64Content, "base64")
|
|
3704
3644
|
})),
|
|
@@ -3775,4 +3715,4 @@ exports.createRouter = createRouter;
|
|
|
3775
3715
|
exports.createWaitAction = createWaitAction;
|
|
3776
3716
|
exports.scaffolderActionRules = scaffolderActionRules;
|
|
3777
3717
|
exports.scaffolderTemplateRules = scaffolderTemplateRules;
|
|
3778
|
-
//# sourceMappingURL=router-
|
|
3718
|
+
//# sourceMappingURL=router-BtUx0eIt.cjs.js.map
|