@backstage/plugin-scaffolder-backend 1.22.6 → 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 +32 -0
- package/alpha/package.json +1 -1
- package/dist/alpha.cjs.js +2 -1
- package/dist/alpha.cjs.js.map +1 -1
- package/dist/cjs/{router-BKGs_U4O.cjs.js → router-CTk9mOV8.cjs.js} +158 -282
- package/dist/cjs/router-CTk9mOV8.cjs.js.map +1 -0
- package/dist/index.cjs.js +2 -1
- package/dist/index.cjs.js.map +1 -1
- package/package.json +21 -20
- package/dist/cjs/router-BKGs_U4O.cjs.js.map +0 -1
|
@@ -43,6 +43,7 @@ var pluginPermissionNode = require('@backstage/plugin-permission-node');
|
|
|
43
43
|
var promClient = require('prom-client');
|
|
44
44
|
var pluginPermissionCommon = require('@backstage/plugin-permission-common');
|
|
45
45
|
var Transport = require('winston-transport');
|
|
46
|
+
var tripleBeam = require('triple-beam');
|
|
46
47
|
var url = require('url');
|
|
47
48
|
var os = require('os');
|
|
48
49
|
|
|
@@ -163,7 +164,6 @@ function createCatalogRegisterAction(options) {
|
|
|
163
164
|
}
|
|
164
165
|
},
|
|
165
166
|
async handler(ctx) {
|
|
166
|
-
var _a, _b;
|
|
167
167
|
const { input } = ctx;
|
|
168
168
|
let catalogInfoUrl;
|
|
169
169
|
if ("catalogInfoUrl" in input) {
|
|
@@ -182,10 +182,10 @@ function createCatalogRegisterAction(options) {
|
|
|
182
182
|
});
|
|
183
183
|
}
|
|
184
184
|
ctx.logger.info(`Registering ${catalogInfoUrl} in the catalog`);
|
|
185
|
-
const { token } =
|
|
185
|
+
const { token } = await auth?.getPluginRequestToken({
|
|
186
186
|
onBehalfOf: await ctx.getInitiatorCredentials(),
|
|
187
187
|
targetPluginId: "catalog"
|
|
188
|
-
})
|
|
188
|
+
}) ?? { token: ctx.secrets?.backstageToken };
|
|
189
189
|
try {
|
|
190
190
|
await catalogClient.addLocation(
|
|
191
191
|
{
|
|
@@ -281,11 +281,10 @@ function createCatalogWriteAction() {
|
|
|
281
281
|
examples: examples$8,
|
|
282
282
|
supportsDryRun: true,
|
|
283
283
|
async handler(ctx) {
|
|
284
|
-
var _a;
|
|
285
284
|
ctx.logger.info(`Writing catalog-info.yaml`);
|
|
286
285
|
const { filePath, entity } = ctx.input;
|
|
287
|
-
const entityRef =
|
|
288
|
-
const path = filePath
|
|
286
|
+
const entityRef = ctx.templateInfo?.entityRef;
|
|
287
|
+
const path = filePath ?? "catalog-info.yaml";
|
|
289
288
|
await fs__default.default.writeFile(
|
|
290
289
|
backendPluginApi.resolveSafeChildPath(ctx.workspacePath, path),
|
|
291
290
|
yaml__namespace.stringify({
|
|
@@ -372,7 +371,6 @@ function createFetchCatalogEntityAction(options) {
|
|
|
372
371
|
})
|
|
373
372
|
},
|
|
374
373
|
async handler(ctx) {
|
|
375
|
-
var _a, _b;
|
|
376
374
|
const { entityRef, entityRefs, optional, defaultKind, defaultNamespace } = ctx.input;
|
|
377
375
|
if (!entityRef && !entityRefs) {
|
|
378
376
|
if (optional) {
|
|
@@ -380,10 +378,10 @@ function createFetchCatalogEntityAction(options) {
|
|
|
380
378
|
}
|
|
381
379
|
throw new Error("Missing entity reference or references");
|
|
382
380
|
}
|
|
383
|
-
const { token } =
|
|
381
|
+
const { token } = await auth?.getPluginRequestToken({
|
|
384
382
|
onBehalfOf: await ctx.getInitiatorCredentials(),
|
|
385
383
|
targetPluginId: "catalog"
|
|
386
|
-
})
|
|
384
|
+
}) ?? { token: ctx.secrets?.backstageToken };
|
|
387
385
|
if (entityRef) {
|
|
388
386
|
const entity = await catalogClient.getEntityByRef(
|
|
389
387
|
catalogModel.stringifyEntityRef(
|
|
@@ -396,7 +394,7 @@ function createFetchCatalogEntityAction(options) {
|
|
|
396
394
|
if (!entity && !optional) {
|
|
397
395
|
throw new Error(`Entity ${entityRef} not found`);
|
|
398
396
|
}
|
|
399
|
-
ctx.output("entity", entity
|
|
397
|
+
ctx.output("entity", entity ?? null);
|
|
400
398
|
}
|
|
401
399
|
if (entityRefs) {
|
|
402
400
|
const entities = await catalogClient.getEntitiesByRefs(
|
|
@@ -415,7 +413,7 @@ function createFetchCatalogEntityAction(options) {
|
|
|
415
413
|
if (!e && !optional) {
|
|
416
414
|
throw new Error(`Entity ${entityRefs[i]} not found`);
|
|
417
415
|
}
|
|
418
|
-
return e
|
|
416
|
+
return e ?? null;
|
|
419
417
|
});
|
|
420
418
|
ctx.output("entities", finalEntities);
|
|
421
419
|
}
|
|
@@ -482,12 +480,11 @@ function createDebugLogAction() {
|
|
|
482
480
|
},
|
|
483
481
|
supportsDryRun: true,
|
|
484
482
|
async handler(ctx) {
|
|
485
|
-
var _a, _b;
|
|
486
483
|
ctx.logger.info(JSON.stringify(ctx.input, null, 2));
|
|
487
|
-
if (
|
|
484
|
+
if (ctx.input?.message) {
|
|
488
485
|
ctx.logger.info(ctx.input.message);
|
|
489
486
|
}
|
|
490
|
-
if (
|
|
487
|
+
if (ctx.input?.listWorkspace) {
|
|
491
488
|
const files = await recursiveReadDir(ctx.workspacePath);
|
|
492
489
|
ctx.logger.info(
|
|
493
490
|
`Workspace:
|
|
@@ -593,20 +590,18 @@ function createWaitAction(options) {
|
|
|
593
590
|
},
|
|
594
591
|
async handler(ctx) {
|
|
595
592
|
const delayTime = luxon.Duration.fromObject(ctx.input);
|
|
596
|
-
const maxWait = toDuration(options
|
|
593
|
+
const maxWait = toDuration(options?.maxWaitTime);
|
|
597
594
|
if (delayTime.minus(maxWait).toMillis() > 0) {
|
|
598
595
|
throw new Error(
|
|
599
596
|
`Waiting duration is longer than the maximum threshold of ${maxWait.toHuman()}`
|
|
600
597
|
);
|
|
601
598
|
}
|
|
602
599
|
await new Promise((resolve) => {
|
|
603
|
-
var _a;
|
|
604
600
|
const controller = new AbortController();
|
|
605
601
|
const timeoutHandle = setTimeout(abort, delayTime.toMillis());
|
|
606
|
-
|
|
602
|
+
ctx.signal?.addEventListener("abort", abort);
|
|
607
603
|
function abort() {
|
|
608
|
-
|
|
609
|
-
(_a2 = ctx.signal) == null ? void 0 : _a2.removeEventListener("abort", abort);
|
|
604
|
+
ctx.signal?.removeEventListener("abort", abort);
|
|
610
605
|
clearTimeout(timeoutHandle);
|
|
611
606
|
controller.abort();
|
|
612
607
|
resolve("finished");
|
|
@@ -682,14 +677,13 @@ function createFetchPlainAction(options) {
|
|
|
682
677
|
},
|
|
683
678
|
supportsDryRun: true,
|
|
684
679
|
async handler(ctx) {
|
|
685
|
-
var _a, _b;
|
|
686
680
|
ctx.logger.info("Fetching plain content from remote URL");
|
|
687
|
-
const targetPath =
|
|
681
|
+
const targetPath = ctx.input.targetPath ?? "./";
|
|
688
682
|
const outputPath = backendPluginApi.resolveSafeChildPath(ctx.workspacePath, targetPath);
|
|
689
683
|
await pluginScaffolderNode.fetchContents({
|
|
690
684
|
reader,
|
|
691
685
|
integrations,
|
|
692
|
-
baseUrl:
|
|
686
|
+
baseUrl: ctx.templateInfo?.baseUrl,
|
|
693
687
|
fetchUrl: ctx.input.url,
|
|
694
688
|
outputPath,
|
|
695
689
|
token: ctx.input.token
|
|
@@ -748,7 +742,6 @@ function createFetchPlainFileAction(options) {
|
|
|
748
742
|
},
|
|
749
743
|
supportsDryRun: true,
|
|
750
744
|
async handler(ctx) {
|
|
751
|
-
var _a;
|
|
752
745
|
ctx.logger.info("Fetching plain content from remote URL");
|
|
753
746
|
const outputPath = backendPluginApi.resolveSafeChildPath(
|
|
754
747
|
ctx.workspacePath,
|
|
@@ -757,7 +750,7 @@ function createFetchPlainFileAction(options) {
|
|
|
757
750
|
await pluginScaffolderNode.fetchFile({
|
|
758
751
|
reader,
|
|
759
752
|
integrations,
|
|
760
|
-
baseUrl:
|
|
753
|
+
baseUrl: ctx.templateInfo?.baseUrl,
|
|
761
754
|
fetchUrl: ctx.input.url,
|
|
762
755
|
outputPath,
|
|
763
756
|
token: ctx.input.token
|
|
@@ -767,8 +760,7 @@ function createFetchPlainFileAction(options) {
|
|
|
767
760
|
}
|
|
768
761
|
|
|
769
762
|
function isNoNodeSnapshotOptionProvided() {
|
|
770
|
-
|
|
771
|
-
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");
|
|
772
764
|
}
|
|
773
765
|
function getMajorNodeVersion() {
|
|
774
766
|
const version = process.versions.node;
|
|
@@ -1043,11 +1035,10 @@ function createFetchTemplateAction(options) {
|
|
|
1043
1035
|
},
|
|
1044
1036
|
supportsDryRun: true,
|
|
1045
1037
|
async handler(ctx) {
|
|
1046
|
-
var _a, _b;
|
|
1047
1038
|
ctx.logger.info("Fetching template content from remote URL");
|
|
1048
1039
|
const workDir = await ctx.createTemporaryDirectory();
|
|
1049
1040
|
const templateDir = backendPluginApi.resolveSafeChildPath(workDir, "template");
|
|
1050
|
-
const targetPath =
|
|
1041
|
+
const targetPath = ctx.input.targetPath ?? "./";
|
|
1051
1042
|
const outputDir = backendPluginApi.resolveSafeChildPath(ctx.workspacePath, targetPath);
|
|
1052
1043
|
if (ctx.input.copyWithoutRender && ctx.input.copyWithoutTemplating) {
|
|
1053
1044
|
throw new errors.InputError(
|
|
@@ -1086,7 +1077,7 @@ function createFetchTemplateAction(options) {
|
|
|
1086
1077
|
await pluginScaffolderNode.fetchContents({
|
|
1087
1078
|
reader,
|
|
1088
1079
|
integrations,
|
|
1089
|
-
baseUrl:
|
|
1080
|
+
baseUrl: ctx.templateInfo?.baseUrl,
|
|
1090
1081
|
fetchUrl: ctx.input.url,
|
|
1091
1082
|
outputPath: templateDir,
|
|
1092
1083
|
token: ctx.input.token
|
|
@@ -1233,8 +1224,7 @@ const createFilesystemDeleteAction = () => {
|
|
|
1233
1224
|
},
|
|
1234
1225
|
supportsDryRun: true,
|
|
1235
1226
|
async handler(ctx) {
|
|
1236
|
-
|
|
1237
|
-
if (!Array.isArray((_a = ctx.input) == null ? void 0 : _a.files)) {
|
|
1227
|
+
if (!Array.isArray(ctx.input?.files)) {
|
|
1238
1228
|
throw new errors.InputError("files must be an Array");
|
|
1239
1229
|
}
|
|
1240
1230
|
for (const file of ctx.input.files) {
|
|
@@ -1311,8 +1301,7 @@ const createFilesystemRenameAction = () => {
|
|
|
1311
1301
|
},
|
|
1312
1302
|
supportsDryRun: true,
|
|
1313
1303
|
async handler(ctx) {
|
|
1314
|
-
|
|
1315
|
-
if (!Array.isArray((_a = ctx.input) == null ? void 0 : _a.files)) {
|
|
1304
|
+
if (!Array.isArray(ctx.input?.files)) {
|
|
1316
1305
|
throw new errors.InputError("files must be an Array");
|
|
1317
1306
|
}
|
|
1318
1307
|
for (const file of ctx.input.files) {
|
|
@@ -1326,7 +1315,7 @@ const createFilesystemRenameAction = () => {
|
|
|
1326
1315
|
const destFilepath = backendPluginApi.resolveSafeChildPath(ctx.workspacePath, file.to);
|
|
1327
1316
|
try {
|
|
1328
1317
|
await fs__default.default.move(sourceFilepath, destFilepath, {
|
|
1329
|
-
overwrite:
|
|
1318
|
+
overwrite: file.overwrite ?? false
|
|
1330
1319
|
});
|
|
1331
1320
|
ctx.logger.info(
|
|
1332
1321
|
`File ${sourceFilepath} renamed to ${destFilepath} successfully`
|
|
@@ -1466,16 +1455,8 @@ const createBuiltinActions = (options) => {
|
|
|
1466
1455
|
return actions;
|
|
1467
1456
|
};
|
|
1468
1457
|
|
|
1469
|
-
var __defProp$4 = Object.defineProperty;
|
|
1470
|
-
var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1471
|
-
var __publicField$4 = (obj, key, value) => {
|
|
1472
|
-
__defNormalProp$4(obj, key + "" , value);
|
|
1473
|
-
return value;
|
|
1474
|
-
};
|
|
1475
1458
|
class TemplateActionRegistry {
|
|
1476
|
-
|
|
1477
|
-
__publicField$4(this, "actions", /* @__PURE__ */ new Map());
|
|
1478
|
-
}
|
|
1459
|
+
actions = /* @__PURE__ */ new Map();
|
|
1479
1460
|
register(action) {
|
|
1480
1461
|
if (this.actions.has(action.id)) {
|
|
1481
1462
|
throw new errors.ConflictError(
|
|
@@ -1545,12 +1526,6 @@ const restoreWorkspace = async (path, buffer) => {
|
|
|
1545
1526
|
}
|
|
1546
1527
|
};
|
|
1547
1528
|
|
|
1548
|
-
var __defProp$3 = Object.defineProperty;
|
|
1549
|
-
var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1550
|
-
var __publicField$3 = (obj, key, value) => {
|
|
1551
|
-
__defNormalProp$3(obj, key + "" , value);
|
|
1552
|
-
return value;
|
|
1553
|
-
};
|
|
1554
1529
|
const migrationsDir = backendPluginApi.resolvePackagePath(
|
|
1555
1530
|
"@backstage/plugin-scaffolder-backend",
|
|
1556
1531
|
"migrations"
|
|
@@ -1571,10 +1546,7 @@ const parseSqlDateToIsoString = (input) => {
|
|
|
1571
1546
|
return input;
|
|
1572
1547
|
};
|
|
1573
1548
|
class DatabaseTaskStore {
|
|
1574
|
-
|
|
1575
|
-
__publicField$3(this, "db");
|
|
1576
|
-
this.db = client;
|
|
1577
|
-
}
|
|
1549
|
+
db;
|
|
1578
1550
|
static async create(options) {
|
|
1579
1551
|
const { database } = options;
|
|
1580
1552
|
const client = await this.getClient(database);
|
|
@@ -1582,9 +1554,8 @@ class DatabaseTaskStore {
|
|
|
1582
1554
|
return new DatabaseTaskStore(client);
|
|
1583
1555
|
}
|
|
1584
1556
|
isRecoverableTask(spec) {
|
|
1585
|
-
var _a, _b;
|
|
1586
1557
|
return ["startOver"].includes(
|
|
1587
|
-
|
|
1558
|
+
spec.EXPERIMENTAL_recovery?.EXPERIMENTAL_strategy ?? "none"
|
|
1588
1559
|
);
|
|
1589
1560
|
}
|
|
1590
1561
|
parseSpec({ spec, id }) {
|
|
@@ -1610,19 +1581,21 @@ class DatabaseTaskStore {
|
|
|
1610
1581
|
return database;
|
|
1611
1582
|
}
|
|
1612
1583
|
static async runMigrations(database, client) {
|
|
1613
|
-
var _a;
|
|
1614
1584
|
if (!isPluginDatabaseManager(database)) {
|
|
1615
1585
|
await client.migrate.latest({
|
|
1616
1586
|
directory: migrationsDir
|
|
1617
1587
|
});
|
|
1618
1588
|
return;
|
|
1619
1589
|
}
|
|
1620
|
-
if (!
|
|
1590
|
+
if (!database.migrations?.skip) {
|
|
1621
1591
|
await client.migrate.latest({
|
|
1622
1592
|
directory: migrationsDir
|
|
1623
1593
|
});
|
|
1624
1594
|
}
|
|
1625
1595
|
}
|
|
1596
|
+
constructor(client) {
|
|
1597
|
+
this.db = client;
|
|
1598
|
+
}
|
|
1626
1599
|
async list(options) {
|
|
1627
1600
|
const queryBuilder = this.db("tasks");
|
|
1628
1601
|
if (options.createdBy) {
|
|
@@ -1631,21 +1604,17 @@ class DatabaseTaskStore {
|
|
|
1631
1604
|
});
|
|
1632
1605
|
}
|
|
1633
1606
|
const results = await queryBuilder.orderBy("created_at", "desc").select();
|
|
1634
|
-
const tasks = results.map((result) => {
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
createdAt: parseSqlDateToIsoString(result.created_at)
|
|
1643
|
-
};
|
|
1644
|
-
});
|
|
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
|
+
}));
|
|
1645
1615
|
return { tasks };
|
|
1646
1616
|
}
|
|
1647
1617
|
async getTask(taskId) {
|
|
1648
|
-
var _a;
|
|
1649
1618
|
const [result] = await this.db("tasks").where({ id: taskId }).select();
|
|
1650
1619
|
if (!result) {
|
|
1651
1620
|
throw new errors.NotFoundError(`No task with id '${taskId}' found`);
|
|
@@ -1660,7 +1629,7 @@ class DatabaseTaskStore {
|
|
|
1660
1629
|
status: result.status,
|
|
1661
1630
|
lastHeartbeatAt: parseSqlDateToIsoString(result.last_heartbeat_at),
|
|
1662
1631
|
createdAt: parseSqlDateToIsoString(result.created_at),
|
|
1663
|
-
createdBy:
|
|
1632
|
+
createdBy: result.created_by ?? void 0,
|
|
1664
1633
|
secrets,
|
|
1665
1634
|
state
|
|
1666
1635
|
};
|
|
@@ -1669,20 +1638,18 @@ class DatabaseTaskStore {
|
|
|
1669
1638
|
}
|
|
1670
1639
|
}
|
|
1671
1640
|
async createTask(options) {
|
|
1672
|
-
var _a;
|
|
1673
1641
|
const taskId = uuid.v4();
|
|
1674
1642
|
await this.db("tasks").insert({
|
|
1675
1643
|
id: taskId,
|
|
1676
1644
|
spec: JSON.stringify(options.spec),
|
|
1677
1645
|
secrets: options.secrets ? JSON.stringify(options.secrets) : void 0,
|
|
1678
|
-
created_by:
|
|
1646
|
+
created_by: options.createdBy ?? null,
|
|
1679
1647
|
status: "open"
|
|
1680
1648
|
});
|
|
1681
1649
|
return { taskId };
|
|
1682
1650
|
}
|
|
1683
1651
|
async claimTask() {
|
|
1684
1652
|
return this.db.transaction(async (tx) => {
|
|
1685
|
-
var _a;
|
|
1686
1653
|
const [task] = await tx("tasks").where({
|
|
1687
1654
|
status: "open"
|
|
1688
1655
|
}).limit(1).select();
|
|
@@ -1715,7 +1682,7 @@ class DatabaseTaskStore {
|
|
|
1715
1682
|
status: "processing",
|
|
1716
1683
|
lastHeartbeatAt: task.last_heartbeat_at,
|
|
1717
1684
|
createdAt: task.created_at,
|
|
1718
|
-
createdBy:
|
|
1685
|
+
createdBy: task.created_by ?? void 0,
|
|
1719
1686
|
secrets,
|
|
1720
1687
|
state: getState()
|
|
1721
1688
|
};
|
|
@@ -1844,7 +1811,7 @@ class DatabaseTaskStore {
|
|
|
1844
1811
|
const { taskId } = options;
|
|
1845
1812
|
const message = `This task was marked as stale as it exceeded its timeout`;
|
|
1846
1813
|
const statusStepEvents = (await this.listEvents({ taskId })).events.filter(
|
|
1847
|
-
({ body }) => body
|
|
1814
|
+
({ body }) => body?.stepId
|
|
1848
1815
|
);
|
|
1849
1816
|
const completedSteps = statusStepEvents.filter(
|
|
1850
1817
|
({ body: { status } }) => status === "failed" || status === "completed"
|
|
@@ -1897,7 +1864,6 @@ class DatabaseTaskStore {
|
|
|
1897
1864
|
const taskIdsToRecover = [];
|
|
1898
1865
|
const timeoutS = luxon.Duration.fromObject(options.timeout).as("seconds");
|
|
1899
1866
|
await this.db.transaction(async (tx) => {
|
|
1900
|
-
var _a, _b;
|
|
1901
1867
|
const heartbeatInterval = intervalFromNowTill(timeoutS, this.db);
|
|
1902
1868
|
const result = await tx("tasks").where("status", "processing").andWhere("last_heartbeat_at", "<=", heartbeatInterval).update(
|
|
1903
1869
|
{
|
|
@@ -1913,7 +1879,7 @@ class DatabaseTaskStore {
|
|
|
1913
1879
|
task_id: id,
|
|
1914
1880
|
event_type: "recovered",
|
|
1915
1881
|
body: JSON.stringify({
|
|
1916
|
-
recoverStrategy:
|
|
1882
|
+
recoverStrategy: taskSpec.EXPERIMENTAL_recovery?.EXPERIMENTAL_strategy ?? "none"
|
|
1917
1883
|
})
|
|
1918
1884
|
});
|
|
1919
1885
|
}
|
|
@@ -1926,20 +1892,19 @@ function isTruthy(value) {
|
|
|
1926
1892
|
return lodash.isArray(value) ? value.length > 0 : !!value;
|
|
1927
1893
|
}
|
|
1928
1894
|
function generateExampleOutput(schema) {
|
|
1929
|
-
var _a, _b;
|
|
1930
1895
|
const { examples } = schema;
|
|
1931
1896
|
if (examples && Array.isArray(examples)) {
|
|
1932
1897
|
return examples[0];
|
|
1933
1898
|
}
|
|
1934
1899
|
if (schema.type === "object") {
|
|
1935
1900
|
return Object.fromEntries(
|
|
1936
|
-
Object.entries(
|
|
1901
|
+
Object.entries(schema.properties ?? {}).map(([key, value]) => [
|
|
1937
1902
|
key,
|
|
1938
1903
|
generateExampleOutput(value)
|
|
1939
1904
|
])
|
|
1940
1905
|
);
|
|
1941
1906
|
} else if (schema.type === "array") {
|
|
1942
|
-
const [firstSchema] =
|
|
1907
|
+
const [firstSchema] = [schema.items]?.flat();
|
|
1943
1908
|
if (firstSchema) {
|
|
1944
1909
|
return [generateExampleOutput(firstSchema)];
|
|
1945
1910
|
}
|
|
@@ -1954,18 +1919,12 @@ function generateExampleOutput(schema) {
|
|
|
1954
1919
|
return "<unknown>";
|
|
1955
1920
|
}
|
|
1956
1921
|
const readDuration$1 = (config$1, key, defaultValue) => {
|
|
1957
|
-
if (config$1
|
|
1922
|
+
if (config$1?.has(key)) {
|
|
1958
1923
|
return config.readDurationFromConfig(config$1, { key });
|
|
1959
1924
|
}
|
|
1960
1925
|
return defaultValue;
|
|
1961
1926
|
};
|
|
1962
1927
|
|
|
1963
|
-
var __defProp$2 = Object.defineProperty;
|
|
1964
|
-
var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1965
|
-
var __publicField$2 = (obj, key, value) => {
|
|
1966
|
-
__defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1967
|
-
return value;
|
|
1968
|
-
};
|
|
1969
1928
|
class TaskManager {
|
|
1970
1929
|
// Runs heartbeat internally
|
|
1971
1930
|
constructor(task, storage, signal, logger, auth, config) {
|
|
@@ -1975,9 +1934,9 @@ class TaskManager {
|
|
|
1975
1934
|
this.logger = logger;
|
|
1976
1935
|
this.auth = auth;
|
|
1977
1936
|
this.config = config;
|
|
1978
|
-
__publicField$2(this, "isDone", false);
|
|
1979
|
-
__publicField$2(this, "heartbeatTimeoutId");
|
|
1980
1937
|
}
|
|
1938
|
+
isDone = false;
|
|
1939
|
+
heartbeatTimeoutId;
|
|
1981
1940
|
static create(task, storage, abortSignal, logger, auth, config) {
|
|
1982
1941
|
const agent = new TaskManager(
|
|
1983
1942
|
task,
|
|
@@ -2006,9 +1965,8 @@ class TaskManager {
|
|
|
2006
1965
|
return this.task.taskId;
|
|
2007
1966
|
}
|
|
2008
1967
|
async rehydrateWorkspace(options) {
|
|
2009
|
-
var _a, _b;
|
|
2010
1968
|
if (this.isWorkspaceSerializationEnabled()) {
|
|
2011
|
-
|
|
1969
|
+
this.storage.rehydrateWorkspace?.(options);
|
|
2012
1970
|
}
|
|
2013
1971
|
}
|
|
2014
1972
|
get done() {
|
|
@@ -2021,35 +1979,31 @@ class TaskManager {
|
|
|
2021
1979
|
});
|
|
2022
1980
|
}
|
|
2023
1981
|
async getTaskState() {
|
|
2024
|
-
|
|
2025
|
-
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 });
|
|
2026
1983
|
}
|
|
2027
1984
|
async updateCheckpoint(options) {
|
|
2028
|
-
var _a, _b;
|
|
2029
1985
|
const { key, ...value } = options;
|
|
2030
1986
|
if (this.task.state) {
|
|
2031
1987
|
this.task.state.checkpoints[key] = value;
|
|
2032
1988
|
} else {
|
|
2033
1989
|
this.task.state = { checkpoints: { [key]: value } };
|
|
2034
1990
|
}
|
|
2035
|
-
await
|
|
1991
|
+
await this.storage.saveTaskState?.({
|
|
2036
1992
|
taskId: this.task.taskId,
|
|
2037
1993
|
state: this.task.state
|
|
2038
|
-
})
|
|
1994
|
+
});
|
|
2039
1995
|
}
|
|
2040
1996
|
async serializeWorkspace(options) {
|
|
2041
|
-
var _a, _b;
|
|
2042
1997
|
if (this.isWorkspaceSerializationEnabled()) {
|
|
2043
|
-
await
|
|
1998
|
+
await this.storage.serializeWorkspace?.({
|
|
2044
1999
|
path: options.path,
|
|
2045
2000
|
taskId: this.task.taskId
|
|
2046
|
-
})
|
|
2001
|
+
});
|
|
2047
2002
|
}
|
|
2048
2003
|
}
|
|
2049
2004
|
async cleanWorkspace() {
|
|
2050
|
-
var _a, _b;
|
|
2051
2005
|
if (this.isWorkspaceSerializationEnabled()) {
|
|
2052
|
-
await
|
|
2006
|
+
await this.storage.cleanWorkspace?.({ taskId: this.task.taskId });
|
|
2053
2007
|
}
|
|
2054
2008
|
}
|
|
2055
2009
|
async complete(result, metadata) {
|
|
@@ -2081,10 +2035,9 @@ class TaskManager {
|
|
|
2081
2035
|
}, 1e3);
|
|
2082
2036
|
}
|
|
2083
2037
|
isWorkspaceSerializationEnabled() {
|
|
2084
|
-
|
|
2085
|
-
return (_b = (_a = this.config) == null ? void 0 : _a.getOptionalBoolean(
|
|
2038
|
+
return this.config?.getOptionalBoolean(
|
|
2086
2039
|
"scaffolder.EXPERIMENTAL_workspaceSerialization"
|
|
2087
|
-
)
|
|
2040
|
+
) ?? false;
|
|
2088
2041
|
}
|
|
2089
2042
|
async getInitiatorCredentials() {
|
|
2090
2043
|
const secrets = this.task.secrets;
|
|
@@ -2113,7 +2066,6 @@ class StorageTaskBroker {
|
|
|
2113
2066
|
this.logger = logger;
|
|
2114
2067
|
this.config = config;
|
|
2115
2068
|
this.auth = auth;
|
|
2116
|
-
__publicField$2(this, "deferredDispatch", defer());
|
|
2117
2069
|
}
|
|
2118
2070
|
async list(options) {
|
|
2119
2071
|
if (!this.storage.list) {
|
|
@@ -2121,8 +2073,9 @@ class StorageTaskBroker {
|
|
|
2121
2073
|
"TaskStore does not implement the list method. Please implement the list method to be able to list tasks"
|
|
2122
2074
|
);
|
|
2123
2075
|
}
|
|
2124
|
-
return await this.storage.list({ createdBy: options
|
|
2076
|
+
return await this.storage.list({ createdBy: options?.createdBy });
|
|
2125
2077
|
}
|
|
2078
|
+
deferredDispatch = defer();
|
|
2126
2079
|
async registerCancellable(taskId, abortController) {
|
|
2127
2080
|
let shouldUnsubscribe = false;
|
|
2128
2081
|
const subscription = this.event$({ taskId, after: void 0 }).subscribe({
|
|
@@ -2146,10 +2099,9 @@ class StorageTaskBroker {
|
|
|
2146
2099
|
});
|
|
2147
2100
|
}
|
|
2148
2101
|
async recoverTasks() {
|
|
2149
|
-
|
|
2150
|
-
const enabled = (_a = this.config && this.config.getOptionalBoolean(
|
|
2102
|
+
const enabled = (this.config && this.config.getOptionalBoolean(
|
|
2151
2103
|
"scaffolder.EXPERIMENTAL_recoverTasks"
|
|
2152
|
-
))
|
|
2104
|
+
)) ?? false;
|
|
2153
2105
|
if (enabled) {
|
|
2154
2106
|
const defaultTimeout = { seconds: 30 };
|
|
2155
2107
|
const timeout = readDuration$1(
|
|
@@ -2157,9 +2109,9 @@ class StorageTaskBroker {
|
|
|
2157
2109
|
"scaffolder.EXPERIMENTAL_recoverTasksTimeout",
|
|
2158
2110
|
defaultTimeout
|
|
2159
2111
|
);
|
|
2160
|
-
const { ids: recoveredTaskIds } =
|
|
2112
|
+
const { ids: recoveredTaskIds } = await this.storage.recoverTasks?.({
|
|
2161
2113
|
timeout
|
|
2162
|
-
})
|
|
2114
|
+
}) ?? { ids: [] };
|
|
2163
2115
|
if (recoveredTaskIds.length > 0) {
|
|
2164
2116
|
this.signalDispatch();
|
|
2165
2117
|
}
|
|
@@ -2261,17 +2213,16 @@ class StorageTaskBroker {
|
|
|
2261
2213
|
this.deferredDispatch = defer();
|
|
2262
2214
|
}
|
|
2263
2215
|
async cancel(taskId) {
|
|
2264
|
-
var _a, _b;
|
|
2265
2216
|
const { events } = await this.storage.listEvents({ taskId });
|
|
2266
|
-
const currentStepId = events.length > 0 ? events.filter(({ body }) => body
|
|
2267
|
-
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?.({
|
|
2268
2219
|
taskId,
|
|
2269
2220
|
body: {
|
|
2270
2221
|
message: `Step ${currentStepId} has been cancelled.`,
|
|
2271
2222
|
stepId: currentStepId,
|
|
2272
2223
|
status: "cancelled"
|
|
2273
2224
|
}
|
|
2274
|
-
})
|
|
2225
|
+
});
|
|
2275
2226
|
}
|
|
2276
2227
|
}
|
|
2277
2228
|
|
|
@@ -2301,8 +2252,7 @@ const hasTag = createTemplatePermissionRule({
|
|
|
2301
2252
|
tag: zod.z.string().describe("Name of the tag to match on")
|
|
2302
2253
|
}),
|
|
2303
2254
|
apply: (resource, { tag }) => {
|
|
2304
|
-
|
|
2305
|
-
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;
|
|
2306
2256
|
},
|
|
2307
2257
|
toQuery: () => ({})
|
|
2308
2258
|
});
|
|
@@ -2373,25 +2323,6 @@ const scaffolderActionRules = {
|
|
|
2373
2323
|
hasStringProperty
|
|
2374
2324
|
};
|
|
2375
2325
|
|
|
2376
|
-
var __accessCheck = (obj, member, msg) => {
|
|
2377
|
-
if (!member.has(obj))
|
|
2378
|
-
throw TypeError("Cannot " + msg);
|
|
2379
|
-
};
|
|
2380
|
-
var __privateGet = (obj, member, getter) => {
|
|
2381
|
-
__accessCheck(obj, member, "read from private field");
|
|
2382
|
-
return member.get(obj);
|
|
2383
|
-
};
|
|
2384
|
-
var __privateAdd = (obj, member, value) => {
|
|
2385
|
-
if (member.has(obj))
|
|
2386
|
-
throw TypeError("Cannot add the same private member more than once");
|
|
2387
|
-
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
2388
|
-
};
|
|
2389
|
-
var __privateSet = (obj, member, value, setter) => {
|
|
2390
|
-
__accessCheck(obj, member, "write to private field");
|
|
2391
|
-
member.set(obj, value);
|
|
2392
|
-
return value;
|
|
2393
|
-
};
|
|
2394
|
-
var _winston, _addRedactions;
|
|
2395
2326
|
const escapeRegExp = (text) => {
|
|
2396
2327
|
return text.replace(/[.*+?^${}(\)|[\]\\]/g, "\\$&");
|
|
2397
2328
|
};
|
|
@@ -2425,28 +2356,23 @@ class BackstageLoggerTransport extends Transport__default.default {
|
|
|
2425
2356
|
callback();
|
|
2426
2357
|
}
|
|
2427
2358
|
}
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
__privateAdd(this, _addRedactions, void 0);
|
|
2432
|
-
__privateSet(this, _winston, winston);
|
|
2433
|
-
__privateSet(this, _addRedactions, addRedactions);
|
|
2434
|
-
}
|
|
2359
|
+
class WinstonLogger {
|
|
2360
|
+
#winston;
|
|
2361
|
+
#addRedactions;
|
|
2435
2362
|
/**
|
|
2436
2363
|
* Creates a {@link WinstonLogger} instance.
|
|
2437
2364
|
*/
|
|
2438
2365
|
static create(options) {
|
|
2439
|
-
|
|
2440
|
-
const redacter = _WinstonLogger.redacter();
|
|
2366
|
+
const redacter = WinstonLogger.redacter();
|
|
2441
2367
|
let logger = winston.createLogger({
|
|
2442
2368
|
level: options.level,
|
|
2443
2369
|
format: winston.format.combine(redacter.format, options.format),
|
|
2444
|
-
transports:
|
|
2370
|
+
transports: options.transports ?? new winston.transports.Console()
|
|
2445
2371
|
});
|
|
2446
2372
|
if (options.meta) {
|
|
2447
2373
|
logger = logger.child(options.meta);
|
|
2448
2374
|
}
|
|
2449
|
-
return new
|
|
2375
|
+
return new WinstonLogger(logger, redacter.add);
|
|
2450
2376
|
}
|
|
2451
2377
|
/**
|
|
2452
2378
|
* Creates a winston log formatter for redacting secrets.
|
|
@@ -2454,21 +2380,14 @@ const _WinstonLogger = class _WinstonLogger {
|
|
|
2454
2380
|
static redacter() {
|
|
2455
2381
|
const redactionSet = /* @__PURE__ */ new Set();
|
|
2456
2382
|
let redactionPattern = void 0;
|
|
2457
|
-
const replace = (obj) => {
|
|
2458
|
-
var _a;
|
|
2459
|
-
for (const key in obj) {
|
|
2460
|
-
if (obj.hasOwnProperty(key)) {
|
|
2461
|
-
if (typeof obj[key] === "object") {
|
|
2462
|
-
obj[key] = replace(obj[key]);
|
|
2463
|
-
} else if (typeof obj[key] === "string") {
|
|
2464
|
-
obj[key] = (_a = obj[key]) == null ? void 0 : _a.replace(redactionPattern, "[REDACTED]");
|
|
2465
|
-
}
|
|
2466
|
-
}
|
|
2467
|
-
}
|
|
2468
|
-
return obj;
|
|
2469
|
-
};
|
|
2470
2383
|
return {
|
|
2471
|
-
format: winston.format(
|
|
2384
|
+
format: winston.format((obj) => {
|
|
2385
|
+
if (!redactionPattern || !obj) {
|
|
2386
|
+
return obj;
|
|
2387
|
+
}
|
|
2388
|
+
obj[tripleBeam.MESSAGE] = obj[tripleBeam.MESSAGE]?.replace?.(redactionPattern, "***");
|
|
2389
|
+
return obj;
|
|
2390
|
+
})(),
|
|
2472
2391
|
add(newRedactions) {
|
|
2473
2392
|
let added = 0;
|
|
2474
2393
|
for (const redactionToTrim of newRedactions) {
|
|
@@ -2515,36 +2434,30 @@ const _WinstonLogger = class _WinstonLogger {
|
|
|
2515
2434
|
})
|
|
2516
2435
|
);
|
|
2517
2436
|
}
|
|
2437
|
+
constructor(winston, addRedactions) {
|
|
2438
|
+
this.#winston = winston;
|
|
2439
|
+
this.#addRedactions = addRedactions;
|
|
2440
|
+
}
|
|
2518
2441
|
error(message, meta) {
|
|
2519
|
-
|
|
2442
|
+
this.#winston.error(message, meta);
|
|
2520
2443
|
}
|
|
2521
2444
|
warn(message, meta) {
|
|
2522
|
-
|
|
2445
|
+
this.#winston.warn(message, meta);
|
|
2523
2446
|
}
|
|
2524
2447
|
info(message, meta) {
|
|
2525
|
-
|
|
2448
|
+
this.#winston.info(message, meta);
|
|
2526
2449
|
}
|
|
2527
2450
|
debug(message, meta) {
|
|
2528
|
-
|
|
2451
|
+
this.#winston.debug(message, meta);
|
|
2529
2452
|
}
|
|
2530
2453
|
child(meta) {
|
|
2531
|
-
return new
|
|
2454
|
+
return new WinstonLogger(this.#winston.child(meta));
|
|
2532
2455
|
}
|
|
2533
2456
|
addRedactions(redactions) {
|
|
2534
|
-
|
|
2535
|
-
(_a = __privateGet(this, _addRedactions)) == null ? void 0 : _a.call(this, redactions);
|
|
2457
|
+
this.#addRedactions?.(redactions);
|
|
2536
2458
|
}
|
|
2537
|
-
}
|
|
2538
|
-
_winston = new WeakMap();
|
|
2539
|
-
_addRedactions = new WeakMap();
|
|
2540
|
-
let WinstonLogger = _WinstonLogger;
|
|
2459
|
+
}
|
|
2541
2460
|
|
|
2542
|
-
var __defProp$1 = Object.defineProperty;
|
|
2543
|
-
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
2544
|
-
var __publicField$1 = (obj, key, value) => {
|
|
2545
|
-
__defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
2546
|
-
return value;
|
|
2547
|
-
};
|
|
2548
2461
|
const isValidTaskSpec = (taskSpec) => {
|
|
2549
2462
|
return taskSpec.apiVersion === "scaffolder.backstage.io/v1beta3";
|
|
2550
2463
|
};
|
|
@@ -2553,11 +2466,10 @@ const createStepLogger = ({
|
|
|
2553
2466
|
step,
|
|
2554
2467
|
rootLogger
|
|
2555
2468
|
}) => {
|
|
2556
|
-
var _a;
|
|
2557
2469
|
const stepLogStream = new stream.PassThrough();
|
|
2558
2470
|
stepLogStream.on("data", async (data) => {
|
|
2559
2471
|
const message = data.toString().trim();
|
|
2560
|
-
if (
|
|
2472
|
+
if (message?.length > 1) {
|
|
2561
2473
|
await task.emitLog(message, { stepId: step.id });
|
|
2562
2474
|
}
|
|
2563
2475
|
});
|
|
@@ -2572,11 +2484,11 @@ const createStepLogger = ({
|
|
|
2572
2484
|
new BackstageLoggerTransport(rootLogger)
|
|
2573
2485
|
]
|
|
2574
2486
|
});
|
|
2575
|
-
taskLogger.addRedactions(Object.values(
|
|
2487
|
+
taskLogger.addRedactions(Object.values(task.secrets ?? {}));
|
|
2576
2488
|
const streamLogger = new stream.PassThrough();
|
|
2577
2489
|
streamLogger.on("data", async (data) => {
|
|
2578
2490
|
const message = data.toString().trim();
|
|
2579
|
-
if (
|
|
2491
|
+
if (message?.length > 1) {
|
|
2580
2492
|
taskLogger.info(message);
|
|
2581
2493
|
}
|
|
2582
2494
|
});
|
|
@@ -2588,14 +2500,13 @@ const isActionAuthorized = pluginPermissionNode.createConditionAuthorizer(
|
|
|
2588
2500
|
class NunjucksWorkflowRunner {
|
|
2589
2501
|
constructor(options) {
|
|
2590
2502
|
this.options = options;
|
|
2591
|
-
__publicField$1(this, "defaultTemplateFilters");
|
|
2592
|
-
__publicField$1(this, "tracker", scaffoldingTracker());
|
|
2593
2503
|
this.defaultTemplateFilters = createDefaultFilters({
|
|
2594
2504
|
integrations: this.options.integrations
|
|
2595
2505
|
});
|
|
2596
2506
|
}
|
|
2507
|
+
defaultTemplateFilters;
|
|
2508
|
+
tracker = scaffoldingTracker();
|
|
2597
2509
|
isSingleTemplateString(input) {
|
|
2598
|
-
var _a, _b;
|
|
2599
2510
|
const { parser, nodes } = nunjucks__default.default;
|
|
2600
2511
|
const parsed = parser.parse(
|
|
2601
2512
|
input,
|
|
@@ -2608,7 +2519,7 @@ class NunjucksWorkflowRunner {
|
|
|
2608
2519
|
}
|
|
2609
2520
|
}
|
|
2610
2521
|
);
|
|
2611
|
-
return parsed.children.length === 1 && !(
|
|
2522
|
+
return parsed.children.length === 1 && !(parsed.children[0]?.children?.[0] instanceof nodes.TemplateData);
|
|
2612
2523
|
}
|
|
2613
2524
|
render(input, context, renderTemplate) {
|
|
2614
2525
|
return JSON.parse(JSON.stringify(input), (_key, value) => {
|
|
@@ -2644,7 +2555,6 @@ class NunjucksWorkflowRunner {
|
|
|
2644
2555
|
});
|
|
2645
2556
|
}
|
|
2646
2557
|
async executeStep(task, step, context, renderTemplate, taskTrack, workspacePath, decision) {
|
|
2647
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
2648
2558
|
const stepTrack = await this.tracker.stepStart(task, step);
|
|
2649
2559
|
if (task.cancelSignal.aborted) {
|
|
2650
2560
|
throw new Error(`Step ${step.name} has been cancelled.`);
|
|
@@ -2665,19 +2575,16 @@ class NunjucksWorkflowRunner {
|
|
|
2665
2575
|
});
|
|
2666
2576
|
if (task.isDryRun) {
|
|
2667
2577
|
const redactedSecrets = Object.fromEntries(
|
|
2668
|
-
Object.entries(
|
|
2669
|
-
secret[0],
|
|
2670
|
-
"[REDACTED]"
|
|
2671
|
-
])
|
|
2578
|
+
Object.entries(task.secrets ?? {}).map((secret) => [secret[0], "***"])
|
|
2672
2579
|
);
|
|
2673
|
-
const debugInput = (
|
|
2580
|
+
const debugInput = (step.input && this.render(
|
|
2674
2581
|
step.input,
|
|
2675
2582
|
{
|
|
2676
2583
|
...context,
|
|
2677
2584
|
secrets: redactedSecrets
|
|
2678
2585
|
},
|
|
2679
2586
|
renderTemplate
|
|
2680
|
-
))
|
|
2587
|
+
)) ?? {};
|
|
2681
2588
|
taskLogger.info(
|
|
2682
2589
|
`Running ${action.id} in dry-run mode with inputs (secrets redacted): ${JSON.stringify(
|
|
2683
2590
|
debugInput,
|
|
@@ -2687,7 +2594,7 @@ class NunjucksWorkflowRunner {
|
|
|
2687
2594
|
);
|
|
2688
2595
|
if (!action.supportsDryRun) {
|
|
2689
2596
|
await taskTrack.skipDryRun(step, action);
|
|
2690
|
-
const outputSchema =
|
|
2597
|
+
const outputSchema = action.schema?.output;
|
|
2691
2598
|
if (outputSchema) {
|
|
2692
2599
|
context.steps[step.id] = {
|
|
2693
2600
|
output: generateExampleOutput(outputSchema)
|
|
@@ -2702,21 +2609,18 @@ class NunjucksWorkflowRunner {
|
|
|
2702
2609
|
([key, value]) => ({
|
|
2703
2610
|
each: { key, value }
|
|
2704
2611
|
})
|
|
2705
|
-
) : [{}]).map((i) => {
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
) : {}
|
|
2715
|
-
};
|
|
2716
|
-
});
|
|
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
|
+
}));
|
|
2717
2621
|
for (const iteration of iterations) {
|
|
2718
2622
|
const actionId = `${action.id}${iteration.each ? `[${iteration.each.key}]` : ""}`;
|
|
2719
|
-
if (
|
|
2623
|
+
if (action.schema?.input) {
|
|
2720
2624
|
const validateResult = jsonschema.validate(
|
|
2721
2625
|
iteration.input,
|
|
2722
2626
|
action.schema.input
|
|
@@ -2743,7 +2647,7 @@ class NunjucksWorkflowRunner {
|
|
|
2743
2647
|
}
|
|
2744
2648
|
const tmpDirs = new Array();
|
|
2745
2649
|
const stepOutput = {};
|
|
2746
|
-
const prevTaskState = await
|
|
2650
|
+
const prevTaskState = await task.getTaskState?.();
|
|
2747
2651
|
for (const iteration of iterations) {
|
|
2748
2652
|
if (iteration.each) {
|
|
2749
2653
|
taskLogger.info(
|
|
@@ -2756,25 +2660,24 @@ class NunjucksWorkflowRunner {
|
|
|
2756
2660
|
}
|
|
2757
2661
|
await action.handler({
|
|
2758
2662
|
input: iteration.input,
|
|
2759
|
-
secrets:
|
|
2663
|
+
secrets: task.secrets ?? {},
|
|
2760
2664
|
// TODO(blam): move to LoggerService and away from Winston
|
|
2761
2665
|
logger: backendCommon.loggerToWinstonLogger(taskLogger),
|
|
2762
2666
|
logStream: streamLogger,
|
|
2763
2667
|
workspacePath,
|
|
2764
2668
|
async checkpoint(keySuffix, fn) {
|
|
2765
|
-
var _a2, _b2, _c2, _d2, _e2;
|
|
2766
2669
|
const key = `v1.task.checkpoint.${keySuffix}`;
|
|
2767
2670
|
try {
|
|
2768
2671
|
let prevValue;
|
|
2769
2672
|
if (prevTaskState) {
|
|
2770
|
-
const prevState =
|
|
2673
|
+
const prevState = prevTaskState.state?.checkpoints?.[key];
|
|
2771
2674
|
if (prevState && prevState.status === "success") {
|
|
2772
2675
|
prevValue = prevState.value;
|
|
2773
2676
|
}
|
|
2774
2677
|
}
|
|
2775
2678
|
const value = prevValue ? prevValue : await fn();
|
|
2776
2679
|
if (!prevValue) {
|
|
2777
|
-
|
|
2680
|
+
task.updateCheckpoint?.({
|
|
2778
2681
|
key,
|
|
2779
2682
|
status: "success",
|
|
2780
2683
|
value
|
|
@@ -2782,14 +2685,14 @@ class NunjucksWorkflowRunner {
|
|
|
2782
2685
|
}
|
|
2783
2686
|
return value;
|
|
2784
2687
|
} catch (err) {
|
|
2785
|
-
|
|
2688
|
+
task.updateCheckpoint?.({
|
|
2786
2689
|
key,
|
|
2787
2690
|
status: "failed",
|
|
2788
2691
|
reason: errors.stringifyError(err)
|
|
2789
2692
|
});
|
|
2790
2693
|
throw err;
|
|
2791
2694
|
} finally {
|
|
2792
|
-
await
|
|
2695
|
+
await task.serializeWorkspace?.({ path: workspacePath });
|
|
2793
2696
|
}
|
|
2794
2697
|
},
|
|
2795
2698
|
createTemporaryDirectory: async () => {
|
|
@@ -2821,18 +2724,17 @@ class NunjucksWorkflowRunner {
|
|
|
2821
2724
|
if (task.cancelSignal.aborted) {
|
|
2822
2725
|
throw new Error(`Step ${step.name} has been cancelled.`);
|
|
2823
2726
|
}
|
|
2824
|
-
await
|
|
2727
|
+
await task.cleanWorkspace?.();
|
|
2825
2728
|
await stepTrack.markSuccessful();
|
|
2826
2729
|
} catch (err) {
|
|
2827
2730
|
await taskTrack.markFailed(step, err);
|
|
2828
2731
|
await stepTrack.markFailed();
|
|
2829
2732
|
throw err;
|
|
2830
2733
|
} finally {
|
|
2831
|
-
await
|
|
2734
|
+
await task.serializeWorkspace?.({ path: workspacePath });
|
|
2832
2735
|
}
|
|
2833
2736
|
}
|
|
2834
2737
|
async execute(task) {
|
|
2835
|
-
var _a;
|
|
2836
2738
|
if (!isValidTaskSpec(task.spec)) {
|
|
2837
2739
|
throw new errors.InputError(
|
|
2838
2740
|
"Wrong template version executed with the workflow engine"
|
|
@@ -2849,7 +2751,7 @@ class NunjucksWorkflowRunner {
|
|
|
2849
2751
|
templateGlobals: additionalTemplateGlobals
|
|
2850
2752
|
});
|
|
2851
2753
|
try {
|
|
2852
|
-
await
|
|
2754
|
+
await task.rehydrateWorkspace?.({ taskId, targetPath: workspacePath });
|
|
2853
2755
|
const taskTrack = await this.tracker.taskStart(task);
|
|
2854
2756
|
await fs__default.default.ensureDir(workspacePath);
|
|
2855
2757
|
const context = {
|
|
@@ -2904,10 +2806,9 @@ function scaffoldingTracker() {
|
|
|
2904
2806
|
labelNames: ["template", "step", "result"]
|
|
2905
2807
|
});
|
|
2906
2808
|
async function taskStart(task) {
|
|
2907
|
-
var _a, _b;
|
|
2908
2809
|
await task.emitLog(`Starting up task with ${task.spec.steps.length} steps`);
|
|
2909
|
-
const template =
|
|
2910
|
-
const user =
|
|
2810
|
+
const template = task.spec.templateInfo?.entityRef || "";
|
|
2811
|
+
const user = task.spec.user?.ref || "";
|
|
2911
2812
|
const taskTimer = taskDuration.startTimer({
|
|
2912
2813
|
template
|
|
2913
2814
|
});
|
|
@@ -2957,12 +2858,11 @@ function scaffoldingTracker() {
|
|
|
2957
2858
|
};
|
|
2958
2859
|
}
|
|
2959
2860
|
async function stepStart(task, step) {
|
|
2960
|
-
var _a;
|
|
2961
2861
|
await task.emitLog(`Beginning step ${step.name}`, {
|
|
2962
2862
|
stepId: step.id,
|
|
2963
2863
|
status: "processing"
|
|
2964
2864
|
});
|
|
2965
|
-
const template =
|
|
2865
|
+
const template = task.spec.templateInfo?.entityRef || "";
|
|
2966
2866
|
const stepTimer = stepDuration.startTimer({
|
|
2967
2867
|
template,
|
|
2968
2868
|
step: step.name
|
|
@@ -3015,24 +2915,18 @@ function scaffoldingTracker() {
|
|
|
3015
2915
|
};
|
|
3016
2916
|
}
|
|
3017
2917
|
|
|
3018
|
-
var __defProp = Object.defineProperty;
|
|
3019
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3020
|
-
var __publicField = (obj, key, value) => {
|
|
3021
|
-
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
3022
|
-
return value;
|
|
3023
|
-
};
|
|
3024
2918
|
class TaskWorker {
|
|
3025
2919
|
constructor(options) {
|
|
3026
2920
|
this.options = options;
|
|
3027
|
-
__publicField(this, "taskQueue");
|
|
3028
|
-
__publicField(this, "logger");
|
|
3029
|
-
__publicField(this, "stopWorkers");
|
|
3030
2921
|
this.stopWorkers = false;
|
|
3031
2922
|
this.logger = options.logger;
|
|
3032
2923
|
this.taskQueue = new PQueue__default.default({
|
|
3033
2924
|
concurrency: options.concurrentTasksLimit
|
|
3034
2925
|
});
|
|
3035
2926
|
}
|
|
2927
|
+
taskQueue;
|
|
2928
|
+
logger;
|
|
2929
|
+
stopWorkers;
|
|
3036
2930
|
static async create(options) {
|
|
3037
2931
|
const {
|
|
3038
2932
|
taskBroker,
|
|
@@ -3063,11 +2957,10 @@ class TaskWorker {
|
|
|
3063
2957
|
});
|
|
3064
2958
|
}
|
|
3065
2959
|
async recoverTasks() {
|
|
3066
|
-
var _a, _b, _c;
|
|
3067
2960
|
try {
|
|
3068
|
-
await
|
|
2961
|
+
await this.options.taskBroker.recoverTasks?.();
|
|
3069
2962
|
} catch (err) {
|
|
3070
|
-
|
|
2963
|
+
this.logger?.error(errors.stringifyError(err));
|
|
3071
2964
|
}
|
|
3072
2965
|
}
|
|
3073
2966
|
start() {
|
|
@@ -3189,7 +3082,7 @@ function createDryRunner(options) {
|
|
|
3189
3082
|
getWorkspaceName: async () => `dry-run-${dryRunId}`,
|
|
3190
3083
|
cancelSignal: abortSignal,
|
|
3191
3084
|
async emitLog(message, logMetadata) {
|
|
3192
|
-
if (
|
|
3085
|
+
if (logMetadata?.stepId === dryRunId) {
|
|
3193
3086
|
return;
|
|
3194
3087
|
}
|
|
3195
3088
|
log.push({
|
|
@@ -3236,10 +3129,9 @@ async function getWorkingDirectory(config, logger) {
|
|
|
3236
3129
|
return workingDirectory;
|
|
3237
3130
|
}
|
|
3238
3131
|
function getEntityBaseUrl(entity) {
|
|
3239
|
-
|
|
3240
|
-
let location = (_a = entity.metadata.annotations) == null ? void 0 : _a[catalogModel.ANNOTATION_SOURCE_LOCATION];
|
|
3132
|
+
let location = entity.metadata.annotations?.[catalogModel.ANNOTATION_SOURCE_LOCATION];
|
|
3241
3133
|
if (!location) {
|
|
3242
|
-
location =
|
|
3134
|
+
location = entity.metadata.annotations?.[catalogModel.ANNOTATION_LOCATION];
|
|
3243
3135
|
}
|
|
3244
3136
|
if (!location) {
|
|
3245
3137
|
return void 0;
|
|
@@ -3278,14 +3170,13 @@ function isSupportedTemplate(entity) {
|
|
|
3278
3170
|
function buildDefaultIdentityClient(options) {
|
|
3279
3171
|
return {
|
|
3280
3172
|
getIdentity: async ({ request }) => {
|
|
3281
|
-
var _a;
|
|
3282
3173
|
const header = request.headers.authorization;
|
|
3283
3174
|
const { logger } = options;
|
|
3284
3175
|
if (!header) {
|
|
3285
3176
|
return void 0;
|
|
3286
3177
|
}
|
|
3287
3178
|
try {
|
|
3288
|
-
const token =
|
|
3179
|
+
const token = header.match(/^Bearer\s(\S+\.\S+\.\S+)$/i)?.[1];
|
|
3289
3180
|
if (!token) {
|
|
3290
3181
|
throw new TypeError("Expected Bearer with JWT");
|
|
3291
3182
|
}
|
|
@@ -3326,7 +3217,6 @@ const readDuration = (config$1, key, defaultValue) => {
|
|
|
3326
3217
|
return defaultValue;
|
|
3327
3218
|
};
|
|
3328
3219
|
async function createRouter(options) {
|
|
3329
|
-
var _a;
|
|
3330
3220
|
const router = Router__default.default();
|
|
3331
3221
|
router.use(express__default.default.json({ limit: "10MB" }));
|
|
3332
3222
|
const {
|
|
@@ -3350,7 +3240,7 @@ async function createRouter(options) {
|
|
|
3350
3240
|
identity,
|
|
3351
3241
|
discovery
|
|
3352
3242
|
});
|
|
3353
|
-
const concurrentTasksLimit =
|
|
3243
|
+
const concurrentTasksLimit = options.concurrentTasksLimit ?? options.config.getOptionalNumber("scaffolder.concurrentTasksLimit");
|
|
3354
3244
|
const logger = parentLogger.child({ plugin: "scaffolder" });
|
|
3355
3245
|
const workingDirectory = await getWorkingDirectory(config, logger);
|
|
3356
3246
|
const integrations = integration.ScmIntegrations.fromConfig(config);
|
|
@@ -3465,7 +3355,6 @@ async function createRouter(options) {
|
|
|
3465
3355
|
router.get(
|
|
3466
3356
|
"/v2/templates/:namespace/:kind/:name/parameter-schema",
|
|
3467
3357
|
async (req, res) => {
|
|
3468
|
-
var _a2, _b;
|
|
3469
3358
|
const credentials = await httpAuth.credentials(req);
|
|
3470
3359
|
const { token } = await auth.getPluginRequestToken({
|
|
3471
3360
|
onBehalfOf: credentials,
|
|
@@ -3476,21 +3365,18 @@ async function createRouter(options) {
|
|
|
3476
3365
|
token,
|
|
3477
3366
|
credentials
|
|
3478
3367
|
);
|
|
3479
|
-
const parameters = [
|
|
3368
|
+
const parameters = [template.spec.parameters ?? []].flat();
|
|
3480
3369
|
const presentation = template.spec.presentation;
|
|
3481
3370
|
res.json({
|
|
3482
|
-
title:
|
|
3371
|
+
title: template.metadata.title ?? template.metadata.name,
|
|
3483
3372
|
...presentation ? { presentation } : {},
|
|
3484
3373
|
description: template.metadata.description,
|
|
3485
3374
|
"ui:options": template.metadata["ui:options"],
|
|
3486
|
-
steps: parameters.map((schema) => {
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
schema
|
|
3492
|
-
};
|
|
3493
|
-
})
|
|
3375
|
+
steps: parameters.map((schema) => ({
|
|
3376
|
+
title: schema.title ?? "Please enter the following information",
|
|
3377
|
+
description: schema.description,
|
|
3378
|
+
schema
|
|
3379
|
+
}))
|
|
3494
3380
|
});
|
|
3495
3381
|
}
|
|
3496
3382
|
).get("/v2/actions", async (_req, res) => {
|
|
@@ -3504,7 +3390,6 @@ async function createRouter(options) {
|
|
|
3504
3390
|
});
|
|
3505
3391
|
res.json(actionsList);
|
|
3506
3392
|
}).post("/v2/tasks", async (req, res) => {
|
|
3507
|
-
var _a2, _b;
|
|
3508
3393
|
const templateRef = req.body.templateRef;
|
|
3509
3394
|
const { kind, namespace, name } = catalogModel.parseEntityRef(templateRef, {
|
|
3510
3395
|
defaultKind: "template"
|
|
@@ -3527,7 +3412,7 @@ async function createRouter(options) {
|
|
|
3527
3412
|
token,
|
|
3528
3413
|
credentials
|
|
3529
3414
|
);
|
|
3530
|
-
for (const parameters of [
|
|
3415
|
+
for (const parameters of [template.spec.parameters ?? []].flat()) {
|
|
3531
3416
|
const result2 = jsonschema.validate(values, parameters);
|
|
3532
3417
|
if (!result2.valid) {
|
|
3533
3418
|
res.status(400).json({ errors: result2.errors });
|
|
@@ -3537,16 +3422,13 @@ async function createRouter(options) {
|
|
|
3537
3422
|
const baseUrl = getEntityBaseUrl(template);
|
|
3538
3423
|
const taskSpec = {
|
|
3539
3424
|
apiVersion: template.apiVersion,
|
|
3540
|
-
steps: template.spec.steps.map((step, index) => {
|
|
3541
|
-
|
|
3542
|
-
|
|
3543
|
-
|
|
3544
|
-
|
|
3545
|
-
name: (_b2 = step.name) != null ? _b2 : step.action
|
|
3546
|
-
};
|
|
3547
|
-
}),
|
|
3425
|
+
steps: template.spec.steps.map((step, index) => ({
|
|
3426
|
+
...step,
|
|
3427
|
+
id: step.id ?? `step-${index + 1}`,
|
|
3428
|
+
name: step.name ?? step.action
|
|
3429
|
+
})),
|
|
3548
3430
|
EXPERIMENTAL_recovery: template.spec.EXPERIMENTAL_recovery,
|
|
3549
|
-
output:
|
|
3431
|
+
output: template.spec.output ?? {},
|
|
3550
3432
|
parameters: values,
|
|
3551
3433
|
user: {
|
|
3552
3434
|
entity: userEntity,
|
|
@@ -3594,9 +3476,8 @@ async function createRouter(options) {
|
|
|
3594
3476
|
delete task.secrets;
|
|
3595
3477
|
res.status(200).json(task);
|
|
3596
3478
|
}).post("/v2/tasks/:taskId/cancel", async (req, res) => {
|
|
3597
|
-
var _a2;
|
|
3598
3479
|
const { taskId } = req.params;
|
|
3599
|
-
await
|
|
3480
|
+
await taskBroker.cancel?.(taskId);
|
|
3600
3481
|
res.status(200).json({ status: "cancelled" });
|
|
3601
3482
|
}).get("/v2/tasks/:taskId/eventstream", async (req, res) => {
|
|
3602
3483
|
const { taskId } = req.params;
|
|
@@ -3615,7 +3496,6 @@ async function createRouter(options) {
|
|
|
3615
3496
|
res.end();
|
|
3616
3497
|
},
|
|
3617
3498
|
next: ({ events }) => {
|
|
3618
|
-
var _a2;
|
|
3619
3499
|
let shouldUnsubscribe = false;
|
|
3620
3500
|
for (const event of events) {
|
|
3621
3501
|
res.write(
|
|
@@ -3628,7 +3508,7 @@ data: ${JSON.stringify(event)}
|
|
|
3628
3508
|
shouldUnsubscribe = true;
|
|
3629
3509
|
}
|
|
3630
3510
|
}
|
|
3631
|
-
|
|
3511
|
+
res.flush?.();
|
|
3632
3512
|
if (shouldUnsubscribe) {
|
|
3633
3513
|
subscription.unsubscribe();
|
|
3634
3514
|
res.end();
|
|
@@ -3662,7 +3542,6 @@ data: ${JSON.stringify(event)}
|
|
|
3662
3542
|
clearTimeout(timeout);
|
|
3663
3543
|
});
|
|
3664
3544
|
}).post("/v2/dry-run", async (req, res) => {
|
|
3665
|
-
var _a2, _b, _c;
|
|
3666
3545
|
const bodySchema = zod.z.object({
|
|
3667
3546
|
template: zod.z.unknown(),
|
|
3668
3547
|
values: zod.z.record(zod.z.unknown()),
|
|
@@ -3683,29 +3562,26 @@ data: ${JSON.stringify(event)}
|
|
|
3683
3562
|
onBehalfOf: credentials,
|
|
3684
3563
|
targetPluginId: "catalog"
|
|
3685
3564
|
});
|
|
3686
|
-
for (const parameters of [
|
|
3565
|
+
for (const parameters of [template.spec.parameters ?? []].flat()) {
|
|
3687
3566
|
const result2 = jsonschema.validate(body.values, parameters);
|
|
3688
3567
|
if (!result2.valid) {
|
|
3689
3568
|
res.status(400).json({ errors: result2.errors });
|
|
3690
3569
|
return;
|
|
3691
3570
|
}
|
|
3692
3571
|
}
|
|
3693
|
-
const steps = template.spec.steps.map((step, index) => {
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
|
|
3698
|
-
name: (_b2 = step.name) != null ? _b2 : step.action
|
|
3699
|
-
};
|
|
3700
|
-
});
|
|
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
|
+
}));
|
|
3701
3577
|
const result = await dryRunner({
|
|
3702
3578
|
spec: {
|
|
3703
3579
|
apiVersion: template.apiVersion,
|
|
3704
3580
|
steps,
|
|
3705
|
-
output:
|
|
3581
|
+
output: template.spec.output ?? {},
|
|
3706
3582
|
parameters: body.values
|
|
3707
3583
|
},
|
|
3708
|
-
directoryContents: (
|
|
3584
|
+
directoryContents: (body.directoryContents ?? []).map((file) => ({
|
|
3709
3585
|
path: file.path,
|
|
3710
3586
|
content: Buffer.from(file.base64Content, "base64")
|
|
3711
3587
|
})),
|
|
@@ -3782,4 +3658,4 @@ exports.createRouter = createRouter;
|
|
|
3782
3658
|
exports.createWaitAction = createWaitAction;
|
|
3783
3659
|
exports.scaffolderActionRules = scaffolderActionRules;
|
|
3784
3660
|
exports.scaffolderTemplateRules = scaffolderTemplateRules;
|
|
3785
|
-
//# sourceMappingURL=router-
|
|
3661
|
+
//# sourceMappingURL=router-CTk9mOV8.cjs.js.map
|