@backstage/plugin-scaffolder-backend 1.13.0-next.2 → 1.13.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 +85 -0
- package/alpha/package.json +1 -1
- package/dist/alpha.cjs.js +24 -14
- package/dist/alpha.cjs.js.map +1 -1
- package/dist/alpha.d.ts +57 -16
- package/dist/cjs/{ScaffolderEntitiesProcessor-21c74c4d.cjs.js → ScaffolderEntitiesProcessor-2f24bb9e.cjs.js} +188 -52
- package/dist/cjs/ScaffolderEntitiesProcessor-2f24bb9e.cjs.js.map +1 -0
- package/dist/index.cjs.js +3 -2
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +5 -3
- package/package.json +18 -18
- package/dist/cjs/ScaffolderEntitiesProcessor-21c74c4d.cjs.js.map +0 -1
|
@@ -36,10 +36,11 @@ var PQueue = require('p-queue');
|
|
|
36
36
|
var winston = require('winston');
|
|
37
37
|
var nunjucks = require('nunjucks');
|
|
38
38
|
var lodash = require('lodash');
|
|
39
|
+
var pluginPermissionNode = require('@backstage/plugin-permission-node');
|
|
39
40
|
var promClient = require('prom-client');
|
|
41
|
+
var pluginPermissionCommon = require('@backstage/plugin-permission-common');
|
|
40
42
|
var url = require('url');
|
|
41
43
|
var os = require('os');
|
|
42
|
-
var pluginPermissionNode = require('@backstage/plugin-permission-node');
|
|
43
44
|
var pluginCatalogNode = require('@backstage/plugin-catalog-node');
|
|
44
45
|
|
|
45
46
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
@@ -1270,7 +1271,7 @@ async function initRepoAndPush({
|
|
|
1270
1271
|
name: (_a = gitAuthorInfo == null ? void 0 : gitAuthorInfo.name) != null ? _a : "Scaffolder",
|
|
1271
1272
|
email: (_b = gitAuthorInfo == null ? void 0 : gitAuthorInfo.email) != null ? _b : "scaffolder@backstage.io"
|
|
1272
1273
|
};
|
|
1273
|
-
await git.commit({
|
|
1274
|
+
const commitHash = await git.commit({
|
|
1274
1275
|
dir,
|
|
1275
1276
|
message: commitMessage,
|
|
1276
1277
|
author: authorInfo,
|
|
@@ -1285,6 +1286,7 @@ async function initRepoAndPush({
|
|
|
1285
1286
|
dir,
|
|
1286
1287
|
remote: "origin"
|
|
1287
1288
|
});
|
|
1289
|
+
return { commitHash };
|
|
1288
1290
|
}
|
|
1289
1291
|
async function commitAndPushRepo({
|
|
1290
1292
|
dir,
|
|
@@ -1307,7 +1309,7 @@ async function commitAndPushRepo({
|
|
|
1307
1309
|
name: (_a = gitAuthorInfo == null ? void 0 : gitAuthorInfo.name) != null ? _a : "Scaffolder",
|
|
1308
1310
|
email: (_b = gitAuthorInfo == null ? void 0 : gitAuthorInfo.email) != null ? _b : "scaffolder@backstage.io"
|
|
1309
1311
|
};
|
|
1310
|
-
await git.commit({
|
|
1312
|
+
const commitHash = await git.commit({
|
|
1311
1313
|
dir,
|
|
1312
1314
|
message: commitMessage,
|
|
1313
1315
|
author: authorInfo,
|
|
@@ -1318,6 +1320,7 @@ async function commitAndPushRepo({
|
|
|
1318
1320
|
remote: "origin",
|
|
1319
1321
|
remoteRef: remoteRef != null ? remoteRef : `refs/heads/${branch}`
|
|
1320
1322
|
});
|
|
1323
|
+
return { commitHash };
|
|
1321
1324
|
}
|
|
1322
1325
|
const enableBranchProtectionOnDefaultRepoBranch = async ({
|
|
1323
1326
|
repoName,
|
|
@@ -1396,6 +1399,9 @@ const enableBranchProtectionOnDefaultRepoBranch = async ({
|
|
|
1396
1399
|
await tryOnce();
|
|
1397
1400
|
}
|
|
1398
1401
|
};
|
|
1402
|
+
function entityRefToName(name) {
|
|
1403
|
+
return name.replace(/^.*[:/]/g, "");
|
|
1404
|
+
}
|
|
1399
1405
|
|
|
1400
1406
|
const DEFAULT_TIMEOUT_MS = 6e4;
|
|
1401
1407
|
async function getOctokitOptions(options) {
|
|
@@ -1516,13 +1522,13 @@ async function createGithubRepoWithCollaboratorsAndTopics(client, repo, owner, r
|
|
|
1516
1522
|
await client.rest.repos.addCollaborator({
|
|
1517
1523
|
owner,
|
|
1518
1524
|
repo,
|
|
1519
|
-
username: collaborator.user,
|
|
1525
|
+
username: entityRefToName(collaborator.user),
|
|
1520
1526
|
permission: collaborator.access
|
|
1521
1527
|
});
|
|
1522
1528
|
} else if ("team" in collaborator) {
|
|
1523
1529
|
await client.rest.teams.addOrUpdateRepoPermissionsInOrg({
|
|
1524
1530
|
org: owner,
|
|
1525
|
-
team_slug: collaborator.team,
|
|
1531
|
+
team_slug: entityRefToName(collaborator.team),
|
|
1526
1532
|
owner,
|
|
1527
1533
|
repo,
|
|
1528
1534
|
permission: collaborator.access
|
|
@@ -1557,7 +1563,7 @@ async function initRepoPushAndProtect(remoteUrl, password, workspacePath, source
|
|
|
1557
1563
|
email: gitAuthorEmail ? gitAuthorEmail : config.getOptionalString("scaffolder.defaultAuthor.email")
|
|
1558
1564
|
};
|
|
1559
1565
|
const commitMessage = gitCommitMessage ? gitCommitMessage : config.getOptionalString("scaffolder.defaultCommitMessage");
|
|
1560
|
-
await initRepoAndPush({
|
|
1566
|
+
const commitResult = await initRepoAndPush({
|
|
1561
1567
|
dir: getRepoSourceDirectory(workspacePath, sourcePath),
|
|
1562
1568
|
remoteUrl,
|
|
1563
1569
|
defaultBranch,
|
|
@@ -1595,6 +1601,7 @@ async function initRepoPushAndProtect(remoteUrl, password, workspacePath, source
|
|
|
1595
1601
|
);
|
|
1596
1602
|
}
|
|
1597
1603
|
}
|
|
1604
|
+
return { commitHash: commitResult.commitHash };
|
|
1598
1605
|
}
|
|
1599
1606
|
function extractCollaboratorName(collaborator) {
|
|
1600
1607
|
if ("username" in collaborator)
|
|
@@ -2004,6 +2011,10 @@ const repoContentsUrl = {
|
|
|
2004
2011
|
title: "A URL to the root of the repository",
|
|
2005
2012
|
type: "string"
|
|
2006
2013
|
};
|
|
2014
|
+
const commitHash = {
|
|
2015
|
+
title: "The git commit hash of the initial commit",
|
|
2016
|
+
type: "string"
|
|
2017
|
+
};
|
|
2007
2018
|
|
|
2008
2019
|
function createGithubRepoCreateAction(options) {
|
|
2009
2020
|
const { integrations, githubCredentialsProvider } = options;
|
|
@@ -2144,7 +2155,8 @@ function createGithubRepoPushAction(options) {
|
|
|
2144
2155
|
type: "object",
|
|
2145
2156
|
properties: {
|
|
2146
2157
|
remoteUrl: remoteUrl,
|
|
2147
|
-
repoContentsUrl: repoContentsUrl
|
|
2158
|
+
repoContentsUrl: repoContentsUrl,
|
|
2159
|
+
commitHash: commitHash
|
|
2148
2160
|
}
|
|
2149
2161
|
}
|
|
2150
2162
|
},
|
|
@@ -2182,7 +2194,7 @@ function createGithubRepoPushAction(options) {
|
|
|
2182
2194
|
const targetRepo = await client.rest.repos.get({ owner, repo });
|
|
2183
2195
|
const remoteUrl = targetRepo.data.clone_url;
|
|
2184
2196
|
const repoContentsUrl = `${targetRepo.data.html_url}/blob/${defaultBranch}`;
|
|
2185
|
-
await initRepoPushAndProtect(
|
|
2197
|
+
const { commitHash } = await initRepoPushAndProtect(
|
|
2186
2198
|
remoteUrl,
|
|
2187
2199
|
octokitOptions.auth,
|
|
2188
2200
|
ctx.workspacePath,
|
|
@@ -2210,6 +2222,7 @@ function createGithubRepoPushAction(options) {
|
|
|
2210
2222
|
);
|
|
2211
2223
|
ctx.output("remoteUrl", remoteUrl);
|
|
2212
2224
|
ctx.output("repoContentsUrl", repoContentsUrl);
|
|
2225
|
+
ctx.output("commitHash", commitHash);
|
|
2213
2226
|
}
|
|
2214
2227
|
});
|
|
2215
2228
|
}
|
|
@@ -2396,6 +2409,10 @@ function createPublishAzureAction(options) {
|
|
|
2396
2409
|
repositoryId: {
|
|
2397
2410
|
title: "The Id of the created repository",
|
|
2398
2411
|
type: "string"
|
|
2412
|
+
},
|
|
2413
|
+
commitHash: {
|
|
2414
|
+
title: "The git commit hash of the initial commit",
|
|
2415
|
+
type: "string"
|
|
2399
2416
|
}
|
|
2400
2417
|
}
|
|
2401
2418
|
}
|
|
@@ -2454,7 +2471,7 @@ function createPublishAzureAction(options) {
|
|
|
2454
2471
|
name: gitAuthorName ? gitAuthorName : config.getOptionalString("scaffolder.defaultAuthor.name"),
|
|
2455
2472
|
email: gitAuthorEmail ? gitAuthorEmail : config.getOptionalString("scaffolder.defaultAuthor.email")
|
|
2456
2473
|
};
|
|
2457
|
-
await initRepoAndPush({
|
|
2474
|
+
const commitResult = await initRepoAndPush({
|
|
2458
2475
|
dir: getRepoSourceDirectory(ctx.workspacePath, ctx.input.sourcePath),
|
|
2459
2476
|
remoteUrl,
|
|
2460
2477
|
defaultBranch,
|
|
@@ -2466,6 +2483,7 @@ function createPublishAzureAction(options) {
|
|
|
2466
2483
|
commitMessage: gitCommitMessage ? gitCommitMessage : config.getOptionalString("scaffolder.defaultCommitMessage"),
|
|
2467
2484
|
gitAuthorInfo
|
|
2468
2485
|
});
|
|
2486
|
+
ctx.output("commitHash", commitResult == null ? void 0 : commitResult.commitHash);
|
|
2469
2487
|
ctx.output("remoteUrl", remoteUrl);
|
|
2470
2488
|
ctx.output("repoContentsUrl", repoContentsUrl);
|
|
2471
2489
|
ctx.output("repositoryId", repositoryId);
|
|
@@ -2665,6 +2683,10 @@ function createPublishBitbucketAction(options) {
|
|
|
2665
2683
|
repoContentsUrl: {
|
|
2666
2684
|
title: "A URL to the root of the repository",
|
|
2667
2685
|
type: "string"
|
|
2686
|
+
},
|
|
2687
|
+
commitHash: {
|
|
2688
|
+
title: "The git commit hash of the initial commit",
|
|
2689
|
+
type: "string"
|
|
2668
2690
|
}
|
|
2669
2691
|
}
|
|
2670
2692
|
}
|
|
@@ -2741,7 +2763,7 @@ function createPublishBitbucketAction(options) {
|
|
|
2741
2763
|
password: integrationConfig.config.appPassword ? integrationConfig.config.appPassword : (_a = integrationConfig.config.token) != null ? _a : ""
|
|
2742
2764
|
};
|
|
2743
2765
|
}
|
|
2744
|
-
await initRepoAndPush({
|
|
2766
|
+
const commitResult = await initRepoAndPush({
|
|
2745
2767
|
dir: getRepoSourceDirectory(ctx.workspacePath, ctx.input.sourcePath),
|
|
2746
2768
|
remoteUrl,
|
|
2747
2769
|
auth,
|
|
@@ -2753,6 +2775,7 @@ function createPublishBitbucketAction(options) {
|
|
|
2753
2775
|
if (enableLFS && host !== "bitbucket.org") {
|
|
2754
2776
|
await performEnableLFS$1({ authorization, host, project, repo });
|
|
2755
2777
|
}
|
|
2778
|
+
ctx.output("commitHash", commitResult == null ? void 0 : commitResult.commitHash);
|
|
2756
2779
|
ctx.output("remoteUrl", remoteUrl);
|
|
2757
2780
|
ctx.output("repoContentsUrl", repoContentsUrl);
|
|
2758
2781
|
}
|
|
@@ -2872,6 +2895,10 @@ function createPublishBitbucketCloudAction(options) {
|
|
|
2872
2895
|
repoContentsUrl: {
|
|
2873
2896
|
title: "A URL to the root of the repository",
|
|
2874
2897
|
type: "string"
|
|
2898
|
+
},
|
|
2899
|
+
commitHash: {
|
|
2900
|
+
title: "The git commit hash of the initial commit",
|
|
2901
|
+
type: "string"
|
|
2875
2902
|
}
|
|
2876
2903
|
}
|
|
2877
2904
|
}
|
|
@@ -2938,7 +2965,7 @@ function createPublishBitbucketCloudAction(options) {
|
|
|
2938
2965
|
password: integrationConfig.config.appPassword
|
|
2939
2966
|
};
|
|
2940
2967
|
}
|
|
2941
|
-
await initRepoAndPush({
|
|
2968
|
+
const commitResult = await initRepoAndPush({
|
|
2942
2969
|
dir: getRepoSourceDirectory(ctx.workspacePath, ctx.input.sourcePath),
|
|
2943
2970
|
remoteUrl,
|
|
2944
2971
|
auth,
|
|
@@ -2949,6 +2976,7 @@ function createPublishBitbucketCloudAction(options) {
|
|
|
2949
2976
|
),
|
|
2950
2977
|
gitAuthorInfo
|
|
2951
2978
|
});
|
|
2979
|
+
ctx.output("commitHash", commitResult == null ? void 0 : commitResult.commitHash);
|
|
2952
2980
|
ctx.output("remoteUrl", remoteUrl);
|
|
2953
2981
|
ctx.output("repoContentsUrl", repoContentsUrl);
|
|
2954
2982
|
}
|
|
@@ -3086,6 +3114,10 @@ function createPublishBitbucketServerAction(options) {
|
|
|
3086
3114
|
repoContentsUrl: {
|
|
3087
3115
|
title: "A URL to the root of the repository",
|
|
3088
3116
|
type: "string"
|
|
3117
|
+
},
|
|
3118
|
+
commitHash: {
|
|
3119
|
+
title: "The git commit hash of the initial commit",
|
|
3120
|
+
type: "string"
|
|
3089
3121
|
}
|
|
3090
3122
|
}
|
|
3091
3123
|
}
|
|
@@ -3146,7 +3178,7 @@ function createPublishBitbucketServerAction(options) {
|
|
|
3146
3178
|
username: authConfig.username,
|
|
3147
3179
|
password: authConfig.password
|
|
3148
3180
|
};
|
|
3149
|
-
await initRepoAndPush({
|
|
3181
|
+
const commitResult = await initRepoAndPush({
|
|
3150
3182
|
dir: getRepoSourceDirectory(ctx.workspacePath, ctx.input.sourcePath),
|
|
3151
3183
|
remoteUrl,
|
|
3152
3184
|
auth,
|
|
@@ -3158,6 +3190,7 @@ function createPublishBitbucketServerAction(options) {
|
|
|
3158
3190
|
if (enableLFS) {
|
|
3159
3191
|
await performEnableLFS({ authorization, host, project, repo });
|
|
3160
3192
|
}
|
|
3193
|
+
ctx.output("commitHash", commitResult == null ? void 0 : commitResult.commitHash);
|
|
3161
3194
|
ctx.output("remoteUrl", remoteUrl);
|
|
3162
3195
|
ctx.output("repoContentsUrl", repoContentsUrl);
|
|
3163
3196
|
}
|
|
@@ -3251,6 +3284,10 @@ function createPublishGerritAction(options) {
|
|
|
3251
3284
|
repoContentsUrl: {
|
|
3252
3285
|
title: "A URL to the root of the repository",
|
|
3253
3286
|
type: "string"
|
|
3287
|
+
},
|
|
3288
|
+
commitHash: {
|
|
3289
|
+
title: "The git commit hash of the initial commit",
|
|
3290
|
+
type: "string"
|
|
3254
3291
|
}
|
|
3255
3292
|
}
|
|
3256
3293
|
}
|
|
@@ -3295,7 +3332,7 @@ function createPublishGerritAction(options) {
|
|
|
3295
3332
|
email: gitAuthorEmail ? gitAuthorEmail : config.getOptionalString("scaffolder.defaultAuthor.email")
|
|
3296
3333
|
};
|
|
3297
3334
|
const remoteUrl = `${integrationConfig.config.cloneUrl}/a/${repo}`;
|
|
3298
|
-
await initRepoAndPush({
|
|
3335
|
+
const commitResult = await initRepoAndPush({
|
|
3299
3336
|
dir: getRepoSourceDirectory(ctx.workspacePath, sourcePath),
|
|
3300
3337
|
remoteUrl,
|
|
3301
3338
|
auth,
|
|
@@ -3306,6 +3343,7 @@ function createPublishGerritAction(options) {
|
|
|
3306
3343
|
});
|
|
3307
3344
|
const repoContentsUrl = `${integrationConfig.config.gitilesBaseUrl}/${repo}/+/refs/heads/${defaultBranch}`;
|
|
3308
3345
|
ctx.output("remoteUrl", remoteUrl);
|
|
3346
|
+
ctx.output("commitHash", commitResult == null ? void 0 : commitResult.commitHash);
|
|
3309
3347
|
ctx.output("repoContentsUrl", repoContentsUrl);
|
|
3310
3348
|
}
|
|
3311
3349
|
});
|
|
@@ -3470,7 +3508,8 @@ function createPublishGithubAction(options) {
|
|
|
3470
3508
|
type: "object",
|
|
3471
3509
|
properties: {
|
|
3472
3510
|
remoteUrl: remoteUrl,
|
|
3473
|
-
repoContentsUrl: repoContentsUrl
|
|
3511
|
+
repoContentsUrl: repoContentsUrl,
|
|
3512
|
+
commitHash: commitHash
|
|
3474
3513
|
}
|
|
3475
3514
|
}
|
|
3476
3515
|
},
|
|
@@ -3545,7 +3584,7 @@ function createPublishGithubAction(options) {
|
|
|
3545
3584
|
);
|
|
3546
3585
|
const remoteUrl = newRepo.clone_url;
|
|
3547
3586
|
const repoContentsUrl = `${newRepo.html_url}/blob/${defaultBranch}`;
|
|
3548
|
-
await initRepoPushAndProtect(
|
|
3587
|
+
const commitResult = await initRepoPushAndProtect(
|
|
3549
3588
|
remoteUrl,
|
|
3550
3589
|
octokitOptions.auth,
|
|
3551
3590
|
ctx.workspacePath,
|
|
@@ -3571,6 +3610,7 @@ function createPublishGithubAction(options) {
|
|
|
3571
3610
|
dismissStaleReviews,
|
|
3572
3611
|
requiredCommitSigning
|
|
3573
3612
|
);
|
|
3613
|
+
ctx.output("commitHash", commitResult == null ? void 0 : commitResult.commitHash);
|
|
3574
3614
|
ctx.output("remoteUrl", remoteUrl);
|
|
3575
3615
|
ctx.output("repoContentsUrl", repoContentsUrl);
|
|
3576
3616
|
}
|
|
@@ -3734,6 +3774,11 @@ const createPublishGithubPullRequestAction = (options) => {
|
|
|
3734
3774
|
type: "string"
|
|
3735
3775
|
},
|
|
3736
3776
|
description: "The teams that will be added as reviewers to the pull request"
|
|
3777
|
+
},
|
|
3778
|
+
commitMessage: {
|
|
3779
|
+
type: "string",
|
|
3780
|
+
title: "Commit Message",
|
|
3781
|
+
description: "The commit message for the pull request commit"
|
|
3737
3782
|
}
|
|
3738
3783
|
}
|
|
3739
3784
|
},
|
|
@@ -3765,7 +3810,8 @@ const createPublishGithubPullRequestAction = (options) => {
|
|
|
3765
3810
|
sourcePath,
|
|
3766
3811
|
token: providedToken,
|
|
3767
3812
|
reviewers,
|
|
3768
|
-
teamReviewers
|
|
3813
|
+
teamReviewers,
|
|
3814
|
+
commitMessage
|
|
3769
3815
|
} = ctx.input;
|
|
3770
3816
|
const { owner, repo, host } = parseRepoUrl(repoUrl, integrations);
|
|
3771
3817
|
if (!owner) {
|
|
@@ -3820,7 +3866,7 @@ const createPublishGithubPullRequestAction = (options) => {
|
|
|
3820
3866
|
changes: [
|
|
3821
3867
|
{
|
|
3822
3868
|
files,
|
|
3823
|
-
commit: title
|
|
3869
|
+
commit: commitMessage != null ? commitMessage : title
|
|
3824
3870
|
}
|
|
3825
3871
|
],
|
|
3826
3872
|
body: description,
|
|
@@ -3950,6 +3996,10 @@ function createPublishGitlabAction(options) {
|
|
|
3950
3996
|
projectId: {
|
|
3951
3997
|
title: "The ID of the project",
|
|
3952
3998
|
type: "string"
|
|
3999
|
+
},
|
|
4000
|
+
commitHash: {
|
|
4001
|
+
title: "The git commit hash of the initial commit",
|
|
4002
|
+
type: "string"
|
|
3953
4003
|
}
|
|
3954
4004
|
}
|
|
3955
4005
|
}
|
|
@@ -4010,7 +4060,7 @@ function createPublishGitlabAction(options) {
|
|
|
4010
4060
|
name: gitAuthorName ? gitAuthorName : config.getOptionalString("scaffolder.defaultAuthor.name"),
|
|
4011
4061
|
email: gitAuthorEmail ? gitAuthorEmail : config.getOptionalString("scaffolder.defaultAuthor.email")
|
|
4012
4062
|
};
|
|
4013
|
-
await initRepoAndPush({
|
|
4063
|
+
const commitResult = await initRepoAndPush({
|
|
4014
4064
|
dir: getRepoSourceDirectory(ctx.workspacePath, ctx.input.sourcePath),
|
|
4015
4065
|
remoteUrl: http_url_to_repo,
|
|
4016
4066
|
defaultBranch,
|
|
@@ -4022,6 +4072,7 @@ function createPublishGitlabAction(options) {
|
|
|
4022
4072
|
commitMessage: gitCommitMessage ? gitCommitMessage : config.getOptionalString("scaffolder.defaultCommitMessage"),
|
|
4023
4073
|
gitAuthorInfo
|
|
4024
4074
|
});
|
|
4075
|
+
ctx.output("commitHash", commitResult == null ? void 0 : commitResult.commitHash);
|
|
4025
4076
|
ctx.output("remoteUrl", remoteUrl);
|
|
4026
4077
|
ctx.output("repoContentsUrl", repoContentsUrl);
|
|
4027
4078
|
ctx.output("projectId", projectId);
|
|
@@ -4890,6 +4941,87 @@ function createHistogramMetric(config) {
|
|
|
4890
4941
|
return metric;
|
|
4891
4942
|
}
|
|
4892
4943
|
|
|
4944
|
+
const createTemplatePermissionRule = pluginPermissionNode.makeCreatePermissionRule();
|
|
4945
|
+
const hasTag = createTemplatePermissionRule({
|
|
4946
|
+
name: "HAS_TAG",
|
|
4947
|
+
resourceType: alpha.RESOURCE_TYPE_SCAFFOLDER_TEMPLATE,
|
|
4948
|
+
description: `Match parameters or steps with the given tag`,
|
|
4949
|
+
paramsSchema: zod.z.object({
|
|
4950
|
+
tag: zod.z.string().describe("Name of the tag to match on")
|
|
4951
|
+
}),
|
|
4952
|
+
apply: (resource, { tag }) => {
|
|
4953
|
+
var _a, _b, _c;
|
|
4954
|
+
return (_c = (_b = (_a = resource["backstage:permissions"]) == null ? void 0 : _a.tags) == null ? void 0 : _b.includes(tag)) != null ? _c : false;
|
|
4955
|
+
},
|
|
4956
|
+
toQuery: () => ({})
|
|
4957
|
+
});
|
|
4958
|
+
const createActionPermissionRule = pluginPermissionNode.makeCreatePermissionRule();
|
|
4959
|
+
const hasActionId = createActionPermissionRule({
|
|
4960
|
+
name: "HAS_ACTION_ID",
|
|
4961
|
+
resourceType: alpha.RESOURCE_TYPE_SCAFFOLDER_ACTION,
|
|
4962
|
+
description: `Match actions with the given actionId`,
|
|
4963
|
+
paramsSchema: zod.z.object({
|
|
4964
|
+
actionId: zod.z.string().describe("Name of the actionId to match on")
|
|
4965
|
+
}),
|
|
4966
|
+
apply: (resource, { actionId }) => {
|
|
4967
|
+
return resource.action === actionId;
|
|
4968
|
+
},
|
|
4969
|
+
toQuery: () => ({})
|
|
4970
|
+
});
|
|
4971
|
+
buildHasProperty({
|
|
4972
|
+
name: "HAS_PROPERTY",
|
|
4973
|
+
valueSchema: zod.z.union([zod.z.string(), zod.z.number(), zod.z.boolean(), zod.z.null()]),
|
|
4974
|
+
validateProperty: false
|
|
4975
|
+
});
|
|
4976
|
+
const hasBooleanProperty = buildHasProperty({
|
|
4977
|
+
name: "HAS_BOOLEAN_PROPERTY",
|
|
4978
|
+
valueSchema: zod.z.boolean()
|
|
4979
|
+
});
|
|
4980
|
+
const hasNumberProperty = buildHasProperty({
|
|
4981
|
+
name: "HAS_NUMBER_PROPERTY",
|
|
4982
|
+
valueSchema: zod.z.number()
|
|
4983
|
+
});
|
|
4984
|
+
const hasStringProperty = buildHasProperty({
|
|
4985
|
+
name: "HAS_STRING_PROPERTY",
|
|
4986
|
+
valueSchema: zod.z.string()
|
|
4987
|
+
});
|
|
4988
|
+
function buildHasProperty({
|
|
4989
|
+
name,
|
|
4990
|
+
valueSchema,
|
|
4991
|
+
validateProperty = true
|
|
4992
|
+
}) {
|
|
4993
|
+
return createActionPermissionRule({
|
|
4994
|
+
name,
|
|
4995
|
+
description: `Allow actions with the specified property`,
|
|
4996
|
+
resourceType: alpha.RESOURCE_TYPE_SCAFFOLDER_ACTION,
|
|
4997
|
+
paramsSchema: zod.z.object({
|
|
4998
|
+
key: zod.z.string().describe(`Property within the action parameters to match on`),
|
|
4999
|
+
value: valueSchema.describe(`Value of the given property to match on`)
|
|
5000
|
+
}),
|
|
5001
|
+
apply: (resource, { key, value }) => {
|
|
5002
|
+
const foundValue = lodash.get(resource.input, key);
|
|
5003
|
+
if (validateProperty && !valueSchema.safeParse(foundValue).success) {
|
|
5004
|
+
return false;
|
|
5005
|
+
}
|
|
5006
|
+
if (value !== void 0) {
|
|
5007
|
+
if (valueSchema.safeParse(value).success) {
|
|
5008
|
+
return value === foundValue;
|
|
5009
|
+
}
|
|
5010
|
+
return false;
|
|
5011
|
+
}
|
|
5012
|
+
return foundValue !== void 0;
|
|
5013
|
+
},
|
|
5014
|
+
toQuery: () => ({})
|
|
5015
|
+
});
|
|
5016
|
+
}
|
|
5017
|
+
const scaffolderTemplateRules = { hasTag };
|
|
5018
|
+
const scaffolderActionRules = {
|
|
5019
|
+
hasActionId,
|
|
5020
|
+
hasBooleanProperty,
|
|
5021
|
+
hasNumberProperty,
|
|
5022
|
+
hasStringProperty
|
|
5023
|
+
};
|
|
5024
|
+
|
|
4893
5025
|
const isValidTaskSpec = (taskSpec) => {
|
|
4894
5026
|
return taskSpec.apiVersion === "scaffolder.backstage.io/v1beta3";
|
|
4895
5027
|
};
|
|
@@ -4916,6 +5048,9 @@ const createStepLogger = ({
|
|
|
4916
5048
|
taskLogger.add(new winston__namespace.transports.Stream({ stream: streamLogger }));
|
|
4917
5049
|
return { taskLogger, streamLogger };
|
|
4918
5050
|
};
|
|
5051
|
+
const isActionAuthorized = pluginPermissionNode.createConditionAuthorizer(
|
|
5052
|
+
Object.values(scaffolderActionRules)
|
|
5053
|
+
);
|
|
4919
5054
|
class NunjucksWorkflowRunner {
|
|
4920
5055
|
constructor(options) {
|
|
4921
5056
|
this.options = options;
|
|
@@ -4973,7 +5108,7 @@ class NunjucksWorkflowRunner {
|
|
|
4973
5108
|
return value;
|
|
4974
5109
|
});
|
|
4975
5110
|
}
|
|
4976
|
-
async executeStep(task, step, context, renderTemplate, taskTrack, workspacePath) {
|
|
5111
|
+
async executeStep(task, step, context, renderTemplate, taskTrack, workspacePath, decision) {
|
|
4977
5112
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
4978
5113
|
const stepTrack = await this.tracker.stepStart(task, step);
|
|
4979
5114
|
if (task.cancelSignal.aborted) {
|
|
@@ -5038,6 +5173,15 @@ class NunjucksWorkflowRunner {
|
|
|
5038
5173
|
);
|
|
5039
5174
|
}
|
|
5040
5175
|
}
|
|
5176
|
+
if (!isActionAuthorized(decision, { action: action.id, input })) {
|
|
5177
|
+
throw new errors.NotAllowedError(
|
|
5178
|
+
`Unauthorized action: ${action.id}. The action is not allowed. Input: ${JSON.stringify(
|
|
5179
|
+
input,
|
|
5180
|
+
null,
|
|
5181
|
+
2
|
|
5182
|
+
)}`
|
|
5183
|
+
);
|
|
5184
|
+
}
|
|
5041
5185
|
const tmpDirs = new Array();
|
|
5042
5186
|
const stepOutput = {};
|
|
5043
5187
|
await action.handler({
|
|
@@ -5074,6 +5218,7 @@ class NunjucksWorkflowRunner {
|
|
|
5074
5218
|
}
|
|
5075
5219
|
}
|
|
5076
5220
|
async execute(task) {
|
|
5221
|
+
var _a;
|
|
5077
5222
|
if (!isValidTaskSpec(task.spec)) {
|
|
5078
5223
|
throw new errors.InputError(
|
|
5079
5224
|
"Wrong template version executed with the workflow engine"
|
|
@@ -5099,6 +5244,10 @@ class NunjucksWorkflowRunner {
|
|
|
5099
5244
|
steps: {},
|
|
5100
5245
|
user: task.spec.user
|
|
5101
5246
|
};
|
|
5247
|
+
const [decision] = this.options.permissions && task.spec.steps.length ? await this.options.permissions.authorizeConditional(
|
|
5248
|
+
[{ permission: alpha.actionExecutePermission }],
|
|
5249
|
+
{ token: (_a = task.secrets) == null ? void 0 : _a.backstageToken }
|
|
5250
|
+
) : [{ result: pluginPermissionCommon.AuthorizeResult.ALLOW }];
|
|
5102
5251
|
for (const step of task.spec.steps) {
|
|
5103
5252
|
await this.executeStep(
|
|
5104
5253
|
task,
|
|
@@ -5106,7 +5255,8 @@ class NunjucksWorkflowRunner {
|
|
|
5106
5255
|
context,
|
|
5107
5256
|
renderTemplate,
|
|
5108
5257
|
taskTrack,
|
|
5109
|
-
workspacePath
|
|
5258
|
+
workspacePath,
|
|
5259
|
+
decision
|
|
5110
5260
|
);
|
|
5111
5261
|
}
|
|
5112
5262
|
const output = this.render(task.spec.output, context, renderTemplate);
|
|
@@ -5256,7 +5406,7 @@ class TaskWorker {
|
|
|
5256
5406
|
constructor(options) {
|
|
5257
5407
|
this.options = options;
|
|
5258
5408
|
this.taskQueue = new PQueue__default["default"]({
|
|
5259
|
-
concurrency:
|
|
5409
|
+
concurrency: options.concurrentTasksLimit
|
|
5260
5410
|
});
|
|
5261
5411
|
}
|
|
5262
5412
|
static async create(options) {
|
|
@@ -5269,7 +5419,8 @@ class TaskWorker {
|
|
|
5269
5419
|
additionalTemplateFilters,
|
|
5270
5420
|
concurrentTasksLimit = 10,
|
|
5271
5421
|
// from 1 to Infinity
|
|
5272
|
-
additionalTemplateGlobals
|
|
5422
|
+
additionalTemplateGlobals,
|
|
5423
|
+
permissions
|
|
5273
5424
|
} = options;
|
|
5274
5425
|
const workflowRunner = new NunjucksWorkflowRunner({
|
|
5275
5426
|
actionRegistry,
|
|
@@ -5277,12 +5428,14 @@ class TaskWorker {
|
|
|
5277
5428
|
logger,
|
|
5278
5429
|
workingDirectory,
|
|
5279
5430
|
additionalTemplateFilters,
|
|
5280
|
-
additionalTemplateGlobals
|
|
5431
|
+
additionalTemplateGlobals,
|
|
5432
|
+
permissions
|
|
5281
5433
|
});
|
|
5282
5434
|
return new TaskWorker({
|
|
5283
5435
|
taskBroker,
|
|
5284
5436
|
runners: { workflowRunner },
|
|
5285
|
-
concurrentTasksLimit
|
|
5437
|
+
concurrentTasksLimit,
|
|
5438
|
+
permissions
|
|
5286
5439
|
});
|
|
5287
5440
|
}
|
|
5288
5441
|
start() {
|
|
@@ -5469,22 +5622,6 @@ async function findTemplate(options) {
|
|
|
5469
5622
|
return template;
|
|
5470
5623
|
}
|
|
5471
5624
|
|
|
5472
|
-
const createScaffolderPermissionRule = pluginPermissionNode.makeCreatePermissionRule();
|
|
5473
|
-
const hasTag = createScaffolderPermissionRule({
|
|
5474
|
-
name: "HAS_TAG",
|
|
5475
|
-
resourceType: alpha.RESOURCE_TYPE_SCAFFOLDER_TEMPLATE,
|
|
5476
|
-
description: `Match parameters or steps with the given tag`,
|
|
5477
|
-
paramsSchema: zod.z.object({
|
|
5478
|
-
tag: zod.z.string().describe("Name of the tag to match on")
|
|
5479
|
-
}),
|
|
5480
|
-
apply: (resource, { tag }) => {
|
|
5481
|
-
var _a, _b, _c;
|
|
5482
|
-
return (_c = (_b = (_a = resource["backstage:permissions"]) == null ? void 0 : _a.tags) == null ? void 0 : _b.includes(tag)) != null ? _c : false;
|
|
5483
|
-
},
|
|
5484
|
-
toQuery: () => ({})
|
|
5485
|
-
});
|
|
5486
|
-
const scaffolderTemplateRules = { hasTag };
|
|
5487
|
-
|
|
5488
5625
|
function isSupportedTemplate(entity) {
|
|
5489
5626
|
return entity.apiVersion === "scaffolder.backstage.io/v1beta3";
|
|
5490
5627
|
}
|
|
@@ -5547,7 +5684,7 @@ async function createRouter(options) {
|
|
|
5547
5684
|
scheduler,
|
|
5548
5685
|
additionalTemplateFilters,
|
|
5549
5686
|
additionalTemplateGlobals,
|
|
5550
|
-
|
|
5687
|
+
permissions,
|
|
5551
5688
|
permissionRules
|
|
5552
5689
|
} = options;
|
|
5553
5690
|
const logger = parentLogger.child({ plugin: "scaffolder" });
|
|
@@ -5589,7 +5726,8 @@ async function createRouter(options) {
|
|
|
5589
5726
|
workingDirectory,
|
|
5590
5727
|
additionalTemplateFilters,
|
|
5591
5728
|
additionalTemplateGlobals,
|
|
5592
|
-
concurrentTasksLimit
|
|
5729
|
+
concurrentTasksLimit,
|
|
5730
|
+
permissions
|
|
5593
5731
|
});
|
|
5594
5732
|
workers.push(worker);
|
|
5595
5733
|
}
|
|
@@ -5609,7 +5747,8 @@ async function createRouter(options) {
|
|
|
5609
5747
|
logger,
|
|
5610
5748
|
workingDirectory,
|
|
5611
5749
|
additionalTemplateFilters,
|
|
5612
|
-
additionalTemplateGlobals
|
|
5750
|
+
additionalTemplateGlobals,
|
|
5751
|
+
permissions
|
|
5613
5752
|
});
|
|
5614
5753
|
const templateRules = Object.values(
|
|
5615
5754
|
scaffolderTemplateRules
|
|
@@ -5659,7 +5798,7 @@ async function createRouter(options) {
|
|
|
5659
5798
|
});
|
|
5660
5799
|
res.json(actionsList);
|
|
5661
5800
|
}).post("/v2/tasks", async (req, res) => {
|
|
5662
|
-
var _a, _b
|
|
5801
|
+
var _a, _b;
|
|
5663
5802
|
const templateRef = req.body.templateRef;
|
|
5664
5803
|
const { kind, namespace, name } = catalogModel.parseEntityRef(templateRef, {
|
|
5665
5804
|
defaultKind: "template"
|
|
@@ -5705,11 +5844,7 @@ async function createRouter(options) {
|
|
|
5705
5844
|
ref: userEntityRef
|
|
5706
5845
|
},
|
|
5707
5846
|
templateInfo: {
|
|
5708
|
-
entityRef: catalogModel.stringifyEntityRef({
|
|
5709
|
-
kind,
|
|
5710
|
-
namespace,
|
|
5711
|
-
name: (_c = template.metadata) == null ? void 0 : _c.name
|
|
5712
|
-
}),
|
|
5847
|
+
entityRef: catalogModel.stringifyEntityRef({ kind, name, namespace }),
|
|
5713
5848
|
baseUrl,
|
|
5714
5849
|
entity: {
|
|
5715
5850
|
metadata: template.metadata
|
|
@@ -5890,10 +6025,10 @@ data: ${JSON.stringify(event)}
|
|
|
5890
6025
|
`Unsupported apiVersion field in schema entity, ${template.apiVersion}`
|
|
5891
6026
|
);
|
|
5892
6027
|
}
|
|
5893
|
-
if (!
|
|
6028
|
+
if (!permissions) {
|
|
5894
6029
|
return template;
|
|
5895
6030
|
}
|
|
5896
|
-
const [parameterDecision, stepDecision] = await
|
|
6031
|
+
const [parameterDecision, stepDecision] = await permissions.authorizeConditional(
|
|
5897
6032
|
[
|
|
5898
6033
|
{ permission: alpha.templateParameterReadPermission },
|
|
5899
6034
|
{ permission: alpha.templateStepReadPermission }
|
|
@@ -6002,5 +6137,6 @@ exports.createRouter = createRouter;
|
|
|
6002
6137
|
exports.createWaitAction = createWaitAction;
|
|
6003
6138
|
exports.executeShellCommand = executeShellCommand;
|
|
6004
6139
|
exports.fetchContents = fetchContents;
|
|
6140
|
+
exports.scaffolderActionRules = scaffolderActionRules;
|
|
6005
6141
|
exports.scaffolderTemplateRules = scaffolderTemplateRules;
|
|
6006
|
-
//# sourceMappingURL=ScaffolderEntitiesProcessor-
|
|
6142
|
+
//# sourceMappingURL=ScaffolderEntitiesProcessor-2f24bb9e.cjs.js.map
|