@backstage/plugin-scaffolder-backend 0.15.23-next.1 → 0.16.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 +78 -0
- package/config.d.ts +0 -25
- package/dist/index.cjs.js +167 -74
- package/dist/index.cjs.js.map +1 -1
- package/package.json +27 -25
- package/dist/index.d.ts +0 -505
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,83 @@
|
|
|
1
1
|
# @backstage/plugin-scaffolder-backend
|
|
2
2
|
|
|
3
|
+
## 0.16.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 661594bf43: **BREAKING**: Updated `TemplateAction` and related types to have its type parameter extend `JsonObject` instead of `InputBase`. The `createTemplateAction` has also been updated to pass through the `TInput` type parameter to the return type, meaning the `TemplateAction` retains its type. This can lead to breakages during type checking especially within tests.
|
|
8
|
+
- 8db2b671c6: **BREAKING**: `ctx.token` is now `ctx.secrets.backstageToken` in Actions. Please update any of your Actions that might call out to Backstage API's with this token.
|
|
9
|
+
- 5a1594330e: **BREAKING** - Removed the `CatalogEntityClient` export. This is no longer provider by this package,
|
|
10
|
+
but you can implement one pretty simply yourself using the `CatalogApi` and applying filters to fetch templates.
|
|
11
|
+
- 7d3471db94: Remove the previously deprecated `scaffolder.provider` config for all providers.
|
|
12
|
+
This config is no longer used anywhere, and adopters should use [`integrations` config](https://backstage.io/docs/integrations) instead.
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5
|
|
17
|
+
- 3e59f90b51: Fix error handling of the `runCommand` helper to return `Error`
|
|
18
|
+
instance.
|
|
19
|
+
- c77c5c7eb6: Added `backstage.role` to `package.json`
|
|
20
|
+
- 216725b434: Updated to use new names for `parseLocationRef` and `stringifyLocationRef`
|
|
21
|
+
- e72d371296: Use `TemplateEntityV1beta2` from `@backstage/plugin-scaffolder-common` instead
|
|
22
|
+
of `@backstage/catalog-model`.
|
|
23
|
+
- 1433045c08: Removed unused `helmet` dependency.
|
|
24
|
+
- 27eccab216: Replaces use of deprecated catalog-model constants.
|
|
25
|
+
- Updated dependencies
|
|
26
|
+
- @backstage/plugin-scaffolder-common@0.2.0
|
|
27
|
+
- @backstage/plugin-catalog-backend@0.21.4
|
|
28
|
+
- @backstage/backend-common@0.10.8
|
|
29
|
+
- @backstage/catalog-client@0.7.0
|
|
30
|
+
- @backstage/errors@0.2.1
|
|
31
|
+
- @backstage/integration@0.7.3
|
|
32
|
+
- @backstage/catalog-model@0.10.0
|
|
33
|
+
- @backstage/config@0.1.14
|
|
34
|
+
- @backstage/types@0.1.2
|
|
35
|
+
- @backstage/plugin-scaffolder-backend-module-cookiecutter@0.2.0
|
|
36
|
+
|
|
37
|
+
## 0.15.24
|
|
38
|
+
|
|
39
|
+
### Patch Changes
|
|
40
|
+
|
|
41
|
+
- 2441d1cf59: chore(deps): bump `knex` from 0.95.6 to 1.0.2
|
|
42
|
+
|
|
43
|
+
This also replaces `sqlite3` with `@vscode/sqlite3` 5.0.7
|
|
44
|
+
|
|
45
|
+
- 2bd5f24043: fix for the `gitlab:publish` action to use the `oauthToken` key when creating a
|
|
46
|
+
`Gitlab` client. This only happens if `ctx.input.token` is provided else the key `token` will be used.
|
|
47
|
+
- 898a56578c: Bump `vm2` to version 3.9.6
|
|
48
|
+
- Updated dependencies
|
|
49
|
+
- @backstage/catalog-client@0.6.0
|
|
50
|
+
- @backstage/backend-common@0.10.7
|
|
51
|
+
- @backstage/plugin-catalog-backend@0.21.3
|
|
52
|
+
- @backstage/plugin-scaffolder-backend-module-cookiecutter@0.1.11
|
|
53
|
+
|
|
54
|
+
## 0.15.24-next.0
|
|
55
|
+
|
|
56
|
+
### Patch Changes
|
|
57
|
+
|
|
58
|
+
- 2441d1cf59: chore(deps): bump `knex` from 0.95.6 to 1.0.2
|
|
59
|
+
|
|
60
|
+
This also replaces `sqlite3` with `@vscode/sqlite3` 5.0.7
|
|
61
|
+
|
|
62
|
+
- 2bd5f24043: fix for the `gitlab:publish` action to use the `oauthToken` key when creating a
|
|
63
|
+
`Gitlab` client. This only happens if `ctx.input.token` is provided else the key `token` will be used.
|
|
64
|
+
- Updated dependencies
|
|
65
|
+
- @backstage/backend-common@0.10.7-next.0
|
|
66
|
+
- @backstage/plugin-catalog-backend@0.21.3-next.0
|
|
67
|
+
- @backstage/plugin-scaffolder-backend-module-cookiecutter@0.1.11-next.0
|
|
68
|
+
|
|
69
|
+
## 0.15.23
|
|
70
|
+
|
|
71
|
+
### Patch Changes
|
|
72
|
+
|
|
73
|
+
- 2e0dbb0e50: Migrate from deprecated package @octokit/rest to octokit
|
|
74
|
+
- c95df1631e: Added support for templating secrets into actions input, and also added an extra `token` input argument to all publishers to provide a token that would override the `integrations.config`.
|
|
75
|
+
You can find more information over at [Writing Templates](https://backstage.io/docs/features/software-templates/writing-templates#using-the-users-oauth-token)
|
|
76
|
+
- Updated dependencies
|
|
77
|
+
- @backstage/plugin-catalog-backend@0.21.2
|
|
78
|
+
- @backstage/backend-common@0.10.6
|
|
79
|
+
- @backstage/plugin-scaffolder-backend-module-cookiecutter@0.1.10
|
|
80
|
+
|
|
3
81
|
## 0.15.23-next.1
|
|
4
82
|
|
|
5
83
|
### Patch Changes
|
package/config.d.ts
CHANGED
|
@@ -28,30 +28,5 @@ export interface Config {
|
|
|
28
28
|
* The commit message used when new components are created.
|
|
29
29
|
*/
|
|
30
30
|
defaultCommitMessage?: string;
|
|
31
|
-
/**
|
|
32
|
-
* @deprecated Replaced by parameters for the publish:github action
|
|
33
|
-
*/
|
|
34
|
-
github?: {
|
|
35
|
-
[key: string]: string;
|
|
36
|
-
};
|
|
37
|
-
/**
|
|
38
|
-
* @deprecated Use the Gitlab integration instead
|
|
39
|
-
*/
|
|
40
|
-
gitlab?: {
|
|
41
|
-
api: { [key: string]: string };
|
|
42
|
-
};
|
|
43
|
-
/**
|
|
44
|
-
* @deprecated Use the Azure integration instead
|
|
45
|
-
*/
|
|
46
|
-
azure?: {
|
|
47
|
-
baseUrl: string;
|
|
48
|
-
api: { [key: string]: string };
|
|
49
|
-
};
|
|
50
|
-
/**
|
|
51
|
-
* @deprecated Use the Bitbucket integration instead
|
|
52
|
-
*/
|
|
53
|
-
bitbucket?: {
|
|
54
|
-
api: { [key: string]: string };
|
|
55
|
-
};
|
|
56
31
|
};
|
|
57
32
|
}
|
package/dist/index.cjs.js
CHANGED
|
@@ -685,7 +685,7 @@ const runCommand = async ({
|
|
|
685
685
|
});
|
|
686
686
|
process.on("close", (code) => {
|
|
687
687
|
if (code !== 0) {
|
|
688
|
-
return reject(`Command ${command} failed, exit code: ${code}`);
|
|
688
|
+
return reject(new Error(`Command ${command} failed, exit code: ${code}`));
|
|
689
689
|
}
|
|
690
690
|
return resolve();
|
|
691
691
|
});
|
|
@@ -854,8 +854,14 @@ function createPublishAzureAction(options) {
|
|
|
854
854
|
description: `Sets the default branch on the repository. The default value is 'master'`
|
|
855
855
|
},
|
|
856
856
|
sourcePath: {
|
|
857
|
-
title: "Path
|
|
857
|
+
title: "Source Path",
|
|
858
|
+
description: "Path within the workspace that will be used as the repository root. If omitted, the entire workspace will be published as the repository.",
|
|
858
859
|
type: "string"
|
|
860
|
+
},
|
|
861
|
+
token: {
|
|
862
|
+
title: "Authentication Token",
|
|
863
|
+
type: "string",
|
|
864
|
+
description: "The token to use for authorization to Azure"
|
|
859
865
|
}
|
|
860
866
|
}
|
|
861
867
|
},
|
|
@@ -874,6 +880,7 @@ function createPublishAzureAction(options) {
|
|
|
874
880
|
}
|
|
875
881
|
},
|
|
876
882
|
async handler(ctx) {
|
|
883
|
+
var _a;
|
|
877
884
|
const { repoUrl, defaultBranch = "master" } = ctx.input;
|
|
878
885
|
const { owner, repo, host, organization } = parseRepoUrl(repoUrl, integrations);
|
|
879
886
|
if (!organization) {
|
|
@@ -883,10 +890,11 @@ function createPublishAzureAction(options) {
|
|
|
883
890
|
if (!integrationConfig) {
|
|
884
891
|
throw new errors.InputError(`No matching integration configuration for host ${host}, please check your integrations config`);
|
|
885
892
|
}
|
|
886
|
-
if (!integrationConfig.config.token) {
|
|
893
|
+
if (!integrationConfig.config.token && !ctx.input.token) {
|
|
887
894
|
throw new errors.InputError(`No token provided for Azure Integration ${host}`);
|
|
888
895
|
}
|
|
889
|
-
const
|
|
896
|
+
const token = (_a = ctx.input.token) != null ? _a : integrationConfig.config.token;
|
|
897
|
+
const authHandler = azureDevopsNodeApi.getPersonalAccessTokenHandler(token);
|
|
890
898
|
const webApi = new azureDevopsNodeApi.WebApi(`https://${host}/${organization}`, authHandler);
|
|
891
899
|
const client = await webApi.getGitApi();
|
|
892
900
|
const createOptions = { name: repo };
|
|
@@ -910,7 +918,7 @@ function createPublishAzureAction(options) {
|
|
|
910
918
|
defaultBranch,
|
|
911
919
|
auth: {
|
|
912
920
|
username: "notempty",
|
|
913
|
-
password:
|
|
921
|
+
password: token
|
|
914
922
|
},
|
|
915
923
|
logger: ctx.logger,
|
|
916
924
|
commitMessage: config.getOptionalString("scaffolder.defaultCommitMessage"),
|
|
@@ -1056,12 +1064,19 @@ function createPublishBitbucketAction(options) {
|
|
|
1056
1064
|
description: `Sets the default branch on the repository. The default value is 'master'`
|
|
1057
1065
|
},
|
|
1058
1066
|
sourcePath: {
|
|
1059
|
-
title: "Path
|
|
1067
|
+
title: "Source Path",
|
|
1068
|
+
description: "Path within the workspace that will be used as the repository root. If omitted, the entire workspace will be published as the repository.",
|
|
1060
1069
|
type: "string"
|
|
1061
1070
|
},
|
|
1062
1071
|
enableLFS: {
|
|
1063
|
-
title: "Enable LFS
|
|
1072
|
+
title: "Enable LFS?",
|
|
1073
|
+
description: "Enable LFS for the repository. Only available for hosted Bitbucket.",
|
|
1064
1074
|
type: "boolean"
|
|
1075
|
+
},
|
|
1076
|
+
token: {
|
|
1077
|
+
title: "Authentication Token",
|
|
1078
|
+
type: "string",
|
|
1079
|
+
description: "The token to use for authorization to BitBucket"
|
|
1065
1080
|
}
|
|
1066
1081
|
}
|
|
1067
1082
|
},
|
|
@@ -1101,7 +1116,7 @@ function createPublishBitbucketAction(options) {
|
|
|
1101
1116
|
if (!integrationConfig) {
|
|
1102
1117
|
throw new errors.InputError(`No matching integration configuration for host ${host}, please check your integrations config`);
|
|
1103
1118
|
}
|
|
1104
|
-
const authorization = getAuthorizationHeader(integrationConfig.config);
|
|
1119
|
+
const authorization = getAuthorizationHeader(ctx.input.token ? { host: integrationConfig.config.host, token: ctx.input.token } : integrationConfig.config);
|
|
1105
1120
|
const apiBaseUrl = integrationConfig.config.apiBaseUrl;
|
|
1106
1121
|
const createMethod = host === "bitbucket.org" ? createBitbucketCloudRepository : createBitbucketServerRepository;
|
|
1107
1122
|
const { remoteUrl, repoContentsUrl } = await createMethod({
|
|
@@ -1118,13 +1133,22 @@ function createPublishBitbucketAction(options) {
|
|
|
1118
1133
|
name: config.getOptionalString("scaffolder.defaultAuthor.name"),
|
|
1119
1134
|
email: config.getOptionalString("scaffolder.defaultAuthor.email")
|
|
1120
1135
|
};
|
|
1136
|
+
let auth;
|
|
1137
|
+
if (ctx.input.token) {
|
|
1138
|
+
auth = {
|
|
1139
|
+
username: "x-token-auth",
|
|
1140
|
+
password: ctx.input.token
|
|
1141
|
+
};
|
|
1142
|
+
} else {
|
|
1143
|
+
auth = {
|
|
1144
|
+
username: integrationConfig.config.username ? integrationConfig.config.username : "x-token-auth",
|
|
1145
|
+
password: integrationConfig.config.appPassword ? integrationConfig.config.appPassword : (_a = integrationConfig.config.token) != null ? _a : ""
|
|
1146
|
+
};
|
|
1147
|
+
}
|
|
1121
1148
|
await initRepoAndPush({
|
|
1122
1149
|
dir: getRepoSourceDirectory(ctx.workspacePath, ctx.input.sourcePath),
|
|
1123
1150
|
remoteUrl,
|
|
1124
|
-
auth
|
|
1125
|
-
username: integrationConfig.config.username ? integrationConfig.config.username : "x-token-auth",
|
|
1126
|
-
password: integrationConfig.config.appPassword ? integrationConfig.config.appPassword : (_a = integrationConfig.config.token) != null ? _a : ""
|
|
1127
|
-
},
|
|
1151
|
+
auth,
|
|
1128
1152
|
defaultBranch,
|
|
1129
1153
|
logger: ctx.logger,
|
|
1130
1154
|
commitMessage: config.getOptionalString("scaffolder.defaultCommitMessage"),
|
|
@@ -1172,7 +1196,7 @@ class OctokitProvider {
|
|
|
1172
1196
|
this.integrations = integrations;
|
|
1173
1197
|
this.githubCredentialsProvider = githubCredentialsProvider || integration.DefaultGithubCredentialsProvider.fromIntegrations(this.integrations);
|
|
1174
1198
|
}
|
|
1175
|
-
async getOctokit(repoUrl) {
|
|
1199
|
+
async getOctokit(repoUrl, options) {
|
|
1176
1200
|
var _a;
|
|
1177
1201
|
const { owner, repo, host } = parseRepoUrl(repoUrl, this.integrations);
|
|
1178
1202
|
if (!owner) {
|
|
@@ -1182,6 +1206,14 @@ class OctokitProvider {
|
|
|
1182
1206
|
if (!integrationConfig) {
|
|
1183
1207
|
throw new errors.InputError(`No integration for host ${host}`);
|
|
1184
1208
|
}
|
|
1209
|
+
if (options == null ? void 0 : options.token) {
|
|
1210
|
+
const client2 = new octokit.Octokit({
|
|
1211
|
+
auth: options.token,
|
|
1212
|
+
baseUrl: integrationConfig.apiBaseUrl,
|
|
1213
|
+
previews: ["nebula-preview"]
|
|
1214
|
+
});
|
|
1215
|
+
return { client: client2, token: options.token, owner, repo };
|
|
1216
|
+
}
|
|
1185
1217
|
const { token } = await this.githubCredentialsProvider.getCredentials({
|
|
1186
1218
|
url: `https://${host}/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}`
|
|
1187
1219
|
});
|
|
@@ -1223,7 +1255,8 @@ function createPublishGithubAction(options) {
|
|
|
1223
1255
|
type: "string"
|
|
1224
1256
|
},
|
|
1225
1257
|
requireCodeOwnerReviews: {
|
|
1226
|
-
title: "Require
|
|
1258
|
+
title: "Require CODEOWNER Reviews?",
|
|
1259
|
+
description: "Require an approved review in PR including files with a designated Code Owner",
|
|
1227
1260
|
type: "boolean"
|
|
1228
1261
|
},
|
|
1229
1262
|
repoVisibility: {
|
|
@@ -1237,7 +1270,8 @@ function createPublishGithubAction(options) {
|
|
|
1237
1270
|
description: `Sets the default branch on the repository. The default value is 'master'`
|
|
1238
1271
|
},
|
|
1239
1272
|
sourcePath: {
|
|
1240
|
-
title: "Path
|
|
1273
|
+
title: "Source Path",
|
|
1274
|
+
description: "Path within the workspace that will be used as the repository root. If omitted, the entire workspace will be published as the repository.",
|
|
1241
1275
|
type: "string"
|
|
1242
1276
|
},
|
|
1243
1277
|
collaborators: {
|
|
@@ -1260,6 +1294,11 @@ function createPublishGithubAction(options) {
|
|
|
1260
1294
|
}
|
|
1261
1295
|
}
|
|
1262
1296
|
},
|
|
1297
|
+
token: {
|
|
1298
|
+
title: "Authentication Token",
|
|
1299
|
+
type: "string",
|
|
1300
|
+
description: "The token to use for authorization to GitHub"
|
|
1301
|
+
},
|
|
1263
1302
|
topics: {
|
|
1264
1303
|
title: "Topics",
|
|
1265
1304
|
type: "array",
|
|
@@ -1292,9 +1331,10 @@ function createPublishGithubAction(options) {
|
|
|
1292
1331
|
repoVisibility = "private",
|
|
1293
1332
|
defaultBranch = "master",
|
|
1294
1333
|
collaborators,
|
|
1295
|
-
topics
|
|
1334
|
+
topics,
|
|
1335
|
+
token: providedToken
|
|
1296
1336
|
} = ctx.input;
|
|
1297
|
-
const { client, token, owner, repo } = await octokitProvider.getOctokit(repoUrl);
|
|
1337
|
+
const { client, token, owner, repo } = await octokitProvider.getOctokit(repoUrl, { token: providedToken });
|
|
1298
1338
|
const user = await client.rest.users.getByUsername({
|
|
1299
1339
|
username: owner
|
|
1300
1340
|
});
|
|
@@ -1402,13 +1442,21 @@ const defaultClientFactory = async ({
|
|
|
1402
1442
|
githubCredentialsProvider,
|
|
1403
1443
|
owner,
|
|
1404
1444
|
repo,
|
|
1405
|
-
host = "github.com"
|
|
1445
|
+
host = "github.com",
|
|
1446
|
+
token: providedToken
|
|
1406
1447
|
}) => {
|
|
1407
1448
|
var _a;
|
|
1408
1449
|
const integrationConfig = (_a = integrations.github.byHost(host)) == null ? void 0 : _a.config;
|
|
1450
|
+
const OctokitPR = octokit.Octokit.plugin(octokitPluginCreatePullRequest.createPullRequest);
|
|
1409
1451
|
if (!integrationConfig) {
|
|
1410
1452
|
throw new errors.InputError(`No integration for host ${host}`);
|
|
1411
1453
|
}
|
|
1454
|
+
if (providedToken) {
|
|
1455
|
+
return new OctokitPR({
|
|
1456
|
+
auth: providedToken,
|
|
1457
|
+
baseUrl: integrationConfig.apiBaseUrl
|
|
1458
|
+
});
|
|
1459
|
+
}
|
|
1412
1460
|
const credentialsProvider = githubCredentialsProvider || integration.SingleInstanceGithubCredentialsProvider.create(integrationConfig);
|
|
1413
1461
|
const { token } = await credentialsProvider.getCredentials({
|
|
1414
1462
|
url: `https://${host}/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}`
|
|
@@ -1416,7 +1464,6 @@ const defaultClientFactory = async ({
|
|
|
1416
1464
|
if (!token) {
|
|
1417
1465
|
throw new errors.InputError(`No token available for host: ${host}, with owner ${owner}, and repo ${repo}`);
|
|
1418
1466
|
}
|
|
1419
|
-
const OctokitPR = octokit.Octokit.plugin(octokitPluginCreatePullRequest.createPullRequest);
|
|
1420
1467
|
return new OctokitPR({
|
|
1421
1468
|
auth: token,
|
|
1422
1469
|
baseUrl: integrationConfig.apiBaseUrl
|
|
@@ -1463,6 +1510,11 @@ const createPublishGithubPullRequestAction = ({
|
|
|
1463
1510
|
type: "string",
|
|
1464
1511
|
title: "Repository Subdirectory",
|
|
1465
1512
|
description: "Subdirectory of repository to apply changes to"
|
|
1513
|
+
},
|
|
1514
|
+
token: {
|
|
1515
|
+
title: "Authentication Token",
|
|
1516
|
+
type: "string",
|
|
1517
|
+
description: "The token to use for authorization to GitHub"
|
|
1466
1518
|
}
|
|
1467
1519
|
}
|
|
1468
1520
|
},
|
|
@@ -1485,7 +1537,8 @@ const createPublishGithubPullRequestAction = ({
|
|
|
1485
1537
|
title,
|
|
1486
1538
|
description,
|
|
1487
1539
|
targetPath,
|
|
1488
|
-
sourcePath
|
|
1540
|
+
sourcePath,
|
|
1541
|
+
token: providedToken
|
|
1489
1542
|
} = ctx.input;
|
|
1490
1543
|
const { owner, repo, host } = parseRepoUrl(repoUrl, integrations);
|
|
1491
1544
|
if (!owner) {
|
|
@@ -1496,7 +1549,8 @@ const createPublishGithubPullRequestAction = ({
|
|
|
1496
1549
|
githubCredentialsProvider,
|
|
1497
1550
|
host,
|
|
1498
1551
|
owner,
|
|
1499
|
-
repo
|
|
1552
|
+
repo,
|
|
1553
|
+
token: providedToken
|
|
1500
1554
|
});
|
|
1501
1555
|
const fileRoot = sourcePath ? backendCommon.resolveSafeChildPath(ctx.workspacePath, sourcePath) : ctx.workspacePath;
|
|
1502
1556
|
const localFilePaths = await globby__default["default"](["./**", "./**/.*", "!.git"], {
|
|
@@ -1570,8 +1624,14 @@ function createPublishGitlabAction(options) {
|
|
|
1570
1624
|
description: `Sets the default branch on the repository. The default value is 'master'`
|
|
1571
1625
|
},
|
|
1572
1626
|
sourcePath: {
|
|
1573
|
-
title: "Path
|
|
1627
|
+
title: "Source Path",
|
|
1628
|
+
description: "Path within the workspace that will be used as the repository root. If omitted, the entire workspace will be published as the repository.",
|
|
1574
1629
|
type: "string"
|
|
1630
|
+
},
|
|
1631
|
+
token: {
|
|
1632
|
+
title: "Authentication Token",
|
|
1633
|
+
type: "string",
|
|
1634
|
+
description: "The token to use for authorization to GitLab"
|
|
1575
1635
|
}
|
|
1576
1636
|
}
|
|
1577
1637
|
},
|
|
@@ -1603,12 +1663,14 @@ function createPublishGitlabAction(options) {
|
|
|
1603
1663
|
if (!integrationConfig) {
|
|
1604
1664
|
throw new errors.InputError(`No matching integration configuration for host ${host}, please check your integrations config`);
|
|
1605
1665
|
}
|
|
1606
|
-
if (!integrationConfig.config.token) {
|
|
1666
|
+
if (!integrationConfig.config.token && !ctx.input.token) {
|
|
1607
1667
|
throw new errors.InputError(`No token available for host ${host}`);
|
|
1608
1668
|
}
|
|
1669
|
+
const token = ctx.input.token || integrationConfig.config.token;
|
|
1670
|
+
const tokenType = ctx.input.token ? "oauthToken" : "token";
|
|
1609
1671
|
const client = new node.Gitlab({
|
|
1610
1672
|
host: integrationConfig.config.baseUrl,
|
|
1611
|
-
|
|
1673
|
+
[tokenType]: token
|
|
1612
1674
|
});
|
|
1613
1675
|
let { id: targetNamespace } = await client.Namespaces.show(owner);
|
|
1614
1676
|
if (!targetNamespace) {
|
|
@@ -1632,7 +1694,7 @@ function createPublishGitlabAction(options) {
|
|
|
1632
1694
|
defaultBranch,
|
|
1633
1695
|
auth: {
|
|
1634
1696
|
username: "oauth2",
|
|
1635
|
-
password:
|
|
1697
|
+
password: token
|
|
1636
1698
|
},
|
|
1637
1699
|
logger: ctx.logger,
|
|
1638
1700
|
commitMessage: config.getOptionalString("scaffolder.defaultCommitMessage"),
|
|
@@ -1682,6 +1744,11 @@ const createPublishGitlabMergeRequestAction = (options) => {
|
|
|
1682
1744
|
type: "string",
|
|
1683
1745
|
title: "Repository Subdirectory",
|
|
1684
1746
|
description: "Subdirectory of repository to apply changes to"
|
|
1747
|
+
},
|
|
1748
|
+
token: {
|
|
1749
|
+
title: "Authentication Token",
|
|
1750
|
+
type: "string",
|
|
1751
|
+
description: "The token to use for authorization to GitLab"
|
|
1685
1752
|
}
|
|
1686
1753
|
}
|
|
1687
1754
|
},
|
|
@@ -1701,6 +1768,7 @@ const createPublishGitlabMergeRequestAction = (options) => {
|
|
|
1701
1768
|
}
|
|
1702
1769
|
},
|
|
1703
1770
|
async handler(ctx) {
|
|
1771
|
+
var _a;
|
|
1704
1772
|
const repoUrl = ctx.input.repoUrl;
|
|
1705
1773
|
const { host } = parseRepoUrl(repoUrl, integrations);
|
|
1706
1774
|
const integrationConfig = integrations.gitlab.byHost(host);
|
|
@@ -1709,12 +1777,14 @@ const createPublishGitlabMergeRequestAction = (options) => {
|
|
|
1709
1777
|
if (!integrationConfig) {
|
|
1710
1778
|
throw new errors.InputError(`No matching integration configuration for host ${host}, please check your integrations config`);
|
|
1711
1779
|
}
|
|
1712
|
-
if (!integrationConfig.config.token) {
|
|
1780
|
+
if (!integrationConfig.config.token && !ctx.input.token) {
|
|
1713
1781
|
throw new errors.InputError(`No token available for host ${host}`);
|
|
1714
1782
|
}
|
|
1783
|
+
const token = (_a = ctx.input.token) != null ? _a : integrationConfig.config.token;
|
|
1784
|
+
const tokenType = ctx.input.token ? "oauthToken" : "token";
|
|
1715
1785
|
const api = new node.Gitlab({
|
|
1716
1786
|
host: integrationConfig.config.baseUrl,
|
|
1717
|
-
|
|
1787
|
+
[tokenType]: token
|
|
1718
1788
|
});
|
|
1719
1789
|
const fileRoot = ctx.workspacePath;
|
|
1720
1790
|
const localFilePaths = await globby__default["default"]([`${ctx.input.targetPath}/**`], {
|
|
@@ -1788,14 +1858,25 @@ function createGithubActionsDispatchAction(options) {
|
|
|
1788
1858
|
title: "Workflow Inputs",
|
|
1789
1859
|
description: "Inputs keys and values to send to GitHub Action configured on the workflow file. The maximum number of properties is 10. ",
|
|
1790
1860
|
type: "object"
|
|
1861
|
+
},
|
|
1862
|
+
token: {
|
|
1863
|
+
title: "Authentication Token",
|
|
1864
|
+
type: "string",
|
|
1865
|
+
description: "The GITHUB_TOKEN to use for authorization to GitHub"
|
|
1791
1866
|
}
|
|
1792
1867
|
}
|
|
1793
1868
|
}
|
|
1794
1869
|
},
|
|
1795
1870
|
async handler(ctx) {
|
|
1796
|
-
const {
|
|
1871
|
+
const {
|
|
1872
|
+
repoUrl,
|
|
1873
|
+
workflowId,
|
|
1874
|
+
branchOrTagName,
|
|
1875
|
+
workflowInputs,
|
|
1876
|
+
token: providedToken
|
|
1877
|
+
} = ctx.input;
|
|
1797
1878
|
ctx.logger.info(`Dispatching workflow ${workflowId} for repo ${repoUrl} on ${branchOrTagName}`);
|
|
1798
|
-
const { client, owner, repo } = await octokitProvider.getOctokit(repoUrl);
|
|
1879
|
+
const { client, owner, repo } = await octokitProvider.getOctokit(repoUrl, { token: providedToken });
|
|
1799
1880
|
await client.rest.actions.createWorkflowDispatch({
|
|
1800
1881
|
owner,
|
|
1801
1882
|
repo,
|
|
@@ -1869,6 +1950,11 @@ function createGithubWebhookAction(options) {
|
|
|
1869
1950
|
title: "Insecure SSL",
|
|
1870
1951
|
type: "boolean",
|
|
1871
1952
|
description: `Determines whether the SSL certificate of the host for url will be verified when delivering payloads. Default 'false'`
|
|
1953
|
+
},
|
|
1954
|
+
token: {
|
|
1955
|
+
title: "Authentication Token",
|
|
1956
|
+
type: "string",
|
|
1957
|
+
description: "The GITHUB_TOKEN to use for authorization to GitHub"
|
|
1872
1958
|
}
|
|
1873
1959
|
}
|
|
1874
1960
|
}
|
|
@@ -1881,10 +1967,11 @@ function createGithubWebhookAction(options) {
|
|
|
1881
1967
|
events = ["push"],
|
|
1882
1968
|
active = true,
|
|
1883
1969
|
contentType = "form",
|
|
1884
|
-
insecureSsl = false
|
|
1970
|
+
insecureSsl = false,
|
|
1971
|
+
token: providedToken
|
|
1885
1972
|
} = ctx.input;
|
|
1886
1973
|
ctx.logger.info(`Creating webhook ${webhookUrl} for repo ${repoUrl}`);
|
|
1887
|
-
const { client, owner, repo } = await octokitProvider.getOctokit(repoUrl);
|
|
1974
|
+
const { client, owner, repo } = await octokitProvider.getOctokit(repoUrl, { token: providedToken });
|
|
1888
1975
|
try {
|
|
1889
1976
|
const insecure_ssl = insecureSsl ? "1" : "0";
|
|
1890
1977
|
await client.rest.repos.createWebhook({
|
|
@@ -2327,7 +2414,7 @@ class HandlebarsWorkflowRunner {
|
|
|
2327
2414
|
this.handlebars.registerHelper("eq", (a, b) => a === b);
|
|
2328
2415
|
}
|
|
2329
2416
|
async execute(task) {
|
|
2330
|
-
var _a, _b
|
|
2417
|
+
var _a, _b;
|
|
2331
2418
|
if (!isValidTaskSpec$1(task.spec)) {
|
|
2332
2419
|
throw new errors.InputError(`Task spec is not a valid v1beta2 task spec`);
|
|
2333
2420
|
}
|
|
@@ -2430,8 +2517,7 @@ class HandlebarsWorkflowRunner {
|
|
|
2430
2517
|
logger: taskLogger,
|
|
2431
2518
|
logStream: stream$1,
|
|
2432
2519
|
input,
|
|
2433
|
-
|
|
2434
|
-
secrets: (_c = task.secrets) != null ? _c : {},
|
|
2520
|
+
secrets: (_b = task.secrets) != null ? _b : {},
|
|
2435
2521
|
workspacePath,
|
|
2436
2522
|
async createTemporaryDirectory() {
|
|
2437
2523
|
const tmpDir = await fs__default["default"].mkdtemp(`${workspacePath}_step-${step.id}-`);
|
|
@@ -2591,8 +2677,8 @@ class NunjucksWorkflowRunner {
|
|
|
2591
2677
|
});
|
|
2592
2678
|
const action = this.options.actionRegistry.get(step.action);
|
|
2593
2679
|
const { taskLogger, streamLogger } = createStepLogger({ task, step });
|
|
2594
|
-
const input = (
|
|
2595
|
-
if ((
|
|
2680
|
+
const input = (_b = step.input && this.render(step.input, { ...context, secrets: (_a = task.secrets) != null ? _a : {} }, renderTemplate)) != null ? _b : {};
|
|
2681
|
+
if ((_c = action.schema) == null ? void 0 : _c.input) {
|
|
2596
2682
|
const validateResult = jsonschema.validate(input, action.schema.input);
|
|
2597
2683
|
if (!validateResult.valid) {
|
|
2598
2684
|
const errors$1 = validateResult.errors.join(", ");
|
|
@@ -2601,13 +2687,9 @@ class NunjucksWorkflowRunner {
|
|
|
2601
2687
|
}
|
|
2602
2688
|
const tmpDirs = new Array();
|
|
2603
2689
|
const stepOutput = {};
|
|
2604
|
-
if (!task.spec.metadata) {
|
|
2605
|
-
console.warn("DEPRECATION NOTICE: metadata is undefined. metadata will be required in the future.");
|
|
2606
|
-
}
|
|
2607
2690
|
await action.handler({
|
|
2608
2691
|
baseUrl: task.spec.baseUrl,
|
|
2609
2692
|
input,
|
|
2610
|
-
token: (_c = task.secrets) == null ? void 0 : _c.token,
|
|
2611
2693
|
secrets: (_d = task.secrets) != null ? _d : {},
|
|
2612
2694
|
logger: taskLogger,
|
|
2613
2695
|
logStream: streamLogger,
|
|
@@ -2700,28 +2782,6 @@ class TaskWorker {
|
|
|
2700
2782
|
}
|
|
2701
2783
|
}
|
|
2702
2784
|
|
|
2703
|
-
class CatalogEntityClient {
|
|
2704
|
-
constructor(catalogClient) {
|
|
2705
|
-
this.catalogClient = catalogClient;
|
|
2706
|
-
}
|
|
2707
|
-
async findTemplate(templateName, options) {
|
|
2708
|
-
const { items: templates } = await this.catalogClient.getEntities({
|
|
2709
|
-
filter: {
|
|
2710
|
-
kind: "template",
|
|
2711
|
-
"metadata.name": templateName
|
|
2712
|
-
}
|
|
2713
|
-
}, options);
|
|
2714
|
-
if (templates.length !== 1) {
|
|
2715
|
-
if (templates.length > 1) {
|
|
2716
|
-
throw new errors.ConflictError("Templates lookup resulted in multiple matches");
|
|
2717
|
-
} else {
|
|
2718
|
-
throw new errors.NotFoundError("Template not found");
|
|
2719
|
-
}
|
|
2720
|
-
}
|
|
2721
|
-
return templates[0];
|
|
2722
|
-
}
|
|
2723
|
-
}
|
|
2724
|
-
|
|
2725
2785
|
async function getWorkingDirectory(config, logger) {
|
|
2726
2786
|
if (!config.has("backend.workingDirectory")) {
|
|
2727
2787
|
return os__default["default"].tmpdir();
|
|
@@ -2739,14 +2799,14 @@ async function getWorkingDirectory(config, logger) {
|
|
|
2739
2799
|
}
|
|
2740
2800
|
function getEntityBaseUrl(entity) {
|
|
2741
2801
|
var _a, _b;
|
|
2742
|
-
let location = (_a = entity.metadata.annotations) == null ? void 0 : _a[catalogModel.
|
|
2802
|
+
let location = (_a = entity.metadata.annotations) == null ? void 0 : _a[catalogModel.ANNOTATION_SOURCE_LOCATION];
|
|
2743
2803
|
if (!location) {
|
|
2744
|
-
location = (_b = entity.metadata.annotations) == null ? void 0 : _b[catalogModel.
|
|
2804
|
+
location = (_b = entity.metadata.annotations) == null ? void 0 : _b[catalogModel.ANNOTATION_LOCATION];
|
|
2745
2805
|
}
|
|
2746
2806
|
if (!location) {
|
|
2747
2807
|
return void 0;
|
|
2748
2808
|
}
|
|
2749
|
-
const { type, target } = catalogModel.
|
|
2809
|
+
const { type, target } = catalogModel.parseLocationRef(location);
|
|
2750
2810
|
if (type === "url") {
|
|
2751
2811
|
return target;
|
|
2752
2812
|
} else if (type === "file") {
|
|
@@ -2754,6 +2814,34 @@ function getEntityBaseUrl(entity) {
|
|
|
2754
2814
|
}
|
|
2755
2815
|
return void 0;
|
|
2756
2816
|
}
|
|
2817
|
+
async function findTemplate({
|
|
2818
|
+
entityRef,
|
|
2819
|
+
token,
|
|
2820
|
+
catalogApi
|
|
2821
|
+
}) {
|
|
2822
|
+
const parsedEntityRef = catalogModel.parseEntityRef(entityRef, {
|
|
2823
|
+
defaultKind: "template",
|
|
2824
|
+
defaultNamespace: "default"
|
|
2825
|
+
});
|
|
2826
|
+
const { items } = await catalogApi.getEntities({
|
|
2827
|
+
filter: {
|
|
2828
|
+
kind: "template",
|
|
2829
|
+
"metadata.name": parsedEntityRef.name,
|
|
2830
|
+
"metadata.namespace": parsedEntityRef.namespace
|
|
2831
|
+
}
|
|
2832
|
+
}, {
|
|
2833
|
+
token
|
|
2834
|
+
});
|
|
2835
|
+
const templates = items.filter((entity) => entity.kind === "Template");
|
|
2836
|
+
if (templates.length !== 1) {
|
|
2837
|
+
if (templates.length > 1) {
|
|
2838
|
+
throw new errors.ConflictError("Templates lookup resulted in multiple matches");
|
|
2839
|
+
} else {
|
|
2840
|
+
throw new errors.NotFoundError("Template not found");
|
|
2841
|
+
}
|
|
2842
|
+
}
|
|
2843
|
+
return templates[0];
|
|
2844
|
+
}
|
|
2757
2845
|
|
|
2758
2846
|
function isSupportedTemplate(entity) {
|
|
2759
2847
|
return entity.apiVersion === "backstage.io/v1beta2" || entity.apiVersion === "scaffolder.backstage.io/v1beta3";
|
|
@@ -2774,7 +2862,6 @@ async function createRouter(options) {
|
|
|
2774
2862
|
} = options;
|
|
2775
2863
|
const logger = parentLogger.child({ plugin: "scaffolder" });
|
|
2776
2864
|
const workingDirectory = await getWorkingDirectory(config, logger);
|
|
2777
|
-
const entityClient = new CatalogEntityClient(catalogClient);
|
|
2778
2865
|
const integrations = integration.ScmIntegrations.fromConfig(config);
|
|
2779
2866
|
let taskBroker;
|
|
2780
2867
|
if (!options.taskBroker) {
|
|
@@ -2817,7 +2904,9 @@ async function createRouter(options) {
|
|
|
2817
2904
|
if (kind.toLowerCase() !== "template") {
|
|
2818
2905
|
throw new errors.InputError(`Invalid kind, only 'Template' kind is supported`);
|
|
2819
2906
|
}
|
|
2820
|
-
const template = await
|
|
2907
|
+
const template = await findTemplate({
|
|
2908
|
+
catalogApi: catalogClient,
|
|
2909
|
+
entityRef: { kind, namespace, name },
|
|
2821
2910
|
token: getBearerToken(req.headers.authorization)
|
|
2822
2911
|
});
|
|
2823
2912
|
if (isSupportedTemplate(template)) {
|
|
@@ -2849,11 +2938,18 @@ async function createRouter(options) {
|
|
|
2849
2938
|
const templateName = req.body.templateName;
|
|
2850
2939
|
const values = req.body.values;
|
|
2851
2940
|
const token = getBearerToken(req.headers.authorization);
|
|
2852
|
-
const template = await
|
|
2853
|
-
|
|
2941
|
+
const template = await findTemplate({
|
|
2942
|
+
catalogApi: catalogClient,
|
|
2943
|
+
entityRef: {
|
|
2944
|
+
name: templateName
|
|
2945
|
+
},
|
|
2946
|
+
token: getBearerToken(req.headers.authorization)
|
|
2854
2947
|
});
|
|
2855
2948
|
let taskSpec;
|
|
2856
2949
|
if (isSupportedTemplate(template)) {
|
|
2950
|
+
if (template.apiVersion === "backstage.io/v1beta2") {
|
|
2951
|
+
logger.warn(`Scaffolding ${catalogModel.stringifyEntityRef(template)} with deprecated apiVersion ${template.apiVersion}. Please migrate the template to backstage.io/v1beta3. https://backstage.io/docs/features/software-templates/migrating-from-v1beta2-to-v1beta3`);
|
|
2952
|
+
}
|
|
2857
2953
|
for (const parameters of [(_a = template.spec.parameters) != null ? _a : []].flat()) {
|
|
2858
2954
|
const result2 = jsonschema.validate(values, parameters);
|
|
2859
2955
|
if (!result2.valid) {
|
|
@@ -2974,13 +3070,11 @@ function getBearerToken(header) {
|
|
|
2974
3070
|
|
|
2975
3071
|
class ScaffolderEntitiesProcessor {
|
|
2976
3072
|
constructor() {
|
|
2977
|
-
this.validators = [
|
|
2978
|
-
catalogModel.entityKindSchemaValidator(pluginScaffolderCommon.templateEntityV1beta3Schema)
|
|
2979
|
-
];
|
|
3073
|
+
this.validators = [pluginScaffolderCommon.templateEntityV1beta3Validator];
|
|
2980
3074
|
}
|
|
2981
3075
|
async validateEntityKind(entity) {
|
|
2982
3076
|
for (const validator of this.validators) {
|
|
2983
|
-
if (validator(entity)) {
|
|
3077
|
+
if (await validator.check(entity)) {
|
|
2984
3078
|
return true;
|
|
2985
3079
|
}
|
|
2986
3080
|
}
|
|
@@ -3024,7 +3118,6 @@ Object.defineProperty(exports, 'createFetchCookiecutterAction', {
|
|
|
3024
3118
|
enumerable: true,
|
|
3025
3119
|
get: function () { return pluginScaffolderBackendModuleCookiecutter.createFetchCookiecutterAction; }
|
|
3026
3120
|
});
|
|
3027
|
-
exports.CatalogEntityClient = CatalogEntityClient;
|
|
3028
3121
|
exports.DatabaseTaskStore = DatabaseTaskStore;
|
|
3029
3122
|
exports.OctokitProvider = OctokitProvider;
|
|
3030
3123
|
exports.ScaffolderEntitiesProcessor = ScaffolderEntitiesProcessor;
|