@backstage/plugin-scaffolder-backend 1.22.7 → 1.22.8-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 +31 -5
- package/alpha/package.json +1 -1
- package/dist/alpha.cjs.js +1 -1
- package/dist/cjs/{router-CM3G1J74.cjs.js → router-CTk9mOV8.cjs.js} +151 -270
- package/dist/cjs/router-CTk9mOV8.cjs.js.map +1 -0
- package/dist/index.cjs.js +1 -1
- package/package.json +20 -20
- package/dist/cjs/router-CM3G1J74.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:
|
|
@@ -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
|
};
|
|
@@ -2426,28 +2356,23 @@ class BackstageLoggerTransport extends Transport__default.default {
|
|
|
2426
2356
|
callback();
|
|
2427
2357
|
}
|
|
2428
2358
|
}
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
__privateAdd(this, _addRedactions, void 0);
|
|
2433
|
-
__privateSet(this, _winston, winston);
|
|
2434
|
-
__privateSet(this, _addRedactions, addRedactions);
|
|
2435
|
-
}
|
|
2359
|
+
class WinstonLogger {
|
|
2360
|
+
#winston;
|
|
2361
|
+
#addRedactions;
|
|
2436
2362
|
/**
|
|
2437
2363
|
* Creates a {@link WinstonLogger} instance.
|
|
2438
2364
|
*/
|
|
2439
2365
|
static create(options) {
|
|
2440
|
-
|
|
2441
|
-
const redacter = _WinstonLogger.redacter();
|
|
2366
|
+
const redacter = WinstonLogger.redacter();
|
|
2442
2367
|
let logger = winston.createLogger({
|
|
2443
2368
|
level: options.level,
|
|
2444
2369
|
format: winston.format.combine(redacter.format, options.format),
|
|
2445
|
-
transports:
|
|
2370
|
+
transports: options.transports ?? new winston.transports.Console()
|
|
2446
2371
|
});
|
|
2447
2372
|
if (options.meta) {
|
|
2448
2373
|
logger = logger.child(options.meta);
|
|
2449
2374
|
}
|
|
2450
|
-
return new
|
|
2375
|
+
return new WinstonLogger(logger, redacter.add);
|
|
2451
2376
|
}
|
|
2452
2377
|
/**
|
|
2453
2378
|
* Creates a winston log formatter for redacting secrets.
|
|
@@ -2457,11 +2382,10 @@ const _WinstonLogger = class _WinstonLogger {
|
|
|
2457
2382
|
let redactionPattern = void 0;
|
|
2458
2383
|
return {
|
|
2459
2384
|
format: winston.format((obj) => {
|
|
2460
|
-
var _a, _b;
|
|
2461
2385
|
if (!redactionPattern || !obj) {
|
|
2462
2386
|
return obj;
|
|
2463
2387
|
}
|
|
2464
|
-
obj[tripleBeam.MESSAGE] =
|
|
2388
|
+
obj[tripleBeam.MESSAGE] = obj[tripleBeam.MESSAGE]?.replace?.(redactionPattern, "***");
|
|
2465
2389
|
return obj;
|
|
2466
2390
|
})(),
|
|
2467
2391
|
add(newRedactions) {
|
|
@@ -2510,36 +2434,30 @@ const _WinstonLogger = class _WinstonLogger {
|
|
|
2510
2434
|
})
|
|
2511
2435
|
);
|
|
2512
2436
|
}
|
|
2437
|
+
constructor(winston, addRedactions) {
|
|
2438
|
+
this.#winston = winston;
|
|
2439
|
+
this.#addRedactions = addRedactions;
|
|
2440
|
+
}
|
|
2513
2441
|
error(message, meta) {
|
|
2514
|
-
|
|
2442
|
+
this.#winston.error(message, meta);
|
|
2515
2443
|
}
|
|
2516
2444
|
warn(message, meta) {
|
|
2517
|
-
|
|
2445
|
+
this.#winston.warn(message, meta);
|
|
2518
2446
|
}
|
|
2519
2447
|
info(message, meta) {
|
|
2520
|
-
|
|
2448
|
+
this.#winston.info(message, meta);
|
|
2521
2449
|
}
|
|
2522
2450
|
debug(message, meta) {
|
|
2523
|
-
|
|
2451
|
+
this.#winston.debug(message, meta);
|
|
2524
2452
|
}
|
|
2525
2453
|
child(meta) {
|
|
2526
|
-
return new
|
|
2454
|
+
return new WinstonLogger(this.#winston.child(meta));
|
|
2527
2455
|
}
|
|
2528
2456
|
addRedactions(redactions) {
|
|
2529
|
-
|
|
2530
|
-
(_a = __privateGet(this, _addRedactions)) == null ? void 0 : _a.call(this, redactions);
|
|
2457
|
+
this.#addRedactions?.(redactions);
|
|
2531
2458
|
}
|
|
2532
|
-
}
|
|
2533
|
-
_winston = new WeakMap();
|
|
2534
|
-
_addRedactions = new WeakMap();
|
|
2535
|
-
let WinstonLogger = _WinstonLogger;
|
|
2459
|
+
}
|
|
2536
2460
|
|
|
2537
|
-
var __defProp$1 = Object.defineProperty;
|
|
2538
|
-
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
2539
|
-
var __publicField$1 = (obj, key, value) => {
|
|
2540
|
-
__defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
2541
|
-
return value;
|
|
2542
|
-
};
|
|
2543
2461
|
const isValidTaskSpec = (taskSpec) => {
|
|
2544
2462
|
return taskSpec.apiVersion === "scaffolder.backstage.io/v1beta3";
|
|
2545
2463
|
};
|
|
@@ -2548,11 +2466,10 @@ const createStepLogger = ({
|
|
|
2548
2466
|
step,
|
|
2549
2467
|
rootLogger
|
|
2550
2468
|
}) => {
|
|
2551
|
-
var _a;
|
|
2552
2469
|
const stepLogStream = new stream.PassThrough();
|
|
2553
2470
|
stepLogStream.on("data", async (data) => {
|
|
2554
2471
|
const message = data.toString().trim();
|
|
2555
|
-
if (
|
|
2472
|
+
if (message?.length > 1) {
|
|
2556
2473
|
await task.emitLog(message, { stepId: step.id });
|
|
2557
2474
|
}
|
|
2558
2475
|
});
|
|
@@ -2567,11 +2484,11 @@ const createStepLogger = ({
|
|
|
2567
2484
|
new BackstageLoggerTransport(rootLogger)
|
|
2568
2485
|
]
|
|
2569
2486
|
});
|
|
2570
|
-
taskLogger.addRedactions(Object.values(
|
|
2487
|
+
taskLogger.addRedactions(Object.values(task.secrets ?? {}));
|
|
2571
2488
|
const streamLogger = new stream.PassThrough();
|
|
2572
2489
|
streamLogger.on("data", async (data) => {
|
|
2573
2490
|
const message = data.toString().trim();
|
|
2574
|
-
if (
|
|
2491
|
+
if (message?.length > 1) {
|
|
2575
2492
|
taskLogger.info(message);
|
|
2576
2493
|
}
|
|
2577
2494
|
});
|
|
@@ -2583,14 +2500,13 @@ const isActionAuthorized = pluginPermissionNode.createConditionAuthorizer(
|
|
|
2583
2500
|
class NunjucksWorkflowRunner {
|
|
2584
2501
|
constructor(options) {
|
|
2585
2502
|
this.options = options;
|
|
2586
|
-
__publicField$1(this, "defaultTemplateFilters");
|
|
2587
|
-
__publicField$1(this, "tracker", scaffoldingTracker());
|
|
2588
2503
|
this.defaultTemplateFilters = createDefaultFilters({
|
|
2589
2504
|
integrations: this.options.integrations
|
|
2590
2505
|
});
|
|
2591
2506
|
}
|
|
2507
|
+
defaultTemplateFilters;
|
|
2508
|
+
tracker = scaffoldingTracker();
|
|
2592
2509
|
isSingleTemplateString(input) {
|
|
2593
|
-
var _a, _b;
|
|
2594
2510
|
const { parser, nodes } = nunjucks__default.default;
|
|
2595
2511
|
const parsed = parser.parse(
|
|
2596
2512
|
input,
|
|
@@ -2603,7 +2519,7 @@ class NunjucksWorkflowRunner {
|
|
|
2603
2519
|
}
|
|
2604
2520
|
}
|
|
2605
2521
|
);
|
|
2606
|
-
return parsed.children.length === 1 && !(
|
|
2522
|
+
return parsed.children.length === 1 && !(parsed.children[0]?.children?.[0] instanceof nodes.TemplateData);
|
|
2607
2523
|
}
|
|
2608
2524
|
render(input, context, renderTemplate) {
|
|
2609
2525
|
return JSON.parse(JSON.stringify(input), (_key, value) => {
|
|
@@ -2639,7 +2555,6 @@ class NunjucksWorkflowRunner {
|
|
|
2639
2555
|
});
|
|
2640
2556
|
}
|
|
2641
2557
|
async executeStep(task, step, context, renderTemplate, taskTrack, workspacePath, decision) {
|
|
2642
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
2643
2558
|
const stepTrack = await this.tracker.stepStart(task, step);
|
|
2644
2559
|
if (task.cancelSignal.aborted) {
|
|
2645
2560
|
throw new Error(`Step ${step.name} has been cancelled.`);
|
|
@@ -2660,19 +2575,16 @@ class NunjucksWorkflowRunner {
|
|
|
2660
2575
|
});
|
|
2661
2576
|
if (task.isDryRun) {
|
|
2662
2577
|
const redactedSecrets = Object.fromEntries(
|
|
2663
|
-
Object.entries(
|
|
2664
|
-
secret[0],
|
|
2665
|
-
"[REDACTED]"
|
|
2666
|
-
])
|
|
2578
|
+
Object.entries(task.secrets ?? {}).map((secret) => [secret[0], "***"])
|
|
2667
2579
|
);
|
|
2668
|
-
const debugInput = (
|
|
2580
|
+
const debugInput = (step.input && this.render(
|
|
2669
2581
|
step.input,
|
|
2670
2582
|
{
|
|
2671
2583
|
...context,
|
|
2672
2584
|
secrets: redactedSecrets
|
|
2673
2585
|
},
|
|
2674
2586
|
renderTemplate
|
|
2675
|
-
))
|
|
2587
|
+
)) ?? {};
|
|
2676
2588
|
taskLogger.info(
|
|
2677
2589
|
`Running ${action.id} in dry-run mode with inputs (secrets redacted): ${JSON.stringify(
|
|
2678
2590
|
debugInput,
|
|
@@ -2682,7 +2594,7 @@ class NunjucksWorkflowRunner {
|
|
|
2682
2594
|
);
|
|
2683
2595
|
if (!action.supportsDryRun) {
|
|
2684
2596
|
await taskTrack.skipDryRun(step, action);
|
|
2685
|
-
const outputSchema =
|
|
2597
|
+
const outputSchema = action.schema?.output;
|
|
2686
2598
|
if (outputSchema) {
|
|
2687
2599
|
context.steps[step.id] = {
|
|
2688
2600
|
output: generateExampleOutput(outputSchema)
|
|
@@ -2697,21 +2609,18 @@ class NunjucksWorkflowRunner {
|
|
|
2697
2609
|
([key, value]) => ({
|
|
2698
2610
|
each: { key, value }
|
|
2699
2611
|
})
|
|
2700
|
-
) : [{}]).map((i) => {
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
) : {}
|
|
2710
|
-
};
|
|
2711
|
-
});
|
|
2612
|
+
) : [{}]).map((i) => ({
|
|
2613
|
+
...i,
|
|
2614
|
+
// Secrets are only passed when templating the input to actions for security reasons
|
|
2615
|
+
input: step.input ? this.render(
|
|
2616
|
+
step.input,
|
|
2617
|
+
{ ...context, secrets: task.secrets ?? {}, ...i },
|
|
2618
|
+
renderTemplate
|
|
2619
|
+
) : {}
|
|
2620
|
+
}));
|
|
2712
2621
|
for (const iteration of iterations) {
|
|
2713
2622
|
const actionId = `${action.id}${iteration.each ? `[${iteration.each.key}]` : ""}`;
|
|
2714
|
-
if (
|
|
2623
|
+
if (action.schema?.input) {
|
|
2715
2624
|
const validateResult = jsonschema.validate(
|
|
2716
2625
|
iteration.input,
|
|
2717
2626
|
action.schema.input
|
|
@@ -2738,7 +2647,7 @@ class NunjucksWorkflowRunner {
|
|
|
2738
2647
|
}
|
|
2739
2648
|
const tmpDirs = new Array();
|
|
2740
2649
|
const stepOutput = {};
|
|
2741
|
-
const prevTaskState = await
|
|
2650
|
+
const prevTaskState = await task.getTaskState?.();
|
|
2742
2651
|
for (const iteration of iterations) {
|
|
2743
2652
|
if (iteration.each) {
|
|
2744
2653
|
taskLogger.info(
|
|
@@ -2751,25 +2660,24 @@ class NunjucksWorkflowRunner {
|
|
|
2751
2660
|
}
|
|
2752
2661
|
await action.handler({
|
|
2753
2662
|
input: iteration.input,
|
|
2754
|
-
secrets:
|
|
2663
|
+
secrets: task.secrets ?? {},
|
|
2755
2664
|
// TODO(blam): move to LoggerService and away from Winston
|
|
2756
2665
|
logger: backendCommon.loggerToWinstonLogger(taskLogger),
|
|
2757
2666
|
logStream: streamLogger,
|
|
2758
2667
|
workspacePath,
|
|
2759
2668
|
async checkpoint(keySuffix, fn) {
|
|
2760
|
-
var _a2, _b2, _c2, _d2, _e2;
|
|
2761
2669
|
const key = `v1.task.checkpoint.${keySuffix}`;
|
|
2762
2670
|
try {
|
|
2763
2671
|
let prevValue;
|
|
2764
2672
|
if (prevTaskState) {
|
|
2765
|
-
const prevState =
|
|
2673
|
+
const prevState = prevTaskState.state?.checkpoints?.[key];
|
|
2766
2674
|
if (prevState && prevState.status === "success") {
|
|
2767
2675
|
prevValue = prevState.value;
|
|
2768
2676
|
}
|
|
2769
2677
|
}
|
|
2770
2678
|
const value = prevValue ? prevValue : await fn();
|
|
2771
2679
|
if (!prevValue) {
|
|
2772
|
-
|
|
2680
|
+
task.updateCheckpoint?.({
|
|
2773
2681
|
key,
|
|
2774
2682
|
status: "success",
|
|
2775
2683
|
value
|
|
@@ -2777,14 +2685,14 @@ class NunjucksWorkflowRunner {
|
|
|
2777
2685
|
}
|
|
2778
2686
|
return value;
|
|
2779
2687
|
} catch (err) {
|
|
2780
|
-
|
|
2688
|
+
task.updateCheckpoint?.({
|
|
2781
2689
|
key,
|
|
2782
2690
|
status: "failed",
|
|
2783
2691
|
reason: errors.stringifyError(err)
|
|
2784
2692
|
});
|
|
2785
2693
|
throw err;
|
|
2786
2694
|
} finally {
|
|
2787
|
-
await
|
|
2695
|
+
await task.serializeWorkspace?.({ path: workspacePath });
|
|
2788
2696
|
}
|
|
2789
2697
|
},
|
|
2790
2698
|
createTemporaryDirectory: async () => {
|
|
@@ -2816,18 +2724,17 @@ class NunjucksWorkflowRunner {
|
|
|
2816
2724
|
if (task.cancelSignal.aborted) {
|
|
2817
2725
|
throw new Error(`Step ${step.name} has been cancelled.`);
|
|
2818
2726
|
}
|
|
2819
|
-
await
|
|
2727
|
+
await task.cleanWorkspace?.();
|
|
2820
2728
|
await stepTrack.markSuccessful();
|
|
2821
2729
|
} catch (err) {
|
|
2822
2730
|
await taskTrack.markFailed(step, err);
|
|
2823
2731
|
await stepTrack.markFailed();
|
|
2824
2732
|
throw err;
|
|
2825
2733
|
} finally {
|
|
2826
|
-
await
|
|
2734
|
+
await task.serializeWorkspace?.({ path: workspacePath });
|
|
2827
2735
|
}
|
|
2828
2736
|
}
|
|
2829
2737
|
async execute(task) {
|
|
2830
|
-
var _a;
|
|
2831
2738
|
if (!isValidTaskSpec(task.spec)) {
|
|
2832
2739
|
throw new errors.InputError(
|
|
2833
2740
|
"Wrong template version executed with the workflow engine"
|
|
@@ -2844,7 +2751,7 @@ class NunjucksWorkflowRunner {
|
|
|
2844
2751
|
templateGlobals: additionalTemplateGlobals
|
|
2845
2752
|
});
|
|
2846
2753
|
try {
|
|
2847
|
-
await
|
|
2754
|
+
await task.rehydrateWorkspace?.({ taskId, targetPath: workspacePath });
|
|
2848
2755
|
const taskTrack = await this.tracker.taskStart(task);
|
|
2849
2756
|
await fs__default.default.ensureDir(workspacePath);
|
|
2850
2757
|
const context = {
|
|
@@ -2899,10 +2806,9 @@ function scaffoldingTracker() {
|
|
|
2899
2806
|
labelNames: ["template", "step", "result"]
|
|
2900
2807
|
});
|
|
2901
2808
|
async function taskStart(task) {
|
|
2902
|
-
var _a, _b;
|
|
2903
2809
|
await task.emitLog(`Starting up task with ${task.spec.steps.length} steps`);
|
|
2904
|
-
const template =
|
|
2905
|
-
const user =
|
|
2810
|
+
const template = task.spec.templateInfo?.entityRef || "";
|
|
2811
|
+
const user = task.spec.user?.ref || "";
|
|
2906
2812
|
const taskTimer = taskDuration.startTimer({
|
|
2907
2813
|
template
|
|
2908
2814
|
});
|
|
@@ -2952,12 +2858,11 @@ function scaffoldingTracker() {
|
|
|
2952
2858
|
};
|
|
2953
2859
|
}
|
|
2954
2860
|
async function stepStart(task, step) {
|
|
2955
|
-
var _a;
|
|
2956
2861
|
await task.emitLog(`Beginning step ${step.name}`, {
|
|
2957
2862
|
stepId: step.id,
|
|
2958
2863
|
status: "processing"
|
|
2959
2864
|
});
|
|
2960
|
-
const template =
|
|
2865
|
+
const template = task.spec.templateInfo?.entityRef || "";
|
|
2961
2866
|
const stepTimer = stepDuration.startTimer({
|
|
2962
2867
|
template,
|
|
2963
2868
|
step: step.name
|
|
@@ -3010,24 +2915,18 @@ function scaffoldingTracker() {
|
|
|
3010
2915
|
};
|
|
3011
2916
|
}
|
|
3012
2917
|
|
|
3013
|
-
var __defProp = Object.defineProperty;
|
|
3014
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3015
|
-
var __publicField = (obj, key, value) => {
|
|
3016
|
-
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
3017
|
-
return value;
|
|
3018
|
-
};
|
|
3019
2918
|
class TaskWorker {
|
|
3020
2919
|
constructor(options) {
|
|
3021
2920
|
this.options = options;
|
|
3022
|
-
__publicField(this, "taskQueue");
|
|
3023
|
-
__publicField(this, "logger");
|
|
3024
|
-
__publicField(this, "stopWorkers");
|
|
3025
2921
|
this.stopWorkers = false;
|
|
3026
2922
|
this.logger = options.logger;
|
|
3027
2923
|
this.taskQueue = new PQueue__default.default({
|
|
3028
2924
|
concurrency: options.concurrentTasksLimit
|
|
3029
2925
|
});
|
|
3030
2926
|
}
|
|
2927
|
+
taskQueue;
|
|
2928
|
+
logger;
|
|
2929
|
+
stopWorkers;
|
|
3031
2930
|
static async create(options) {
|
|
3032
2931
|
const {
|
|
3033
2932
|
taskBroker,
|
|
@@ -3058,11 +2957,10 @@ class TaskWorker {
|
|
|
3058
2957
|
});
|
|
3059
2958
|
}
|
|
3060
2959
|
async recoverTasks() {
|
|
3061
|
-
var _a, _b, _c;
|
|
3062
2960
|
try {
|
|
3063
|
-
await
|
|
2961
|
+
await this.options.taskBroker.recoverTasks?.();
|
|
3064
2962
|
} catch (err) {
|
|
3065
|
-
|
|
2963
|
+
this.logger?.error(errors.stringifyError(err));
|
|
3066
2964
|
}
|
|
3067
2965
|
}
|
|
3068
2966
|
start() {
|
|
@@ -3184,7 +3082,7 @@ function createDryRunner(options) {
|
|
|
3184
3082
|
getWorkspaceName: async () => `dry-run-${dryRunId}`,
|
|
3185
3083
|
cancelSignal: abortSignal,
|
|
3186
3084
|
async emitLog(message, logMetadata) {
|
|
3187
|
-
if (
|
|
3085
|
+
if (logMetadata?.stepId === dryRunId) {
|
|
3188
3086
|
return;
|
|
3189
3087
|
}
|
|
3190
3088
|
log.push({
|
|
@@ -3231,10 +3129,9 @@ async function getWorkingDirectory(config, logger) {
|
|
|
3231
3129
|
return workingDirectory;
|
|
3232
3130
|
}
|
|
3233
3131
|
function getEntityBaseUrl(entity) {
|
|
3234
|
-
|
|
3235
|
-
let location = (_a = entity.metadata.annotations) == null ? void 0 : _a[catalogModel.ANNOTATION_SOURCE_LOCATION];
|
|
3132
|
+
let location = entity.metadata.annotations?.[catalogModel.ANNOTATION_SOURCE_LOCATION];
|
|
3236
3133
|
if (!location) {
|
|
3237
|
-
location =
|
|
3134
|
+
location = entity.metadata.annotations?.[catalogModel.ANNOTATION_LOCATION];
|
|
3238
3135
|
}
|
|
3239
3136
|
if (!location) {
|
|
3240
3137
|
return void 0;
|
|
@@ -3273,14 +3170,13 @@ function isSupportedTemplate(entity) {
|
|
|
3273
3170
|
function buildDefaultIdentityClient(options) {
|
|
3274
3171
|
return {
|
|
3275
3172
|
getIdentity: async ({ request }) => {
|
|
3276
|
-
var _a;
|
|
3277
3173
|
const header = request.headers.authorization;
|
|
3278
3174
|
const { logger } = options;
|
|
3279
3175
|
if (!header) {
|
|
3280
3176
|
return void 0;
|
|
3281
3177
|
}
|
|
3282
3178
|
try {
|
|
3283
|
-
const token =
|
|
3179
|
+
const token = header.match(/^Bearer\s(\S+\.\S+\.\S+)$/i)?.[1];
|
|
3284
3180
|
if (!token) {
|
|
3285
3181
|
throw new TypeError("Expected Bearer with JWT");
|
|
3286
3182
|
}
|
|
@@ -3321,7 +3217,6 @@ const readDuration = (config$1, key, defaultValue) => {
|
|
|
3321
3217
|
return defaultValue;
|
|
3322
3218
|
};
|
|
3323
3219
|
async function createRouter(options) {
|
|
3324
|
-
var _a;
|
|
3325
3220
|
const router = Router__default.default();
|
|
3326
3221
|
router.use(express__default.default.json({ limit: "10MB" }));
|
|
3327
3222
|
const {
|
|
@@ -3345,7 +3240,7 @@ async function createRouter(options) {
|
|
|
3345
3240
|
identity,
|
|
3346
3241
|
discovery
|
|
3347
3242
|
});
|
|
3348
|
-
const concurrentTasksLimit =
|
|
3243
|
+
const concurrentTasksLimit = options.concurrentTasksLimit ?? options.config.getOptionalNumber("scaffolder.concurrentTasksLimit");
|
|
3349
3244
|
const logger = parentLogger.child({ plugin: "scaffolder" });
|
|
3350
3245
|
const workingDirectory = await getWorkingDirectory(config, logger);
|
|
3351
3246
|
const integrations = integration.ScmIntegrations.fromConfig(config);
|
|
@@ -3460,7 +3355,6 @@ async function createRouter(options) {
|
|
|
3460
3355
|
router.get(
|
|
3461
3356
|
"/v2/templates/:namespace/:kind/:name/parameter-schema",
|
|
3462
3357
|
async (req, res) => {
|
|
3463
|
-
var _a2, _b;
|
|
3464
3358
|
const credentials = await httpAuth.credentials(req);
|
|
3465
3359
|
const { token } = await auth.getPluginRequestToken({
|
|
3466
3360
|
onBehalfOf: credentials,
|
|
@@ -3471,21 +3365,18 @@ async function createRouter(options) {
|
|
|
3471
3365
|
token,
|
|
3472
3366
|
credentials
|
|
3473
3367
|
);
|
|
3474
|
-
const parameters = [
|
|
3368
|
+
const parameters = [template.spec.parameters ?? []].flat();
|
|
3475
3369
|
const presentation = template.spec.presentation;
|
|
3476
3370
|
res.json({
|
|
3477
|
-
title:
|
|
3371
|
+
title: template.metadata.title ?? template.metadata.name,
|
|
3478
3372
|
...presentation ? { presentation } : {},
|
|
3479
3373
|
description: template.metadata.description,
|
|
3480
3374
|
"ui:options": template.metadata["ui:options"],
|
|
3481
|
-
steps: parameters.map((schema) => {
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
schema
|
|
3487
|
-
};
|
|
3488
|
-
})
|
|
3375
|
+
steps: parameters.map((schema) => ({
|
|
3376
|
+
title: schema.title ?? "Please enter the following information",
|
|
3377
|
+
description: schema.description,
|
|
3378
|
+
schema
|
|
3379
|
+
}))
|
|
3489
3380
|
});
|
|
3490
3381
|
}
|
|
3491
3382
|
).get("/v2/actions", async (_req, res) => {
|
|
@@ -3499,7 +3390,6 @@ async function createRouter(options) {
|
|
|
3499
3390
|
});
|
|
3500
3391
|
res.json(actionsList);
|
|
3501
3392
|
}).post("/v2/tasks", async (req, res) => {
|
|
3502
|
-
var _a2, _b;
|
|
3503
3393
|
const templateRef = req.body.templateRef;
|
|
3504
3394
|
const { kind, namespace, name } = catalogModel.parseEntityRef(templateRef, {
|
|
3505
3395
|
defaultKind: "template"
|
|
@@ -3522,7 +3412,7 @@ async function createRouter(options) {
|
|
|
3522
3412
|
token,
|
|
3523
3413
|
credentials
|
|
3524
3414
|
);
|
|
3525
|
-
for (const parameters of [
|
|
3415
|
+
for (const parameters of [template.spec.parameters ?? []].flat()) {
|
|
3526
3416
|
const result2 = jsonschema.validate(values, parameters);
|
|
3527
3417
|
if (!result2.valid) {
|
|
3528
3418
|
res.status(400).json({ errors: result2.errors });
|
|
@@ -3532,16 +3422,13 @@ async function createRouter(options) {
|
|
|
3532
3422
|
const baseUrl = getEntityBaseUrl(template);
|
|
3533
3423
|
const taskSpec = {
|
|
3534
3424
|
apiVersion: template.apiVersion,
|
|
3535
|
-
steps: template.spec.steps.map((step, index) => {
|
|
3536
|
-
|
|
3537
|
-
|
|
3538
|
-
|
|
3539
|
-
|
|
3540
|
-
name: (_b2 = step.name) != null ? _b2 : step.action
|
|
3541
|
-
};
|
|
3542
|
-
}),
|
|
3425
|
+
steps: template.spec.steps.map((step, index) => ({
|
|
3426
|
+
...step,
|
|
3427
|
+
id: step.id ?? `step-${index + 1}`,
|
|
3428
|
+
name: step.name ?? step.action
|
|
3429
|
+
})),
|
|
3543
3430
|
EXPERIMENTAL_recovery: template.spec.EXPERIMENTAL_recovery,
|
|
3544
|
-
output:
|
|
3431
|
+
output: template.spec.output ?? {},
|
|
3545
3432
|
parameters: values,
|
|
3546
3433
|
user: {
|
|
3547
3434
|
entity: userEntity,
|
|
@@ -3589,9 +3476,8 @@ async function createRouter(options) {
|
|
|
3589
3476
|
delete task.secrets;
|
|
3590
3477
|
res.status(200).json(task);
|
|
3591
3478
|
}).post("/v2/tasks/:taskId/cancel", async (req, res) => {
|
|
3592
|
-
var _a2;
|
|
3593
3479
|
const { taskId } = req.params;
|
|
3594
|
-
await
|
|
3480
|
+
await taskBroker.cancel?.(taskId);
|
|
3595
3481
|
res.status(200).json({ status: "cancelled" });
|
|
3596
3482
|
}).get("/v2/tasks/:taskId/eventstream", async (req, res) => {
|
|
3597
3483
|
const { taskId } = req.params;
|
|
@@ -3610,7 +3496,6 @@ async function createRouter(options) {
|
|
|
3610
3496
|
res.end();
|
|
3611
3497
|
},
|
|
3612
3498
|
next: ({ events }) => {
|
|
3613
|
-
var _a2;
|
|
3614
3499
|
let shouldUnsubscribe = false;
|
|
3615
3500
|
for (const event of events) {
|
|
3616
3501
|
res.write(
|
|
@@ -3623,7 +3508,7 @@ data: ${JSON.stringify(event)}
|
|
|
3623
3508
|
shouldUnsubscribe = true;
|
|
3624
3509
|
}
|
|
3625
3510
|
}
|
|
3626
|
-
|
|
3511
|
+
res.flush?.();
|
|
3627
3512
|
if (shouldUnsubscribe) {
|
|
3628
3513
|
subscription.unsubscribe();
|
|
3629
3514
|
res.end();
|
|
@@ -3657,7 +3542,6 @@ data: ${JSON.stringify(event)}
|
|
|
3657
3542
|
clearTimeout(timeout);
|
|
3658
3543
|
});
|
|
3659
3544
|
}).post("/v2/dry-run", async (req, res) => {
|
|
3660
|
-
var _a2, _b, _c;
|
|
3661
3545
|
const bodySchema = zod.z.object({
|
|
3662
3546
|
template: zod.z.unknown(),
|
|
3663
3547
|
values: zod.z.record(zod.z.unknown()),
|
|
@@ -3678,29 +3562,26 @@ data: ${JSON.stringify(event)}
|
|
|
3678
3562
|
onBehalfOf: credentials,
|
|
3679
3563
|
targetPluginId: "catalog"
|
|
3680
3564
|
});
|
|
3681
|
-
for (const parameters of [
|
|
3565
|
+
for (const parameters of [template.spec.parameters ?? []].flat()) {
|
|
3682
3566
|
const result2 = jsonschema.validate(body.values, parameters);
|
|
3683
3567
|
if (!result2.valid) {
|
|
3684
3568
|
res.status(400).json({ errors: result2.errors });
|
|
3685
3569
|
return;
|
|
3686
3570
|
}
|
|
3687
3571
|
}
|
|
3688
|
-
const steps = template.spec.steps.map((step, index) => {
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
name: (_b2 = step.name) != null ? _b2 : step.action
|
|
3694
|
-
};
|
|
3695
|
-
});
|
|
3572
|
+
const steps = template.spec.steps.map((step, index) => ({
|
|
3573
|
+
...step,
|
|
3574
|
+
id: step.id ?? `step-${index + 1}`,
|
|
3575
|
+
name: step.name ?? step.action
|
|
3576
|
+
}));
|
|
3696
3577
|
const result = await dryRunner({
|
|
3697
3578
|
spec: {
|
|
3698
3579
|
apiVersion: template.apiVersion,
|
|
3699
3580
|
steps,
|
|
3700
|
-
output:
|
|
3581
|
+
output: template.spec.output ?? {},
|
|
3701
3582
|
parameters: body.values
|
|
3702
3583
|
},
|
|
3703
|
-
directoryContents: (
|
|
3584
|
+
directoryContents: (body.directoryContents ?? []).map((file) => ({
|
|
3704
3585
|
path: file.path,
|
|
3705
3586
|
content: Buffer.from(file.base64Content, "base64")
|
|
3706
3587
|
})),
|
|
@@ -3777,4 +3658,4 @@ exports.createRouter = createRouter;
|
|
|
3777
3658
|
exports.createWaitAction = createWaitAction;
|
|
3778
3659
|
exports.scaffolderActionRules = scaffolderActionRules;
|
|
3779
3660
|
exports.scaffolderTemplateRules = scaffolderTemplateRules;
|
|
3780
|
-
//# sourceMappingURL=router-
|
|
3661
|
+
//# sourceMappingURL=router-CTk9mOV8.cjs.js.map
|