@backstage/plugin-scaffolder-backend 0.15.15 → 0.15.16
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 +9 -0
- package/dist/index.cjs.js +142 -146
- package/dist/index.cjs.js.map +1 -1
- package/package.json +7 -7
package/dist/index.cjs.js
CHANGED
|
@@ -45,14 +45,12 @@ function _interopNamespace(e) {
|
|
|
45
45
|
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
46
46
|
Object.defineProperty(n, k, d.get ? d : {
|
|
47
47
|
enumerable: true,
|
|
48
|
-
get: function () {
|
|
49
|
-
return e[k];
|
|
50
|
-
}
|
|
48
|
+
get: function () { return e[k]; }
|
|
51
49
|
});
|
|
52
50
|
}
|
|
53
51
|
});
|
|
54
52
|
}
|
|
55
|
-
n[
|
|
53
|
+
n["default"] = e;
|
|
56
54
|
return Object.freeze(n);
|
|
57
55
|
}
|
|
58
56
|
|
|
@@ -73,7 +71,7 @@ const createTemplateAction = (templateAction) => {
|
|
|
73
71
|
};
|
|
74
72
|
|
|
75
73
|
function createCatalogRegisterAction(options) {
|
|
76
|
-
const {catalogClient, integrations} = options;
|
|
74
|
+
const { catalogClient, integrations } = options;
|
|
77
75
|
return createTemplateAction({
|
|
78
76
|
id: "catalog:register",
|
|
79
77
|
description: "Registers entities from a catalog descriptor file in the workspace into the software catalog.",
|
|
@@ -122,12 +120,12 @@ function createCatalogRegisterAction(options) {
|
|
|
122
120
|
},
|
|
123
121
|
async handler(ctx) {
|
|
124
122
|
var _a;
|
|
125
|
-
const {input} = ctx;
|
|
123
|
+
const { input } = ctx;
|
|
126
124
|
let catalogInfoUrl;
|
|
127
125
|
if ("catalogInfoUrl" in input) {
|
|
128
126
|
catalogInfoUrl = input.catalogInfoUrl;
|
|
129
127
|
} else {
|
|
130
|
-
const {repoContentsUrl, catalogInfoPath = "/catalog-info.yaml"} = input;
|
|
128
|
+
const { repoContentsUrl, catalogInfoPath = "/catalog-info.yaml" } = input;
|
|
131
129
|
const integration = integrations.byUrl(repoContentsUrl);
|
|
132
130
|
if (!integration) {
|
|
133
131
|
throw new errors.InputError(`No integration found for host ${repoContentsUrl}`);
|
|
@@ -141,15 +139,15 @@ function createCatalogRegisterAction(options) {
|
|
|
141
139
|
await catalogClient.addLocation({
|
|
142
140
|
type: "url",
|
|
143
141
|
target: catalogInfoUrl
|
|
144
|
-
}, ctx.token ? {token: ctx.token} : {});
|
|
142
|
+
}, ctx.token ? { token: ctx.token } : {});
|
|
145
143
|
try {
|
|
146
144
|
const result = await catalogClient.addLocation({
|
|
147
145
|
dryRun: true,
|
|
148
146
|
type: "url",
|
|
149
147
|
target: catalogInfoUrl
|
|
150
|
-
}, ctx.token ? {token: ctx.token} : {});
|
|
148
|
+
}, ctx.token ? { token: ctx.token } : {});
|
|
151
149
|
if (result.entities.length > 0) {
|
|
152
|
-
const {entities} = result;
|
|
150
|
+
const { entities } = result;
|
|
153
151
|
const entity = (_a = entities.find((e) => !e.metadata.name.startsWith("generated-"))) != null ? _a : entities[0];
|
|
154
152
|
ctx.output("entityRef", catalogModel.stringifyEntityRef(entity));
|
|
155
153
|
}
|
|
@@ -181,8 +179,8 @@ function createCatalogWriteAction() {
|
|
|
181
179
|
},
|
|
182
180
|
async handler(ctx) {
|
|
183
181
|
ctx.logStream.write(`Writing catalog-info.yaml`);
|
|
184
|
-
const {entity} = ctx.input;
|
|
185
|
-
await fs__default[
|
|
182
|
+
const { entity } = ctx.input;
|
|
183
|
+
await fs__default["default"].writeFile(backendCommon.resolveSafeChildPath(ctx.workspacePath, "catalog-info.yaml"), yaml__namespace.stringify(entity));
|
|
186
184
|
}
|
|
187
185
|
});
|
|
188
186
|
}
|
|
@@ -250,8 +248,8 @@ async function fetchContents({
|
|
|
250
248
|
}
|
|
251
249
|
if (!fetchUrlIsAbsolute && (baseUrl == null ? void 0 : baseUrl.startsWith("file://"))) {
|
|
252
250
|
const basePath = baseUrl.slice("file://".length);
|
|
253
|
-
const srcDir = backendCommon.resolveSafeChildPath(path__default[
|
|
254
|
-
await fs__default[
|
|
251
|
+
const srcDir = backendCommon.resolveSafeChildPath(path__default["default"].dirname(basePath), fetchUrl);
|
|
252
|
+
await fs__default["default"].copy(srcDir, outputPath);
|
|
255
253
|
} else {
|
|
256
254
|
let readUrl;
|
|
257
255
|
if (fetchUrlIsAbsolute) {
|
|
@@ -269,13 +267,13 @@ async function fetchContents({
|
|
|
269
267
|
throw new errors.InputError(`Failed to fetch, template location could not be determined and the fetch URL is relative, ${fetchUrl}`);
|
|
270
268
|
}
|
|
271
269
|
const res = await reader.readTree(readUrl);
|
|
272
|
-
await fs__default[
|
|
273
|
-
await res.dir({targetDir: outputPath});
|
|
270
|
+
await fs__default["default"].ensureDir(outputPath);
|
|
271
|
+
await res.dir({ targetDir: outputPath });
|
|
274
272
|
}
|
|
275
273
|
}
|
|
276
274
|
|
|
277
275
|
function createFetchPlainAction(options) {
|
|
278
|
-
const {reader, integrations} = options;
|
|
276
|
+
const { reader, integrations } = options;
|
|
279
277
|
return createTemplateAction({
|
|
280
278
|
id: "fetch:plain",
|
|
281
279
|
description: "Downloads content and places it in the workspace, or optionally in a subdirectory specified by the 'targetPath' input option.",
|
|
@@ -382,15 +380,15 @@ const { render, renderCompat } = (() => {
|
|
|
382
380
|
`;
|
|
383
381
|
class SecureTemplater {
|
|
384
382
|
static async loadRenderer(options = {}) {
|
|
385
|
-
const {parseRepoUrl, cookiecutterCompat} = options;
|
|
383
|
+
const { parseRepoUrl, cookiecutterCompat } = options;
|
|
386
384
|
let sandbox = void 0;
|
|
387
385
|
if (parseRepoUrl) {
|
|
388
386
|
sandbox = {
|
|
389
387
|
parseRepoUrl: (url) => JSON.stringify(parseRepoUrl(url))
|
|
390
388
|
};
|
|
391
389
|
}
|
|
392
|
-
const vm = new vm2.VM({sandbox});
|
|
393
|
-
const nunjucksSource = await fs__default[
|
|
390
|
+
const vm = new vm2.VM({ sandbox });
|
|
391
|
+
const nunjucksSource = await fs__default["default"].readFile(backendCommon.resolvePackagePath("@backstage/plugin-scaffolder-backend", "assets/nunjucks.js.txt"), "utf-8");
|
|
394
392
|
vm.run(mkScript(nunjucksSource));
|
|
395
393
|
const render = (template, values) => {
|
|
396
394
|
if (!vm) {
|
|
@@ -408,7 +406,7 @@ class SecureTemplater {
|
|
|
408
406
|
}
|
|
409
407
|
|
|
410
408
|
function createFetchTemplateAction(options) {
|
|
411
|
-
const {reader, integrations} = options;
|
|
409
|
+
const { reader, integrations } = options;
|
|
412
410
|
return createTemplateAction({
|
|
413
411
|
id: "fetch:template",
|
|
414
412
|
description: "Downloads a skeleton, templates variables into file and directory names and content, and places the result in the workspace, or optionally in a subdirectory specified by the 'targetPath' input option.",
|
|
@@ -481,19 +479,19 @@ function createFetchTemplateAction(options) {
|
|
|
481
479
|
outputPath: templateDir
|
|
482
480
|
});
|
|
483
481
|
ctx.logger.info("Listing files and directories in template");
|
|
484
|
-
const allEntriesInTemplate = await globby__default[
|
|
482
|
+
const allEntriesInTemplate = await globby__default["default"](`**/*`, {
|
|
485
483
|
cwd: templateDir,
|
|
486
484
|
dot: true,
|
|
487
485
|
onlyFiles: false,
|
|
488
486
|
markDirectories: true
|
|
489
487
|
});
|
|
490
|
-
const nonTemplatedEntries = new Set((await Promise.all((ctx.input.copyWithoutRender || []).map((pattern) => globby__default[
|
|
488
|
+
const nonTemplatedEntries = new Set((await Promise.all((ctx.input.copyWithoutRender || []).map((pattern) => globby__default["default"](pattern, {
|
|
491
489
|
cwd: templateDir,
|
|
492
490
|
dot: true,
|
|
493
491
|
onlyFiles: false,
|
|
494
492
|
markDirectories: true
|
|
495
493
|
})))).flat());
|
|
496
|
-
const {cookiecutterCompat, values} = ctx.input;
|
|
494
|
+
const { cookiecutterCompat, values } = ctx.input;
|
|
497
495
|
const context = {
|
|
498
496
|
[cookiecutterCompat ? "cookiecutter" : "values"]: values
|
|
499
497
|
};
|
|
@@ -526,17 +524,17 @@ function createFetchTemplateAction(options) {
|
|
|
526
524
|
}
|
|
527
525
|
if (location.endsWith("/")) {
|
|
528
526
|
ctx.logger.info(`Writing directory ${location} to template output path.`);
|
|
529
|
-
await fs__default[
|
|
527
|
+
await fs__default["default"].ensureDir(outputPath);
|
|
530
528
|
} else {
|
|
531
529
|
const inputFilePath = backendCommon.resolveSafeChildPath(templateDir, location);
|
|
532
530
|
if (await isbinaryfile.isBinaryFile(inputFilePath)) {
|
|
533
531
|
ctx.logger.info(`Copying binary file ${location} to template output path.`);
|
|
534
|
-
await fs__default[
|
|
532
|
+
await fs__default["default"].copy(inputFilePath, outputPath);
|
|
535
533
|
} else {
|
|
536
|
-
const statsObj = await fs__default[
|
|
534
|
+
const statsObj = await fs__default["default"].stat(inputFilePath);
|
|
537
535
|
ctx.logger.info(`Writing file ${location} to template output path with mode ${statsObj.mode}.`);
|
|
538
|
-
const inputFileContents = await fs__default[
|
|
539
|
-
await fs__default[
|
|
536
|
+
const inputFileContents = await fs__default["default"].readFile(inputFilePath, "utf-8");
|
|
537
|
+
await fs__default["default"].outputFile(outputPath, renderContents ? renderTemplate(inputFileContents, context) : inputFileContents, { mode: statsObj.mode });
|
|
540
538
|
}
|
|
541
539
|
}
|
|
542
540
|
}
|
|
@@ -573,7 +571,7 @@ const createFilesystemDeleteAction = () => {
|
|
|
573
571
|
for (const file of ctx.input.files) {
|
|
574
572
|
const filepath = backendCommon.resolveSafeChildPath(ctx.workspacePath, file);
|
|
575
573
|
try {
|
|
576
|
-
await fs__default[
|
|
574
|
+
await fs__default["default"].remove(filepath);
|
|
577
575
|
ctx.logger.info(`File ${filepath} deleted successfully`);
|
|
578
576
|
} catch (err) {
|
|
579
577
|
ctx.logger.error(`Failed to delete file ${filepath}:`, err);
|
|
@@ -631,7 +629,7 @@ const createFilesystemRenameAction = () => {
|
|
|
631
629
|
const sourceFilepath = backendCommon.resolveSafeChildPath(ctx.workspacePath, file.from);
|
|
632
630
|
const destFilepath = backendCommon.resolveSafeChildPath(ctx.workspacePath, file.to);
|
|
633
631
|
try {
|
|
634
|
-
await fs__default[
|
|
632
|
+
await fs__default["default"].move(sourceFilepath, destFilepath, {
|
|
635
633
|
overwrite: (_b = file.overwrite) != null ? _b : false
|
|
636
634
|
});
|
|
637
635
|
ctx.logger.info(`File ${sourceFilepath} renamed to ${destFilepath} successfully`);
|
|
@@ -688,7 +686,7 @@ async function initRepoAndPush({
|
|
|
688
686
|
dir,
|
|
689
687
|
defaultBranch
|
|
690
688
|
});
|
|
691
|
-
await git.add({dir, filepath: "."});
|
|
689
|
+
await git.add({ dir, filepath: "." });
|
|
692
690
|
const authorInfo = {
|
|
693
691
|
name: (_a = gitAuthorInfo == null ? void 0 : gitAuthorInfo.name) != null ? _a : "Scaffolder",
|
|
694
692
|
email: (_b = gitAuthorInfo == null ? void 0 : gitAuthorInfo.email) != null ? _b : "scaffolder@backstage.io"
|
|
@@ -726,7 +724,7 @@ const enableBranchProtectionOnDefaultRepoBranch = async ({
|
|
|
726
724
|
owner,
|
|
727
725
|
repo: repoName,
|
|
728
726
|
branch: defaultBranch,
|
|
729
|
-
required_status_checks: {strict: true, contexts: []},
|
|
727
|
+
required_status_checks: { strict: true, contexts: [] },
|
|
730
728
|
restrictions: null,
|
|
731
729
|
enforce_admins: true,
|
|
732
730
|
required_pull_request_reviews: {
|
|
@@ -800,7 +798,7 @@ const parseRepoUrl = (repoUrl, integrations) => {
|
|
|
800
798
|
if (!repo) {
|
|
801
799
|
throw new errors.InputError(`Invalid repo URL passed to publisher: ${repoUrl}, missing repo`);
|
|
802
800
|
}
|
|
803
|
-
return {host, owner, repo, organization, workspace, project};
|
|
801
|
+
return { host, owner, repo, organization, workspace, project };
|
|
804
802
|
};
|
|
805
803
|
const isExecutable = (fileMode) => {
|
|
806
804
|
const executeBitMask = 73;
|
|
@@ -809,7 +807,7 @@ const isExecutable = (fileMode) => {
|
|
|
809
807
|
};
|
|
810
808
|
|
|
811
809
|
function createPublishAzureAction(options) {
|
|
812
|
-
const {integrations, config} = options;
|
|
810
|
+
const { integrations, config } = options;
|
|
813
811
|
return createTemplateAction({
|
|
814
812
|
id: "publish:azure",
|
|
815
813
|
description: "Initializes a git repository of the content in the workspace, and publishes it to Azure.",
|
|
@@ -852,8 +850,8 @@ function createPublishAzureAction(options) {
|
|
|
852
850
|
}
|
|
853
851
|
},
|
|
854
852
|
async handler(ctx) {
|
|
855
|
-
const {repoUrl, defaultBranch = "master"} = ctx.input;
|
|
856
|
-
const {owner, repo, host, organization} = parseRepoUrl(repoUrl, integrations);
|
|
853
|
+
const { repoUrl, defaultBranch = "master" } = ctx.input;
|
|
854
|
+
const { owner, repo, host, organization } = parseRepoUrl(repoUrl, integrations);
|
|
857
855
|
if (!organization) {
|
|
858
856
|
throw new errors.InputError(`Invalid URL provider was included in the repo URL to create ${ctx.input.repoUrl}, missing organization`);
|
|
859
857
|
}
|
|
@@ -867,7 +865,7 @@ function createPublishAzureAction(options) {
|
|
|
867
865
|
const authHandler = azureDevopsNodeApi.getPersonalAccessTokenHandler(integrationConfig.config.token);
|
|
868
866
|
const webApi = new azureDevopsNodeApi.WebApi(`https://${host}/${organization}`, authHandler);
|
|
869
867
|
const client = await webApi.getGitApi();
|
|
870
|
-
const createOptions = {name: repo};
|
|
868
|
+
const createOptions = { name: repo };
|
|
871
869
|
const returnedRepo = await client.createRepository(createOptions, owner);
|
|
872
870
|
if (!returnedRepo) {
|
|
873
871
|
throw new errors.InputError(`Unable to create the repository with Organization ${organization}, Project ${owner} and Repo ${repo}.
|
|
@@ -915,7 +913,7 @@ const createBitbucketCloudRepository = async (opts) => {
|
|
|
915
913
|
scm: "git",
|
|
916
914
|
description,
|
|
917
915
|
is_private: repoVisibility === "private",
|
|
918
|
-
project: {key: project}
|
|
916
|
+
project: { key: project }
|
|
919
917
|
}),
|
|
920
918
|
headers: {
|
|
921
919
|
Authorization: authorization,
|
|
@@ -924,7 +922,7 @@ const createBitbucketCloudRepository = async (opts) => {
|
|
|
924
922
|
};
|
|
925
923
|
let response;
|
|
926
924
|
try {
|
|
927
|
-
response = await fetch__default[
|
|
925
|
+
response = await fetch__default["default"](`https://api.bitbucket.org/2.0/repositories/${workspace}/${repo}`, options);
|
|
928
926
|
} catch (e) {
|
|
929
927
|
throw new Error(`Unable to create repository, ${e}`);
|
|
930
928
|
}
|
|
@@ -939,7 +937,7 @@ const createBitbucketCloudRepository = async (opts) => {
|
|
|
939
937
|
}
|
|
940
938
|
}
|
|
941
939
|
const repoContentsUrl = `${r.links.html.href}/src/master`;
|
|
942
|
-
return {remoteUrl, repoContentsUrl};
|
|
940
|
+
return { remoteUrl, repoContentsUrl };
|
|
943
941
|
};
|
|
944
942
|
const createBitbucketServerRepository = async (opts) => {
|
|
945
943
|
const {
|
|
@@ -966,7 +964,7 @@ const createBitbucketServerRepository = async (opts) => {
|
|
|
966
964
|
};
|
|
967
965
|
try {
|
|
968
966
|
const baseUrl = apiBaseUrl ? apiBaseUrl : `https://${host}/rest/api/1.0`;
|
|
969
|
-
response = await fetch__default[
|
|
967
|
+
response = await fetch__default["default"](`${baseUrl}/projects/${project}/repos`, options);
|
|
970
968
|
} catch (e) {
|
|
971
969
|
throw new Error(`Unable to create repository, ${e}`);
|
|
972
970
|
}
|
|
@@ -981,7 +979,7 @@ const createBitbucketServerRepository = async (opts) => {
|
|
|
981
979
|
}
|
|
982
980
|
}
|
|
983
981
|
const repoContentsUrl = `${r.links.self[0].href}`;
|
|
984
|
-
return {remoteUrl, repoContentsUrl};
|
|
982
|
+
return { remoteUrl, repoContentsUrl };
|
|
985
983
|
};
|
|
986
984
|
const getAuthorizationHeader = (config) => {
|
|
987
985
|
if (config.username && config.appPassword) {
|
|
@@ -994,19 +992,19 @@ const getAuthorizationHeader = (config) => {
|
|
|
994
992
|
throw new Error(`Authorization has not been provided for Bitbucket. Please add either username + appPassword or token to the Integrations config`);
|
|
995
993
|
};
|
|
996
994
|
const performEnableLFS = async (opts) => {
|
|
997
|
-
const {authorization, host, project, repo} = opts;
|
|
995
|
+
const { authorization, host, project, repo } = opts;
|
|
998
996
|
const options = {
|
|
999
997
|
method: "PUT",
|
|
1000
998
|
headers: {
|
|
1001
999
|
Authorization: authorization
|
|
1002
1000
|
}
|
|
1003
1001
|
};
|
|
1004
|
-
const {ok, status, statusText} = await fetch__default[
|
|
1002
|
+
const { ok, status, statusText } = await fetch__default["default"](`https://${host}/rest/git-lfs/admin/projects/${project}/repos/${repo}/enabled`, options);
|
|
1005
1003
|
if (!ok)
|
|
1006
1004
|
throw new Error(`Failed to enable LFS in the repository, ${status}: ${statusText}`);
|
|
1007
1005
|
};
|
|
1008
1006
|
function createPublishBitbucketAction(options) {
|
|
1009
|
-
const {integrations, config} = options;
|
|
1007
|
+
const { integrations, config } = options;
|
|
1010
1008
|
return createTemplateAction({
|
|
1011
1009
|
id: "publish:bitbucket",
|
|
1012
1010
|
description: "Initializes a git repository of the content in the workspace, and publishes it to Bitbucket.",
|
|
@@ -1066,7 +1064,7 @@ function createPublishBitbucketAction(options) {
|
|
|
1066
1064
|
repoVisibility = "private",
|
|
1067
1065
|
enableLFS = false
|
|
1068
1066
|
} = ctx.input;
|
|
1069
|
-
const {workspace, project, repo, host} = parseRepoUrl(repoUrl, integrations);
|
|
1067
|
+
const { workspace, project, repo, host } = parseRepoUrl(repoUrl, integrations);
|
|
1070
1068
|
if (host === "bitbucket.org") {
|
|
1071
1069
|
if (!workspace) {
|
|
1072
1070
|
throw new errors.InputError(`Invalid URL provider was included in the repo URL to create ${ctx.input.repoUrl}, missing workspace`);
|
|
@@ -1082,7 +1080,7 @@ function createPublishBitbucketAction(options) {
|
|
|
1082
1080
|
const authorization = getAuthorizationHeader(integrationConfig.config);
|
|
1083
1081
|
const apiBaseUrl = integrationConfig.config.apiBaseUrl;
|
|
1084
1082
|
const createMethod = host === "bitbucket.org" ? createBitbucketCloudRepository : createBitbucketServerRepository;
|
|
1085
|
-
const {remoteUrl, repoContentsUrl} = await createMethod({
|
|
1083
|
+
const { remoteUrl, repoContentsUrl } = await createMethod({
|
|
1086
1084
|
authorization,
|
|
1087
1085
|
host,
|
|
1088
1086
|
workspace: workspace || "",
|
|
@@ -1109,7 +1107,7 @@ function createPublishBitbucketAction(options) {
|
|
|
1109
1107
|
gitAuthorInfo
|
|
1110
1108
|
});
|
|
1111
1109
|
if (enableLFS && host !== "bitbucket.org") {
|
|
1112
|
-
await performEnableLFS({authorization, host, project, repo});
|
|
1110
|
+
await performEnableLFS({ authorization, host, project, repo });
|
|
1113
1111
|
}
|
|
1114
1112
|
ctx.output("remoteUrl", remoteUrl);
|
|
1115
1113
|
ctx.output("repoContentsUrl", repoContentsUrl);
|
|
@@ -1134,13 +1132,13 @@ function createPublishFileAction() {
|
|
|
1134
1132
|
}
|
|
1135
1133
|
},
|
|
1136
1134
|
async handler(ctx) {
|
|
1137
|
-
const {path: path$1} = ctx.input;
|
|
1138
|
-
const exists = await fs__default[
|
|
1135
|
+
const { path: path$1 } = ctx.input;
|
|
1136
|
+
const exists = await fs__default["default"].pathExists(path$1);
|
|
1139
1137
|
if (exists) {
|
|
1140
1138
|
throw new errors.InputError("Output path already exists");
|
|
1141
1139
|
}
|
|
1142
|
-
await fs__default[
|
|
1143
|
-
await fs__default[
|
|
1140
|
+
await fs__default["default"].ensureDir(path.dirname(path$1));
|
|
1141
|
+
await fs__default["default"].copy(ctx.workspacePath, path$1);
|
|
1144
1142
|
}
|
|
1145
1143
|
});
|
|
1146
1144
|
}
|
|
@@ -1155,7 +1153,7 @@ class OctokitProvider {
|
|
|
1155
1153
|
}
|
|
1156
1154
|
async getOctokit(repoUrl) {
|
|
1157
1155
|
var _a;
|
|
1158
|
-
const {owner, repo, host} = parseRepoUrl(repoUrl, this.integrations);
|
|
1156
|
+
const { owner, repo, host } = parseRepoUrl(repoUrl, this.integrations);
|
|
1159
1157
|
if (!owner) {
|
|
1160
1158
|
throw new errors.InputError(`No owner provided for repo ${repoUrl}`);
|
|
1161
1159
|
}
|
|
@@ -1167,7 +1165,7 @@ class OctokitProvider {
|
|
|
1167
1165
|
if (!credentialsProvider) {
|
|
1168
1166
|
throw new errors.InputError(`No matching credentials for host ${host}, please check your integrations config`);
|
|
1169
1167
|
}
|
|
1170
|
-
const {token} = await credentialsProvider.getCredentials({
|
|
1168
|
+
const { token } = await credentialsProvider.getCredentials({
|
|
1171
1169
|
url: `https://${host}/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}`
|
|
1172
1170
|
});
|
|
1173
1171
|
if (!token) {
|
|
@@ -1178,12 +1176,12 @@ class OctokitProvider {
|
|
|
1178
1176
|
baseUrl: integrationConfig.apiBaseUrl,
|
|
1179
1177
|
previews: ["nebula-preview"]
|
|
1180
1178
|
});
|
|
1181
|
-
return {client, token, owner, repo};
|
|
1179
|
+
return { client, token, owner, repo };
|
|
1182
1180
|
}
|
|
1183
1181
|
}
|
|
1184
1182
|
|
|
1185
1183
|
function createPublishGithubAction(options) {
|
|
1186
|
-
const {integrations, config} = options;
|
|
1184
|
+
const { integrations, config } = options;
|
|
1187
1185
|
const octokitProvider = new OctokitProvider(integrations);
|
|
1188
1186
|
return createTemplateAction({
|
|
1189
1187
|
id: "publish:github",
|
|
@@ -1279,7 +1277,7 @@ function createPublishGithubAction(options) {
|
|
|
1279
1277
|
collaborators,
|
|
1280
1278
|
topics
|
|
1281
1279
|
} = ctx.input;
|
|
1282
|
-
const {client, token, owner, repo} = await octokitProvider.getOctokit(repoUrl);
|
|
1280
|
+
const { client, token, owner, repo } = await octokitProvider.getOctokit(repoUrl);
|
|
1283
1281
|
const user = await client.users.getByUsername({
|
|
1284
1282
|
username: owner
|
|
1285
1283
|
});
|
|
@@ -1294,7 +1292,7 @@ function createPublishGithubAction(options) {
|
|
|
1294
1292
|
private: repoVisibility === "private",
|
|
1295
1293
|
description
|
|
1296
1294
|
});
|
|
1297
|
-
const {data: newRepo} = await repoCreationPromise;
|
|
1295
|
+
const { data: newRepo } = await repoCreationPromise;
|
|
1298
1296
|
if (access == null ? void 0 : access.startsWith(`${owner}/`)) {
|
|
1299
1297
|
const [, team] = access.split("/");
|
|
1300
1298
|
await client.teams.addOrUpdateRepoPermissionsInOrg({
|
|
@@ -1397,7 +1395,7 @@ const defaultClientFactory = async ({
|
|
|
1397
1395
|
if (!credentialsProvider) {
|
|
1398
1396
|
throw new errors.InputError(`No matching credentials for host ${host}, please check your integrations config`);
|
|
1399
1397
|
}
|
|
1400
|
-
const {token} = await credentialsProvider.getCredentials({
|
|
1398
|
+
const { token } = await credentialsProvider.getCredentials({
|
|
1401
1399
|
url: `https://${host}/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}`
|
|
1402
1400
|
});
|
|
1403
1401
|
if (!token) {
|
|
@@ -1473,21 +1471,21 @@ const createPublishGithubPullRequestAction = ({
|
|
|
1473
1471
|
targetPath,
|
|
1474
1472
|
sourcePath
|
|
1475
1473
|
} = ctx.input;
|
|
1476
|
-
const {owner, repo, host} = parseRepoUrl(repoUrl, integrations);
|
|
1474
|
+
const { owner, repo, host } = parseRepoUrl(repoUrl, integrations);
|
|
1477
1475
|
if (!owner) {
|
|
1478
1476
|
throw new errors.InputError(`No owner provided for host: ${host}, and repo ${repo}`);
|
|
1479
1477
|
}
|
|
1480
|
-
const client = await clientFactory({integrations, host, owner, repo});
|
|
1478
|
+
const client = await clientFactory({ integrations, host, owner, repo });
|
|
1481
1479
|
const fileRoot = sourcePath ? backendCommon.resolveSafeChildPath(ctx.workspacePath, sourcePath) : ctx.workspacePath;
|
|
1482
|
-
const localFilePaths = await globby__default[
|
|
1480
|
+
const localFilePaths = await globby__default["default"](["./**", "./**/.*", "!.git"], {
|
|
1483
1481
|
cwd: fileRoot,
|
|
1484
1482
|
gitignore: true,
|
|
1485
1483
|
dot: true
|
|
1486
1484
|
});
|
|
1487
1485
|
const fileContents = await Promise.all(localFilePaths.map((filePath) => {
|
|
1488
1486
|
const absPath = backendCommon.resolveSafeChildPath(fileRoot, filePath);
|
|
1489
|
-
const base64EncodedContent = fs__default[
|
|
1490
|
-
const fileStat = fs__default[
|
|
1487
|
+
const base64EncodedContent = fs__default["default"].readFileSync(absPath).toString("base64");
|
|
1488
|
+
const fileStat = fs__default["default"].statSync(absPath);
|
|
1491
1489
|
const githubTreeItemMode = isExecutable(fileStat.mode) ? "100755" : "100644";
|
|
1492
1490
|
const encoding = "base64";
|
|
1493
1491
|
return {
|
|
@@ -1526,7 +1524,7 @@ const createPublishGithubPullRequestAction = ({
|
|
|
1526
1524
|
};
|
|
1527
1525
|
|
|
1528
1526
|
function createPublishGitlabAction(options) {
|
|
1529
|
-
const {integrations, config} = options;
|
|
1527
|
+
const { integrations, config } = options;
|
|
1530
1528
|
return createTemplateAction({
|
|
1531
1529
|
id: "publish:gitlab",
|
|
1532
1530
|
description: "Initializes a git repository of the content in the workspace, and publishes it to GitLab.",
|
|
@@ -1575,7 +1573,7 @@ function createPublishGitlabAction(options) {
|
|
|
1575
1573
|
repoVisibility = "private",
|
|
1576
1574
|
defaultBranch = "master"
|
|
1577
1575
|
} = ctx.input;
|
|
1578
|
-
const {owner, repo, host} = parseRepoUrl(repoUrl, integrations);
|
|
1576
|
+
const { owner, repo, host } = parseRepoUrl(repoUrl, integrations);
|
|
1579
1577
|
if (!owner) {
|
|
1580
1578
|
throw new errors.InputError(`No owner provided for host: ${host}, and repo ${repo}`);
|
|
1581
1579
|
}
|
|
@@ -1590,12 +1588,12 @@ function createPublishGitlabAction(options) {
|
|
|
1590
1588
|
host: integrationConfig.config.baseUrl,
|
|
1591
1589
|
token: integrationConfig.config.token
|
|
1592
1590
|
});
|
|
1593
|
-
let {id: targetNamespace} = await client.Namespaces.show(owner);
|
|
1591
|
+
let { id: targetNamespace } = await client.Namespaces.show(owner);
|
|
1594
1592
|
if (!targetNamespace) {
|
|
1595
|
-
const {id} = await client.Users.current();
|
|
1593
|
+
const { id } = await client.Users.current();
|
|
1596
1594
|
targetNamespace = id;
|
|
1597
1595
|
}
|
|
1598
|
-
const {http_url_to_repo} = await client.Projects.create({
|
|
1596
|
+
const { http_url_to_repo } = await client.Projects.create({
|
|
1599
1597
|
namespace_id: targetNamespace,
|
|
1600
1598
|
name: repo,
|
|
1601
1599
|
visibility: repoVisibility
|
|
@@ -1625,7 +1623,7 @@ function createPublishGitlabAction(options) {
|
|
|
1625
1623
|
}
|
|
1626
1624
|
|
|
1627
1625
|
function createGithubActionsDispatchAction(options) {
|
|
1628
|
-
const {integrations} = options;
|
|
1626
|
+
const { integrations } = options;
|
|
1629
1627
|
const octokitProvider = new OctokitProvider(integrations);
|
|
1630
1628
|
return createTemplateAction({
|
|
1631
1629
|
id: "github:actions:dispatch",
|
|
@@ -1654,9 +1652,9 @@ function createGithubActionsDispatchAction(options) {
|
|
|
1654
1652
|
}
|
|
1655
1653
|
},
|
|
1656
1654
|
async handler(ctx) {
|
|
1657
|
-
const {repoUrl, workflowId, branchOrTagName} = ctx.input;
|
|
1655
|
+
const { repoUrl, workflowId, branchOrTagName } = ctx.input;
|
|
1658
1656
|
ctx.logger.info(`Dispatching workflow ${workflowId} for repo ${repoUrl} on ${branchOrTagName}`);
|
|
1659
|
-
const {client, owner, repo} = await octokitProvider.getOctokit(repoUrl);
|
|
1657
|
+
const { client, owner, repo } = await octokitProvider.getOctokit(repoUrl);
|
|
1660
1658
|
await client.rest.actions.createWorkflowDispatch({
|
|
1661
1659
|
owner,
|
|
1662
1660
|
repo,
|
|
@@ -1669,7 +1667,7 @@ function createGithubActionsDispatchAction(options) {
|
|
|
1669
1667
|
}
|
|
1670
1668
|
|
|
1671
1669
|
function createGithubWebhookAction(options) {
|
|
1672
|
-
const {integrations, defaultWebhookSecret} = options;
|
|
1670
|
+
const { integrations, defaultWebhookSecret } = options;
|
|
1673
1671
|
const octokitProvider = new OctokitProvider(integrations);
|
|
1674
1672
|
const eventNames = webhooks.emitterEventNames.filter((event) => !event.includes("."));
|
|
1675
1673
|
return createTemplateAction({
|
|
@@ -1744,7 +1742,7 @@ function createGithubWebhookAction(options) {
|
|
|
1744
1742
|
insecureSsl = false
|
|
1745
1743
|
} = ctx.input;
|
|
1746
1744
|
ctx.logger.info(`Creating webhook ${webhookUrl} for repo ${repoUrl}`);
|
|
1747
|
-
const {client, owner, repo} = await octokitProvider.getOctokit(repoUrl);
|
|
1745
|
+
const { client, owner, repo } = await octokitProvider.getOctokit(repoUrl);
|
|
1748
1746
|
try {
|
|
1749
1747
|
const insecure_ssl = insecureSsl ? "1" : "0";
|
|
1750
1748
|
await client.repos.createWebhook({
|
|
@@ -1769,7 +1767,7 @@ function createGithubWebhookAction(options) {
|
|
|
1769
1767
|
}
|
|
1770
1768
|
|
|
1771
1769
|
const createBuiltinActions = (options) => {
|
|
1772
|
-
const {reader, integrations, containerRunner, catalogClient, config} = options;
|
|
1770
|
+
const { reader, integrations, containerRunner, catalogClient, config } = options;
|
|
1773
1771
|
return [
|
|
1774
1772
|
createFetchPlainAction({
|
|
1775
1773
|
reader,
|
|
@@ -1804,7 +1802,7 @@ const createBuiltinActions = (options) => {
|
|
|
1804
1802
|
config
|
|
1805
1803
|
}),
|
|
1806
1804
|
createDebugLogAction(),
|
|
1807
|
-
createCatalogRegisterAction({catalogClient, integrations}),
|
|
1805
|
+
createCatalogRegisterAction({ catalogClient, integrations }),
|
|
1808
1806
|
createCatalogWriteAction(),
|
|
1809
1807
|
createFilesystemDeleteAction(),
|
|
1810
1808
|
createFilesystemRenameAction(),
|
|
@@ -1819,7 +1817,7 @@ const createBuiltinActions = (options) => {
|
|
|
1819
1817
|
|
|
1820
1818
|
class TemplateActionRegistry {
|
|
1821
1819
|
constructor() {
|
|
1822
|
-
this.actions = new Map();
|
|
1820
|
+
this.actions = /* @__PURE__ */ new Map();
|
|
1823
1821
|
}
|
|
1824
1822
|
register(action) {
|
|
1825
1823
|
if (this.actions.has(action.id)) {
|
|
@@ -1851,7 +1849,7 @@ class DatabaseTaskStore {
|
|
|
1851
1849
|
this.db = options.database;
|
|
1852
1850
|
}
|
|
1853
1851
|
async getTask(taskId) {
|
|
1854
|
-
const [result] = await this.db("tasks").where({id: taskId}).select();
|
|
1852
|
+
const [result] = await this.db("tasks").where({ id: taskId }).select();
|
|
1855
1853
|
if (!result) {
|
|
1856
1854
|
throw new errors.NotFoundError(`No task with id '${taskId}' found`);
|
|
1857
1855
|
}
|
|
@@ -1878,7 +1876,7 @@ class DatabaseTaskStore {
|
|
|
1878
1876
|
secrets: secrets ? JSON.stringify(secrets) : void 0,
|
|
1879
1877
|
status: "open"
|
|
1880
1878
|
});
|
|
1881
|
-
return {taskId};
|
|
1879
|
+
return { taskId };
|
|
1882
1880
|
}
|
|
1883
1881
|
async claimTask() {
|
|
1884
1882
|
return this.db.transaction(async (tx) => {
|
|
@@ -1888,7 +1886,7 @@ class DatabaseTaskStore {
|
|
|
1888
1886
|
if (!task) {
|
|
1889
1887
|
return void 0;
|
|
1890
1888
|
}
|
|
1891
|
-
const updateCount = await tx("tasks").where({id: task.id, status: "open"}).update({
|
|
1889
|
+
const updateCount = await tx("tasks").where({ id: task.id, status: "open" }).update({
|
|
1892
1890
|
status: "processing",
|
|
1893
1891
|
last_heartbeat_at: this.db.fn.now()
|
|
1894
1892
|
});
|
|
@@ -1912,14 +1910,14 @@ class DatabaseTaskStore {
|
|
|
1912
1910
|
});
|
|
1913
1911
|
}
|
|
1914
1912
|
async heartbeatTask(taskId) {
|
|
1915
|
-
const updateCount = await this.db("tasks").where({id: taskId, status: "processing"}).update({
|
|
1913
|
+
const updateCount = await this.db("tasks").where({ id: taskId, status: "processing" }).update({
|
|
1916
1914
|
last_heartbeat_at: this.db.fn.now()
|
|
1917
1915
|
});
|
|
1918
1916
|
if (updateCount === 0) {
|
|
1919
1917
|
throw new errors.ConflictError(`No running task with taskId ${taskId} found`);
|
|
1920
1918
|
}
|
|
1921
1919
|
}
|
|
1922
|
-
async listStaleTasks({timeoutS}) {
|
|
1920
|
+
async listStaleTasks({ timeoutS }) {
|
|
1923
1921
|
const rawRows = await this.db("tasks").where("status", "processing").andWhere("last_heartbeat_at", "<=", this.db.client.config.client === "sqlite3" ? this.db.raw(`datetime('now', ?)`, [`-${timeoutS} seconds`]) : this.db.raw(`dateadd('second', ?, ?)`, [
|
|
1924
1922
|
`-${timeoutS}`,
|
|
1925
1923
|
this.db.fn.now()
|
|
@@ -1927,7 +1925,7 @@ class DatabaseTaskStore {
|
|
|
1927
1925
|
const tasks = rawRows.map((row) => ({
|
|
1928
1926
|
taskId: row.id
|
|
1929
1927
|
}));
|
|
1930
|
-
return {tasks};
|
|
1928
|
+
return { tasks };
|
|
1931
1929
|
}
|
|
1932
1930
|
async completeTask({
|
|
1933
1931
|
taskId,
|
|
@@ -1967,7 +1965,7 @@ class DatabaseTaskStore {
|
|
|
1967
1965
|
});
|
|
1968
1966
|
});
|
|
1969
1967
|
}
|
|
1970
|
-
async emitLogEvent({taskId, body}) {
|
|
1968
|
+
async emitLogEvent({ taskId, body }) {
|
|
1971
1969
|
const serliazedBody = JSON.stringify(body);
|
|
1972
1970
|
await this.db("task_events").insert({
|
|
1973
1971
|
task_id: taskId,
|
|
@@ -1994,13 +1992,13 @@ class DatabaseTaskStore {
|
|
|
1994
1992
|
taskId,
|
|
1995
1993
|
body,
|
|
1996
1994
|
type: event.event_type,
|
|
1997
|
-
createdAt: typeof event.created_at === "string" ? luxon.DateTime.fromSQL(event.created_at, {zone: "UTC"}).toISO() : event.created_at
|
|
1995
|
+
createdAt: typeof event.created_at === "string" ? luxon.DateTime.fromSQL(event.created_at, { zone: "UTC" }).toISO() : event.created_at
|
|
1998
1996
|
};
|
|
1999
1997
|
} catch (error) {
|
|
2000
1998
|
throw new Error(`Failed to parse event body from event taskId=${taskId} id=${event.id}, ${error}`);
|
|
2001
1999
|
}
|
|
2002
2000
|
});
|
|
2003
|
-
return {events};
|
|
2001
|
+
return { events };
|
|
2004
2002
|
}
|
|
2005
2003
|
}
|
|
2006
2004
|
|
|
@@ -2031,7 +2029,7 @@ class TaskManager {
|
|
|
2031
2029
|
async emitLog(message, metadata) {
|
|
2032
2030
|
await this.storage.emitLogEvent({
|
|
2033
2031
|
taskId: this.state.taskId,
|
|
2034
|
-
body: {message, ...metadata}
|
|
2032
|
+
body: { message, ...metadata }
|
|
2035
2033
|
});
|
|
2036
2034
|
}
|
|
2037
2035
|
async complete(result, metadata) {
|
|
@@ -2066,7 +2064,7 @@ function defer() {
|
|
|
2066
2064
|
const promise = new Promise((_resolve) => {
|
|
2067
2065
|
resolve = _resolve;
|
|
2068
2066
|
});
|
|
2069
|
-
return {promise, resolve};
|
|
2067
|
+
return { promise, resolve };
|
|
2070
2068
|
}
|
|
2071
2069
|
class StorageTaskBroker {
|
|
2072
2070
|
constructor(storage, logger) {
|
|
@@ -2098,7 +2096,7 @@ class StorageTaskBroker {
|
|
|
2098
2096
|
return this.storage.getTask(taskId);
|
|
2099
2097
|
}
|
|
2100
2098
|
observe(options, callback) {
|
|
2101
|
-
const {taskId} = options;
|
|
2099
|
+
const { taskId } = options;
|
|
2102
2100
|
let cancelled = false;
|
|
2103
2101
|
const unsubscribe = () => {
|
|
2104
2102
|
cancelled = true;
|
|
@@ -2106,24 +2104,24 @@ class StorageTaskBroker {
|
|
|
2106
2104
|
(async () => {
|
|
2107
2105
|
let after = options.after;
|
|
2108
2106
|
while (!cancelled) {
|
|
2109
|
-
const result = await this.storage.listEvents({taskId, after});
|
|
2110
|
-
const {events} = result;
|
|
2107
|
+
const result = await this.storage.listEvents({ taskId, after });
|
|
2108
|
+
const { events } = result;
|
|
2111
2109
|
if (events.length) {
|
|
2112
2110
|
after = events[events.length - 1].id;
|
|
2113
2111
|
try {
|
|
2114
2112
|
callback(void 0, result);
|
|
2115
2113
|
} catch (error) {
|
|
2116
2114
|
errors.assertError(error);
|
|
2117
|
-
callback(error, {events: []});
|
|
2115
|
+
callback(error, { events: [] });
|
|
2118
2116
|
}
|
|
2119
2117
|
}
|
|
2120
2118
|
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
2121
2119
|
}
|
|
2122
2120
|
})();
|
|
2123
|
-
return {unsubscribe};
|
|
2121
|
+
return { unsubscribe };
|
|
2124
2122
|
}
|
|
2125
2123
|
async vacuumTasks(timeoutS) {
|
|
2126
|
-
const {tasks} = await this.storage.listStaleTasks(timeoutS);
|
|
2124
|
+
const { tasks } = await this.storage.listStaleTasks(timeoutS);
|
|
2127
2125
|
await Promise.all(tasks.map(async (task) => {
|
|
2128
2126
|
try {
|
|
2129
2127
|
await this.storage.completeTask({
|
|
@@ -2160,7 +2158,7 @@ class HandlebarsWorkflowRunner {
|
|
|
2160
2158
|
return JSON.stringify(parseRepoUrl(repoUrl, this.options.integrations));
|
|
2161
2159
|
});
|
|
2162
2160
|
this.handlebars.registerHelper("projectSlug", (repoUrl) => {
|
|
2163
|
-
const {owner, repo} = parseRepoUrl(repoUrl, this.options.integrations);
|
|
2161
|
+
const { owner, repo } = parseRepoUrl(repoUrl, this.options.integrations);
|
|
2164
2162
|
return `${owner}/${repo}`;
|
|
2165
2163
|
});
|
|
2166
2164
|
this.handlebars.registerHelper("json", (obj) => JSON.stringify(obj));
|
|
@@ -2172,14 +2170,14 @@ class HandlebarsWorkflowRunner {
|
|
|
2172
2170
|
if (!isValidTaskSpec$1(task.spec)) {
|
|
2173
2171
|
throw new errors.InputError(`Task spec is not a valid v1beta2 task spec`);
|
|
2174
2172
|
}
|
|
2175
|
-
const {actionRegistry} = this.options;
|
|
2176
|
-
const workspacePath = path__default[
|
|
2173
|
+
const { actionRegistry } = this.options;
|
|
2174
|
+
const workspacePath = path__default["default"].join(this.options.workingDirectory, await task.getWorkspaceName());
|
|
2177
2175
|
try {
|
|
2178
|
-
await fs__default[
|
|
2176
|
+
await fs__default["default"].ensureDir(workspacePath);
|
|
2179
2177
|
await task.emitLog(`Starting up task with ${task.spec.steps.length} steps`);
|
|
2180
|
-
const templateCtx = {parameters: task.spec.values, steps: {}};
|
|
2178
|
+
const templateCtx = { parameters: task.spec.values, steps: {} };
|
|
2181
2179
|
for (const step of task.spec.steps) {
|
|
2182
|
-
const metadata = {stepId: step.id};
|
|
2180
|
+
const metadata = { stepId: step.id };
|
|
2183
2181
|
try {
|
|
2184
2182
|
const taskLogger = winston__namespace.createLogger({
|
|
2185
2183
|
level: process.env.LOG_LEVEL || "info",
|
|
@@ -2193,7 +2191,7 @@ class HandlebarsWorkflowRunner {
|
|
|
2193
2191
|
await task.emitLog(message, metadata);
|
|
2194
2192
|
}
|
|
2195
2193
|
});
|
|
2196
|
-
taskLogger.add(new winston__namespace.transports.Stream({stream: stream$1}));
|
|
2194
|
+
taskLogger.add(new winston__namespace.transports.Stream({ stream: stream$1 }));
|
|
2197
2195
|
if (step.if !== void 0) {
|
|
2198
2196
|
let skip = !step.if;
|
|
2199
2197
|
if (typeof step.if === "string") {
|
|
@@ -2274,7 +2272,7 @@ class HandlebarsWorkflowRunner {
|
|
|
2274
2272
|
token: (_b = task.secrets) == null ? void 0 : _b.token,
|
|
2275
2273
|
workspacePath,
|
|
2276
2274
|
async createTemporaryDirectory() {
|
|
2277
|
-
const tmpDir = await fs__default[
|
|
2275
|
+
const tmpDir = await fs__default["default"].mkdtemp(`${workspacePath}_step-${step.id}-`);
|
|
2278
2276
|
tmpDirs.push(tmpDir);
|
|
2279
2277
|
return tmpDir;
|
|
2280
2278
|
},
|
|
@@ -2284,9 +2282,9 @@ class HandlebarsWorkflowRunner {
|
|
|
2284
2282
|
metadata: task.spec.metadata
|
|
2285
2283
|
});
|
|
2286
2284
|
for (const tmpDir of tmpDirs) {
|
|
2287
|
-
await fs__default[
|
|
2285
|
+
await fs__default["default"].remove(tmpDir);
|
|
2288
2286
|
}
|
|
2289
|
-
templateCtx.steps[step.id] = {output: stepOutputs};
|
|
2287
|
+
templateCtx.steps[step.id] = { output: stepOutputs };
|
|
2290
2288
|
await task.emitLog(`Finished step ${step.name}`, {
|
|
2291
2289
|
...metadata,
|
|
2292
2290
|
status: "completed"
|
|
@@ -2320,10 +2318,10 @@ class HandlebarsWorkflowRunner {
|
|
|
2320
2318
|
}
|
|
2321
2319
|
return value;
|
|
2322
2320
|
});
|
|
2323
|
-
return {output};
|
|
2321
|
+
return { output };
|
|
2324
2322
|
} finally {
|
|
2325
2323
|
if (workspacePath) {
|
|
2326
|
-
await fs__default[
|
|
2324
|
+
await fs__default["default"].remove(workspacePath);
|
|
2327
2325
|
}
|
|
2328
2326
|
}
|
|
2329
2327
|
}
|
|
@@ -2336,7 +2334,7 @@ const createStepLogger = ({
|
|
|
2336
2334
|
task,
|
|
2337
2335
|
step
|
|
2338
2336
|
}) => {
|
|
2339
|
-
const metadata = {stepId: step.id};
|
|
2337
|
+
const metadata = { stepId: step.id };
|
|
2340
2338
|
const taskLogger = winston__namespace.createLogger({
|
|
2341
2339
|
level: process.env.LOG_LEVEL || "info",
|
|
2342
2340
|
format: winston__namespace.format.combine(winston__namespace.format.colorize(), winston__namespace.format.timestamp(), winston__namespace.format.simple()),
|
|
@@ -2349,8 +2347,8 @@ const createStepLogger = ({
|
|
|
2349
2347
|
await task.emitLog(message, metadata);
|
|
2350
2348
|
}
|
|
2351
2349
|
});
|
|
2352
|
-
taskLogger.add(new winston__namespace.transports.Stream({stream: streamLogger}));
|
|
2353
|
-
return {taskLogger, streamLogger};
|
|
2350
|
+
taskLogger.add(new winston__namespace.transports.Stream({ stream: streamLogger }));
|
|
2351
|
+
return { taskLogger, streamLogger };
|
|
2354
2352
|
};
|
|
2355
2353
|
class NunjucksWorkflowRunner {
|
|
2356
2354
|
constructor(options) {
|
|
@@ -2358,7 +2356,7 @@ class NunjucksWorkflowRunner {
|
|
|
2358
2356
|
}
|
|
2359
2357
|
isSingleTemplateString(input) {
|
|
2360
2358
|
var _a, _b;
|
|
2361
|
-
const {parser, nodes} = nunjucks__default[
|
|
2359
|
+
const { parser, nodes } = nunjucks__default["default"];
|
|
2362
2360
|
const parsed = parser.parse(input, {}, {
|
|
2363
2361
|
autoescape: false,
|
|
2364
2362
|
tags: {
|
|
@@ -2401,15 +2399,15 @@ class NunjucksWorkflowRunner {
|
|
|
2401
2399
|
if (!isValidTaskSpec(task.spec)) {
|
|
2402
2400
|
throw new errors.InputError("Wrong template version executed with the workflow engine");
|
|
2403
2401
|
}
|
|
2404
|
-
const workspacePath = path__default[
|
|
2405
|
-
const {integrations} = this.options;
|
|
2402
|
+
const workspacePath = path__default["default"].join(this.options.workingDirectory, await task.getWorkspaceName());
|
|
2403
|
+
const { integrations } = this.options;
|
|
2406
2404
|
const renderTemplate = await SecureTemplater.loadRenderer({
|
|
2407
2405
|
parseRepoUrl(url) {
|
|
2408
2406
|
return parseRepoUrl(url, integrations);
|
|
2409
2407
|
}
|
|
2410
2408
|
});
|
|
2411
2409
|
try {
|
|
2412
|
-
await fs__default[
|
|
2410
|
+
await fs__default["default"].ensureDir(workspacePath);
|
|
2413
2411
|
await task.emitLog(`Starting up task with ${task.spec.steps.length} steps`);
|
|
2414
2412
|
const context = {
|
|
2415
2413
|
parameters: task.spec.parameters,
|
|
@@ -2420,7 +2418,7 @@ class NunjucksWorkflowRunner {
|
|
|
2420
2418
|
if (step.if) {
|
|
2421
2419
|
const ifResult = await this.render(step.if, context, renderTemplate);
|
|
2422
2420
|
if (!isTruthy(ifResult)) {
|
|
2423
|
-
await task.emitLog(`Skipping step ${step.id} because it's if condition was false`, {stepId: step.id, status: "skipped"});
|
|
2421
|
+
await task.emitLog(`Skipping step ${step.id} because it's if condition was false`, { stepId: step.id, status: "skipped" });
|
|
2424
2422
|
continue;
|
|
2425
2423
|
}
|
|
2426
2424
|
}
|
|
@@ -2429,7 +2427,7 @@ class NunjucksWorkflowRunner {
|
|
|
2429
2427
|
status: "processing"
|
|
2430
2428
|
});
|
|
2431
2429
|
const action = this.options.actionRegistry.get(step.action);
|
|
2432
|
-
const {taskLogger, streamLogger} = createStepLogger({task, step});
|
|
2430
|
+
const { taskLogger, streamLogger } = createStepLogger({ task, step });
|
|
2433
2431
|
const input = (_a = step.input && this.render(step.input, context, renderTemplate)) != null ? _a : {};
|
|
2434
2432
|
if ((_b = action.schema) == null ? void 0 : _b.input) {
|
|
2435
2433
|
const validateResult = jsonschema.validate(input, action.schema.input);
|
|
@@ -2450,7 +2448,7 @@ class NunjucksWorkflowRunner {
|
|
|
2450
2448
|
logStream: streamLogger,
|
|
2451
2449
|
workspacePath,
|
|
2452
2450
|
createTemporaryDirectory: async () => {
|
|
2453
|
-
const tmpDir = await fs__default[
|
|
2451
|
+
const tmpDir = await fs__default["default"].mkdtemp(`${workspacePath}_step-${step.id}-`);
|
|
2454
2452
|
tmpDirs.push(tmpDir);
|
|
2455
2453
|
return tmpDir;
|
|
2456
2454
|
},
|
|
@@ -2460,9 +2458,9 @@ class NunjucksWorkflowRunner {
|
|
|
2460
2458
|
metadata: task.spec.metadata
|
|
2461
2459
|
});
|
|
2462
2460
|
for (const tmpDir of tmpDirs) {
|
|
2463
|
-
await fs__default[
|
|
2461
|
+
await fs__default["default"].remove(tmpDir);
|
|
2464
2462
|
}
|
|
2465
|
-
context.steps[step.id] = {output: stepOutput};
|
|
2463
|
+
context.steps[step.id] = { output: stepOutput };
|
|
2466
2464
|
await task.emitLog(`Finished step ${step.name}`, {
|
|
2467
2465
|
stepId: step.id,
|
|
2468
2466
|
status: "completed"
|
|
@@ -2476,10 +2474,10 @@ class NunjucksWorkflowRunner {
|
|
|
2476
2474
|
}
|
|
2477
2475
|
}
|
|
2478
2476
|
const output = this.render(task.spec.output, context, renderTemplate);
|
|
2479
|
-
return {output};
|
|
2477
|
+
return { output };
|
|
2480
2478
|
} finally {
|
|
2481
2479
|
if (workspacePath) {
|
|
2482
|
-
await fs__default[
|
|
2480
|
+
await fs__default["default"].remove(workspacePath);
|
|
2483
2481
|
}
|
|
2484
2482
|
}
|
|
2485
2483
|
}
|
|
@@ -2511,7 +2509,7 @@ class TaskWorker {
|
|
|
2511
2509
|
});
|
|
2512
2510
|
return new TaskWorker({
|
|
2513
2511
|
taskBroker,
|
|
2514
|
-
runners: {legacyWorkflowRunner, workflowRunner}
|
|
2512
|
+
runners: { legacyWorkflowRunner, workflowRunner }
|
|
2515
2513
|
});
|
|
2516
2514
|
}
|
|
2517
2515
|
start() {
|
|
@@ -2524,12 +2522,12 @@ class TaskWorker {
|
|
|
2524
2522
|
}
|
|
2525
2523
|
async runOneTask(task) {
|
|
2526
2524
|
try {
|
|
2527
|
-
const {output} = task.spec.apiVersion === "scaffolder.backstage.io/v1beta3" ? await this.options.runners.workflowRunner.execute(task) : await this.options.runners.legacyWorkflowRunner.execute(task);
|
|
2528
|
-
await task.complete("completed", {output});
|
|
2525
|
+
const { output } = task.spec.apiVersion === "scaffolder.backstage.io/v1beta3" ? await this.options.runners.workflowRunner.execute(task) : await this.options.runners.legacyWorkflowRunner.execute(task);
|
|
2526
|
+
await task.complete("completed", { output });
|
|
2529
2527
|
} catch (error) {
|
|
2530
2528
|
errors.assertError(error);
|
|
2531
2529
|
await task.complete("failed", {
|
|
2532
|
-
error: {name: error.name, message: error.message}
|
|
2530
|
+
error: { name: error.name, message: error.message }
|
|
2533
2531
|
});
|
|
2534
2532
|
}
|
|
2535
2533
|
}
|
|
@@ -2540,7 +2538,7 @@ class CatalogEntityClient {
|
|
|
2540
2538
|
this.catalogClient = catalogClient;
|
|
2541
2539
|
}
|
|
2542
2540
|
async findTemplate(templateName, options) {
|
|
2543
|
-
const {items: templates} = await this.catalogClient.getEntities({
|
|
2541
|
+
const { items: templates } = await this.catalogClient.getEntities({
|
|
2544
2542
|
filter: {
|
|
2545
2543
|
kind: "template",
|
|
2546
2544
|
"metadata.name": templateName
|
|
@@ -2559,11 +2557,11 @@ class CatalogEntityClient {
|
|
|
2559
2557
|
|
|
2560
2558
|
async function getWorkingDirectory(config, logger) {
|
|
2561
2559
|
if (!config.has("backend.workingDirectory")) {
|
|
2562
|
-
return os__default[
|
|
2560
|
+
return os__default["default"].tmpdir();
|
|
2563
2561
|
}
|
|
2564
2562
|
const workingDirectory = config.getString("backend.workingDirectory");
|
|
2565
2563
|
try {
|
|
2566
|
-
await fs__default[
|
|
2564
|
+
await fs__default["default"].access(workingDirectory, fs__default["default"].constants.F_OK | fs__default["default"].constants.W_OK);
|
|
2567
2565
|
logger.info(`using working directory: ${workingDirectory}`);
|
|
2568
2566
|
} catch (err) {
|
|
2569
2567
|
errors.assertError(err);
|
|
@@ -2581,7 +2579,7 @@ function getEntityBaseUrl(entity) {
|
|
|
2581
2579
|
if (!location) {
|
|
2582
2580
|
return void 0;
|
|
2583
2581
|
}
|
|
2584
|
-
const {type, target} = catalogModel.parseLocationReference(location);
|
|
2582
|
+
const { type, target } = catalogModel.parseLocationReference(location);
|
|
2585
2583
|
if (type === "url") {
|
|
2586
2584
|
return target;
|
|
2587
2585
|
} else if (type === "file") {
|
|
@@ -2594,8 +2592,8 @@ function isSupportedTemplate(entity) {
|
|
|
2594
2592
|
return entity.apiVersion === "backstage.io/v1beta2" || entity.apiVersion === "scaffolder.backstage.io/v1beta3";
|
|
2595
2593
|
}
|
|
2596
2594
|
async function createRouter(options) {
|
|
2597
|
-
const router = Router__default[
|
|
2598
|
-
router.use(express__default[
|
|
2595
|
+
const router = Router__default["default"]();
|
|
2596
|
+
router.use(express__default["default"].json());
|
|
2599
2597
|
const {
|
|
2600
2598
|
logger: parentLogger,
|
|
2601
2599
|
config,
|
|
@@ -2606,7 +2604,7 @@ async function createRouter(options) {
|
|
|
2606
2604
|
containerRunner,
|
|
2607
2605
|
taskWorkers
|
|
2608
2606
|
} = options;
|
|
2609
|
-
const logger = parentLogger.child({plugin: "scaffolder"});
|
|
2607
|
+
const logger = parentLogger.child({ plugin: "scaffolder" });
|
|
2610
2608
|
const workingDirectory = await getWorkingDirectory(config, logger);
|
|
2611
2609
|
const entityClient = new CatalogEntityClient(catalogClient);
|
|
2612
2610
|
const integrations = integration.ScmIntegrations.fromConfig(config);
|
|
@@ -2642,7 +2640,7 @@ async function createRouter(options) {
|
|
|
2642
2640
|
workers.forEach((worker) => worker.start());
|
|
2643
2641
|
router.get("/v2/templates/:namespace/:kind/:name/parameter-schema", async (req, res) => {
|
|
2644
2642
|
var _a, _b;
|
|
2645
|
-
const {namespace, kind, name} = req.params;
|
|
2643
|
+
const { namespace, kind, name } = req.params;
|
|
2646
2644
|
if (namespace !== "default") {
|
|
2647
2645
|
throw new errors.InputError(`Invalid namespace, only 'default' namespace is supported`);
|
|
2648
2646
|
}
|
|
@@ -2689,7 +2687,7 @@ async function createRouter(options) {
|
|
|
2689
2687
|
for (const parameters of [(_a = template.spec.parameters) != null ? _a : []].flat()) {
|
|
2690
2688
|
const result2 = jsonschema.validate(values, parameters);
|
|
2691
2689
|
if (!result2.valid) {
|
|
2692
|
-
res.status(400).json({errors: result2.errors});
|
|
2690
|
+
res.status(400).json({ errors: result2.errors });
|
|
2693
2691
|
return;
|
|
2694
2692
|
}
|
|
2695
2693
|
}
|
|
@@ -2707,7 +2705,7 @@ async function createRouter(options) {
|
|
|
2707
2705
|
};
|
|
2708
2706
|
}),
|
|
2709
2707
|
output: (_b = template.spec.output) != null ? _b : {},
|
|
2710
|
-
metadata: {name: (_c = template.metadata) == null ? void 0 : _c.name}
|
|
2708
|
+
metadata: { name: (_c = template.metadata) == null ? void 0 : _c.name }
|
|
2711
2709
|
} : {
|
|
2712
2710
|
apiVersion: template.apiVersion,
|
|
2713
2711
|
baseUrl,
|
|
@@ -2721,7 +2719,7 @@ async function createRouter(options) {
|
|
|
2721
2719
|
};
|
|
2722
2720
|
}),
|
|
2723
2721
|
output: (_d = template.spec.output) != null ? _d : {},
|
|
2724
|
-
metadata: {name: (_e = template.metadata) == null ? void 0 : _e.name}
|
|
2722
|
+
metadata: { name: (_e = template.metadata) == null ? void 0 : _e.name }
|
|
2725
2723
|
};
|
|
2726
2724
|
} else {
|
|
2727
2725
|
throw new errors.InputError(`Unsupported apiVersion field in schema entity, ${template.apiVersion}`);
|
|
@@ -2729,9 +2727,9 @@ async function createRouter(options) {
|
|
|
2729
2727
|
const result = await taskBroker.dispatch(taskSpec, {
|
|
2730
2728
|
token
|
|
2731
2729
|
});
|
|
2732
|
-
res.status(201).json({id: result.taskId});
|
|
2730
|
+
res.status(201).json({ id: result.taskId });
|
|
2733
2731
|
}).get("/v2/tasks/:taskId", async (req, res) => {
|
|
2734
|
-
const {taskId} = req.params;
|
|
2732
|
+
const { taskId } = req.params;
|
|
2735
2733
|
const task = await taskBroker.get(taskId);
|
|
2736
2734
|
if (!task) {
|
|
2737
2735
|
throw new errors.NotFoundError(`Task with id ${taskId} does not exist`);
|
|
@@ -2739,7 +2737,7 @@ async function createRouter(options) {
|
|
|
2739
2737
|
delete task.secrets;
|
|
2740
2738
|
res.status(200).json(task);
|
|
2741
2739
|
}).get("/v2/tasks/:taskId/eventstream", async (req, res) => {
|
|
2742
|
-
const {taskId} = req.params;
|
|
2740
|
+
const { taskId } = req.params;
|
|
2743
2741
|
const after = req.query.after !== void 0 ? Number(req.query.after) : void 0;
|
|
2744
2742
|
logger.debug(`Event stream observing taskId '${taskId}' opened`);
|
|
2745
2743
|
res.writeHead(200, {
|
|
@@ -2747,7 +2745,7 @@ async function createRouter(options) {
|
|
|
2747
2745
|
"Cache-Control": "no-cache",
|
|
2748
2746
|
"Content-Type": "text/event-stream"
|
|
2749
2747
|
});
|
|
2750
|
-
const {unsubscribe} = taskBroker.observe({taskId, after}, (error, {events}) => {
|
|
2748
|
+
const { unsubscribe } = taskBroker.observe({ taskId, after }, (error, { events }) => {
|
|
2751
2749
|
var _a;
|
|
2752
2750
|
if (error) {
|
|
2753
2751
|
logger.error(`Received error from event stream when observing taskId '${taskId}', ${error}`);
|
|
@@ -2771,7 +2769,7 @@ data: ${JSON.stringify(event)}
|
|
|
2771
2769
|
logger.debug(`Event stream observing taskId '${taskId}' closed`);
|
|
2772
2770
|
});
|
|
2773
2771
|
}).get("/v2/tasks/:taskId/events", async (req, res) => {
|
|
2774
|
-
const {taskId} = req.params;
|
|
2772
|
+
const { taskId } = req.params;
|
|
2775
2773
|
const after = Number(req.query.after) || void 0;
|
|
2776
2774
|
let unsubscribe = () => {
|
|
2777
2775
|
};
|
|
@@ -2779,7 +2777,7 @@ data: ${JSON.stringify(event)}
|
|
|
2779
2777
|
unsubscribe();
|
|
2780
2778
|
res.json([]);
|
|
2781
2779
|
}, 3e4);
|
|
2782
|
-
({unsubscribe} = taskBroker.observe({taskId, after}, (error, {events}) => {
|
|
2780
|
+
({ unsubscribe } = taskBroker.observe({ taskId, after }, (error, { events }) => {
|
|
2783
2781
|
clearTimeout(timeout);
|
|
2784
2782
|
unsubscribe();
|
|
2785
2783
|
if (error) {
|
|
@@ -2792,7 +2790,7 @@ data: ${JSON.stringify(event)}
|
|
|
2792
2790
|
clearTimeout(timeout);
|
|
2793
2791
|
});
|
|
2794
2792
|
});
|
|
2795
|
-
const app = express__default[
|
|
2793
|
+
const app = express__default["default"]();
|
|
2796
2794
|
app.set("logger", logger);
|
|
2797
2795
|
app.use("/", router);
|
|
2798
2796
|
return app;
|
|
@@ -2852,9 +2850,7 @@ class ScaffolderEntitiesProcessor {
|
|
|
2852
2850
|
|
|
2853
2851
|
Object.defineProperty(exports, 'createFetchCookiecutterAction', {
|
|
2854
2852
|
enumerable: true,
|
|
2855
|
-
get: function () {
|
|
2856
|
-
return pluginScaffolderBackendModuleCookiecutter.createFetchCookiecutterAction;
|
|
2857
|
-
}
|
|
2853
|
+
get: function () { return pluginScaffolderBackendModuleCookiecutter.createFetchCookiecutterAction; }
|
|
2858
2854
|
});
|
|
2859
2855
|
exports.CatalogEntityClient = CatalogEntityClient;
|
|
2860
2856
|
exports.DatabaseTaskStore = DatabaseTaskStore;
|