mobbdev 0.0.110 → 0.0.112
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/dist/index.mjs +1647 -1143
- package/package.json +7 -6
package/dist/index.mjs
CHANGED
|
@@ -524,7 +524,7 @@ import fetch3 from "node-fetch";
|
|
|
524
524
|
import open2 from "open";
|
|
525
525
|
import semver from "semver";
|
|
526
526
|
import tmp2 from "tmp";
|
|
527
|
-
import { z as
|
|
527
|
+
import { z as z12 } from "zod";
|
|
528
528
|
|
|
529
529
|
// src/features/analysis/git.ts
|
|
530
530
|
import Debug2 from "debug";
|
|
@@ -952,35 +952,46 @@ var GQLClient = class {
|
|
|
952
952
|
import { Octokit as Octokit3 } from "@octokit/core";
|
|
953
953
|
import Debug5 from "debug";
|
|
954
954
|
import parseDiff2 from "parse-diff";
|
|
955
|
-
import { z as
|
|
955
|
+
import { z as z11 } from "zod";
|
|
956
956
|
|
|
957
957
|
// src/features/analysis/scm/ado.ts
|
|
958
|
-
import
|
|
958
|
+
import querystring from "node:querystring";
|
|
959
959
|
import * as api from "azure-devops-node-api";
|
|
960
|
-
import { z as z9 } from "zod";
|
|
961
|
-
|
|
962
|
-
// src/features/analysis/scm/scm.ts
|
|
963
|
-
import { Octokit as Octokit2 } from "@octokit/core";
|
|
964
|
-
import { z as z8 } from "zod";
|
|
965
|
-
|
|
966
|
-
// src/features/analysis/scm/github/encryptSecret.ts
|
|
967
|
-
import sodium from "libsodium-wrappers";
|
|
968
|
-
async function encryptSecret(secret, key) {
|
|
969
|
-
await sodium.ready;
|
|
970
|
-
const binkey = sodium.from_base64(key, sodium.base64_variants.ORIGINAL);
|
|
971
|
-
const binsec = sodium.from_string(secret);
|
|
972
|
-
const encBytes = sodium.crypto_box_seal(binsec, binkey);
|
|
973
|
-
return sodium.to_base64(encBytes, sodium.base64_variants.ORIGINAL);
|
|
974
|
-
}
|
|
975
|
-
|
|
976
|
-
// src/features/analysis/scm/github/github.ts
|
|
977
|
-
import { RequestError } from "@octokit/request-error";
|
|
978
|
-
import { Octokit } from "octokit";
|
|
979
960
|
import { z as z3 } from "zod";
|
|
980
961
|
|
|
962
|
+
// src/features/analysis/scm/types.ts
|
|
963
|
+
var ReferenceType = /* @__PURE__ */ ((ReferenceType2) => {
|
|
964
|
+
ReferenceType2["BRANCH"] = "BRANCH";
|
|
965
|
+
ReferenceType2["COMMIT"] = "COMMIT";
|
|
966
|
+
ReferenceType2["TAG"] = "TAG";
|
|
967
|
+
return ReferenceType2;
|
|
968
|
+
})(ReferenceType || {});
|
|
969
|
+
var ScmLibScmType = /* @__PURE__ */ ((ScmLibScmType2) => {
|
|
970
|
+
ScmLibScmType2["GITHUB"] = "GITHUB";
|
|
971
|
+
ScmLibScmType2["GITLAB"] = "GITLAB";
|
|
972
|
+
ScmLibScmType2["ADO"] = "ADO";
|
|
973
|
+
ScmLibScmType2["BITBUCKET"] = "BITBUCKET";
|
|
974
|
+
return ScmLibScmType2;
|
|
975
|
+
})(ScmLibScmType || {});
|
|
976
|
+
var scmCloudUrl = {
|
|
977
|
+
GitLab: "https://gitlab.com",
|
|
978
|
+
GitHub: "https://github.com",
|
|
979
|
+
Ado: "https://dev.azure.com",
|
|
980
|
+
Bitbucket: "https://bitbucket.org"
|
|
981
|
+
};
|
|
982
|
+
var ScmType = /* @__PURE__ */ ((ScmType2) => {
|
|
983
|
+
ScmType2["GitHub"] = "GitHub";
|
|
984
|
+
ScmType2["GitLab"] = "GitLab";
|
|
985
|
+
ScmType2["Ado"] = "Ado";
|
|
986
|
+
ScmType2["Bitbucket"] = "Bitbucket";
|
|
987
|
+
return ScmType2;
|
|
988
|
+
})(ScmType || {});
|
|
989
|
+
|
|
981
990
|
// src/features/analysis/scm/urlParser.ts
|
|
982
|
-
function
|
|
991
|
+
function detectAdoUrl(args) {
|
|
992
|
+
const { pathname, hostname, scmType } = args;
|
|
983
993
|
const hostnameParts = hostname.split(".");
|
|
994
|
+
const adoHostname = new URL(scmCloudUrl.Ado).hostname;
|
|
984
995
|
if (hostnameParts.length === 3 && hostnameParts[1] === "visualstudio" && hostnameParts[2] === "com") {
|
|
985
996
|
if (pathname.length === 2 && pathname[0] === "_git") {
|
|
986
997
|
return {
|
|
@@ -997,7 +1008,7 @@ function getRepoInfo(pathname, hostname, scmType) {
|
|
|
997
1008
|
};
|
|
998
1009
|
}
|
|
999
1010
|
}
|
|
1000
|
-
if (hostname ===
|
|
1011
|
+
if (hostname === adoHostname || scmType === "Ado" /* Ado */) {
|
|
1001
1012
|
if (pathname.length === 3 && pathname[1] === "_git") {
|
|
1002
1013
|
return {
|
|
1003
1014
|
organization: pathname[0],
|
|
@@ -1013,7 +1024,12 @@ function getRepoInfo(pathname, hostname, scmType) {
|
|
|
1013
1024
|
};
|
|
1014
1025
|
}
|
|
1015
1026
|
}
|
|
1016
|
-
|
|
1027
|
+
return null;
|
|
1028
|
+
}
|
|
1029
|
+
function detectGithubUrl(args) {
|
|
1030
|
+
const { pathname, hostname, scmType } = args;
|
|
1031
|
+
const githubHostname = new URL(scmCloudUrl.GitHub).hostname;
|
|
1032
|
+
if (hostname === githubHostname || scmType === "GitHub" /* GitHub */) {
|
|
1017
1033
|
if (pathname.length === 2) {
|
|
1018
1034
|
return {
|
|
1019
1035
|
organization: pathname[0],
|
|
@@ -1022,7 +1038,12 @@ function getRepoInfo(pathname, hostname, scmType) {
|
|
|
1022
1038
|
};
|
|
1023
1039
|
}
|
|
1024
1040
|
}
|
|
1025
|
-
|
|
1041
|
+
return null;
|
|
1042
|
+
}
|
|
1043
|
+
function detectGitlabUrl(args) {
|
|
1044
|
+
const { pathname, hostname, scmType } = args;
|
|
1045
|
+
const gitlabHostname = new URL(scmCloudUrl.GitLab).hostname;
|
|
1046
|
+
if (hostname === gitlabHostname || scmType === "GitLab" /* GitLab */) {
|
|
1026
1047
|
if (pathname.length >= 2) {
|
|
1027
1048
|
return {
|
|
1028
1049
|
organization: pathname[0],
|
|
@@ -1033,13 +1054,46 @@ function getRepoInfo(pathname, hostname, scmType) {
|
|
|
1033
1054
|
}
|
|
1034
1055
|
return null;
|
|
1035
1056
|
}
|
|
1057
|
+
function detectBitbucketUrl(args) {
|
|
1058
|
+
const { pathname, hostname, scmType } = args;
|
|
1059
|
+
const bitbucketHostname = new URL(scmCloudUrl.Bitbucket).hostname;
|
|
1060
|
+
if (hostname === bitbucketHostname || scmType === "Bitbucket" /* Bitbucket */) {
|
|
1061
|
+
if (pathname.length === 2) {
|
|
1062
|
+
return {
|
|
1063
|
+
organization: pathname[0],
|
|
1064
|
+
projectName: void 0,
|
|
1065
|
+
repoName: pathname[1]
|
|
1066
|
+
};
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
return null;
|
|
1070
|
+
}
|
|
1071
|
+
var getRepoUrlFunctionMap = {
|
|
1072
|
+
["GitLab" /* GitLab */]: detectGitlabUrl,
|
|
1073
|
+
["GitHub" /* GitHub */]: detectGithubUrl,
|
|
1074
|
+
["Ado" /* Ado */]: detectAdoUrl,
|
|
1075
|
+
["Bitbucket" /* Bitbucket */]: detectBitbucketUrl
|
|
1076
|
+
};
|
|
1077
|
+
function getRepoInfo(args) {
|
|
1078
|
+
for (const detectUrl of Object.values(getRepoUrlFunctionMap)) {
|
|
1079
|
+
const detectUrlRes = detectUrl(args);
|
|
1080
|
+
if (detectUrlRes) {
|
|
1081
|
+
return detectUrlRes;
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
return null;
|
|
1085
|
+
}
|
|
1036
1086
|
var NAME_REGEX = /[a-z0-9\-_.+]+/i;
|
|
1037
1087
|
var parseScmURL = (scmURL, scmType) => {
|
|
1038
1088
|
try {
|
|
1039
1089
|
const url = new URL(scmURL);
|
|
1040
1090
|
const hostname = url.hostname.toLowerCase();
|
|
1041
1091
|
const projectPath = url.pathname.substring(1).replace(/.git$/i, "");
|
|
1042
|
-
const repo = getRepoInfo(
|
|
1092
|
+
const repo = getRepoInfo({
|
|
1093
|
+
pathname: projectPath.split("/"),
|
|
1094
|
+
hostname,
|
|
1095
|
+
scmType
|
|
1096
|
+
});
|
|
1043
1097
|
if (!repo)
|
|
1044
1098
|
return null;
|
|
1045
1099
|
const { organization, repoName, projectName } = repo;
|
|
@@ -1076,255 +1130,894 @@ var sanityRepoURL = (scmURL) => {
|
|
|
1076
1130
|
}
|
|
1077
1131
|
};
|
|
1078
1132
|
|
|
1079
|
-
// src/features/analysis/scm/
|
|
1133
|
+
// src/features/analysis/scm/ado.ts
|
|
1080
1134
|
function removeTrailingSlash(str) {
|
|
1081
1135
|
return str.trim().replace(/\/+$/, "");
|
|
1082
1136
|
}
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
authoredDate
|
|
1110
|
-
}
|
|
1111
|
-
startingLine
|
|
1112
|
-
endingLine
|
|
1113
|
-
age
|
|
1114
|
-
}
|
|
1115
|
-
}
|
|
1116
|
-
}
|
|
1117
|
-
|
|
1118
|
-
}
|
|
1119
|
-
}
|
|
1137
|
+
async function _getOrgsForOauthToken({ oauthToken }) {
|
|
1138
|
+
const profileZ = z3.object({
|
|
1139
|
+
displayName: z3.string(),
|
|
1140
|
+
publicAlias: z3.string().min(1),
|
|
1141
|
+
emailAddress: z3.string(),
|
|
1142
|
+
coreRevision: z3.number(),
|
|
1143
|
+
timeStamp: z3.string(),
|
|
1144
|
+
id: z3.string(),
|
|
1145
|
+
revision: z3.number()
|
|
1146
|
+
});
|
|
1147
|
+
const accountsZ = z3.object({
|
|
1148
|
+
count: z3.number(),
|
|
1149
|
+
value: z3.array(
|
|
1150
|
+
z3.object({
|
|
1151
|
+
accountId: z3.string(),
|
|
1152
|
+
accountUri: z3.string(),
|
|
1153
|
+
accountName: z3.string()
|
|
1154
|
+
})
|
|
1155
|
+
)
|
|
1156
|
+
});
|
|
1157
|
+
const profileRes = await fetch(
|
|
1158
|
+
"https://app.vssps.visualstudio.com/_apis/profile/profiles/me?api-version=6.0",
|
|
1159
|
+
{
|
|
1160
|
+
method: "GET",
|
|
1161
|
+
headers: {
|
|
1162
|
+
Authorization: `Bearer ${oauthToken}`
|
|
1120
1163
|
}
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
const
|
|
1124
|
-
|
|
1164
|
+
}
|
|
1165
|
+
);
|
|
1166
|
+
const profileJson = await profileRes.json();
|
|
1167
|
+
const profile = profileZ.parse(profileJson);
|
|
1168
|
+
const accountsRes = await fetch(
|
|
1169
|
+
`https://app.vssps.visualstudio.com/_apis/accounts?memberId=${profile.publicAlias}&api-version=6.0`,
|
|
1170
|
+
{
|
|
1171
|
+
method: "GET",
|
|
1172
|
+
headers: {
|
|
1173
|
+
Authorization: `Bearer ${oauthToken}`
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1176
|
+
);
|
|
1177
|
+
const accountsJson = await accountsRes.json();
|
|
1178
|
+
const accounts = accountsZ.parse(accountsJson);
|
|
1179
|
+
const orgs = accounts.value.map((account) => account.accountName).filter((value, index, array) => array.indexOf(value) === index);
|
|
1180
|
+
return orgs;
|
|
1125
1181
|
}
|
|
1126
|
-
|
|
1182
|
+
function _getPublicAdoClient({ orgName }) {
|
|
1183
|
+
const orgUrl = `https://dev.azure.com/${orgName}`;
|
|
1184
|
+
const authHandler = api.getPersonalAccessTokenHandler("");
|
|
1185
|
+
authHandler.canHandleAuthentication = () => false;
|
|
1186
|
+
authHandler.prepareRequest = (_options) => {
|
|
1187
|
+
return;
|
|
1188
|
+
};
|
|
1189
|
+
const connection = new api.WebApi(orgUrl, authHandler);
|
|
1190
|
+
return connection;
|
|
1191
|
+
}
|
|
1192
|
+
function getAdoTokenType(token) {
|
|
1193
|
+
if (token.includes(".")) {
|
|
1194
|
+
return "OAUTH" /* OAUTH */;
|
|
1195
|
+
}
|
|
1196
|
+
return "PAT" /* PAT */;
|
|
1197
|
+
}
|
|
1198
|
+
async function getAdoApiClient({
|
|
1199
|
+
accessToken,
|
|
1200
|
+
tokenOrg,
|
|
1201
|
+
orgName
|
|
1202
|
+
}) {
|
|
1203
|
+
if (!accessToken || tokenOrg && tokenOrg !== orgName) {
|
|
1204
|
+
return _getPublicAdoClient({ orgName });
|
|
1205
|
+
}
|
|
1206
|
+
const orgUrl = `https://dev.azure.com/${orgName}`;
|
|
1207
|
+
if (getAdoTokenType(accessToken) === "OAUTH" /* OAUTH */) {
|
|
1208
|
+
const connection2 = new api.WebApi(orgUrl, api.getBearerHandler(accessToken));
|
|
1209
|
+
return connection2;
|
|
1210
|
+
}
|
|
1211
|
+
const authHandler = api.getPersonalAccessTokenHandler(accessToken);
|
|
1212
|
+
const connection = new api.WebApi(orgUrl, authHandler);
|
|
1213
|
+
return connection;
|
|
1214
|
+
}
|
|
1215
|
+
async function adoValidateParams({
|
|
1216
|
+
url,
|
|
1217
|
+
accessToken,
|
|
1218
|
+
tokenOrg
|
|
1219
|
+
}) {
|
|
1127
1220
|
try {
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1221
|
+
if (!url && accessToken && getAdoTokenType(accessToken) === "OAUTH" /* OAUTH */) {
|
|
1222
|
+
await _getOrgsForOauthToken({ oauthToken: accessToken });
|
|
1223
|
+
return;
|
|
1131
1224
|
}
|
|
1225
|
+
let org = tokenOrg;
|
|
1132
1226
|
if (url) {
|
|
1133
|
-
const { owner
|
|
1134
|
-
|
|
1227
|
+
const { owner } = parseAdoOwnerAndRepo(url);
|
|
1228
|
+
org = owner;
|
|
1135
1229
|
}
|
|
1230
|
+
if (!org) {
|
|
1231
|
+
throw new InvalidRepoUrlError(`invalid ADO ORG ${org}`);
|
|
1232
|
+
}
|
|
1233
|
+
const api2 = await getAdoApiClient({
|
|
1234
|
+
accessToken,
|
|
1235
|
+
tokenOrg,
|
|
1236
|
+
orgName: org
|
|
1237
|
+
});
|
|
1238
|
+
await api2.connect();
|
|
1136
1239
|
} catch (e) {
|
|
1137
1240
|
const error = e;
|
|
1138
|
-
const code = error.status || error.statusCode || error.response?.status || error.response?.statusCode || error.response?.code;
|
|
1139
|
-
|
|
1140
|
-
|
|
1241
|
+
const code = error.code || error.status || error.statusCode || error.response?.status || error.response?.statusCode || error.response?.code;
|
|
1242
|
+
const description = error.description || `${e}`;
|
|
1243
|
+
if (code === 401 || code === 403 || description.includes("401") || description.includes("403")) {
|
|
1244
|
+
throw new InvalidAccessTokenError(`invalid ADO access token`);
|
|
1141
1245
|
}
|
|
1142
|
-
if (code === 404) {
|
|
1143
|
-
throw new InvalidRepoUrlError(`invalid
|
|
1246
|
+
if (code === 404 || description.includes("404") || description.includes("Not Found")) {
|
|
1247
|
+
throw new InvalidRepoUrlError(`invalid ADO repo URL ${url}`);
|
|
1144
1248
|
}
|
|
1145
1249
|
throw e;
|
|
1146
1250
|
}
|
|
1147
1251
|
}
|
|
1148
|
-
async function
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
}
|
|
1153
|
-
async function getGithubIsUserCollaborator(username, accessToken, repoUrl) {
|
|
1252
|
+
async function getAdoIsUserCollaborator({
|
|
1253
|
+
accessToken,
|
|
1254
|
+
tokenOrg,
|
|
1255
|
+
repoUrl
|
|
1256
|
+
}) {
|
|
1154
1257
|
try {
|
|
1155
|
-
const { owner, repo } =
|
|
1156
|
-
const
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
username
|
|
1258
|
+
const { owner, repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
|
|
1259
|
+
const api2 = await getAdoApiClient({
|
|
1260
|
+
accessToken,
|
|
1261
|
+
tokenOrg,
|
|
1262
|
+
orgName: owner
|
|
1161
1263
|
});
|
|
1162
|
-
|
|
1163
|
-
|
|
1264
|
+
const git = await api2.getGitApi();
|
|
1265
|
+
const branches = await git.getBranches(repo, projectName);
|
|
1266
|
+
if (!branches || branches.length === 0) {
|
|
1267
|
+
throw new InvalidRepoUrlError("no branches");
|
|
1164
1268
|
}
|
|
1269
|
+
return true;
|
|
1165
1270
|
} catch (e) {
|
|
1166
1271
|
return false;
|
|
1167
1272
|
}
|
|
1168
|
-
return false;
|
|
1169
1273
|
}
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1274
|
+
var adoStatusNumberToEnumMap = {
|
|
1275
|
+
1: "active" /* active */,
|
|
1276
|
+
2: "abandoned" /* abandoned */,
|
|
1277
|
+
3: "completed" /* completed */,
|
|
1278
|
+
4: "all" /* all */
|
|
1279
|
+
};
|
|
1280
|
+
async function getAdoPullRequestStatus({
|
|
1281
|
+
accessToken,
|
|
1282
|
+
tokenOrg,
|
|
1283
|
+
repoUrl,
|
|
1284
|
+
prNumber
|
|
1285
|
+
}) {
|
|
1286
|
+
const { owner, repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
|
|
1287
|
+
const api2 = await getAdoApiClient({
|
|
1288
|
+
accessToken,
|
|
1289
|
+
tokenOrg,
|
|
1290
|
+
orgName: owner
|
|
1177
1291
|
});
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
return "draft";
|
|
1292
|
+
const git = await api2.getGitApi();
|
|
1293
|
+
const res = await git.getPullRequest(repo, prNumber, projectName);
|
|
1294
|
+
if (!res.status || res.status < 1 || res.status > 3) {
|
|
1295
|
+
throw new Error("bad pr status for ADO");
|
|
1183
1296
|
}
|
|
1184
|
-
return res.
|
|
1297
|
+
return adoStatusNumberToEnumMap[res.status];
|
|
1185
1298
|
}
|
|
1186
|
-
async function
|
|
1187
|
-
|
|
1188
|
-
|
|
1299
|
+
async function getAdoIsRemoteBranch({
|
|
1300
|
+
accessToken,
|
|
1301
|
+
tokenOrg,
|
|
1302
|
+
repoUrl,
|
|
1303
|
+
branch
|
|
1304
|
+
}) {
|
|
1305
|
+
const { owner, repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
|
|
1306
|
+
const api2 = await getAdoApiClient({
|
|
1307
|
+
accessToken,
|
|
1308
|
+
tokenOrg,
|
|
1309
|
+
orgName: owner
|
|
1310
|
+
});
|
|
1311
|
+
const git = await api2.getGitApi();
|
|
1189
1312
|
try {
|
|
1190
|
-
const
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
return branch === res.data.name;
|
|
1313
|
+
const branchStatus = await git.getBranch(repo, branch, projectName);
|
|
1314
|
+
if (!branchStatus || !branchStatus.commit) {
|
|
1315
|
+
throw new InvalidRepoUrlError("no branch status");
|
|
1316
|
+
}
|
|
1317
|
+
return branchStatus.name === branch;
|
|
1196
1318
|
} catch (e) {
|
|
1197
1319
|
return false;
|
|
1198
1320
|
}
|
|
1199
1321
|
}
|
|
1200
|
-
async function
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1322
|
+
async function getAdoRepoList({
|
|
1323
|
+
orgName,
|
|
1324
|
+
tokenOrg,
|
|
1325
|
+
accessToken
|
|
1326
|
+
}) {
|
|
1327
|
+
let orgs = [];
|
|
1328
|
+
if (getAdoTokenType(accessToken) === "OAUTH" /* OAUTH */) {
|
|
1329
|
+
orgs = await _getOrgsForOauthToken({ oauthToken: accessToken });
|
|
1330
|
+
}
|
|
1331
|
+
if (orgs.length === 0 && !orgName) {
|
|
1332
|
+
throw new Error(`no orgs for ADO`);
|
|
1333
|
+
} else if (orgs.length === 0 && orgName) {
|
|
1334
|
+
orgs = [orgName];
|
|
1335
|
+
}
|
|
1336
|
+
const repos = (await Promise.allSettled(
|
|
1337
|
+
orgs.map(async (org) => {
|
|
1338
|
+
const orgApi = await getAdoApiClient({
|
|
1339
|
+
accessToken,
|
|
1340
|
+
tokenOrg,
|
|
1341
|
+
orgName: org
|
|
1342
|
+
});
|
|
1343
|
+
const gitOrg = await orgApi.getGitApi();
|
|
1344
|
+
const orgRepos = await gitOrg.getRepositories();
|
|
1345
|
+
const repoInfoList = (await Promise.allSettled(
|
|
1346
|
+
orgRepos.map(async (repo) => {
|
|
1347
|
+
if (!repo.name || !repo.remoteUrl || !repo.defaultBranch) {
|
|
1348
|
+
throw new InvalidRepoUrlError("bad repo");
|
|
1349
|
+
}
|
|
1350
|
+
const branch = await gitOrg.getBranch(
|
|
1351
|
+
repo.name,
|
|
1352
|
+
repo.defaultBranch.replace(/^refs\/heads\//, ""),
|
|
1353
|
+
repo.project?.name
|
|
1354
|
+
);
|
|
1355
|
+
return {
|
|
1356
|
+
repoName: repo.name,
|
|
1357
|
+
repoUrl: repo.remoteUrl.replace(
|
|
1358
|
+
/^[hH][tT][tT][pP][sS]:\/\/[^/]+@/,
|
|
1359
|
+
"https://"
|
|
1360
|
+
),
|
|
1361
|
+
repoOwner: org,
|
|
1362
|
+
repoIsPublic: repo.project?.visibility === 2,
|
|
1363
|
+
//2 is public in the ADO API
|
|
1364
|
+
repoLanguages: [],
|
|
1365
|
+
repoUpdatedAt: branch.commit?.committer?.date?.toDateString() || repo.project?.lastUpdateTime?.toDateString() || (/* @__PURE__ */ new Date()).toDateString()
|
|
1366
|
+
};
|
|
1367
|
+
})
|
|
1368
|
+
)).reduce((acc, res) => {
|
|
1369
|
+
if (res.status === "fulfilled") {
|
|
1370
|
+
acc.push(res.value);
|
|
1209
1371
|
}
|
|
1210
|
-
return
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
};
|
|
1218
|
-
}
|
|
1219
|
-
);
|
|
1220
|
-
} catch (e) {
|
|
1221
|
-
if (e instanceof RequestError && e.status === 401) {
|
|
1222
|
-
return [];
|
|
1223
|
-
}
|
|
1224
|
-
if (e instanceof RequestError && e.status === 404) {
|
|
1225
|
-
return [];
|
|
1372
|
+
return acc;
|
|
1373
|
+
}, []);
|
|
1374
|
+
return repoInfoList;
|
|
1375
|
+
})
|
|
1376
|
+
)).reduce((acc, res) => {
|
|
1377
|
+
if (res.status === "fulfilled") {
|
|
1378
|
+
return acc.concat(res.value);
|
|
1226
1379
|
}
|
|
1227
|
-
|
|
1228
|
-
}
|
|
1229
|
-
|
|
1230
|
-
async function getGithubBranchList(accessToken, repoUrl) {
|
|
1231
|
-
const { owner, repo } = parseGithubOwnerAndRepo(repoUrl);
|
|
1232
|
-
const oktoKit = getOktoKit({ githubAuthToken: accessToken });
|
|
1233
|
-
const res = await oktoKit.rest.repos.listBranches({
|
|
1234
|
-
owner,
|
|
1235
|
-
repo,
|
|
1236
|
-
per_page: 1e3,
|
|
1237
|
-
page: 1
|
|
1238
|
-
});
|
|
1239
|
-
return res.data.map((branch) => branch.name);
|
|
1380
|
+
return acc;
|
|
1381
|
+
}, []);
|
|
1382
|
+
return repos;
|
|
1240
1383
|
}
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
repo,
|
|
1247
|
-
title: options.title,
|
|
1248
|
-
body: options.body,
|
|
1249
|
-
head: options.sourceBranchName,
|
|
1250
|
-
base: options.targetBranchName,
|
|
1251
|
-
draft: false,
|
|
1252
|
-
maintainer_can_modify: true
|
|
1253
|
-
});
|
|
1254
|
-
return res.data.number;
|
|
1384
|
+
function getAdoPrUrl({
|
|
1385
|
+
url,
|
|
1386
|
+
prNumber
|
|
1387
|
+
}) {
|
|
1388
|
+
return `${url}/pullrequest/${prNumber}`;
|
|
1255
1389
|
}
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
}
|
|
1264
|
-
return { url: res.data.html_url ? String(res.data.html_url) : null };
|
|
1390
|
+
function getAdoDownloadUrl({
|
|
1391
|
+
repoUrl,
|
|
1392
|
+
branch
|
|
1393
|
+
}) {
|
|
1394
|
+
const { owner, repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
|
|
1395
|
+
const url = new URL(repoUrl);
|
|
1396
|
+
const origin = url.origin.toLowerCase().endsWith(".visualstudio.com") ? "https://dev.azure.com" : url.origin.toLowerCase();
|
|
1397
|
+
return `${origin}/${owner}/${projectName}/_apis/git/repositories/${repo}/items/items?path=/&versionDescriptor[versionOptions]=0&versionDescriptor[versionType]=commit&versionDescriptor[version]=${branch}&resolveLfs=true&$format=zip&api-version=5.0&download=true`;
|
|
1265
1398
|
}
|
|
1266
|
-
async function
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1399
|
+
async function getAdoBranchList({
|
|
1400
|
+
accessToken,
|
|
1401
|
+
tokenOrg,
|
|
1402
|
+
repoUrl
|
|
1403
|
+
}) {
|
|
1404
|
+
const { owner, repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
|
|
1405
|
+
const api2 = await getAdoApiClient({
|
|
1406
|
+
accessToken,
|
|
1407
|
+
tokenOrg,
|
|
1408
|
+
orgName: owner
|
|
1272
1409
|
});
|
|
1273
|
-
|
|
1274
|
-
}
|
|
1275
|
-
async function getGithubRepoDefaultBranch(repoUrl, options) {
|
|
1276
|
-
const oktoKit = getOktoKit(options);
|
|
1277
|
-
const { owner, repo } = parseGithubOwnerAndRepo(repoUrl);
|
|
1278
|
-
return (await oktoKit.rest.repos.get({ repo, owner })).data.default_branch;
|
|
1279
|
-
}
|
|
1280
|
-
async function getGithubReferenceData({ ref, gitHubUrl }, options) {
|
|
1281
|
-
const { owner, repo } = parseGithubOwnerAndRepo(gitHubUrl);
|
|
1282
|
-
let res;
|
|
1410
|
+
const git = await api2.getGitApi();
|
|
1283
1411
|
try {
|
|
1284
|
-
const
|
|
1285
|
-
res
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
type: "TAG" /* TAG */,
|
|
1299
|
-
sha: data.sha
|
|
1300
|
-
}))
|
|
1301
|
-
]);
|
|
1302
|
-
return res;
|
|
1412
|
+
const res = await git.getBranches(repo, projectName);
|
|
1413
|
+
res.sort((a, b) => {
|
|
1414
|
+
if (!a.commit?.committer?.date || !b.commit?.committer?.date) {
|
|
1415
|
+
return 0;
|
|
1416
|
+
}
|
|
1417
|
+
return b.commit?.committer?.date.getTime() - a.commit?.committer?.date.getTime();
|
|
1418
|
+
});
|
|
1419
|
+
return res.reduce((acc, branch) => {
|
|
1420
|
+
if (!branch.name) {
|
|
1421
|
+
return acc;
|
|
1422
|
+
}
|
|
1423
|
+
acc.push(branch.name);
|
|
1424
|
+
return acc;
|
|
1425
|
+
}, []);
|
|
1303
1426
|
} catch (e) {
|
|
1304
|
-
|
|
1305
|
-
throw new RefNotFoundError(`ref: ${ref} does not exist`);
|
|
1306
|
-
}
|
|
1307
|
-
throw e;
|
|
1427
|
+
return [];
|
|
1308
1428
|
}
|
|
1309
1429
|
}
|
|
1310
|
-
async function
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1430
|
+
async function createAdoPullRequest(options) {
|
|
1431
|
+
const { owner, repo, projectName } = parseAdoOwnerAndRepo(options.repoUrl);
|
|
1432
|
+
const api2 = await getAdoApiClient({
|
|
1433
|
+
accessToken: options.accessToken,
|
|
1434
|
+
tokenOrg: options.tokenOrg,
|
|
1435
|
+
orgName: owner
|
|
1315
1436
|
});
|
|
1437
|
+
const git = await api2.getGitApi();
|
|
1438
|
+
const res = await git.createPullRequest(
|
|
1439
|
+
{
|
|
1440
|
+
sourceRefName: `refs/heads/${options.sourceBranchName}`,
|
|
1441
|
+
targetRefName: `refs/heads/${options.targetBranchName}`,
|
|
1442
|
+
title: options.title,
|
|
1443
|
+
description: options.body
|
|
1444
|
+
},
|
|
1445
|
+
repo,
|
|
1446
|
+
projectName
|
|
1447
|
+
);
|
|
1448
|
+
return res.pullRequestId;
|
|
1316
1449
|
}
|
|
1317
|
-
async function
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
});
|
|
1323
|
-
const
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1450
|
+
async function getAdoRepoDefaultBranch({
|
|
1451
|
+
repoUrl,
|
|
1452
|
+
tokenOrg,
|
|
1453
|
+
accessToken
|
|
1454
|
+
}) {
|
|
1455
|
+
const { owner, repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
|
|
1456
|
+
const api2 = await getAdoApiClient({
|
|
1457
|
+
accessToken,
|
|
1458
|
+
tokenOrg,
|
|
1459
|
+
orgName: owner
|
|
1460
|
+
});
|
|
1461
|
+
const git = await api2.getGitApi();
|
|
1462
|
+
const branches = await git.getBranches(repo, projectName);
|
|
1463
|
+
if (!branches || branches.length === 0) {
|
|
1464
|
+
throw new InvalidRepoUrlError("no branches");
|
|
1465
|
+
}
|
|
1466
|
+
const res = branches.find((branch) => branch.isBaseVersion);
|
|
1467
|
+
if (!res || !res.name) {
|
|
1468
|
+
throw new InvalidRepoUrlError("no default branch");
|
|
1469
|
+
}
|
|
1470
|
+
return res.name;
|
|
1471
|
+
}
|
|
1472
|
+
async function getAdoReferenceData({
|
|
1473
|
+
ref,
|
|
1474
|
+
repoUrl,
|
|
1475
|
+
accessToken,
|
|
1476
|
+
tokenOrg
|
|
1477
|
+
}) {
|
|
1478
|
+
const { owner, repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
|
|
1479
|
+
const api2 = await getAdoApiClient({
|
|
1480
|
+
accessToken,
|
|
1481
|
+
tokenOrg,
|
|
1482
|
+
orgName: owner
|
|
1483
|
+
});
|
|
1484
|
+
if (!projectName) {
|
|
1485
|
+
throw new InvalidUrlPatternError("no project name");
|
|
1486
|
+
}
|
|
1487
|
+
const git = await api2.getGitApi();
|
|
1488
|
+
const results = await Promise.allSettled([
|
|
1489
|
+
(async () => {
|
|
1490
|
+
const res = await git.getBranch(repo, ref, projectName);
|
|
1491
|
+
if (!res.commit || !res.commit.commitId) {
|
|
1492
|
+
throw new InvalidRepoUrlError("no commit on branch");
|
|
1493
|
+
}
|
|
1494
|
+
return {
|
|
1495
|
+
sha: res.commit.commitId,
|
|
1496
|
+
type: "BRANCH" /* BRANCH */,
|
|
1497
|
+
date: res.commit.committer?.date || /* @__PURE__ */ new Date()
|
|
1498
|
+
};
|
|
1499
|
+
})(),
|
|
1500
|
+
(async () => {
|
|
1501
|
+
const res = await git.getCommits(
|
|
1502
|
+
repo,
|
|
1503
|
+
{
|
|
1504
|
+
fromCommitId: ref,
|
|
1505
|
+
toCommitId: ref,
|
|
1506
|
+
$top: 1
|
|
1507
|
+
},
|
|
1508
|
+
projectName
|
|
1509
|
+
);
|
|
1510
|
+
const commit = res[0];
|
|
1511
|
+
if (!commit || !commit.commitId) {
|
|
1512
|
+
throw new Error("no commit");
|
|
1513
|
+
}
|
|
1514
|
+
return {
|
|
1515
|
+
sha: commit.commitId,
|
|
1516
|
+
type: "COMMIT" /* COMMIT */,
|
|
1517
|
+
date: commit.committer?.date || /* @__PURE__ */ new Date()
|
|
1518
|
+
};
|
|
1519
|
+
})(),
|
|
1520
|
+
(async () => {
|
|
1521
|
+
const res = await git.getRefs(repo, projectName, `tags/${ref}`);
|
|
1522
|
+
if (!res[0] || !res[0].objectId) {
|
|
1523
|
+
throw new Error("no tag ref");
|
|
1524
|
+
}
|
|
1525
|
+
let objectId = res[0].objectId;
|
|
1526
|
+
try {
|
|
1527
|
+
const tag = await git.getAnnotatedTag(projectName, repo, objectId);
|
|
1528
|
+
if (tag.taggedObject?.objectId) {
|
|
1529
|
+
objectId = tag.taggedObject.objectId;
|
|
1530
|
+
}
|
|
1531
|
+
} catch (e) {
|
|
1532
|
+
}
|
|
1533
|
+
const commitRes2 = await git.getCommits(
|
|
1534
|
+
repo,
|
|
1535
|
+
{
|
|
1536
|
+
fromCommitId: objectId,
|
|
1537
|
+
toCommitId: objectId,
|
|
1538
|
+
$top: 1
|
|
1539
|
+
},
|
|
1540
|
+
projectName
|
|
1541
|
+
);
|
|
1542
|
+
const commit = commitRes2[0];
|
|
1543
|
+
if (!commit) {
|
|
1544
|
+
throw new Error("no commit");
|
|
1545
|
+
}
|
|
1546
|
+
return {
|
|
1547
|
+
sha: objectId,
|
|
1548
|
+
type: "TAG" /* TAG */,
|
|
1549
|
+
date: commit.committer?.date || /* @__PURE__ */ new Date()
|
|
1550
|
+
};
|
|
1551
|
+
})()
|
|
1552
|
+
]);
|
|
1553
|
+
const [branchRes, commitRes, tagRes] = results;
|
|
1554
|
+
if (tagRes.status === "fulfilled") {
|
|
1555
|
+
return tagRes.value;
|
|
1556
|
+
}
|
|
1557
|
+
if (branchRes.status === "fulfilled") {
|
|
1558
|
+
return branchRes.value;
|
|
1559
|
+
}
|
|
1560
|
+
if (commitRes.status === "fulfilled") {
|
|
1561
|
+
return commitRes.value;
|
|
1562
|
+
}
|
|
1563
|
+
throw new RefNotFoundError(`ref: ${ref} does not exist`);
|
|
1564
|
+
}
|
|
1565
|
+
function parseAdoOwnerAndRepo(adoUrl) {
|
|
1566
|
+
adoUrl = removeTrailingSlash(adoUrl);
|
|
1567
|
+
const parsingResult = parseScmURL(adoUrl, "Ado" /* Ado */);
|
|
1568
|
+
if (!parsingResult || parsingResult.hostname !== "dev.azure.com" && !parsingResult.hostname.endsWith(".visualstudio.com")) {
|
|
1569
|
+
throw new InvalidUrlPatternError(`invalid ADO repo URL: ${adoUrl}`);
|
|
1570
|
+
}
|
|
1571
|
+
const { organization, repoName, projectName, projectPath, pathElements } = parsingResult;
|
|
1572
|
+
return {
|
|
1573
|
+
owner: organization,
|
|
1574
|
+
repo: repoName,
|
|
1575
|
+
projectName,
|
|
1576
|
+
projectPath,
|
|
1577
|
+
pathElements
|
|
1578
|
+
};
|
|
1579
|
+
}
|
|
1580
|
+
async function getAdoBlameRanges() {
|
|
1581
|
+
return [];
|
|
1582
|
+
}
|
|
1583
|
+
var ADO_ACCESS_TOKEN_URL = "https://app.vssps.visualstudio.com/oauth2/token";
|
|
1584
|
+
var AdoAuthResultZ = z3.object({
|
|
1585
|
+
access_token: z3.string().min(1),
|
|
1586
|
+
token_type: z3.string().min(1),
|
|
1587
|
+
refresh_token: z3.string().min(1)
|
|
1588
|
+
});
|
|
1589
|
+
async function getAdoToken({
|
|
1590
|
+
token,
|
|
1591
|
+
adoClientSecret,
|
|
1592
|
+
tokenType,
|
|
1593
|
+
redirectUri
|
|
1594
|
+
}) {
|
|
1595
|
+
const res = await fetch(ADO_ACCESS_TOKEN_URL, {
|
|
1596
|
+
method: "POST",
|
|
1597
|
+
headers: {
|
|
1598
|
+
Accept: "application/json",
|
|
1599
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
1600
|
+
},
|
|
1601
|
+
body: querystring.stringify({
|
|
1602
|
+
client_assertion_type: "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
|
|
1603
|
+
client_assertion: adoClientSecret,
|
|
1604
|
+
redirect_uri: redirectUri,
|
|
1605
|
+
assertion: token,
|
|
1606
|
+
grant_type: tokenType === "code" /* CODE */ ? "urn:ietf:params:oauth:grant-type:jwt-bearer" : "refresh_token"
|
|
1607
|
+
})
|
|
1608
|
+
});
|
|
1609
|
+
const authResult = await res.json();
|
|
1610
|
+
return AdoAuthResultZ.parse(authResult);
|
|
1611
|
+
}
|
|
1612
|
+
var AdoSdk = {
|
|
1613
|
+
getAdoApiClient,
|
|
1614
|
+
adoValidateParams,
|
|
1615
|
+
getAdoIsUserCollaborator,
|
|
1616
|
+
getAdoPullRequestStatus,
|
|
1617
|
+
getAdoIsRemoteBranch,
|
|
1618
|
+
getAdoRepoList,
|
|
1619
|
+
getAdoDownloadUrl,
|
|
1620
|
+
getAdoBranchList,
|
|
1621
|
+
createAdoPullRequest,
|
|
1622
|
+
getAdoRepoDefaultBranch,
|
|
1623
|
+
getAdoReferenceData,
|
|
1624
|
+
parseAdoOwnerAndRepo,
|
|
1625
|
+
getAdoBlameRanges,
|
|
1626
|
+
getAdoToken,
|
|
1627
|
+
getAdoTokenType
|
|
1628
|
+
};
|
|
1629
|
+
|
|
1630
|
+
// src/features/analysis/scm/bitbucket/bitbucket.ts
|
|
1631
|
+
import querystring3 from "node:querystring";
|
|
1632
|
+
import * as bitbucketPkg from "bitbucket";
|
|
1633
|
+
import { z as z10 } from "zod";
|
|
1634
|
+
|
|
1635
|
+
// src/features/analysis/scm/scm.ts
|
|
1636
|
+
import { Octokit as Octokit2 } from "@octokit/core";
|
|
1637
|
+
import { z as z9 } from "zod";
|
|
1638
|
+
|
|
1639
|
+
// src/features/analysis/scm/github/encryptSecret.ts
|
|
1640
|
+
import sodium from "libsodium-wrappers";
|
|
1641
|
+
async function encryptSecret(secret, key) {
|
|
1642
|
+
await sodium.ready;
|
|
1643
|
+
const binkey = sodium.from_base64(key, sodium.base64_variants.ORIGINAL);
|
|
1644
|
+
const binsec = sodium.from_string(secret);
|
|
1645
|
+
const encBytes = sodium.crypto_box_seal(binsec, binkey);
|
|
1646
|
+
return sodium.to_base64(encBytes, sodium.base64_variants.ORIGINAL);
|
|
1647
|
+
}
|
|
1648
|
+
|
|
1649
|
+
// src/features/analysis/scm/github/github.ts
|
|
1650
|
+
import { RequestError } from "@octokit/request-error";
|
|
1651
|
+
import { Octokit } from "octokit";
|
|
1652
|
+
import { z as z4 } from "zod";
|
|
1653
|
+
|
|
1654
|
+
// src/features/analysis/scm/utils/get_issue_type.ts
|
|
1655
|
+
var getIssueType = (issueType) => {
|
|
1656
|
+
switch (issueType) {
|
|
1657
|
+
case "SQL_Injection" /* SqlInjection */:
|
|
1658
|
+
return "SQL Injection";
|
|
1659
|
+
case "CMDi_relative_path_command" /* CmDiRelativePathCommand */:
|
|
1660
|
+
return "Relative Path Command Injection";
|
|
1661
|
+
case "CMDi" /* CmDi */:
|
|
1662
|
+
return "Command Injection";
|
|
1663
|
+
case "XXE" /* Xxe */:
|
|
1664
|
+
return "XXE";
|
|
1665
|
+
case "XSS" /* Xss */:
|
|
1666
|
+
return "XSS";
|
|
1667
|
+
case "PT" /* Pt */:
|
|
1668
|
+
return "Path Traversal";
|
|
1669
|
+
case "ZIP_SLIP" /* ZipSlip */:
|
|
1670
|
+
return "Zip Slip";
|
|
1671
|
+
case "INSECURE_RANDOMNESS" /* InsecureRandomness */:
|
|
1672
|
+
return "Insecure Randomness";
|
|
1673
|
+
case "SSRF" /* Ssrf */:
|
|
1674
|
+
return "Server Side Request Forgery";
|
|
1675
|
+
case "TYPE_CONFUSION" /* TypeConfusion */:
|
|
1676
|
+
return "Type Confusion";
|
|
1677
|
+
case "REGEX_INJECTION" /* RegexInjection */:
|
|
1678
|
+
return "Regular Expression Injection";
|
|
1679
|
+
case "INCOMPLETE_URL_SANITIZATION" /* IncompleteUrlSanitization */:
|
|
1680
|
+
return "Incomplete URL Sanitization";
|
|
1681
|
+
case "LOG_FORGING" /* LogForging */:
|
|
1682
|
+
return "Log Forging";
|
|
1683
|
+
case "LOCALE_DEPENDENT_COMPARISON" /* LocaleDependentComparison */:
|
|
1684
|
+
return "Locale Dependent Comparison";
|
|
1685
|
+
case "MISSING_CHECK_AGAINST_NULL" /* MissingCheckAgainstNull */:
|
|
1686
|
+
return "Missing Check against Null";
|
|
1687
|
+
case "PASSWORD_IN_COMMENT" /* PasswordInComment */:
|
|
1688
|
+
return "Password in Comment";
|
|
1689
|
+
case "OVERLY_BROAD_CATCH" /* OverlyBroadCatch */:
|
|
1690
|
+
return "Poor Error Handling: Overly Broad Catch";
|
|
1691
|
+
case "USE_OF_SYSTEM_OUTPUT_STREAM" /* UseOfSystemOutputStream */:
|
|
1692
|
+
return "Use of System.out/System.err";
|
|
1693
|
+
case "DANGEROUS_FUNCTION_OVERFLOW" /* DangerousFunctionOverflow */:
|
|
1694
|
+
return "Use of dangerous function";
|
|
1695
|
+
case "DOS_STRING_BUILDER" /* DosStringBuilder */:
|
|
1696
|
+
return "Denial of Service: StringBuilder";
|
|
1697
|
+
case "OPEN_REDIRECT" /* OpenRedirect */:
|
|
1698
|
+
return "Open Redirect";
|
|
1699
|
+
case "WEAK_XML_SCHEMA_UNBOUNDED_OCCURRENCES" /* WeakXmlSchemaUnboundedOccurrences */:
|
|
1700
|
+
return "Weak XML Schema: Unbounded Occurrences";
|
|
1701
|
+
case "SYSTEM_INFORMATION_LEAK" /* SystemInformationLeak */:
|
|
1702
|
+
return "System Information Leak";
|
|
1703
|
+
case "HTTP_RESPONSE_SPLITTING" /* HttpResponseSplitting */:
|
|
1704
|
+
return "HTTP response splitting";
|
|
1705
|
+
case "HTTP_ONLY_COOKIE" /* HttpOnlyCookie */:
|
|
1706
|
+
return "Cookie is not HttpOnly";
|
|
1707
|
+
case "INSECURE_COOKIE" /* InsecureCookie */:
|
|
1708
|
+
return "Insecure Cookie";
|
|
1709
|
+
case "TRUST_BOUNDARY_VIOLATION" /* TrustBoundaryViolation */:
|
|
1710
|
+
return "Trust Boundary Violation";
|
|
1711
|
+
case "MISSING_EQUALS_OR_HASHCODE" /* MissingEqualsOrHashcode */:
|
|
1712
|
+
return "Missing equals or hashcode method";
|
|
1713
|
+
default: {
|
|
1714
|
+
return issueType ? issueType.replaceAll("_", " ") : "Other";
|
|
1715
|
+
}
|
|
1716
|
+
}
|
|
1717
|
+
};
|
|
1718
|
+
|
|
1719
|
+
// src/features/analysis/scm/utils/index.ts
|
|
1720
|
+
function getFixUrlWithRedirect(params) {
|
|
1721
|
+
const {
|
|
1722
|
+
fixId,
|
|
1723
|
+
projectId,
|
|
1724
|
+
organizationId,
|
|
1725
|
+
analysisId,
|
|
1726
|
+
redirectUrl,
|
|
1727
|
+
appBaseUrl,
|
|
1728
|
+
commentId
|
|
1729
|
+
} = params;
|
|
1730
|
+
const searchParams = new URLSearchParams();
|
|
1731
|
+
searchParams.append("commit_redirect_url", redirectUrl);
|
|
1732
|
+
searchParams.append("comment_id", commentId.toString());
|
|
1733
|
+
return `${getFixUrl({
|
|
1734
|
+
appBaseUrl,
|
|
1735
|
+
fixId,
|
|
1736
|
+
projectId,
|
|
1737
|
+
organizationId,
|
|
1738
|
+
analysisId
|
|
1739
|
+
})}?${searchParams.toString()}`;
|
|
1740
|
+
}
|
|
1741
|
+
function getFixUrl({
|
|
1742
|
+
appBaseUrl,
|
|
1743
|
+
fixId,
|
|
1744
|
+
projectId,
|
|
1745
|
+
organizationId,
|
|
1746
|
+
analysisId
|
|
1747
|
+
}) {
|
|
1748
|
+
return `${appBaseUrl}/organization/${organizationId}/project/${projectId}/report/${analysisId}/fix/${fixId}`;
|
|
1749
|
+
}
|
|
1750
|
+
function getCommitUrl(params) {
|
|
1751
|
+
const {
|
|
1752
|
+
fixId,
|
|
1753
|
+
projectId,
|
|
1754
|
+
organizationId,
|
|
1755
|
+
analysisId,
|
|
1756
|
+
redirectUrl,
|
|
1757
|
+
appBaseUrl,
|
|
1758
|
+
commentId
|
|
1759
|
+
} = params;
|
|
1760
|
+
const searchParams = new URLSearchParams();
|
|
1761
|
+
searchParams.append("redirect_url", redirectUrl);
|
|
1762
|
+
searchParams.append("comment_id", commentId.toString());
|
|
1763
|
+
return `${getFixUrl({
|
|
1764
|
+
appBaseUrl,
|
|
1765
|
+
fixId,
|
|
1766
|
+
projectId,
|
|
1767
|
+
organizationId,
|
|
1768
|
+
analysisId
|
|
1769
|
+
})}/commit?${searchParams.toString()}`;
|
|
1770
|
+
}
|
|
1771
|
+
function removeTrailingSlash2(str) {
|
|
1772
|
+
return str.trim().replace(/\/+$/, "");
|
|
1773
|
+
}
|
|
1774
|
+
|
|
1775
|
+
// src/features/analysis/scm/github/github.ts
|
|
1776
|
+
var EnvVariablesZod = z4.object({
|
|
1777
|
+
GITHUB_API_TOKEN: z4.string().optional()
|
|
1778
|
+
});
|
|
1779
|
+
var { GITHUB_API_TOKEN } = EnvVariablesZod.parse(process.env);
|
|
1780
|
+
var GetBlameDocument = `
|
|
1781
|
+
query GetBlame(
|
|
1782
|
+
$owner: String!
|
|
1783
|
+
$repo: String!
|
|
1784
|
+
$ref: String!
|
|
1785
|
+
$path: String!
|
|
1786
|
+
) {
|
|
1787
|
+
repository(name: $repo, owner: $owner) {
|
|
1788
|
+
# branch name
|
|
1789
|
+
object(expression: $ref) {
|
|
1790
|
+
# cast Target to a Commit
|
|
1791
|
+
... on Commit {
|
|
1792
|
+
# full repo-relative path to blame file
|
|
1793
|
+
blame(path: $path) {
|
|
1794
|
+
ranges {
|
|
1795
|
+
commit {
|
|
1796
|
+
author {
|
|
1797
|
+
user {
|
|
1798
|
+
name
|
|
1799
|
+
login
|
|
1800
|
+
}
|
|
1801
|
+
}
|
|
1802
|
+
authoredDate
|
|
1803
|
+
}
|
|
1804
|
+
startingLine
|
|
1805
|
+
endingLine
|
|
1806
|
+
age
|
|
1807
|
+
}
|
|
1808
|
+
}
|
|
1809
|
+
}
|
|
1810
|
+
|
|
1811
|
+
}
|
|
1812
|
+
}
|
|
1813
|
+
}
|
|
1814
|
+
`;
|
|
1815
|
+
function getOktoKit(options) {
|
|
1816
|
+
const token = options?.githubAuthToken ?? GITHUB_API_TOKEN ?? "";
|
|
1817
|
+
return new Octokit({ auth: token });
|
|
1818
|
+
}
|
|
1819
|
+
async function githubValidateParams(url, accessToken) {
|
|
1820
|
+
try {
|
|
1821
|
+
const oktoKit = getOktoKit({ githubAuthToken: accessToken });
|
|
1822
|
+
if (accessToken) {
|
|
1823
|
+
await oktoKit.rest.users.getAuthenticated();
|
|
1824
|
+
}
|
|
1825
|
+
if (url) {
|
|
1826
|
+
const { owner, repo } = parseGithubOwnerAndRepo(url);
|
|
1827
|
+
await oktoKit.rest.repos.get({ repo, owner });
|
|
1828
|
+
}
|
|
1829
|
+
} catch (e) {
|
|
1830
|
+
const error = e;
|
|
1831
|
+
const code = error.status || error.statusCode || error.response?.status || error.response?.statusCode || error.response?.code;
|
|
1832
|
+
if (code === 401 || code === 403) {
|
|
1833
|
+
throw new InvalidAccessTokenError(`invalid github access token`);
|
|
1834
|
+
}
|
|
1835
|
+
if (code === 404) {
|
|
1836
|
+
throw new InvalidRepoUrlError(`invalid github repo Url ${url}`);
|
|
1837
|
+
}
|
|
1838
|
+
throw e;
|
|
1839
|
+
}
|
|
1840
|
+
}
|
|
1841
|
+
async function getGithubUsername(accessToken) {
|
|
1842
|
+
const oktoKit = getOktoKit({ githubAuthToken: accessToken });
|
|
1843
|
+
const res = await oktoKit.rest.users.getAuthenticated();
|
|
1844
|
+
return res.data.login;
|
|
1845
|
+
}
|
|
1846
|
+
async function getGithubIsUserCollaborator(username, accessToken, repoUrl) {
|
|
1847
|
+
try {
|
|
1848
|
+
const { owner, repo } = parseGithubOwnerAndRepo(repoUrl);
|
|
1849
|
+
const oktoKit = getOktoKit({ githubAuthToken: accessToken });
|
|
1850
|
+
const res = await oktoKit.rest.repos.checkCollaborator({
|
|
1851
|
+
owner,
|
|
1852
|
+
repo,
|
|
1853
|
+
username
|
|
1854
|
+
});
|
|
1855
|
+
if (res.status === 204) {
|
|
1856
|
+
return true;
|
|
1857
|
+
}
|
|
1858
|
+
} catch (e) {
|
|
1859
|
+
return false;
|
|
1860
|
+
}
|
|
1861
|
+
return false;
|
|
1862
|
+
}
|
|
1863
|
+
async function getGithubPullRequestStatus(accessToken, repoUrl, prNumber) {
|
|
1864
|
+
const { owner, repo } = parseGithubOwnerAndRepo(repoUrl);
|
|
1865
|
+
const oktoKit = getOktoKit({ githubAuthToken: accessToken });
|
|
1866
|
+
const res = await oktoKit.rest.pulls.get({
|
|
1867
|
+
owner,
|
|
1868
|
+
repo,
|
|
1869
|
+
pull_number: prNumber
|
|
1870
|
+
});
|
|
1871
|
+
if (res.data.merged) {
|
|
1872
|
+
return "merged";
|
|
1873
|
+
}
|
|
1874
|
+
if (res.data.draft) {
|
|
1875
|
+
return "draft";
|
|
1876
|
+
}
|
|
1877
|
+
return res.data.state;
|
|
1878
|
+
}
|
|
1879
|
+
async function getGithubIsRemoteBranch(accessToken, repoUrl, branch) {
|
|
1880
|
+
const { owner, repo } = parseGithubOwnerAndRepo(repoUrl);
|
|
1881
|
+
const oktoKit = getOktoKit({ githubAuthToken: accessToken });
|
|
1882
|
+
try {
|
|
1883
|
+
const res = await oktoKit.rest.repos.getBranch({
|
|
1884
|
+
owner,
|
|
1885
|
+
repo,
|
|
1886
|
+
branch
|
|
1887
|
+
});
|
|
1888
|
+
return branch === res.data.name;
|
|
1889
|
+
} catch (e) {
|
|
1890
|
+
return false;
|
|
1891
|
+
}
|
|
1892
|
+
}
|
|
1893
|
+
async function getGithubRepoList(accessToken) {
|
|
1894
|
+
const oktoKit = getOktoKit({ githubAuthToken: accessToken });
|
|
1895
|
+
try {
|
|
1896
|
+
const githubRepos = await getRepos(oktoKit);
|
|
1897
|
+
return githubRepos.map(
|
|
1898
|
+
(repo) => {
|
|
1899
|
+
const repoLanguages = [];
|
|
1900
|
+
if (repo.language) {
|
|
1901
|
+
repoLanguages.push(repo.language);
|
|
1902
|
+
}
|
|
1903
|
+
return {
|
|
1904
|
+
repoName: repo.name,
|
|
1905
|
+
repoUrl: repo.html_url,
|
|
1906
|
+
repoOwner: repo.owner.login,
|
|
1907
|
+
repoLanguages,
|
|
1908
|
+
repoIsPublic: !repo.private,
|
|
1909
|
+
repoUpdatedAt: repo.updated_at
|
|
1910
|
+
};
|
|
1911
|
+
}
|
|
1912
|
+
);
|
|
1913
|
+
} catch (e) {
|
|
1914
|
+
if (e instanceof RequestError && e.status === 401) {
|
|
1915
|
+
return [];
|
|
1916
|
+
}
|
|
1917
|
+
if (e instanceof RequestError && e.status === 404) {
|
|
1918
|
+
return [];
|
|
1919
|
+
}
|
|
1920
|
+
throw e;
|
|
1921
|
+
}
|
|
1922
|
+
}
|
|
1923
|
+
async function getGithubBranchList(accessToken, repoUrl) {
|
|
1924
|
+
const { owner, repo } = parseGithubOwnerAndRepo(repoUrl);
|
|
1925
|
+
const oktoKit = getOktoKit({ githubAuthToken: accessToken });
|
|
1926
|
+
const res = await oktoKit.rest.repos.listBranches({
|
|
1927
|
+
owner,
|
|
1928
|
+
repo,
|
|
1929
|
+
per_page: 1e3,
|
|
1930
|
+
page: 1
|
|
1931
|
+
});
|
|
1932
|
+
return res.data.map((branch) => branch.name);
|
|
1933
|
+
}
|
|
1934
|
+
async function createPullRequest(options) {
|
|
1935
|
+
const { owner, repo } = parseGithubOwnerAndRepo(options.repoUrl);
|
|
1936
|
+
const oktoKit = getOktoKit({ githubAuthToken: options.accessToken });
|
|
1937
|
+
const res = await oktoKit.rest.pulls.create({
|
|
1938
|
+
owner,
|
|
1939
|
+
repo,
|
|
1940
|
+
title: options.title,
|
|
1941
|
+
body: options.body,
|
|
1942
|
+
head: options.sourceBranchName,
|
|
1943
|
+
base: options.targetBranchName,
|
|
1944
|
+
draft: false,
|
|
1945
|
+
maintainer_can_modify: true
|
|
1946
|
+
});
|
|
1947
|
+
return res.data.number;
|
|
1948
|
+
}
|
|
1949
|
+
async function forkRepo(options) {
|
|
1950
|
+
const { owner, repo } = parseGithubOwnerAndRepo(options.repoUrl);
|
|
1951
|
+
const oktoKit = getOktoKit({ githubAuthToken: options.accessToken });
|
|
1952
|
+
const res = await oktoKit.rest.repos.createFork({
|
|
1953
|
+
owner,
|
|
1954
|
+
repo,
|
|
1955
|
+
default_branch_only: false
|
|
1956
|
+
});
|
|
1957
|
+
return { url: res.data.html_url ? String(res.data.html_url) : null };
|
|
1958
|
+
}
|
|
1959
|
+
async function getRepos(oktoKit) {
|
|
1960
|
+
const res = await oktoKit.request("GET /user/repos?sort=updated", {
|
|
1961
|
+
headers: {
|
|
1962
|
+
"X-GitHub-Api-Version": "2022-11-28",
|
|
1963
|
+
per_page: 100
|
|
1964
|
+
}
|
|
1965
|
+
});
|
|
1966
|
+
return res.data;
|
|
1967
|
+
}
|
|
1968
|
+
async function getGithubRepoDefaultBranch(repoUrl, options) {
|
|
1969
|
+
const oktoKit = getOktoKit(options);
|
|
1970
|
+
const { owner, repo } = parseGithubOwnerAndRepo(repoUrl);
|
|
1971
|
+
return (await oktoKit.rest.repos.get({ repo, owner })).data.default_branch;
|
|
1972
|
+
}
|
|
1973
|
+
async function getGithubReferenceData({ ref, gitHubUrl }, options) {
|
|
1974
|
+
const { owner, repo } = parseGithubOwnerAndRepo(gitHubUrl);
|
|
1975
|
+
let res;
|
|
1976
|
+
try {
|
|
1977
|
+
const oktoKit = getOktoKit(options);
|
|
1978
|
+
res = await Promise.any([
|
|
1979
|
+
getBranch({ owner, repo, branch: ref }, oktoKit).then((result) => ({
|
|
1980
|
+
date: result.data.commit.commit.committer?.date ? new Date(result.data.commit.commit.committer?.date) : void 0,
|
|
1981
|
+
type: "BRANCH" /* BRANCH */,
|
|
1982
|
+
sha: result.data.commit.sha
|
|
1983
|
+
})),
|
|
1984
|
+
getCommit({ commitSha: ref, repo, owner }, oktoKit).then((commit) => ({
|
|
1985
|
+
date: new Date(commit.data.committer.date),
|
|
1986
|
+
type: "COMMIT" /* COMMIT */,
|
|
1987
|
+
sha: commit.data.sha
|
|
1988
|
+
})),
|
|
1989
|
+
getTagDate({ owner, repo, tag: ref }, oktoKit).then((data) => ({
|
|
1990
|
+
date: new Date(data.date),
|
|
1991
|
+
type: "TAG" /* TAG */,
|
|
1992
|
+
sha: data.sha
|
|
1993
|
+
}))
|
|
1994
|
+
]);
|
|
1995
|
+
return res;
|
|
1996
|
+
} catch (e) {
|
|
1997
|
+
if (e instanceof AggregateError) {
|
|
1998
|
+
throw new RefNotFoundError(`ref: ${ref} does not exist`);
|
|
1999
|
+
}
|
|
2000
|
+
throw e;
|
|
2001
|
+
}
|
|
2002
|
+
}
|
|
2003
|
+
async function getBranch({ branch, owner, repo }, oktoKit) {
|
|
2004
|
+
return oktoKit.rest.repos.getBranch({
|
|
2005
|
+
branch,
|
|
2006
|
+
owner,
|
|
2007
|
+
repo
|
|
2008
|
+
});
|
|
2009
|
+
}
|
|
2010
|
+
async function getTagDate({ tag, owner, repo }, oktoKit) {
|
|
2011
|
+
const refResponse = await oktoKit.rest.git.getRef({
|
|
2012
|
+
ref: `tags/${tag}`,
|
|
2013
|
+
owner,
|
|
2014
|
+
repo
|
|
2015
|
+
});
|
|
2016
|
+
const tagSha = refResponse.data.object.sha;
|
|
2017
|
+
if (refResponse.data.object.type === "commit") {
|
|
2018
|
+
const res2 = await oktoKit.rest.git.getCommit({
|
|
2019
|
+
commit_sha: tagSha,
|
|
2020
|
+
owner,
|
|
1328
2021
|
repo
|
|
1329
2022
|
});
|
|
1330
2023
|
return {
|
|
@@ -1354,7 +2047,7 @@ async function getCommit({
|
|
|
1354
2047
|
});
|
|
1355
2048
|
}
|
|
1356
2049
|
function parseGithubOwnerAndRepo(gitHubUrl) {
|
|
1357
|
-
gitHubUrl =
|
|
2050
|
+
gitHubUrl = removeTrailingSlash2(gitHubUrl);
|
|
1358
2051
|
const parsingResult = parseScmURL(gitHubUrl, "GitHub" /* GitHub */);
|
|
1359
2052
|
if (!parsingResult || parsingResult.hostname !== "github.com") {
|
|
1360
2053
|
throw new InvalidUrlPatternError(`invalid github repo Url ${gitHubUrl}`);
|
|
@@ -1558,30 +2251,30 @@ function deleteGeneralPrComment(client, params) {
|
|
|
1558
2251
|
}
|
|
1559
2252
|
|
|
1560
2253
|
// src/features/analysis/scm/gitlab/gitlab.ts
|
|
1561
|
-
import
|
|
2254
|
+
import querystring2 from "node:querystring";
|
|
1562
2255
|
import {
|
|
1563
2256
|
Gitlab
|
|
1564
2257
|
} from "@gitbeaker/rest";
|
|
1565
2258
|
import { ProxyAgent } from "undici";
|
|
1566
|
-
import { z as
|
|
2259
|
+
import { z as z6 } from "zod";
|
|
1567
2260
|
|
|
1568
2261
|
// src/features/analysis/scm/gitlab/types.ts
|
|
1569
|
-
import { z as
|
|
1570
|
-
var GitlabAuthResultZ =
|
|
1571
|
-
access_token:
|
|
1572
|
-
token_type:
|
|
1573
|
-
refresh_token:
|
|
2262
|
+
import { z as z5 } from "zod";
|
|
2263
|
+
var GitlabAuthResultZ = z5.object({
|
|
2264
|
+
access_token: z5.string(),
|
|
2265
|
+
token_type: z5.string(),
|
|
2266
|
+
refresh_token: z5.string()
|
|
1574
2267
|
});
|
|
1575
2268
|
|
|
1576
2269
|
// src/features/analysis/scm/gitlab/gitlab.ts
|
|
1577
|
-
var EnvVariablesZod2 =
|
|
1578
|
-
GITLAB_API_TOKEN:
|
|
1579
|
-
BROKERED_HOSTS:
|
|
2270
|
+
var EnvVariablesZod2 = z6.object({
|
|
2271
|
+
GITLAB_API_TOKEN: z6.string().optional(),
|
|
2272
|
+
BROKERED_HOSTS: z6.string().toLowerCase().transform(
|
|
1580
2273
|
(x) => x.split(",").map((url) => url.trim(), []).filter(Boolean)
|
|
1581
2274
|
).default("")
|
|
1582
2275
|
});
|
|
1583
2276
|
var { GITLAB_API_TOKEN, BROKERED_HOSTS } = EnvVariablesZod2.parse(process.env);
|
|
1584
|
-
function
|
|
2277
|
+
function removeTrailingSlash3(str) {
|
|
1585
2278
|
return str.trim().replace(/\/+$/, "");
|
|
1586
2279
|
}
|
|
1587
2280
|
function getGitBeaker(options) {
|
|
@@ -1641,6 +2334,11 @@ async function getGitlabIsUserCollaborator({
|
|
|
1641
2334
|
return false;
|
|
1642
2335
|
}
|
|
1643
2336
|
}
|
|
2337
|
+
var gitlabMergeRequestStatus = {
|
|
2338
|
+
merged: "merged",
|
|
2339
|
+
opened: "opened",
|
|
2340
|
+
closed: "closed"
|
|
2341
|
+
};
|
|
1644
2342
|
async function getGitlabMergeRequestStatus({
|
|
1645
2343
|
accessToken,
|
|
1646
2344
|
repoUrl,
|
|
@@ -1650,9 +2348,9 @@ async function getGitlabMergeRequestStatus({
|
|
|
1650
2348
|
const api2 = getGitBeaker({ url: repoUrl, gitlabAuthToken: accessToken });
|
|
1651
2349
|
const res = await api2.MergeRequests.show(projectPath, mrNumber);
|
|
1652
2350
|
switch (res.state) {
|
|
1653
|
-
case
|
|
1654
|
-
case
|
|
1655
|
-
case
|
|
2351
|
+
case gitlabMergeRequestStatus.merged:
|
|
2352
|
+
case gitlabMergeRequestStatus.opened:
|
|
2353
|
+
case gitlabMergeRequestStatus.closed:
|
|
1656
2354
|
return res.state;
|
|
1657
2355
|
default:
|
|
1658
2356
|
throw new Error(`unknown merge request state ${res.state}`);
|
|
@@ -1805,7 +2503,7 @@ async function getGitlabReferenceData({ ref, gitlabUrl }, options) {
|
|
|
1805
2503
|
throw new RefNotFoundError(`ref: ${ref} does not exist`);
|
|
1806
2504
|
}
|
|
1807
2505
|
function parseGitlabOwnerAndRepo(gitlabUrl) {
|
|
1808
|
-
gitlabUrl =
|
|
2506
|
+
gitlabUrl = removeTrailingSlash3(gitlabUrl);
|
|
1809
2507
|
const parsingResult = parseScmURL(gitlabUrl, "GitLab" /* GitLab */);
|
|
1810
2508
|
if (!parsingResult || !parsingResult.repoName) {
|
|
1811
2509
|
throw new InvalidUrlPatternError(`invalid gitlab repo Url ${gitlabUrl}`);
|
|
@@ -1871,84 +2569,84 @@ import parseDiff from "parse-diff";
|
|
|
1871
2569
|
import path3 from "path";
|
|
1872
2570
|
import { simpleGit as simpleGit2 } from "simple-git";
|
|
1873
2571
|
import tmp from "tmp";
|
|
1874
|
-
import { z as
|
|
2572
|
+
import { z as z8 } from "zod";
|
|
1875
2573
|
|
|
1876
2574
|
// src/features/analysis/scm/scmSubmit/types.ts
|
|
1877
|
-
import { z as
|
|
1878
|
-
var BaseSubmitToScmMessageZ =
|
|
1879
|
-
submitFixRequestId:
|
|
1880
|
-
fixes:
|
|
1881
|
-
|
|
1882
|
-
fixId:
|
|
1883
|
-
diff:
|
|
2575
|
+
import { z as z7 } from "zod";
|
|
2576
|
+
var BaseSubmitToScmMessageZ = z7.object({
|
|
2577
|
+
submitFixRequestId: z7.string().uuid(),
|
|
2578
|
+
fixes: z7.array(
|
|
2579
|
+
z7.object({
|
|
2580
|
+
fixId: z7.string().uuid(),
|
|
2581
|
+
diff: z7.string()
|
|
1884
2582
|
})
|
|
1885
2583
|
),
|
|
1886
|
-
commitHash:
|
|
1887
|
-
repoUrl:
|
|
2584
|
+
commitHash: z7.string(),
|
|
2585
|
+
repoUrl: z7.string()
|
|
1888
2586
|
});
|
|
1889
2587
|
var submitToScmMessageType = {
|
|
1890
2588
|
commitToSameBranch: "commitToSameBranch",
|
|
1891
2589
|
submitFixesForDifferentBranch: "submitFixesForDifferentBranch"
|
|
1892
2590
|
};
|
|
1893
2591
|
var CommitToSameBranchParamsZ = BaseSubmitToScmMessageZ.merge(
|
|
1894
|
-
|
|
1895
|
-
type:
|
|
1896
|
-
branch:
|
|
1897
|
-
commitMessage:
|
|
1898
|
-
commitDescription:
|
|
1899
|
-
githubCommentId:
|
|
2592
|
+
z7.object({
|
|
2593
|
+
type: z7.literal(submitToScmMessageType.commitToSameBranch),
|
|
2594
|
+
branch: z7.string(),
|
|
2595
|
+
commitMessage: z7.string(),
|
|
2596
|
+
commitDescription: z7.string().nullish(),
|
|
2597
|
+
githubCommentId: z7.number().nullish()
|
|
1900
2598
|
})
|
|
1901
2599
|
);
|
|
1902
|
-
var SubmitFixesToDifferentBranchParamsZ =
|
|
1903
|
-
type:
|
|
1904
|
-
submitBranch:
|
|
1905
|
-
baseBranch:
|
|
2600
|
+
var SubmitFixesToDifferentBranchParamsZ = z7.object({
|
|
2601
|
+
type: z7.literal(submitToScmMessageType.submitFixesForDifferentBranch),
|
|
2602
|
+
submitBranch: z7.string(),
|
|
2603
|
+
baseBranch: z7.string()
|
|
1906
2604
|
}).merge(BaseSubmitToScmMessageZ);
|
|
1907
|
-
var SubmitFixesMessageZ =
|
|
2605
|
+
var SubmitFixesMessageZ = z7.union([
|
|
1908
2606
|
CommitToSameBranchParamsZ,
|
|
1909
2607
|
SubmitFixesToDifferentBranchParamsZ
|
|
1910
2608
|
]);
|
|
1911
|
-
var FixResponseArrayZ =
|
|
1912
|
-
|
|
1913
|
-
fixId:
|
|
2609
|
+
var FixResponseArrayZ = z7.array(
|
|
2610
|
+
z7.object({
|
|
2611
|
+
fixId: z7.string().uuid()
|
|
1914
2612
|
})
|
|
1915
2613
|
);
|
|
1916
|
-
var SubmitFixesBaseResponseMessageZ =
|
|
1917
|
-
submitFixRequestId:
|
|
1918
|
-
submitBranches:
|
|
1919
|
-
|
|
1920
|
-
branchName:
|
|
2614
|
+
var SubmitFixesBaseResponseMessageZ = z7.object({
|
|
2615
|
+
submitFixRequestId: z7.string().uuid(),
|
|
2616
|
+
submitBranches: z7.array(
|
|
2617
|
+
z7.object({
|
|
2618
|
+
branchName: z7.string(),
|
|
1921
2619
|
fixes: FixResponseArrayZ
|
|
1922
2620
|
})
|
|
1923
2621
|
),
|
|
1924
|
-
error:
|
|
1925
|
-
type:
|
|
2622
|
+
error: z7.object({
|
|
2623
|
+
type: z7.enum([
|
|
1926
2624
|
"InitialRepoAccessError",
|
|
1927
2625
|
"PushBranchError",
|
|
1928
2626
|
"UnknownError"
|
|
1929
2627
|
]),
|
|
1930
|
-
info:
|
|
1931
|
-
message:
|
|
1932
|
-
pushBranchName:
|
|
2628
|
+
info: z7.object({
|
|
2629
|
+
message: z7.string(),
|
|
2630
|
+
pushBranchName: z7.string().optional()
|
|
1933
2631
|
})
|
|
1934
2632
|
}).optional()
|
|
1935
2633
|
});
|
|
1936
|
-
var SubmitFixesToSameBranchResponseMessageZ =
|
|
1937
|
-
type:
|
|
1938
|
-
githubCommentId:
|
|
2634
|
+
var SubmitFixesToSameBranchResponseMessageZ = z7.object({
|
|
2635
|
+
type: z7.literal(submitToScmMessageType.commitToSameBranch),
|
|
2636
|
+
githubCommentId: z7.number().nullish()
|
|
1939
2637
|
}).merge(SubmitFixesBaseResponseMessageZ);
|
|
1940
|
-
var SubmitFixesToDifferentBranchResponseMessageZ =
|
|
1941
|
-
type:
|
|
1942
|
-
githubCommentId:
|
|
2638
|
+
var SubmitFixesToDifferentBranchResponseMessageZ = z7.object({
|
|
2639
|
+
type: z7.literal(submitToScmMessageType.submitFixesForDifferentBranch),
|
|
2640
|
+
githubCommentId: z7.number().optional()
|
|
1943
2641
|
}).merge(SubmitFixesBaseResponseMessageZ);
|
|
1944
|
-
var SubmitFixesResponseMessageZ =
|
|
2642
|
+
var SubmitFixesResponseMessageZ = z7.discriminatedUnion("type", [
|
|
1945
2643
|
SubmitFixesToSameBranchResponseMessageZ,
|
|
1946
2644
|
SubmitFixesToDifferentBranchResponseMessageZ
|
|
1947
2645
|
]);
|
|
1948
2646
|
|
|
1949
2647
|
// src/features/analysis/scm/scmSubmit/index.ts
|
|
1950
|
-
var EnvVariablesZod3 =
|
|
1951
|
-
BROKERED_HOSTS:
|
|
2648
|
+
var EnvVariablesZod3 = z8.object({
|
|
2649
|
+
BROKERED_HOSTS: z8.string().toLowerCase().transform(
|
|
1952
2650
|
(x) => x.split(",").map((url) => url.trim(), []).filter(Boolean)
|
|
1953
2651
|
).default("")
|
|
1954
2652
|
});
|
|
@@ -1965,49 +2663,59 @@ var isValidBranchName = async (branchName) => {
|
|
|
1965
2663
|
return false;
|
|
1966
2664
|
}
|
|
1967
2665
|
};
|
|
1968
|
-
var FixesZ =
|
|
2666
|
+
var FixesZ = z8.array(z8.object({ fixId: z8.string(), diff: z8.string() })).nonempty();
|
|
1969
2667
|
|
|
1970
2668
|
// src/features/analysis/scm/scm.ts
|
|
2669
|
+
var GetRefererenceResultZ = z9.object({
|
|
2670
|
+
date: z9.date().optional(),
|
|
2671
|
+
sha: z9.string(),
|
|
2672
|
+
type: z9.nativeEnum(ReferenceType)
|
|
2673
|
+
});
|
|
1971
2674
|
function getCloudScmLibTypeFromUrl(url) {
|
|
1972
2675
|
if (!url) {
|
|
1973
2676
|
return void 0;
|
|
1974
2677
|
}
|
|
1975
2678
|
const urlObject = new URL(url);
|
|
1976
2679
|
const hostname = urlObject.hostname.toLowerCase();
|
|
1977
|
-
if (hostname ===
|
|
2680
|
+
if (hostname === scmCloudHostname.GitLab) {
|
|
1978
2681
|
return "GITLAB" /* GITLAB */;
|
|
1979
2682
|
}
|
|
1980
|
-
if (hostname ===
|
|
2683
|
+
if (hostname === scmCloudHostname.GitHub) {
|
|
1981
2684
|
return "GITHUB" /* GITHUB */;
|
|
1982
2685
|
}
|
|
1983
|
-
if (hostname ===
|
|
2686
|
+
if (hostname === scmCloudHostname.Ado || hostname.endsWith(".visualstudio.com")) {
|
|
1984
2687
|
return "ADO" /* ADO */;
|
|
1985
2688
|
}
|
|
2689
|
+
if (hostname === scmCloudHostname.Bitbucket) {
|
|
2690
|
+
return "BITBUCKET" /* BITBUCKET */;
|
|
2691
|
+
}
|
|
1986
2692
|
return void 0;
|
|
1987
2693
|
}
|
|
2694
|
+
var scmCloudHostname = {
|
|
2695
|
+
GitLab: new URL(scmCloudUrl.GitLab).hostname,
|
|
2696
|
+
GitHub: new URL(scmCloudUrl.GitHub).hostname,
|
|
2697
|
+
Ado: new URL(scmCloudUrl.Ado).hostname,
|
|
2698
|
+
Bitbucket: new URL(scmCloudUrl.Bitbucket).hostname
|
|
2699
|
+
};
|
|
2700
|
+
var scmLibScmTypeToScmType = {
|
|
2701
|
+
["GITLAB" /* GITLAB */]: "GitLab" /* GitLab */,
|
|
2702
|
+
["GITHUB" /* GITHUB */]: "GitHub" /* GitHub */,
|
|
2703
|
+
["ADO" /* ADO */]: "Ado" /* Ado */,
|
|
2704
|
+
["BITBUCKET" /* BITBUCKET */]: "Bitbucket" /* Bitbucket */
|
|
2705
|
+
};
|
|
2706
|
+
var scmTypeToScmLibScmType = {
|
|
2707
|
+
["GitLab" /* GitLab */]: "GITLAB" /* GITLAB */,
|
|
2708
|
+
["GitHub" /* GitHub */]: "GITHUB" /* GITHUB */,
|
|
2709
|
+
["Ado" /* Ado */]: "ADO" /* ADO */,
|
|
2710
|
+
["Bitbucket" /* Bitbucket */]: "BITBUCKET" /* BITBUCKET */
|
|
2711
|
+
};
|
|
1988
2712
|
function getScmTypeFromScmLibType(scmLibType) {
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
}
|
|
1992
|
-
if (scmLibType === "GITHUB" /* GITHUB */) {
|
|
1993
|
-
return "GitHub" /* GitHub */;
|
|
1994
|
-
}
|
|
1995
|
-
if (scmLibType === "ADO" /* ADO */) {
|
|
1996
|
-
return "Ado" /* Ado */;
|
|
1997
|
-
}
|
|
1998
|
-
throw new Error(`unknown scm lib type: ${scmLibType}`);
|
|
2713
|
+
const parsedScmLibType = z9.nativeEnum(ScmLibScmType).parse(scmLibType);
|
|
2714
|
+
return scmLibScmTypeToScmType[parsedScmLibType];
|
|
1999
2715
|
}
|
|
2000
2716
|
function getScmLibTypeFromScmType(scmType) {
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
}
|
|
2004
|
-
if (scmType === "GitHub" /* GitHub */) {
|
|
2005
|
-
return "GITHUB" /* GITHUB */;
|
|
2006
|
-
}
|
|
2007
|
-
if (scmType === "Ado" /* Ado */) {
|
|
2008
|
-
return "ADO" /* ADO */;
|
|
2009
|
-
}
|
|
2010
|
-
throw new Error(`unknown scm type: ${scmType}`);
|
|
2717
|
+
const parsedScmType = z9.nativeEnum(ScmType).parse(scmType);
|
|
2718
|
+
return scmTypeToScmLibScmType[parsedScmType];
|
|
2011
2719
|
}
|
|
2012
2720
|
function getScmConfig({
|
|
2013
2721
|
url,
|
|
@@ -2103,6 +2811,19 @@ var RepoNoTokenAccessError = class extends Error {
|
|
|
2103
2811
|
super(m);
|
|
2104
2812
|
}
|
|
2105
2813
|
};
|
|
2814
|
+
function buildAuthrizedRepoUrl(args) {
|
|
2815
|
+
const { url, username, password } = args;
|
|
2816
|
+
const is_http = url.toLowerCase().startsWith("http://");
|
|
2817
|
+
const is_https = url.toLowerCase().startsWith("https://");
|
|
2818
|
+
if (is_http) {
|
|
2819
|
+
return `http://${username}:${password}@${url.toLowerCase().replace("http://", "")}`;
|
|
2820
|
+
} else if (is_https) {
|
|
2821
|
+
return `https://${username}:${password}@${url.toLowerCase().replace("https://", "")}`;
|
|
2822
|
+
} else {
|
|
2823
|
+
console.error(`invalid scm url ${url}`);
|
|
2824
|
+
throw new Error(`invalid scm url ${url}`);
|
|
2825
|
+
}
|
|
2826
|
+
}
|
|
2106
2827
|
var SCMLib = class {
|
|
2107
2828
|
constructor(url, accessToken, scmOrg) {
|
|
2108
2829
|
__publicField(this, "url");
|
|
@@ -2118,24 +2839,45 @@ var SCMLib = class {
|
|
|
2118
2839
|
throw new Error("no url");
|
|
2119
2840
|
}
|
|
2120
2841
|
const trimmedUrl = this.url.trim().replace(/\/$/, "");
|
|
2121
|
-
|
|
2842
|
+
const accessToken = this.getAccessToken();
|
|
2843
|
+
if (!accessToken) {
|
|
2122
2844
|
return trimmedUrl;
|
|
2123
2845
|
}
|
|
2846
|
+
console.log(
|
|
2847
|
+
"this instanceof BitbucketSCMLib",
|
|
2848
|
+
this instanceof BitbucketSCMLib
|
|
2849
|
+
);
|
|
2124
2850
|
const scmLibType = this.getScmLibType();
|
|
2125
2851
|
if (scmLibType === "ADO" /* ADO */) {
|
|
2126
|
-
return `https://${
|
|
2852
|
+
return `https://${accessToken}@${trimmedUrl.toLowerCase().replace("https://", "")}`;
|
|
2127
2853
|
}
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2854
|
+
if (this instanceof BitbucketSCMLib) {
|
|
2855
|
+
const authData = this.getAuthData();
|
|
2856
|
+
switch (authData.authType) {
|
|
2857
|
+
case "public": {
|
|
2858
|
+
return trimmedUrl;
|
|
2859
|
+
}
|
|
2860
|
+
case "token": {
|
|
2861
|
+
const { token } = authData;
|
|
2862
|
+
const username2 = await this._getUsernameForAuthUrl();
|
|
2863
|
+
return buildAuthrizedRepoUrl({
|
|
2864
|
+
url: trimmedUrl,
|
|
2865
|
+
username: username2,
|
|
2866
|
+
password: token
|
|
2867
|
+
});
|
|
2868
|
+
}
|
|
2869
|
+
case "basic": {
|
|
2870
|
+
const { username: username2, password } = authData;
|
|
2871
|
+
return buildAuthrizedRepoUrl({ url: trimmedUrl, username: username2, password });
|
|
2872
|
+
}
|
|
2873
|
+
}
|
|
2138
2874
|
}
|
|
2875
|
+
const username = await this._getUsernameForAuthUrl();
|
|
2876
|
+
return buildAuthrizedRepoUrl({
|
|
2877
|
+
url: trimmedUrl,
|
|
2878
|
+
username,
|
|
2879
|
+
password: accessToken
|
|
2880
|
+
});
|
|
2139
2881
|
}
|
|
2140
2882
|
getAccessToken() {
|
|
2141
2883
|
return this.accessToken || "";
|
|
@@ -2149,6 +2891,12 @@ var SCMLib = class {
|
|
|
2149
2891
|
}
|
|
2150
2892
|
return this.url.split("/").at(-1) || "";
|
|
2151
2893
|
}
|
|
2894
|
+
_validateToken() {
|
|
2895
|
+
if (!this.accessToken) {
|
|
2896
|
+
console.error("no access token");
|
|
2897
|
+
throw new Error("no access token");
|
|
2898
|
+
}
|
|
2899
|
+
}
|
|
2152
2900
|
static async getIsValidBranchName(branchName) {
|
|
2153
2901
|
return isValidBranchName(branchName);
|
|
2154
2902
|
}
|
|
@@ -2163,20 +2911,27 @@ var SCMLib = class {
|
|
|
2163
2911
|
trimmedUrl = url.trim().replace(/\/$/, "").replace(/.git$/i, "");
|
|
2164
2912
|
}
|
|
2165
2913
|
try {
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2914
|
+
switch (scmType) {
|
|
2915
|
+
case "GITHUB" /* GITHUB */: {
|
|
2916
|
+
const scm = new GithubSCMLib(trimmedUrl, accessToken, scmOrg);
|
|
2917
|
+
await scm.validateParams();
|
|
2918
|
+
return scm;
|
|
2919
|
+
}
|
|
2920
|
+
case "GITLAB" /* GITLAB */: {
|
|
2921
|
+
const scm = new GitlabSCMLib(trimmedUrl, accessToken, scmOrg);
|
|
2922
|
+
await scm.validateParams();
|
|
2923
|
+
return scm;
|
|
2924
|
+
}
|
|
2925
|
+
case "ADO" /* ADO */: {
|
|
2926
|
+
const scm = new AdoSCMLib(trimmedUrl, accessToken, scmOrg);
|
|
2927
|
+
await scm.validateParams();
|
|
2928
|
+
return scm;
|
|
2929
|
+
}
|
|
2930
|
+
case "BITBUCKET" /* BITBUCKET */: {
|
|
2931
|
+
const scm = new BitbucketSCMLib(trimmedUrl, accessToken, scmOrg);
|
|
2932
|
+
await scm.validateParams();
|
|
2933
|
+
return scm;
|
|
2934
|
+
}
|
|
2180
2935
|
}
|
|
2181
2936
|
} catch (e) {
|
|
2182
2937
|
if (e instanceof InvalidRepoUrlError && url) {
|
|
@@ -2187,36 +2942,24 @@ var SCMLib = class {
|
|
|
2187
2942
|
}
|
|
2188
2943
|
_validateAccessTokenAndUrl() {
|
|
2189
2944
|
if (!this.accessToken) {
|
|
2945
|
+
console.error("no access token");
|
|
2190
2946
|
throw new InvalidAccessTokenError("no access token");
|
|
2191
2947
|
}
|
|
2948
|
+
this._validateUrl();
|
|
2949
|
+
}
|
|
2950
|
+
_validateUrl() {
|
|
2192
2951
|
if (!this.url) {
|
|
2952
|
+
console.error("no url");
|
|
2193
2953
|
throw new InvalidRepoUrlError("no url");
|
|
2194
2954
|
}
|
|
2195
2955
|
}
|
|
2196
2956
|
};
|
|
2197
2957
|
var AdoSCMLib = class extends SCMLib {
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
getPrComment(_commentId) {
|
|
2202
|
-
throw new Error("getPrComment not implemented.");
|
|
2203
|
-
}
|
|
2204
|
-
async forkRepo() {
|
|
2205
|
-
throw new Error("forkRepo not supported yet");
|
|
2206
|
-
}
|
|
2207
|
-
async createOrUpdateRepositorySecret() {
|
|
2208
|
-
throw new Error("createOrUpdateRepositorySecret not supported yet");
|
|
2209
|
-
}
|
|
2210
|
-
async createPullRequestWithNewFile(_sourceRepoUrl, _filesPaths, _userRepoUrl, _title, _body) {
|
|
2211
|
-
throw new Error("createPullRequestWithNewFile not supported yet");
|
|
2212
|
-
}
|
|
2213
|
-
async createSubmitRequest(targetBranchName, sourceBranchName, title, body) {
|
|
2214
|
-
if (!this.accessToken || !this.url) {
|
|
2215
|
-
console.error("no access token or no url");
|
|
2216
|
-
throw new Error("no access token or no url");
|
|
2217
|
-
}
|
|
2958
|
+
async createSubmitRequest(params) {
|
|
2959
|
+
this._validateAccessTokenAndUrl();
|
|
2960
|
+
const { targetBranchName, sourceBranchName, title, body } = params;
|
|
2218
2961
|
return String(
|
|
2219
|
-
await createAdoPullRequest({
|
|
2962
|
+
await AdoSdk.createAdoPullRequest({
|
|
2220
2963
|
title,
|
|
2221
2964
|
body,
|
|
2222
2965
|
targetBranchName,
|
|
@@ -2228,7 +2971,7 @@ var AdoSCMLib = class extends SCMLib {
|
|
|
2228
2971
|
);
|
|
2229
2972
|
}
|
|
2230
2973
|
async validateParams() {
|
|
2231
|
-
return adoValidateParams({
|
|
2974
|
+
return AdoSdk.adoValidateParams({
|
|
2232
2975
|
url: this.url,
|
|
2233
2976
|
accessToken: this.accessToken,
|
|
2234
2977
|
tokenOrg: this.scmOrg
|
|
@@ -2239,18 +2982,15 @@ var AdoSCMLib = class extends SCMLib {
|
|
|
2239
2982
|
console.error("no access token");
|
|
2240
2983
|
throw new Error("no access token");
|
|
2241
2984
|
}
|
|
2242
|
-
return getAdoRepoList({
|
|
2985
|
+
return AdoSdk.getAdoRepoList({
|
|
2243
2986
|
orgName: scmOrg,
|
|
2244
2987
|
tokenOrg: this.scmOrg,
|
|
2245
2988
|
accessToken: this.accessToken
|
|
2246
2989
|
});
|
|
2247
2990
|
}
|
|
2248
2991
|
async getBranchList() {
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
throw new Error("no access token or no url");
|
|
2252
|
-
}
|
|
2253
|
-
return getAdoBranchList({
|
|
2992
|
+
this._validateAccessTokenAndUrl();
|
|
2993
|
+
return AdoSdk.getAdoBranchList({
|
|
2254
2994
|
accessToken: this.accessToken,
|
|
2255
2995
|
tokenOrg: this.scmOrg,
|
|
2256
2996
|
repoUrl: this.url
|
|
@@ -2261,7 +3001,7 @@ var AdoSCMLib = class extends SCMLib {
|
|
|
2261
3001
|
}
|
|
2262
3002
|
getAuthHeaders() {
|
|
2263
3003
|
if (this.accessToken) {
|
|
2264
|
-
if (getAdoTokenType(this.accessToken) === "OAUTH" /* OAUTH */) {
|
|
3004
|
+
if (AdoSdk.getAdoTokenType(this.accessToken) === "OAUTH" /* OAUTH */) {
|
|
2265
3005
|
return {
|
|
2266
3006
|
authorization: `Bearer ${this.accessToken}`
|
|
2267
3007
|
};
|
|
@@ -2276,21 +3016,17 @@ var AdoSCMLib = class extends SCMLib {
|
|
|
2276
3016
|
return {};
|
|
2277
3017
|
}
|
|
2278
3018
|
getDownloadUrl(sha) {
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
return getAdoDownloadUrl({ repoUrl: this.url, branch: sha });
|
|
3019
|
+
this._validateUrl();
|
|
3020
|
+
return Promise.resolve(
|
|
3021
|
+
AdoSdk.getAdoDownloadUrl({ repoUrl: this.url, branch: sha })
|
|
3022
|
+
);
|
|
2284
3023
|
}
|
|
2285
3024
|
async _getUsernameForAuthUrl() {
|
|
2286
3025
|
throw new Error("_getUsernameForAuthUrl() is not relevant for ADO");
|
|
2287
3026
|
}
|
|
2288
3027
|
async getIsRemoteBranch(branch) {
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
throw new Error("no access token or no url");
|
|
2292
|
-
}
|
|
2293
|
-
return getAdoIsRemoteBranch({
|
|
3028
|
+
this._validateAccessTokenAndUrl();
|
|
3029
|
+
return AdoSdk.getAdoIsRemoteBranch({
|
|
2294
3030
|
accessToken: this.accessToken,
|
|
2295
3031
|
tokenOrg: this.scmOrg,
|
|
2296
3032
|
repoUrl: this.url,
|
|
@@ -2298,11 +3034,8 @@ var AdoSCMLib = class extends SCMLib {
|
|
|
2298
3034
|
});
|
|
2299
3035
|
}
|
|
2300
3036
|
async getUserHasAccessToRepo() {
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
throw new Error("no access token or no url");
|
|
2304
|
-
}
|
|
2305
|
-
return getAdoIsUserCollaborator({
|
|
3037
|
+
this._validateAccessTokenAndUrl();
|
|
3038
|
+
return AdoSdk.getAdoIsUserCollaborator({
|
|
2306
3039
|
accessToken: this.accessToken,
|
|
2307
3040
|
tokenOrg: this.scmOrg,
|
|
2308
3041
|
repoUrl: this.url
|
|
@@ -2312,11 +3045,8 @@ var AdoSCMLib = class extends SCMLib {
|
|
|
2312
3045
|
throw new Error("getUsername() is not relevant for ADO");
|
|
2313
3046
|
}
|
|
2314
3047
|
async getSubmitRequestStatus(scmSubmitRequestId) {
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
throw new Error("no access token or no url");
|
|
2318
|
-
}
|
|
2319
|
-
const state = await getAdoPullRequestStatus({
|
|
3048
|
+
this._validateAccessTokenAndUrl();
|
|
3049
|
+
const state = await AdoSdk.getAdoPullRequestStatus({
|
|
2320
3050
|
accessToken: this.accessToken,
|
|
2321
3051
|
tokenOrg: this.scmOrg,
|
|
2322
3052
|
repoUrl: this.url,
|
|
@@ -2324,24 +3054,21 @@ var AdoSCMLib = class extends SCMLib {
|
|
|
2324
3054
|
});
|
|
2325
3055
|
switch (state) {
|
|
2326
3056
|
case "completed" /* completed */:
|
|
2327
|
-
return "
|
|
3057
|
+
return "merged";
|
|
2328
3058
|
case "active" /* active */:
|
|
2329
|
-
return "
|
|
3059
|
+
return "open";
|
|
2330
3060
|
case "abandoned" /* abandoned */:
|
|
2331
|
-
return "
|
|
3061
|
+
return "closed";
|
|
2332
3062
|
default:
|
|
2333
3063
|
throw new Error(`unknown state ${state}`);
|
|
2334
3064
|
}
|
|
2335
3065
|
}
|
|
2336
3066
|
async getRepoBlameRanges(_ref, _path) {
|
|
2337
|
-
return await getAdoBlameRanges();
|
|
3067
|
+
return await AdoSdk.getAdoBlameRanges();
|
|
2338
3068
|
}
|
|
2339
3069
|
async getReferenceData(ref) {
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
throw new Error("no url");
|
|
2343
|
-
}
|
|
2344
|
-
return await getAdoReferenceData({
|
|
3070
|
+
this._validateUrl();
|
|
3071
|
+
return await AdoSdk.getAdoReferenceData({
|
|
2345
3072
|
ref,
|
|
2346
3073
|
repoUrl: this.url,
|
|
2347
3074
|
accessToken: this.accessToken,
|
|
@@ -2349,11 +3076,8 @@ var AdoSCMLib = class extends SCMLib {
|
|
|
2349
3076
|
});
|
|
2350
3077
|
}
|
|
2351
3078
|
async getRepoDefaultBranch() {
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
throw new Error("no url");
|
|
2355
|
-
}
|
|
2356
|
-
return await getAdoRepoDefaultBranch({
|
|
3079
|
+
this._validateUrl();
|
|
3080
|
+
return await AdoSdk.getAdoRepoDefaultBranch({
|
|
2357
3081
|
repoUrl: this.url,
|
|
2358
3082
|
tokenOrg: this.scmOrg,
|
|
2359
3083
|
accessToken: this.accessToken
|
|
@@ -2363,22 +3087,11 @@ var AdoSCMLib = class extends SCMLib {
|
|
|
2363
3087
|
this._validateAccessTokenAndUrl();
|
|
2364
3088
|
return Promise.resolve(getAdoPrUrl({ prNumber, url: this.url }));
|
|
2365
3089
|
}
|
|
2366
|
-
postGeneralPrComment() {
|
|
2367
|
-
throw new Error("Method not implemented.");
|
|
2368
|
-
}
|
|
2369
|
-
getGeneralPrComments() {
|
|
2370
|
-
throw new Error("Method not implemented.");
|
|
2371
|
-
}
|
|
2372
|
-
deleteGeneralPrComment() {
|
|
2373
|
-
throw new Error("Method not implemented.");
|
|
2374
|
-
}
|
|
2375
3090
|
};
|
|
2376
3091
|
var GitlabSCMLib = class extends SCMLib {
|
|
2377
|
-
async createSubmitRequest(
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
throw new Error("no access token or no url");
|
|
2381
|
-
}
|
|
3092
|
+
async createSubmitRequest(params) {
|
|
3093
|
+
this._validateAccessTokenAndUrl();
|
|
3094
|
+
const { targetBranchName, sourceBranchName, title, body } = params;
|
|
2382
3095
|
return String(
|
|
2383
3096
|
await createMergeRequest({
|
|
2384
3097
|
title,
|
|
@@ -2396,23 +3109,6 @@ var GitlabSCMLib = class extends SCMLib {
|
|
|
2396
3109
|
accessToken: this.accessToken
|
|
2397
3110
|
});
|
|
2398
3111
|
}
|
|
2399
|
-
async forkRepo() {
|
|
2400
|
-
if (!this.accessToken) {
|
|
2401
|
-
console.error("no access token");
|
|
2402
|
-
throw new Error("no access token");
|
|
2403
|
-
}
|
|
2404
|
-
throw new Error("not supported yet");
|
|
2405
|
-
}
|
|
2406
|
-
async createOrUpdateRepositorySecret() {
|
|
2407
|
-
if (!this.accessToken) {
|
|
2408
|
-
console.error("no access token");
|
|
2409
|
-
throw new Error("no access token");
|
|
2410
|
-
}
|
|
2411
|
-
throw new Error("not supported yet");
|
|
2412
|
-
}
|
|
2413
|
-
async createPullRequestWithNewFile(_sourceRepoUrl, _filesPaths, _userRepoUrl, _title, _body) {
|
|
2414
|
-
throw new Error("not implemented");
|
|
2415
|
-
}
|
|
2416
3112
|
async getRepoList(_scmOrg) {
|
|
2417
3113
|
if (!this.accessToken) {
|
|
2418
3114
|
console.error("no access token");
|
|
@@ -2421,10 +3117,7 @@ var GitlabSCMLib = class extends SCMLib {
|
|
|
2421
3117
|
return getGitlabRepoList(this.url, this.accessToken);
|
|
2422
3118
|
}
|
|
2423
3119
|
async getBranchList() {
|
|
2424
|
-
|
|
2425
|
-
console.error("no access token or no url");
|
|
2426
|
-
throw new Error("no access token or no url");
|
|
2427
|
-
}
|
|
3120
|
+
this._validateAccessTokenAndUrl();
|
|
2428
3121
|
return getGitlabBranchList({
|
|
2429
3122
|
accessToken: this.accessToken,
|
|
2430
3123
|
repoUrl: this.url
|
|
@@ -2445,7 +3138,9 @@ var GitlabSCMLib = class extends SCMLib {
|
|
|
2445
3138
|
getDownloadUrl(sha) {
|
|
2446
3139
|
const urlSplit = this.url?.split("/") || [];
|
|
2447
3140
|
const repoName = urlSplit[urlSplit?.length - 1];
|
|
2448
|
-
return
|
|
3141
|
+
return Promise.resolve(
|
|
3142
|
+
`${this.url}/-/archive/${sha}/${repoName}-${sha}.zip`
|
|
3143
|
+
);
|
|
2449
3144
|
}
|
|
2450
3145
|
async _getUsernameForAuthUrl() {
|
|
2451
3146
|
if (this?.accessToken?.startsWith("glpat-")) {
|
|
@@ -2455,10 +3150,7 @@ var GitlabSCMLib = class extends SCMLib {
|
|
|
2455
3150
|
}
|
|
2456
3151
|
}
|
|
2457
3152
|
async getIsRemoteBranch(branch) {
|
|
2458
|
-
|
|
2459
|
-
console.error("no access token or no url");
|
|
2460
|
-
throw new Error("no access token or no url");
|
|
2461
|
-
}
|
|
3153
|
+
this._validateAccessTokenAndUrl();
|
|
2462
3154
|
return getGitlabIsRemoteBranch({
|
|
2463
3155
|
accessToken: this.accessToken,
|
|
2464
3156
|
repoUrl: this.url,
|
|
@@ -2466,10 +3158,7 @@ var GitlabSCMLib = class extends SCMLib {
|
|
|
2466
3158
|
});
|
|
2467
3159
|
}
|
|
2468
3160
|
async getUserHasAccessToRepo() {
|
|
2469
|
-
|
|
2470
|
-
console.error("no access token or no url");
|
|
2471
|
-
throw new Error("no access token or no url");
|
|
2472
|
-
}
|
|
3161
|
+
this._validateAccessTokenAndUrl();
|
|
2473
3162
|
const username = await this.getUsername();
|
|
2474
3163
|
return getGitlabIsUserCollaborator({
|
|
2475
3164
|
username,
|
|
@@ -2478,38 +3167,29 @@ var GitlabSCMLib = class extends SCMLib {
|
|
|
2478
3167
|
});
|
|
2479
3168
|
}
|
|
2480
3169
|
async getUsername() {
|
|
2481
|
-
|
|
2482
|
-
console.error("no access token");
|
|
2483
|
-
throw new Error("no access token");
|
|
2484
|
-
}
|
|
3170
|
+
this._validateAccessTokenAndUrl();
|
|
2485
3171
|
return getGitlabUsername(this.url, this.accessToken);
|
|
2486
3172
|
}
|
|
2487
3173
|
async getSubmitRequestStatus(scmSubmitRequestId) {
|
|
2488
|
-
|
|
2489
|
-
console.error("no access token or no url");
|
|
2490
|
-
throw new Error("no access token or no url");
|
|
2491
|
-
}
|
|
3174
|
+
this._validateAccessTokenAndUrl();
|
|
2492
3175
|
const state = await getGitlabMergeRequestStatus({
|
|
2493
3176
|
accessToken: this.accessToken,
|
|
2494
3177
|
repoUrl: this.url,
|
|
2495
3178
|
mrNumber: Number(scmSubmitRequestId)
|
|
2496
3179
|
});
|
|
2497
3180
|
switch (state) {
|
|
2498
|
-
case
|
|
2499
|
-
return "
|
|
2500
|
-
case
|
|
2501
|
-
return "
|
|
2502
|
-
case
|
|
2503
|
-
return "
|
|
3181
|
+
case gitlabMergeRequestStatus.merged:
|
|
3182
|
+
return "merged";
|
|
3183
|
+
case gitlabMergeRequestStatus.opened:
|
|
3184
|
+
return "open";
|
|
3185
|
+
case gitlabMergeRequestStatus.closed:
|
|
3186
|
+
return "closed";
|
|
2504
3187
|
default:
|
|
2505
3188
|
throw new Error(`unknown state ${state}`);
|
|
2506
3189
|
}
|
|
2507
3190
|
}
|
|
2508
3191
|
async getRepoBlameRanges(ref, path9) {
|
|
2509
|
-
|
|
2510
|
-
console.error("no url");
|
|
2511
|
-
throw new Error("no url");
|
|
2512
|
-
}
|
|
3192
|
+
this._validateUrl();
|
|
2513
3193
|
return await getGitlabBlameRanges(
|
|
2514
3194
|
{ ref, path: path9, gitlabUrl: this.url },
|
|
2515
3195
|
{
|
|
@@ -2519,10 +3199,7 @@ var GitlabSCMLib = class extends SCMLib {
|
|
|
2519
3199
|
);
|
|
2520
3200
|
}
|
|
2521
3201
|
async getReferenceData(ref) {
|
|
2522
|
-
|
|
2523
|
-
console.error("no url");
|
|
2524
|
-
throw new Error("no url");
|
|
2525
|
-
}
|
|
3202
|
+
this._validateUrl();
|
|
2526
3203
|
return await getGitlabReferenceData(
|
|
2527
3204
|
{ ref, gitlabUrl: this.url },
|
|
2528
3205
|
{
|
|
@@ -2532,21 +3209,12 @@ var GitlabSCMLib = class extends SCMLib {
|
|
|
2532
3209
|
);
|
|
2533
3210
|
}
|
|
2534
3211
|
async getRepoDefaultBranch() {
|
|
2535
|
-
|
|
2536
|
-
console.error("no url");
|
|
2537
|
-
throw new Error("no url");
|
|
2538
|
-
}
|
|
3212
|
+
this._validateUrl();
|
|
2539
3213
|
return await getGitlabRepoDefaultBranch(this.url, {
|
|
2540
3214
|
url: this.url,
|
|
2541
3215
|
gitlabAuthToken: this.accessToken
|
|
2542
3216
|
});
|
|
2543
3217
|
}
|
|
2544
|
-
getPrComment(_commentId) {
|
|
2545
|
-
throw new Error("getPrComment not implemented.");
|
|
2546
|
-
}
|
|
2547
|
-
updatePrComment(_params, _oktokit) {
|
|
2548
|
-
throw new Error("updatePrComment not implemented.");
|
|
2549
|
-
}
|
|
2550
3218
|
async getPrUrl(prNumber) {
|
|
2551
3219
|
this._validateAccessTokenAndUrl();
|
|
2552
3220
|
const res = await getGitlabMergeRequest({
|
|
@@ -2556,15 +3224,6 @@ var GitlabSCMLib = class extends SCMLib {
|
|
|
2556
3224
|
});
|
|
2557
3225
|
return res.web_url;
|
|
2558
3226
|
}
|
|
2559
|
-
postGeneralPrComment() {
|
|
2560
|
-
throw new Error("Method not implemented.");
|
|
2561
|
-
}
|
|
2562
|
-
getGeneralPrComments() {
|
|
2563
|
-
throw new Error("Method not implemented.");
|
|
2564
|
-
}
|
|
2565
|
-
deleteGeneralPrComment() {
|
|
2566
|
-
throw new Error("Method not implemented.");
|
|
2567
|
-
}
|
|
2568
3227
|
};
|
|
2569
3228
|
var GithubSCMLib = class extends SCMLib {
|
|
2570
3229
|
// we don't always need a url, what's important is that we have an access token
|
|
@@ -2573,11 +3232,9 @@ var GithubSCMLib = class extends SCMLib {
|
|
|
2573
3232
|
__publicField(this, "oktokit");
|
|
2574
3233
|
this.oktokit = new Octokit2({ auth: accessToken });
|
|
2575
3234
|
}
|
|
2576
|
-
async createSubmitRequest(
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
throw new Error("no access token or no url");
|
|
2580
|
-
}
|
|
3235
|
+
async createSubmitRequest(params) {
|
|
3236
|
+
this._validateAccessTokenAndUrl();
|
|
3237
|
+
const { targetBranchName, sourceBranchName, title, body } = params;
|
|
2581
3238
|
return String(
|
|
2582
3239
|
await createPullRequest({
|
|
2583
3240
|
title,
|
|
@@ -2590,10 +3247,7 @@ var GithubSCMLib = class extends SCMLib {
|
|
|
2590
3247
|
);
|
|
2591
3248
|
}
|
|
2592
3249
|
async forkRepo(repoUrl) {
|
|
2593
|
-
|
|
2594
|
-
console.error("no access token");
|
|
2595
|
-
throw new Error("no access token");
|
|
2596
|
-
}
|
|
3250
|
+
this._validateToken();
|
|
2597
3251
|
return forkRepo({
|
|
2598
3252
|
repoUrl,
|
|
2599
3253
|
accessToken: this.accessToken
|
|
@@ -2699,7 +3353,7 @@ var GithubSCMLib = class extends SCMLib {
|
|
|
2699
3353
|
owner,
|
|
2700
3354
|
repo
|
|
2701
3355
|
});
|
|
2702
|
-
return
|
|
3356
|
+
return z9.string().parse(prRes.data);
|
|
2703
3357
|
}
|
|
2704
3358
|
async getRepoList(_scmOrg) {
|
|
2705
3359
|
if (!this.accessToken) {
|
|
@@ -2709,10 +3363,7 @@ var GithubSCMLib = class extends SCMLib {
|
|
|
2709
3363
|
return getGithubRepoList(this.accessToken);
|
|
2710
3364
|
}
|
|
2711
3365
|
async getBranchList() {
|
|
2712
|
-
|
|
2713
|
-
console.error("no access token or no url");
|
|
2714
|
-
throw new Error("no access token or no url");
|
|
2715
|
-
}
|
|
3366
|
+
this._validateAccessTokenAndUrl();
|
|
2716
3367
|
return getGithubBranchList(this.accessToken, this.url);
|
|
2717
3368
|
}
|
|
2718
3369
|
getScmLibType() {
|
|
@@ -2725,16 +3376,13 @@ var GithubSCMLib = class extends SCMLib {
|
|
|
2725
3376
|
return {};
|
|
2726
3377
|
}
|
|
2727
3378
|
getDownloadUrl(sha) {
|
|
2728
|
-
return `${this.url}/zipball/${sha}
|
|
3379
|
+
return Promise.resolve(`${this.url}/zipball/${sha}`);
|
|
2729
3380
|
}
|
|
2730
3381
|
async _getUsernameForAuthUrl() {
|
|
2731
3382
|
return this.getUsername();
|
|
2732
3383
|
}
|
|
2733
3384
|
async getIsRemoteBranch(branch) {
|
|
2734
|
-
|
|
2735
|
-
console.error("no access token or no url");
|
|
2736
|
-
throw new Error("no access token or no url");
|
|
2737
|
-
}
|
|
3385
|
+
this._validateAccessTokenAndUrl();
|
|
2738
3386
|
return getGithubIsRemoteBranch(this.accessToken, this.url, branch);
|
|
2739
3387
|
}
|
|
2740
3388
|
async getUserHasAccessToRepo() {
|
|
@@ -2762,25 +3410,10 @@ var GithubSCMLib = class extends SCMLib {
|
|
|
2762
3410
|
this.url,
|
|
2763
3411
|
Number(scmSubmitRequestId)
|
|
2764
3412
|
);
|
|
2765
|
-
|
|
2766
|
-
return "MERGED" /* MERGED */;
|
|
2767
|
-
}
|
|
2768
|
-
if (state === "open") {
|
|
2769
|
-
return "OPEN" /* OPEN */;
|
|
2770
|
-
}
|
|
2771
|
-
if (state === "draft") {
|
|
2772
|
-
return "DRAFT" /* DRAFT */;
|
|
2773
|
-
}
|
|
2774
|
-
if (state === "closed") {
|
|
2775
|
-
return "CLOSED" /* CLOSED */;
|
|
2776
|
-
}
|
|
2777
|
-
throw new Error(`unknown state ${state}`);
|
|
3413
|
+
return state;
|
|
2778
3414
|
}
|
|
2779
3415
|
async getRepoBlameRanges(ref, path9) {
|
|
2780
|
-
|
|
2781
|
-
console.error("no url");
|
|
2782
|
-
throw new Error("no url");
|
|
2783
|
-
}
|
|
3416
|
+
this._validateUrl();
|
|
2784
3417
|
return await getGithubBlameRanges(
|
|
2785
3418
|
{ ref, path: path9, gitHubUrl: this.url },
|
|
2786
3419
|
{
|
|
@@ -2789,10 +3422,7 @@ var GithubSCMLib = class extends SCMLib {
|
|
|
2789
3422
|
);
|
|
2790
3423
|
}
|
|
2791
3424
|
async getReferenceData(ref) {
|
|
2792
|
-
|
|
2793
|
-
console.error("no url");
|
|
2794
|
-
throw new Error("no url");
|
|
2795
|
-
}
|
|
3425
|
+
this._validateUrl();
|
|
2796
3426
|
return await getGithubReferenceData(
|
|
2797
3427
|
{ ref, gitHubUrl: this.url },
|
|
2798
3428
|
{
|
|
@@ -2801,10 +3431,7 @@ var GithubSCMLib = class extends SCMLib {
|
|
|
2801
3431
|
);
|
|
2802
3432
|
}
|
|
2803
3433
|
async getPrComment(commentId) {
|
|
2804
|
-
|
|
2805
|
-
console.error("no url");
|
|
2806
|
-
throw new Error("no url");
|
|
2807
|
-
}
|
|
3434
|
+
this._validateUrl();
|
|
2808
3435
|
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
2809
3436
|
return await getPrComment(this.oktokit, {
|
|
2810
3437
|
repo,
|
|
@@ -2813,10 +3440,7 @@ var GithubSCMLib = class extends SCMLib {
|
|
|
2813
3440
|
});
|
|
2814
3441
|
}
|
|
2815
3442
|
async getRepoDefaultBranch() {
|
|
2816
|
-
|
|
2817
|
-
console.error("no url");
|
|
2818
|
-
throw new Error("no url");
|
|
2819
|
-
}
|
|
3443
|
+
this._validateUrl();
|
|
2820
3444
|
return await getGithubRepoDefaultBranch(this.url, {
|
|
2821
3445
|
githubAuthToken: this.accessToken
|
|
2822
3446
|
});
|
|
@@ -2836,10 +3460,7 @@ var GithubSCMLib = class extends SCMLib {
|
|
|
2836
3460
|
}
|
|
2837
3461
|
async postGeneralPrComment(params, auth) {
|
|
2838
3462
|
const { prNumber, body } = params;
|
|
2839
|
-
|
|
2840
|
-
console.error("no url");
|
|
2841
|
-
throw new Error("no url");
|
|
2842
|
-
}
|
|
3463
|
+
this._validateUrl();
|
|
2843
3464
|
const oktoKit = auth ? new Octokit2({ auth: auth.authToken }) : this.oktokit;
|
|
2844
3465
|
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
2845
3466
|
return await postGeneralPrComment(oktoKit, {
|
|
@@ -2851,10 +3472,7 @@ var GithubSCMLib = class extends SCMLib {
|
|
|
2851
3472
|
}
|
|
2852
3473
|
async getGeneralPrComments(params, auth) {
|
|
2853
3474
|
const { prNumber } = params;
|
|
2854
|
-
|
|
2855
|
-
console.error("no url");
|
|
2856
|
-
throw new Error("no url");
|
|
2857
|
-
}
|
|
3475
|
+
this._validateUrl();
|
|
2858
3476
|
const oktoKit = auth ? new Octokit2({ auth: auth.authToken }) : this.oktokit;
|
|
2859
3477
|
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
2860
3478
|
return await getGeneralPrComments(oktoKit, {
|
|
@@ -2864,10 +3482,7 @@ var GithubSCMLib = class extends SCMLib {
|
|
|
2864
3482
|
});
|
|
2865
3483
|
}
|
|
2866
3484
|
async deleteGeneralPrComment({ commentId }, auth) {
|
|
2867
|
-
|
|
2868
|
-
console.error("no url");
|
|
2869
|
-
throw new Error("no url");
|
|
2870
|
-
}
|
|
3485
|
+
this._validateUrl();
|
|
2871
3486
|
const oktoKit = auth ? new Octokit2({ auth: auth.authToken }) : this.oktokit;
|
|
2872
3487
|
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
2873
3488
|
return deleteGeneralPrComment(oktoKit, {
|
|
@@ -2878,7 +3493,7 @@ var GithubSCMLib = class extends SCMLib {
|
|
|
2878
3493
|
}
|
|
2879
3494
|
};
|
|
2880
3495
|
var StubSCMLib = class extends SCMLib {
|
|
2881
|
-
async createSubmitRequest(
|
|
3496
|
+
async createSubmitRequest(_params) {
|
|
2882
3497
|
console.error("createSubmitRequest() not implemented");
|
|
2883
3498
|
throw new Error("createSubmitRequest() not implemented");
|
|
2884
3499
|
}
|
|
@@ -2894,10 +3509,6 @@ var StubSCMLib = class extends SCMLib {
|
|
|
2894
3509
|
console.error("getDownloadUrl() not implemented");
|
|
2895
3510
|
throw new Error("getDownloadUrl() not implemented");
|
|
2896
3511
|
}
|
|
2897
|
-
async _getUsernameForAuthUrl() {
|
|
2898
|
-
console.error("_getUsernameForAuthUrl() not implemented");
|
|
2899
|
-
throw new Error("_getUsernameForAuthUrl() not implemented");
|
|
2900
|
-
}
|
|
2901
3512
|
async getIsRemoteBranch(_branch) {
|
|
2902
3513
|
console.error("getIsRemoteBranch() not implemented");
|
|
2903
3514
|
throw new Error("getIsRemoteBranch() not implemented");
|
|
@@ -2906,18 +3517,6 @@ var StubSCMLib = class extends SCMLib {
|
|
|
2906
3517
|
console.error("validateParams() not implemented");
|
|
2907
3518
|
throw new Error("validateParams() not implemented");
|
|
2908
3519
|
}
|
|
2909
|
-
async forkRepo() {
|
|
2910
|
-
console.error("forkRepo() not implemented");
|
|
2911
|
-
throw new Error("forkRepo() not implemented");
|
|
2912
|
-
}
|
|
2913
|
-
async createOrUpdateRepositorySecret() {
|
|
2914
|
-
console.error("forkRepo() not implemented");
|
|
2915
|
-
throw new Error("forkRepo() not implemented");
|
|
2916
|
-
}
|
|
2917
|
-
async createPullRequestWithNewFile(_sourceRepoUrl, _filesPaths, _userRepoUrl, _title, _body) {
|
|
2918
|
-
console.error("createPullRequestWithNewFile() not implemented");
|
|
2919
|
-
throw new Error("createPullRequestWithNewFile() not implemented");
|
|
2920
|
-
}
|
|
2921
3520
|
async getRepoList(_scmOrg) {
|
|
2922
3521
|
console.error("getRepoList() not implemented");
|
|
2923
3522
|
throw new Error("getRepoList() not implemented");
|
|
@@ -2950,607 +3549,496 @@ var StubSCMLib = class extends SCMLib {
|
|
|
2950
3549
|
console.error("getRepoDefaultBranch() not implemented");
|
|
2951
3550
|
throw new Error("getRepoDefaultBranch() not implemented");
|
|
2952
3551
|
}
|
|
2953
|
-
async getPrComment(_commentId) {
|
|
2954
|
-
console.error("getPrComment() not implemented");
|
|
2955
|
-
throw new Error("getPrComment() not implemented");
|
|
2956
|
-
}
|
|
2957
|
-
async updatePrComment() {
|
|
2958
|
-
console.error("updatePrComment() not implemented");
|
|
2959
|
-
throw new Error("updatePrComment() not implemented");
|
|
2960
|
-
}
|
|
2961
3552
|
async getPrUrl(_prNumber) {
|
|
2962
3553
|
console.error("getPr() not implemented");
|
|
2963
3554
|
throw new Error("getPr() not implemented");
|
|
2964
3555
|
}
|
|
2965
|
-
|
|
3556
|
+
_getUsernameForAuthUrl() {
|
|
2966
3557
|
throw new Error("Method not implemented.");
|
|
2967
3558
|
}
|
|
2968
|
-
|
|
2969
|
-
|
|
3559
|
+
};
|
|
3560
|
+
function getUserAndPassword(token) {
|
|
3561
|
+
const [username, password] = token.split(":");
|
|
3562
|
+
const safePasswordAndUsername = z9.object({ username: z9.string(), password: z9.string() }).parse({ username, password });
|
|
3563
|
+
return {
|
|
3564
|
+
username: safePasswordAndUsername.username,
|
|
3565
|
+
password: safePasswordAndUsername.password
|
|
3566
|
+
};
|
|
3567
|
+
}
|
|
3568
|
+
function createBitbucketSdk(token) {
|
|
3569
|
+
if (!token) {
|
|
3570
|
+
return getBitbucketSdk({ authType: "public" });
|
|
2970
3571
|
}
|
|
2971
|
-
|
|
2972
|
-
|
|
3572
|
+
if (token.includes(":")) {
|
|
3573
|
+
const { password, username } = getUserAndPassword(token);
|
|
3574
|
+
return getBitbucketSdk({
|
|
3575
|
+
authType: "basic",
|
|
3576
|
+
username,
|
|
3577
|
+
password
|
|
3578
|
+
});
|
|
2973
3579
|
}
|
|
2974
|
-
};
|
|
2975
|
-
|
|
2976
|
-
// src/features/analysis/scm/ado.ts
|
|
2977
|
-
function removeTrailingSlash3(str) {
|
|
2978
|
-
return str.trim().replace(/\/+$/, "");
|
|
3580
|
+
return getBitbucketSdk({ authType: "token", token });
|
|
2979
3581
|
}
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
accountId: z9.string(),
|
|
2995
|
-
accountUri: z9.string(),
|
|
2996
|
-
accountName: z9.string()
|
|
2997
|
-
})
|
|
2998
|
-
)
|
|
2999
|
-
});
|
|
3000
|
-
const profileRes = await fetch(
|
|
3001
|
-
"https://app.vssps.visualstudio.com/_apis/profile/profiles/me?api-version=6.0",
|
|
3002
|
-
{
|
|
3003
|
-
method: "GET",
|
|
3004
|
-
headers: {
|
|
3005
|
-
Authorization: `Bearer ${oauthToken}`
|
|
3582
|
+
var BitbucketSCMLib = class extends SCMLib {
|
|
3583
|
+
constructor(url, accessToken, scmOrg) {
|
|
3584
|
+
super(url, accessToken, scmOrg);
|
|
3585
|
+
__publicField(this, "bitbucketSdk");
|
|
3586
|
+
const bitbucketSdk = createBitbucketSdk(accessToken);
|
|
3587
|
+
this.bitbucketSdk = bitbucketSdk;
|
|
3588
|
+
}
|
|
3589
|
+
getAuthData() {
|
|
3590
|
+
const authType = this.bitbucketSdk.getAuthType();
|
|
3591
|
+
switch (authType) {
|
|
3592
|
+
case "basic": {
|
|
3593
|
+
this._validateToken();
|
|
3594
|
+
const { username, password } = getUserAndPassword(this.accessToken);
|
|
3595
|
+
return { username, password, authType };
|
|
3006
3596
|
}
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
const profileJson = await profileRes.json();
|
|
3010
|
-
const profile = profileZ.parse(profileJson);
|
|
3011
|
-
const accountsRes = await fetch(
|
|
3012
|
-
`https://app.vssps.visualstudio.com/_apis/accounts?memberId=${profile.publicAlias}&api-version=6.0`,
|
|
3013
|
-
{
|
|
3014
|
-
method: "GET",
|
|
3015
|
-
headers: {
|
|
3016
|
-
Authorization: `Bearer ${oauthToken}`
|
|
3597
|
+
case "token": {
|
|
3598
|
+
return { authType, token: z9.string().parse(this.accessToken) };
|
|
3017
3599
|
}
|
|
3600
|
+
case "public":
|
|
3601
|
+
return { authType };
|
|
3018
3602
|
}
|
|
3019
|
-
);
|
|
3020
|
-
const accountsJson = await accountsRes.json();
|
|
3021
|
-
const accounts = accountsZ.parse(accountsJson);
|
|
3022
|
-
const orgs = accounts.value.map((account) => account.accountName).filter((value, index, array) => array.indexOf(value) === index);
|
|
3023
|
-
return orgs;
|
|
3024
|
-
}
|
|
3025
|
-
function _getPublicAdoClient({ orgName }) {
|
|
3026
|
-
const orgUrl = `https://dev.azure.com/${orgName}`;
|
|
3027
|
-
const authHandler = api.getPersonalAccessTokenHandler("");
|
|
3028
|
-
authHandler.canHandleAuthentication = () => false;
|
|
3029
|
-
authHandler.prepareRequest = (_options) => {
|
|
3030
|
-
return;
|
|
3031
|
-
};
|
|
3032
|
-
const connection = new api.WebApi(orgUrl, authHandler);
|
|
3033
|
-
return connection;
|
|
3034
|
-
}
|
|
3035
|
-
function getAdoTokenType(token) {
|
|
3036
|
-
if (token.includes(".")) {
|
|
3037
|
-
return "OAUTH" /* OAUTH */;
|
|
3038
|
-
}
|
|
3039
|
-
return "PAT" /* PAT */;
|
|
3040
|
-
}
|
|
3041
|
-
async function getAdoApiClient({
|
|
3042
|
-
accessToken,
|
|
3043
|
-
tokenOrg,
|
|
3044
|
-
orgName
|
|
3045
|
-
}) {
|
|
3046
|
-
if (!accessToken || tokenOrg && tokenOrg !== orgName) {
|
|
3047
|
-
return _getPublicAdoClient({ orgName });
|
|
3048
3603
|
}
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
const
|
|
3052
|
-
|
|
3604
|
+
async createSubmitRequest(params) {
|
|
3605
|
+
this._validateAccessTokenAndUrl();
|
|
3606
|
+
const pullRequestRes = await this.bitbucketSdk.createPullRequest({
|
|
3607
|
+
...params,
|
|
3608
|
+
repoUrl: this.url
|
|
3609
|
+
});
|
|
3610
|
+
return String(z9.number().parse(pullRequestRes.id));
|
|
3053
3611
|
}
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
async function adoValidateParams({
|
|
3059
|
-
url,
|
|
3060
|
-
accessToken,
|
|
3061
|
-
tokenOrg
|
|
3062
|
-
}) {
|
|
3063
|
-
try {
|
|
3064
|
-
if (!url && accessToken && getAdoTokenType(accessToken) === "OAUTH" /* OAUTH */) {
|
|
3065
|
-
await _getOrgsForOauthToken({ oauthToken: accessToken });
|
|
3066
|
-
return;
|
|
3067
|
-
}
|
|
3068
|
-
let org = tokenOrg;
|
|
3069
|
-
if (url) {
|
|
3070
|
-
const { owner } = parseAdoOwnerAndRepo(url);
|
|
3071
|
-
org = owner;
|
|
3072
|
-
}
|
|
3073
|
-
if (!org) {
|
|
3074
|
-
throw new InvalidRepoUrlError(`invalid ADO ORG ${org}`);
|
|
3075
|
-
}
|
|
3076
|
-
const api2 = await getAdoApiClient({
|
|
3077
|
-
accessToken,
|
|
3078
|
-
tokenOrg,
|
|
3079
|
-
orgName: org
|
|
3612
|
+
async validateParams() {
|
|
3613
|
+
return validateBitbucketParams({
|
|
3614
|
+
bitbucketClient: this.bitbucketSdk,
|
|
3615
|
+
url: this.url
|
|
3080
3616
|
});
|
|
3081
|
-
await api2.connect();
|
|
3082
|
-
} catch (e) {
|
|
3083
|
-
const error = e;
|
|
3084
|
-
const code = error.code || error.status || error.statusCode || error.response?.status || error.response?.statusCode || error.response?.code;
|
|
3085
|
-
const description = error.description || `${e}`;
|
|
3086
|
-
if (code === 401 || code === 403 || description.includes("401") || description.includes("403")) {
|
|
3087
|
-
throw new InvalidAccessTokenError(`invalid ADO access token`);
|
|
3088
|
-
}
|
|
3089
|
-
if (code === 404 || description.includes("404") || description.includes("Not Found")) {
|
|
3090
|
-
throw new InvalidRepoUrlError(`invalid ADO repo URL ${url}`);
|
|
3091
|
-
}
|
|
3092
|
-
throw e;
|
|
3093
3617
|
}
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
repoUrl
|
|
3099
|
-
}) {
|
|
3100
|
-
try {
|
|
3101
|
-
const { owner, repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
|
|
3102
|
-
const api2 = await getAdoApiClient({
|
|
3103
|
-
accessToken,
|
|
3104
|
-
tokenOrg,
|
|
3105
|
-
orgName: owner
|
|
3618
|
+
async getRepoList(scmOrg) {
|
|
3619
|
+
this._validateToken();
|
|
3620
|
+
return this.bitbucketSdk.getRepos({
|
|
3621
|
+
workspaceSlug: scmOrg
|
|
3106
3622
|
});
|
|
3107
|
-
const git = await api2.getGitApi();
|
|
3108
|
-
const branches = await git.getBranches(repo, projectName);
|
|
3109
|
-
if (!branches || branches.length === 0) {
|
|
3110
|
-
throw new InvalidRepoUrlError("no branches");
|
|
3111
|
-
}
|
|
3112
|
-
return true;
|
|
3113
|
-
} catch (e) {
|
|
3114
|
-
return false;
|
|
3115
3623
|
}
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
4: "all" /* all */
|
|
3122
|
-
};
|
|
3123
|
-
async function getAdoPullRequestStatus({
|
|
3124
|
-
accessToken,
|
|
3125
|
-
tokenOrg,
|
|
3126
|
-
repoUrl,
|
|
3127
|
-
prNumber
|
|
3128
|
-
}) {
|
|
3129
|
-
const { owner, repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
|
|
3130
|
-
const api2 = await getAdoApiClient({
|
|
3131
|
-
accessToken,
|
|
3132
|
-
tokenOrg,
|
|
3133
|
-
orgName: owner
|
|
3134
|
-
});
|
|
3135
|
-
const git = await api2.getGitApi();
|
|
3136
|
-
const res = await git.getPullRequest(repo, prNumber, projectName);
|
|
3137
|
-
if (!res.status || res.status < 1 || res.status > 3) {
|
|
3138
|
-
throw new Error("bad pr status for ADO");
|
|
3624
|
+
async getBranchList() {
|
|
3625
|
+
this._validateAccessTokenAndUrl();
|
|
3626
|
+
return this.bitbucketSdk.getBranchList({
|
|
3627
|
+
repoUrl: this.url
|
|
3628
|
+
});
|
|
3139
3629
|
}
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3630
|
+
getScmLibType() {
|
|
3631
|
+
return "BITBUCKET" /* BITBUCKET */;
|
|
3632
|
+
}
|
|
3633
|
+
getAuthHeaders() {
|
|
3634
|
+
const authType = this.bitbucketSdk.getAuthType();
|
|
3635
|
+
switch (authType) {
|
|
3636
|
+
case "public":
|
|
3637
|
+
return {};
|
|
3638
|
+
case "token":
|
|
3639
|
+
return { authorization: `Bearer ${this.accessToken}` };
|
|
3640
|
+
case "basic": {
|
|
3641
|
+
this._validateToken();
|
|
3642
|
+
const { username, password } = getUserAndPassword(this.accessToken);
|
|
3643
|
+
return {
|
|
3644
|
+
authorization: `Basic ${Buffer.from(
|
|
3645
|
+
username + ":" + password
|
|
3646
|
+
).toString("base64")}`
|
|
3647
|
+
};
|
|
3648
|
+
}
|
|
3159
3649
|
}
|
|
3160
|
-
return branchStatus.name === branch;
|
|
3161
|
-
} catch (e) {
|
|
3162
|
-
return false;
|
|
3163
3650
|
}
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
tokenOrg,
|
|
3168
|
-
accessToken
|
|
3169
|
-
}) {
|
|
3170
|
-
let orgs = [];
|
|
3171
|
-
if (getAdoTokenType(accessToken) === "OAUTH" /* OAUTH */) {
|
|
3172
|
-
orgs = await _getOrgsForOauthToken({ oauthToken: accessToken });
|
|
3651
|
+
async getDownloadUrl(sha) {
|
|
3652
|
+
this._validateUrl();
|
|
3653
|
+
return this.bitbucketSdk.getDownloadUrl({ url: this.url, sha });
|
|
3173
3654
|
}
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
|
|
3655
|
+
async _getUsernameForAuthUrl() {
|
|
3656
|
+
this._validateAccessTokenAndUrl();
|
|
3657
|
+
const user = await this.bitbucketSdk.getUser();
|
|
3658
|
+
if (!user.username) {
|
|
3659
|
+
throw new Error("no username found");
|
|
3660
|
+
}
|
|
3661
|
+
return user.username;
|
|
3178
3662
|
}
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
3663
|
+
async getIsRemoteBranch(branch) {
|
|
3664
|
+
this._validateAccessTokenAndUrl();
|
|
3665
|
+
try {
|
|
3666
|
+
const res = await this.bitbucketSdk.getBranch({
|
|
3667
|
+
branchName: branch,
|
|
3668
|
+
repoUrl: this.url
|
|
3185
3669
|
});
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
orgRepos.map(async (repo) => {
|
|
3190
|
-
if (!repo.name || !repo.remoteUrl || !repo.defaultBranch) {
|
|
3191
|
-
throw new InvalidRepoUrlError("bad repo");
|
|
3192
|
-
}
|
|
3193
|
-
const branch = await gitOrg.getBranch(
|
|
3194
|
-
repo.name,
|
|
3195
|
-
repo.defaultBranch.replace(/^refs\/heads\//, ""),
|
|
3196
|
-
repo.project?.name
|
|
3197
|
-
);
|
|
3198
|
-
return {
|
|
3199
|
-
repoName: repo.name,
|
|
3200
|
-
repoUrl: repo.remoteUrl.replace(
|
|
3201
|
-
/^[hH][tT][tT][pP][sS]:\/\/[^/]+@/,
|
|
3202
|
-
"https://"
|
|
3203
|
-
),
|
|
3204
|
-
repoOwner: org,
|
|
3205
|
-
repoIsPublic: repo.project?.visibility === 2,
|
|
3206
|
-
//2 is public in the ADO API
|
|
3207
|
-
repoLanguages: [],
|
|
3208
|
-
repoUpdatedAt: branch.commit?.committer?.date?.toDateString() || repo.project?.lastUpdateTime?.toDateString() || (/* @__PURE__ */ new Date()).toDateString()
|
|
3209
|
-
};
|
|
3210
|
-
})
|
|
3211
|
-
)).reduce((acc, res) => {
|
|
3212
|
-
if (res.status === "fulfilled") {
|
|
3213
|
-
acc.push(res.value);
|
|
3214
|
-
}
|
|
3215
|
-
return acc;
|
|
3216
|
-
}, []);
|
|
3217
|
-
return repoInfoList;
|
|
3218
|
-
})
|
|
3219
|
-
)).reduce((acc, res) => {
|
|
3220
|
-
if (res.status === "fulfilled") {
|
|
3221
|
-
return acc.concat(res.value);
|
|
3670
|
+
return res.name === branch;
|
|
3671
|
+
} catch (e) {
|
|
3672
|
+
return false;
|
|
3222
3673
|
}
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
}
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
|
|
3232
|
-
}
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
const url = new URL(repoUrl);
|
|
3239
|
-
const origin = url.origin.toLowerCase().endsWith(".visualstudio.com") ? "https://dev.azure.com" : url.origin.toLowerCase();
|
|
3240
|
-
return `${origin}/${owner}/${projectName}/_apis/git/repositories/${repo}/items/items?path=/&versionDescriptor[versionOptions]=0&versionDescriptor[versionType]=commit&versionDescriptor[version]=${branch}&resolveLfs=true&$format=zip&api-version=5.0&download=true`;
|
|
3241
|
-
}
|
|
3242
|
-
async function getAdoBranchList({
|
|
3243
|
-
accessToken,
|
|
3244
|
-
tokenOrg,
|
|
3245
|
-
repoUrl
|
|
3246
|
-
}) {
|
|
3247
|
-
const { owner, repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
|
|
3248
|
-
const api2 = await getAdoApiClient({
|
|
3249
|
-
accessToken,
|
|
3250
|
-
tokenOrg,
|
|
3251
|
-
orgName: owner
|
|
3252
|
-
});
|
|
3253
|
-
const git = await api2.getGitApi();
|
|
3254
|
-
try {
|
|
3255
|
-
const res = await git.getBranches(repo, projectName);
|
|
3256
|
-
res.sort((a, b) => {
|
|
3257
|
-
if (!a.commit?.committer?.date || !b.commit?.committer?.date) {
|
|
3258
|
-
return 0;
|
|
3259
|
-
}
|
|
3260
|
-
return b.commit?.committer?.date.getTime() - a.commit?.committer?.date.getTime();
|
|
3674
|
+
}
|
|
3675
|
+
async getUserHasAccessToRepo() {
|
|
3676
|
+
this._validateAccessTokenAndUrl();
|
|
3677
|
+
return this.bitbucketSdk.getIsUserCollaborator({ repoUrl: this.url });
|
|
3678
|
+
}
|
|
3679
|
+
async getUsername() {
|
|
3680
|
+
this._validateToken();
|
|
3681
|
+
const res = await this.bitbucketSdk.getUser();
|
|
3682
|
+
return z9.string().parse(res.username);
|
|
3683
|
+
}
|
|
3684
|
+
async getSubmitRequestStatus(_scmSubmitRequestId) {
|
|
3685
|
+
this._validateAccessTokenAndUrl();
|
|
3686
|
+
const pullRequestRes = await this.bitbucketSdk.getPullRequest({
|
|
3687
|
+
prNumber: Number(_scmSubmitRequestId),
|
|
3688
|
+
url: this.url
|
|
3261
3689
|
});
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
return
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
|
|
3690
|
+
switch (pullRequestRes.state) {
|
|
3691
|
+
case "OPEN":
|
|
3692
|
+
return "open";
|
|
3693
|
+
case "MERGED":
|
|
3694
|
+
return "merged";
|
|
3695
|
+
case "DECLINED":
|
|
3696
|
+
return "closed";
|
|
3697
|
+
default:
|
|
3698
|
+
throw new Error(`unknown state ${pullRequestRes.state} `);
|
|
3699
|
+
}
|
|
3700
|
+
}
|
|
3701
|
+
async getRepoBlameRanges(_ref, _path) {
|
|
3270
3702
|
return [];
|
|
3271
3703
|
}
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
const api2 = await getAdoApiClient({
|
|
3276
|
-
accessToken: options.accessToken,
|
|
3277
|
-
tokenOrg: options.tokenOrg,
|
|
3278
|
-
orgName: owner
|
|
3279
|
-
});
|
|
3280
|
-
const git = await api2.getGitApi();
|
|
3281
|
-
const res = await git.createPullRequest(
|
|
3282
|
-
{
|
|
3283
|
-
sourceRefName: `refs/heads/${options.sourceBranchName}`,
|
|
3284
|
-
targetRefName: `refs/heads/${options.targetBranchName}`,
|
|
3285
|
-
title: options.title,
|
|
3286
|
-
description: options.body
|
|
3287
|
-
},
|
|
3288
|
-
repo,
|
|
3289
|
-
projectName
|
|
3290
|
-
);
|
|
3291
|
-
return res.pullRequestId;
|
|
3292
|
-
}
|
|
3293
|
-
async function getAdoRepoDefaultBranch({
|
|
3294
|
-
repoUrl,
|
|
3295
|
-
tokenOrg,
|
|
3296
|
-
accessToken
|
|
3297
|
-
}) {
|
|
3298
|
-
const { owner, repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
|
|
3299
|
-
const api2 = await getAdoApiClient({
|
|
3300
|
-
accessToken,
|
|
3301
|
-
tokenOrg,
|
|
3302
|
-
orgName: owner
|
|
3303
|
-
});
|
|
3304
|
-
const git = await api2.getGitApi();
|
|
3305
|
-
const branches = await git.getBranches(repo, projectName);
|
|
3306
|
-
if (!branches || branches.length === 0) {
|
|
3307
|
-
throw new InvalidRepoUrlError("no branches");
|
|
3704
|
+
async getReferenceData(ref) {
|
|
3705
|
+
this._validateUrl();
|
|
3706
|
+
return this.bitbucketSdk.getReferenceData({ url: this.url, ref });
|
|
3308
3707
|
}
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3708
|
+
async getRepoDefaultBranch() {
|
|
3709
|
+
this._validateUrl();
|
|
3710
|
+
const repoRes = await this.bitbucketSdk.getRepo({ repoUrl: this.url });
|
|
3711
|
+
return z9.string().parse(repoRes.mainbranch?.name);
|
|
3312
3712
|
}
|
|
3313
|
-
|
|
3713
|
+
getPrUrl(prNumber) {
|
|
3714
|
+
this._validateUrl();
|
|
3715
|
+
const { repoSlug, workspace } = parseBitbucketOrganizationAndRepo(this.url);
|
|
3716
|
+
return Promise.resolve(
|
|
3717
|
+
`https://bitbucket.org/${workspace}/${repoSlug}/pull-requests/${prNumber}`
|
|
3718
|
+
);
|
|
3719
|
+
}
|
|
3720
|
+
async refreshToken(params) {
|
|
3721
|
+
const getBitbucketTokenResponse = await getBitbucketToken({
|
|
3722
|
+
authType: "refresh_token",
|
|
3723
|
+
...params
|
|
3724
|
+
});
|
|
3725
|
+
return {
|
|
3726
|
+
accessToken: getBitbucketTokenResponse.access_token,
|
|
3727
|
+
refreshToken: getBitbucketTokenResponse.refresh_token
|
|
3728
|
+
};
|
|
3729
|
+
}
|
|
3730
|
+
};
|
|
3731
|
+
|
|
3732
|
+
// src/features/analysis/scm/bitbucket/bitbucket.ts
|
|
3733
|
+
var { Bitbucket } = bitbucketPkg;
|
|
3734
|
+
var BITBUCKET_HOSTNAME = "bitbucket.org";
|
|
3735
|
+
var TokenExpiredErrorZ = z10.object({
|
|
3736
|
+
status: z10.number(),
|
|
3737
|
+
error: z10.object({
|
|
3738
|
+
type: z10.string(),
|
|
3739
|
+
error: z10.object({
|
|
3740
|
+
message: z10.string()
|
|
3741
|
+
})
|
|
3742
|
+
})
|
|
3743
|
+
});
|
|
3744
|
+
var BITBUCKET_ACCESS_TOKEN_URL = `https://${BITBUCKET_HOSTNAME}/site/oauth2/access_token`;
|
|
3745
|
+
var BitbucketAuthResultZ = z10.object({
|
|
3746
|
+
access_token: z10.string(),
|
|
3747
|
+
token_type: z10.string(),
|
|
3748
|
+
refresh_token: z10.string()
|
|
3749
|
+
});
|
|
3750
|
+
var BitbucketParseResultZ = z10.object({
|
|
3751
|
+
organization: z10.string(),
|
|
3752
|
+
repoName: z10.string(),
|
|
3753
|
+
hostname: z10.literal(BITBUCKET_HOSTNAME)
|
|
3754
|
+
});
|
|
3755
|
+
function parseBitbucketOrganizationAndRepo(bitbucketUrl) {
|
|
3756
|
+
const parsedGitHubUrl = removeTrailingSlash2(bitbucketUrl);
|
|
3757
|
+
const parsingResult = parseScmURL(parsedGitHubUrl, "Bitbucket" /* Bitbucket */);
|
|
3758
|
+
const validatedBitbucketResult = BitbucketParseResultZ.parse(parsingResult);
|
|
3759
|
+
return {
|
|
3760
|
+
workspace: validatedBitbucketResult.organization,
|
|
3761
|
+
repoSlug: validatedBitbucketResult.repoName
|
|
3762
|
+
};
|
|
3314
3763
|
}
|
|
3315
|
-
async function
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3764
|
+
async function getBitbucketToken(params) {
|
|
3765
|
+
const { bitbucketClientId, bitbucketClientSecret, authType } = params;
|
|
3766
|
+
const res = await fetch(BITBUCKET_ACCESS_TOKEN_URL, {
|
|
3767
|
+
method: "POST",
|
|
3768
|
+
headers: {
|
|
3769
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
3770
|
+
Authorization: "Basic " + btoa(`${bitbucketClientId}:${bitbucketClientSecret}`)
|
|
3771
|
+
},
|
|
3772
|
+
body: querystring3.stringify(
|
|
3773
|
+
authType === "refresh_token" ? {
|
|
3774
|
+
grant_type: authType,
|
|
3775
|
+
refresh_token: params.refreshToken
|
|
3776
|
+
} : {
|
|
3777
|
+
grant_type: authType,
|
|
3778
|
+
code: params.code
|
|
3779
|
+
}
|
|
3780
|
+
)
|
|
3326
3781
|
});
|
|
3327
|
-
|
|
3328
|
-
|
|
3782
|
+
const authResult = await res.json();
|
|
3783
|
+
return BitbucketAuthResultZ.parse(authResult);
|
|
3784
|
+
}
|
|
3785
|
+
function getBitbucketIntance(params) {
|
|
3786
|
+
switch (params.authType) {
|
|
3787
|
+
case "public":
|
|
3788
|
+
return new Bitbucket();
|
|
3789
|
+
case "token":
|
|
3790
|
+
return new Bitbucket({ auth: { token: params.token } });
|
|
3791
|
+
case "basic":
|
|
3792
|
+
return new Bitbucket({
|
|
3793
|
+
auth: {
|
|
3794
|
+
password: params.password,
|
|
3795
|
+
username: params.username
|
|
3796
|
+
}
|
|
3797
|
+
});
|
|
3329
3798
|
}
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3799
|
+
}
|
|
3800
|
+
function getBitbucketSdk(params) {
|
|
3801
|
+
const bitbucketClient = getBitbucketIntance(params);
|
|
3802
|
+
return {
|
|
3803
|
+
getAuthType() {
|
|
3804
|
+
return params.authType;
|
|
3805
|
+
},
|
|
3806
|
+
async getRepos(params2) {
|
|
3807
|
+
const repoRes = params2?.workspaceSlug ? await getRepositoriesByWorkspace(bitbucketClient, {
|
|
3808
|
+
workspaceSlug: params2.workspaceSlug
|
|
3809
|
+
}) : await getllUsersrepositories(bitbucketClient);
|
|
3810
|
+
return repoRes.map((repo) => ({
|
|
3811
|
+
repoIsPublic: !repo.is_private,
|
|
3812
|
+
repoName: repo.name || "unknown repo name",
|
|
3813
|
+
repoOwner: repo.owner?.username || "unknown owner",
|
|
3814
|
+
// language can be empty string
|
|
3815
|
+
repoLanguages: repo.language ? [repo.language] : [],
|
|
3816
|
+
repoUpdatedAt: repo.updated_on ? repo.updated_on : (/* @__PURE__ */ new Date()).toISOString(),
|
|
3817
|
+
repoUrl: repo.links?.html?.href || ""
|
|
3818
|
+
}));
|
|
3819
|
+
},
|
|
3820
|
+
async getBranchList(params2) {
|
|
3821
|
+
const { workspace, repoSlug } = parseBitbucketOrganizationAndRepo(
|
|
3822
|
+
params2.repoUrl
|
|
3352
3823
|
);
|
|
3353
|
-
const
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
}
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
type: "COMMIT" /* COMMIT */,
|
|
3360
|
-
date: commit.committer?.date || /* @__PURE__ */ new Date()
|
|
3361
|
-
};
|
|
3362
|
-
})(),
|
|
3363
|
-
(async () => {
|
|
3364
|
-
const res = await git.getRefs(repo, projectName, `tags/${ref}`);
|
|
3365
|
-
if (!res[0] || !res[0].objectId) {
|
|
3366
|
-
throw new Error("no tag ref");
|
|
3824
|
+
const res = await bitbucketClient.refs.listBranches({
|
|
3825
|
+
repo_slug: repoSlug,
|
|
3826
|
+
workspace
|
|
3827
|
+
});
|
|
3828
|
+
if (!res.data.values) {
|
|
3829
|
+
return [];
|
|
3367
3830
|
}
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3831
|
+
return res.data.values.filter((branch) => !!branch.name).map((branch) => z10.string().parse(branch.name));
|
|
3832
|
+
},
|
|
3833
|
+
async getIsUserCollaborator(params2) {
|
|
3834
|
+
const { repoUrl } = params2;
|
|
3835
|
+
const { repoSlug, workspace } = parseBitbucketOrganizationAndRepo(repoUrl);
|
|
3836
|
+
const fullRepoName = `${workspace}/${repoSlug}`;
|
|
3837
|
+
const res = await bitbucketClient.user.listPermissionsForRepos({
|
|
3838
|
+
q: `repository.full_name~"${fullRepoName}"`
|
|
3839
|
+
});
|
|
3840
|
+
return res.data.values?.some(
|
|
3841
|
+
(res2) => res2.repository?.full_name === fullRepoName
|
|
3842
|
+
) ?? false;
|
|
3843
|
+
},
|
|
3844
|
+
async createPullRequest(params2) {
|
|
3845
|
+
const { repoSlug, workspace } = parseBitbucketOrganizationAndRepo(
|
|
3846
|
+
params2.repoUrl
|
|
3847
|
+
);
|
|
3848
|
+
const res = await bitbucketClient.pullrequests.create({
|
|
3849
|
+
repo_slug: repoSlug,
|
|
3850
|
+
workspace,
|
|
3851
|
+
_body: {
|
|
3852
|
+
type: "pullrequest",
|
|
3853
|
+
title: params2.title,
|
|
3854
|
+
summary: {
|
|
3855
|
+
raw: params2.body
|
|
3856
|
+
},
|
|
3857
|
+
source: {
|
|
3858
|
+
branch: {
|
|
3859
|
+
name: params2.sourceBranchName
|
|
3860
|
+
}
|
|
3861
|
+
},
|
|
3862
|
+
destination: {
|
|
3863
|
+
branch: {
|
|
3864
|
+
name: params2.targetBranchName
|
|
3865
|
+
}
|
|
3866
|
+
}
|
|
3373
3867
|
}
|
|
3868
|
+
});
|
|
3869
|
+
return res.data;
|
|
3870
|
+
},
|
|
3871
|
+
async getDownloadlink(params2) {
|
|
3872
|
+
const { repoSlug, workspace } = parseBitbucketOrganizationAndRepo(
|
|
3873
|
+
params2.repoUrl
|
|
3874
|
+
);
|
|
3875
|
+
const res = await bitbucketClient.downloads.list({
|
|
3876
|
+
repo_slug: repoSlug,
|
|
3877
|
+
workspace
|
|
3878
|
+
});
|
|
3879
|
+
return res.data;
|
|
3880
|
+
},
|
|
3881
|
+
async getBranch(params2) {
|
|
3882
|
+
const { repoSlug, workspace } = parseBitbucketOrganizationAndRepo(
|
|
3883
|
+
params2.repoUrl
|
|
3884
|
+
);
|
|
3885
|
+
const res = await bitbucketClient.refs.getBranch({
|
|
3886
|
+
name: params2.branchName,
|
|
3887
|
+
repo_slug: repoSlug,
|
|
3888
|
+
workspace
|
|
3889
|
+
});
|
|
3890
|
+
return res.data;
|
|
3891
|
+
},
|
|
3892
|
+
async getRepo(params2) {
|
|
3893
|
+
const { repoSlug, workspace } = parseBitbucketOrganizationAndRepo(
|
|
3894
|
+
params2.repoUrl
|
|
3895
|
+
);
|
|
3896
|
+
const res = await bitbucketClient.repositories.get({
|
|
3897
|
+
repo_slug: repoSlug,
|
|
3898
|
+
workspace
|
|
3899
|
+
});
|
|
3900
|
+
return res.data;
|
|
3901
|
+
},
|
|
3902
|
+
async getCommit(params2) {
|
|
3903
|
+
const { repoSlug, workspace } = parseBitbucketOrganizationAndRepo(
|
|
3904
|
+
params2.repoUrl
|
|
3905
|
+
);
|
|
3906
|
+
const res = await bitbucketClient.commits.get({
|
|
3907
|
+
commit: params2.commitSha,
|
|
3908
|
+
repo_slug: repoSlug,
|
|
3909
|
+
workspace
|
|
3910
|
+
});
|
|
3911
|
+
return res.data;
|
|
3912
|
+
},
|
|
3913
|
+
async getUser() {
|
|
3914
|
+
const res = await bitbucketClient.user.get({});
|
|
3915
|
+
return res.data;
|
|
3916
|
+
},
|
|
3917
|
+
async getReferenceData({
|
|
3918
|
+
ref,
|
|
3919
|
+
url
|
|
3920
|
+
}) {
|
|
3921
|
+
try {
|
|
3922
|
+
return await Promise.any([
|
|
3923
|
+
this.getBranchRef({ repoUrl: url, branchName: ref }),
|
|
3924
|
+
this.getTagRef({ repoUrl: url, tagName: ref }),
|
|
3925
|
+
this.getCommitRef({ repoUrl: url, commitSha: ref })
|
|
3926
|
+
]);
|
|
3374
3927
|
} catch (e) {
|
|
3928
|
+
console.log("e", e);
|
|
3929
|
+
if (e instanceof AggregateError) {
|
|
3930
|
+
throw new RefNotFoundError(`Invalid reference ${ref} for ${url}`);
|
|
3931
|
+
}
|
|
3932
|
+
throw e;
|
|
3375
3933
|
}
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
|
|
3379
|
-
|
|
3380
|
-
|
|
3381
|
-
|
|
3382
|
-
|
|
3383
|
-
|
|
3934
|
+
},
|
|
3935
|
+
async getTagRef(params2) {
|
|
3936
|
+
const { tagName, repoUrl } = params2;
|
|
3937
|
+
const { repoSlug, workspace } = parseBitbucketOrganizationAndRepo(repoUrl);
|
|
3938
|
+
const tagRes = await bitbucketClient.refs.getTag({
|
|
3939
|
+
repo_slug: repoSlug,
|
|
3940
|
+
workspace,
|
|
3941
|
+
name: tagName
|
|
3942
|
+
});
|
|
3943
|
+
return GetRefererenceResultZ.parse({
|
|
3944
|
+
sha: tagRes.data.target?.hash,
|
|
3945
|
+
type: "TAG" /* TAG */,
|
|
3946
|
+
date: new Date(z10.string().parse(tagRes.data.target?.date))
|
|
3947
|
+
});
|
|
3948
|
+
},
|
|
3949
|
+
async getBranchRef(params2) {
|
|
3950
|
+
const getBranchRes = await this.getBranch(params2);
|
|
3951
|
+
return GetRefererenceResultZ.parse({
|
|
3952
|
+
sha: getBranchRes.target?.hash,
|
|
3953
|
+
type: "BRANCH" /* BRANCH */,
|
|
3954
|
+
date: new Date(z10.string().parse(getBranchRes.target?.date))
|
|
3955
|
+
});
|
|
3956
|
+
},
|
|
3957
|
+
async getCommitRef(params2) {
|
|
3958
|
+
const getCommitRes = await this.getCommit(params2);
|
|
3959
|
+
return GetRefererenceResultZ.parse({
|
|
3960
|
+
sha: getCommitRes.hash,
|
|
3961
|
+
type: "COMMIT" /* COMMIT */,
|
|
3962
|
+
date: new Date(z10.string().parse(getCommitRes.date))
|
|
3963
|
+
});
|
|
3964
|
+
},
|
|
3965
|
+
async getDownloadUrl({ url, sha }) {
|
|
3966
|
+
this.getReferenceData({ ref: sha, url });
|
|
3967
|
+
const repoRes = await this.getRepo({ repoUrl: url });
|
|
3968
|
+
const parsedRepoUrl = z10.string().url().parse(repoRes.links?.html?.href);
|
|
3969
|
+
return `${parsedRepoUrl}/get/${sha}.zip`;
|
|
3970
|
+
},
|
|
3971
|
+
async getPullRequest(params2) {
|
|
3972
|
+
const { repoSlug, workspace } = parseBitbucketOrganizationAndRepo(
|
|
3973
|
+
params2.url
|
|
3384
3974
|
);
|
|
3385
|
-
const
|
|
3386
|
-
|
|
3387
|
-
|
|
3975
|
+
const res = await bitbucketClient.pullrequests.get({
|
|
3976
|
+
pull_request_id: params2.prNumber,
|
|
3977
|
+
repo_slug: repoSlug,
|
|
3978
|
+
workspace
|
|
3979
|
+
});
|
|
3980
|
+
return res.data;
|
|
3981
|
+
}
|
|
3982
|
+
};
|
|
3983
|
+
}
|
|
3984
|
+
async function validateBitbucketParams(params) {
|
|
3985
|
+
const { bitbucketClient } = params;
|
|
3986
|
+
const authType = bitbucketClient.getAuthType();
|
|
3987
|
+
console.log("authType", authType, params.url);
|
|
3988
|
+
try {
|
|
3989
|
+
if (authType !== "public") {
|
|
3990
|
+
await bitbucketClient.getUser();
|
|
3991
|
+
}
|
|
3992
|
+
if (params.url) {
|
|
3993
|
+
await bitbucketClient.getRepo({ repoUrl: params.url });
|
|
3994
|
+
}
|
|
3995
|
+
} catch (e) {
|
|
3996
|
+
const safeParseError = TokenExpiredErrorZ.safeParse(e);
|
|
3997
|
+
if (safeParseError.success) {
|
|
3998
|
+
switch (safeParseError.data.status) {
|
|
3999
|
+
case 401:
|
|
4000
|
+
throw new InvalidAccessTokenError(
|
|
4001
|
+
safeParseError.data.error.error.message
|
|
4002
|
+
);
|
|
4003
|
+
case 404:
|
|
4004
|
+
throw new InvalidRepoUrlError(safeParseError.data.error.error.message);
|
|
3388
4005
|
}
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
type: "TAG" /* TAG */,
|
|
3392
|
-
date: commit.committer?.date || /* @__PURE__ */ new Date()
|
|
3393
|
-
};
|
|
3394
|
-
})()
|
|
3395
|
-
]);
|
|
3396
|
-
const [branchRes, commitRes, tagRes] = results;
|
|
3397
|
-
if (tagRes.status === "fulfilled") {
|
|
3398
|
-
return tagRes.value;
|
|
3399
|
-
}
|
|
3400
|
-
if (branchRes.status === "fulfilled") {
|
|
3401
|
-
return branchRes.value;
|
|
3402
|
-
}
|
|
3403
|
-
if (commitRes.status === "fulfilled") {
|
|
3404
|
-
return commitRes.value;
|
|
4006
|
+
}
|
|
4007
|
+
throw e;
|
|
3405
4008
|
}
|
|
3406
|
-
throw new RefNotFoundError(`ref: ${ref} does not exist`);
|
|
3407
4009
|
}
|
|
3408
|
-
function
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
4010
|
+
async function getUsersworkspacesSlugs(bitbucketClient) {
|
|
4011
|
+
const res = await bitbucketClient.workspaces.getWorkspaces({});
|
|
4012
|
+
return res.data.values?.map((v) => z10.string().parse(v.slug));
|
|
4013
|
+
}
|
|
4014
|
+
async function getllUsersrepositories(bitbucketClient) {
|
|
4015
|
+
const userWorspacesSlugs = await getUsersworkspacesSlugs(bitbucketClient);
|
|
4016
|
+
if (!userWorspacesSlugs) {
|
|
4017
|
+
return [];
|
|
3413
4018
|
}
|
|
3414
|
-
const
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
4019
|
+
const allWorkspaceRepos = [];
|
|
4020
|
+
for (const workspaceSlug of userWorspacesSlugs) {
|
|
4021
|
+
const repos = await bitbucketClient.repositories.list({
|
|
4022
|
+
workspace: workspaceSlug
|
|
4023
|
+
});
|
|
4024
|
+
if (!repos.data.values) {
|
|
4025
|
+
continue;
|
|
4026
|
+
}
|
|
4027
|
+
allWorkspaceRepos.push(...repos.data.values);
|
|
4028
|
+
}
|
|
4029
|
+
return allWorkspaceRepos;
|
|
3422
4030
|
}
|
|
3423
|
-
async function
|
|
3424
|
-
|
|
4031
|
+
async function getRepositoriesByWorkspace(bitbucketClient, { workspaceSlug }) {
|
|
4032
|
+
const res = await bitbucketClient.repositories.list({
|
|
4033
|
+
workspace: workspaceSlug
|
|
4034
|
+
});
|
|
4035
|
+
return res.data.values ?? [];
|
|
3425
4036
|
}
|
|
3426
|
-
var AdoAuthResultZ = z9.object({
|
|
3427
|
-
access_token: z9.string().min(1),
|
|
3428
|
-
token_type: z9.string().min(1),
|
|
3429
|
-
refresh_token: z9.string().min(1)
|
|
3430
|
-
});
|
|
3431
4037
|
|
|
3432
4038
|
// src/features/analysis/scm/constants.ts
|
|
3433
4039
|
var MOBB_ICON_IMG = "https://app.mobb.ai/gh-action/Logo_Rounded_Icon.svg";
|
|
3434
4040
|
var COMMIT_FIX_SVG = `https://app.mobb.ai/gh-action/commit-button.svg`;
|
|
3435
4041
|
|
|
3436
|
-
// src/features/analysis/scm/utils/get_issue_type.ts
|
|
3437
|
-
var getIssueType = (issueType) => {
|
|
3438
|
-
switch (issueType) {
|
|
3439
|
-
case "SQL_Injection" /* SqlInjection */:
|
|
3440
|
-
return "SQL Injection";
|
|
3441
|
-
case "CMDi_relative_path_command" /* CmDiRelativePathCommand */:
|
|
3442
|
-
return "Relative Path Command Injection";
|
|
3443
|
-
case "CMDi" /* CmDi */:
|
|
3444
|
-
return "Command Injection";
|
|
3445
|
-
case "XXE" /* Xxe */:
|
|
3446
|
-
return "XXE";
|
|
3447
|
-
case "XSS" /* Xss */:
|
|
3448
|
-
return "XSS";
|
|
3449
|
-
case "PT" /* Pt */:
|
|
3450
|
-
return "Path Traversal";
|
|
3451
|
-
case "ZIP_SLIP" /* ZipSlip */:
|
|
3452
|
-
return "Zip Slip";
|
|
3453
|
-
case "INSECURE_RANDOMNESS" /* InsecureRandomness */:
|
|
3454
|
-
return "Insecure Randomness";
|
|
3455
|
-
case "SSRF" /* Ssrf */:
|
|
3456
|
-
return "Server Side Request Forgery";
|
|
3457
|
-
case "TYPE_CONFUSION" /* TypeConfusion */:
|
|
3458
|
-
return "Type Confusion";
|
|
3459
|
-
case "REGEX_INJECTION" /* RegexInjection */:
|
|
3460
|
-
return "Regular Expression Injection";
|
|
3461
|
-
case "INCOMPLETE_URL_SANITIZATION" /* IncompleteUrlSanitization */:
|
|
3462
|
-
return "Incomplete URL Sanitization";
|
|
3463
|
-
case "LOG_FORGING" /* LogForging */:
|
|
3464
|
-
return "Log Forging";
|
|
3465
|
-
case "LOCALE_DEPENDENT_COMPARISON" /* LocaleDependentComparison */:
|
|
3466
|
-
return "Locale Dependent Comparison";
|
|
3467
|
-
case "MISSING_CHECK_AGAINST_NULL" /* MissingCheckAgainstNull */:
|
|
3468
|
-
return "Missing Check against Null";
|
|
3469
|
-
case "PASSWORD_IN_COMMENT" /* PasswordInComment */:
|
|
3470
|
-
return "Password in Comment";
|
|
3471
|
-
case "OVERLY_BROAD_CATCH" /* OverlyBroadCatch */:
|
|
3472
|
-
return "Poor Error Handling: Overly Broad Catch";
|
|
3473
|
-
case "USE_OF_SYSTEM_OUTPUT_STREAM" /* UseOfSystemOutputStream */:
|
|
3474
|
-
return "Use of System.out/System.err";
|
|
3475
|
-
case "DANGEROUS_FUNCTION_OVERFLOW" /* DangerousFunctionOverflow */:
|
|
3476
|
-
return "Use of dangerous function";
|
|
3477
|
-
case "DOS_STRING_BUILDER" /* DosStringBuilder */:
|
|
3478
|
-
return "Denial of Service: StringBuilder";
|
|
3479
|
-
case "OPEN_REDIRECT" /* OpenRedirect */:
|
|
3480
|
-
return "Open Redirect";
|
|
3481
|
-
case "WEAK_XML_SCHEMA_UNBOUNDED_OCCURRENCES" /* WeakXmlSchemaUnboundedOccurrences */:
|
|
3482
|
-
return "Weak XML Schema: Unbounded Occurrences";
|
|
3483
|
-
case "SYSTEM_INFORMATION_LEAK" /* SystemInformationLeak */:
|
|
3484
|
-
return "System Information Leak";
|
|
3485
|
-
case "HTTP_RESPONSE_SPLITTING" /* HttpResponseSplitting */:
|
|
3486
|
-
return "HTTP response splitting";
|
|
3487
|
-
case "HTTP_ONLY_COOKIE" /* HttpOnlyCookie */:
|
|
3488
|
-
return "Cookie is not HttpOnly";
|
|
3489
|
-
case "INSECURE_COOKIE" /* InsecureCookie */:
|
|
3490
|
-
return "Insecure Cookie";
|
|
3491
|
-
case "TRUST_BOUNDARY_VIOLATION" /* TrustBoundaryViolation */:
|
|
3492
|
-
return "Trust Boundary Violation";
|
|
3493
|
-
case "MISSING_EQUALS_OR_HASHCODE" /* MissingEqualsOrHashcode */:
|
|
3494
|
-
return "Missing equals or hashcode method";
|
|
3495
|
-
default: {
|
|
3496
|
-
return issueType ? issueType.replaceAll("_", " ") : "Other";
|
|
3497
|
-
}
|
|
3498
|
-
}
|
|
3499
|
-
};
|
|
3500
|
-
|
|
3501
|
-
// src/features/analysis/scm/utils/index.ts
|
|
3502
|
-
function getFixUrlWithRedirect(params) {
|
|
3503
|
-
const {
|
|
3504
|
-
fixId,
|
|
3505
|
-
projectId,
|
|
3506
|
-
organizationId,
|
|
3507
|
-
analysisId,
|
|
3508
|
-
redirectUrl,
|
|
3509
|
-
appBaseUrl,
|
|
3510
|
-
commentId
|
|
3511
|
-
} = params;
|
|
3512
|
-
const searchParams = new URLSearchParams();
|
|
3513
|
-
searchParams.append("commit_redirect_url", redirectUrl);
|
|
3514
|
-
searchParams.append("comment_id", commentId.toString());
|
|
3515
|
-
return `${getFixUrl({
|
|
3516
|
-
appBaseUrl,
|
|
3517
|
-
fixId,
|
|
3518
|
-
projectId,
|
|
3519
|
-
organizationId,
|
|
3520
|
-
analysisId
|
|
3521
|
-
})}?${searchParams.toString()}`;
|
|
3522
|
-
}
|
|
3523
|
-
function getFixUrl({
|
|
3524
|
-
appBaseUrl,
|
|
3525
|
-
fixId,
|
|
3526
|
-
projectId,
|
|
3527
|
-
organizationId,
|
|
3528
|
-
analysisId
|
|
3529
|
-
}) {
|
|
3530
|
-
return `${appBaseUrl}/organization/${organizationId}/project/${projectId}/report/${analysisId}/fix/${fixId}`;
|
|
3531
|
-
}
|
|
3532
|
-
function getCommitUrl(params) {
|
|
3533
|
-
const {
|
|
3534
|
-
fixId,
|
|
3535
|
-
projectId,
|
|
3536
|
-
organizationId,
|
|
3537
|
-
analysisId,
|
|
3538
|
-
redirectUrl,
|
|
3539
|
-
appBaseUrl,
|
|
3540
|
-
commentId
|
|
3541
|
-
} = params;
|
|
3542
|
-
const searchParams = new URLSearchParams();
|
|
3543
|
-
searchParams.append("redirect_url", redirectUrl);
|
|
3544
|
-
searchParams.append("comment_id", commentId.toString());
|
|
3545
|
-
return `${getFixUrl({
|
|
3546
|
-
appBaseUrl,
|
|
3547
|
-
fixId,
|
|
3548
|
-
projectId,
|
|
3549
|
-
organizationId,
|
|
3550
|
-
analysisId
|
|
3551
|
-
})}/commit?${searchParams.toString()}`;
|
|
3552
|
-
}
|
|
3553
|
-
|
|
3554
4042
|
// src/features/analysis/utils/by_key.ts
|
|
3555
4043
|
function keyBy(array, keyBy2) {
|
|
3556
4044
|
return array.reduce((acc, item) => {
|
|
@@ -3658,7 +4146,7 @@ async function getRelevantVulenrabilitiesFromDiff(params) {
|
|
|
3658
4146
|
});
|
|
3659
4147
|
const lineAddedRanges = calculateRanges(fileNumbers);
|
|
3660
4148
|
const fileFilter = {
|
|
3661
|
-
path:
|
|
4149
|
+
path: z11.string().parse(file.to),
|
|
3662
4150
|
ranges: lineAddedRanges.map(([startLine, endLine]) => ({
|
|
3663
4151
|
endLine,
|
|
3664
4152
|
startLine
|
|
@@ -4456,9 +4944,7 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
4456
4944
|
apiKey: apiKey || config2.get("apiToken")
|
|
4457
4945
|
});
|
|
4458
4946
|
await handleMobbLogin();
|
|
4459
|
-
const { projectId, organizationId } = await gqlClient.getOrgAndProjectId(
|
|
4460
|
-
mobbProjectName
|
|
4461
|
-
);
|
|
4947
|
+
const { projectId, organizationId } = await gqlClient.getOrgAndProjectId(mobbProjectName);
|
|
4462
4948
|
const {
|
|
4463
4949
|
uploadS3BucketInfo: { repoUploadInfo, reportUploadInfo }
|
|
4464
4950
|
} = await gqlClient.uploadS3BucketInfo();
|
|
@@ -4521,6 +5007,7 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
4521
5007
|
});
|
|
4522
5008
|
const reference = ref ?? await scm.getRepoDefaultBranch();
|
|
4523
5009
|
const { sha } = await scm.getReferenceData(reference);
|
|
5010
|
+
const downloadUrl = await scm.getDownloadUrl(sha);
|
|
4524
5011
|
debug10("org id %s", organizationId);
|
|
4525
5012
|
debug10("project id %s", projectId);
|
|
4526
5013
|
debug10("default branch %s", reference);
|
|
@@ -4529,7 +5016,7 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
4529
5016
|
dirname,
|
|
4530
5017
|
ci,
|
|
4531
5018
|
authHeaders: scm.getAuthHeaders(),
|
|
4532
|
-
downloadUrl
|
|
5019
|
+
downloadUrl
|
|
4533
5020
|
});
|
|
4534
5021
|
if (command === "scan") {
|
|
4535
5022
|
reportPath = await getReport(SupportedScannersZ.parse(scanner));
|
|
@@ -4556,7 +5043,7 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
4556
5043
|
spinner: mobbSpinner,
|
|
4557
5044
|
submitVulnerabilityReportVariables: {
|
|
4558
5045
|
fixReportId: reportUploadInfo.fixReportId,
|
|
4559
|
-
repoUrl:
|
|
5046
|
+
repoUrl: z12.string().parse(repo),
|
|
4560
5047
|
reference,
|
|
4561
5048
|
projectId,
|
|
4562
5049
|
vulnerabilityReportFileName: "report.json",
|
|
@@ -4578,8 +5065,8 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
4578
5065
|
analysisId,
|
|
4579
5066
|
gqlClient,
|
|
4580
5067
|
scm,
|
|
4581
|
-
githubActionToken:
|
|
4582
|
-
scanner:
|
|
5068
|
+
githubActionToken: z12.string().parse(githubActionToken),
|
|
5069
|
+
scanner: z12.nativeEnum(SCANNERS).parse(scanner)
|
|
4583
5070
|
}),
|
|
4584
5071
|
callbackStates: ["Finished" /* Finished */]
|
|
4585
5072
|
});
|
|
@@ -4987,21 +5474,22 @@ var commitHashOption = {
|
|
|
4987
5474
|
};
|
|
4988
5475
|
var scmTypeOption = {
|
|
4989
5476
|
demandOption: true,
|
|
4990
|
-
describe: chalk5.bold("SCM type (GitHub, GitLab, Ado)"),
|
|
5477
|
+
describe: chalk5.bold("SCM type (GitHub, GitLab, Ado, Bitbucket)"),
|
|
4991
5478
|
type: "string"
|
|
4992
5479
|
};
|
|
4993
5480
|
var urlOption = {
|
|
4994
5481
|
describe: chalk5.bold(
|
|
4995
|
-
"URL of the repository (used in GitHub, GitLab, Azure DevOps)"
|
|
5482
|
+
"URL of the repository (used in GitHub, GitLab, Azure DevOps, Bitbucket)"
|
|
4996
5483
|
),
|
|
4997
|
-
type: "string"
|
|
5484
|
+
type: "string",
|
|
5485
|
+
demandOption: true
|
|
4998
5486
|
};
|
|
4999
5487
|
var scmOrgOption = {
|
|
5000
5488
|
describe: chalk5.bold("Organization name in SCM (used in Azure DevOps)"),
|
|
5001
5489
|
type: "string"
|
|
5002
5490
|
};
|
|
5003
5491
|
var scmUsernameOption = {
|
|
5004
|
-
describe: chalk5.bold("Username in SCM (used in GitHub)"),
|
|
5492
|
+
describe: chalk5.bold("Username in SCM (used in GitHub, Bitbucket)"),
|
|
5005
5493
|
type: "string"
|
|
5006
5494
|
};
|
|
5007
5495
|
var scmRefreshTokenOption = {
|
|
@@ -5010,13 +5498,14 @@ var scmRefreshTokenOption = {
|
|
|
5010
5498
|
};
|
|
5011
5499
|
var scmTokenOption = {
|
|
5012
5500
|
describe: chalk5.bold("SCM API token"),
|
|
5013
|
-
type: "string"
|
|
5501
|
+
type: "string",
|
|
5502
|
+
demandOption: true
|
|
5014
5503
|
};
|
|
5015
5504
|
|
|
5016
5505
|
// src/args/validation.ts
|
|
5017
5506
|
import chalk6 from "chalk";
|
|
5018
5507
|
import path8 from "path";
|
|
5019
|
-
import { z as
|
|
5508
|
+
import { z as z13 } from "zod";
|
|
5020
5509
|
function throwRepoUrlErrorMessage({
|
|
5021
5510
|
error,
|
|
5022
5511
|
repoUrl,
|
|
@@ -5033,7 +5522,7 @@ Example:
|
|
|
5033
5522
|
)}`;
|
|
5034
5523
|
throw new CliError(formattedErrorMessage);
|
|
5035
5524
|
}
|
|
5036
|
-
var UrlZ =
|
|
5525
|
+
var UrlZ = z13.string({
|
|
5037
5526
|
invalid_type_error: "is not a valid GitHub / GitLab / ADO URL"
|
|
5038
5527
|
}).refine((data) => !!sanityRepoURL(data), {
|
|
5039
5528
|
message: "is not a valid GitHub / GitLab / ADO URL"
|
|
@@ -5181,6 +5670,7 @@ async function scanHandler(args) {
|
|
|
5181
5670
|
}
|
|
5182
5671
|
|
|
5183
5672
|
// src/args/commands/token.ts
|
|
5673
|
+
import { z as z14 } from "zod";
|
|
5184
5674
|
function addScmTokenBuilder(args) {
|
|
5185
5675
|
return args.option("scm-type", scmTypeOption).option("url", urlOption).option("token", scmTokenOption).option("organization", scmOrgOption).option("username", scmUsernameOption).option("refresh-token", scmRefreshTokenOption).option("api-key", apiKeyOption).example(
|
|
5186
5676
|
"$0 add-scm-token --scm-type Ado --url https://dev.azure.com/adoorg/test/_git/repo --token abcdef0123456 --organization myOrg",
|
|
@@ -5188,22 +5678,36 @@ function addScmTokenBuilder(args) {
|
|
|
5188
5678
|
).help().demandOption(["url", "token"]);
|
|
5189
5679
|
}
|
|
5190
5680
|
function validateAddScmTokenOptions(argv) {
|
|
5191
|
-
if (!argv.
|
|
5192
|
-
throw new CliError(errorMessages.missingUrl);
|
|
5193
|
-
}
|
|
5194
|
-
if (!argv.token) {
|
|
5195
|
-
throw new CliError(errorMessages.missingToken);
|
|
5196
|
-
}
|
|
5197
|
-
if ("GitHub" /* GitHub */ !== argv.scmType && "Ado" /* Ado */ !== argv.scmType && "GitLab" /* GitLab */ !== argv.scmType) {
|
|
5681
|
+
if (!z14.nativeEnum(ScmType).safeParse(argv.scmType).success) {
|
|
5198
5682
|
throw new CliError(
|
|
5199
|
-
"\nError: --scm-type must reference a valid SCM type (GitHub, GitLab, Ado)"
|
|
5683
|
+
"\nError: --scm-type must reference a valid SCM type (GitHub, GitLab, Ado, Bitbutcket)"
|
|
5200
5684
|
);
|
|
5201
5685
|
}
|
|
5686
|
+
Object.values(scmValidationMap).forEach((validate) => validate(argv));
|
|
5687
|
+
}
|
|
5688
|
+
var scmValidationMap = {
|
|
5689
|
+
["GitHub" /* GitHub */]: validateGithub,
|
|
5690
|
+
["GitLab" /* GitLab */]: () => {
|
|
5691
|
+
return;
|
|
5692
|
+
},
|
|
5693
|
+
["Ado" /* Ado */]: validateAdo,
|
|
5694
|
+
["Bitbucket" /* Bitbucket */]: validateBitbucket
|
|
5695
|
+
};
|
|
5696
|
+
function validateBitbucket(argv) {
|
|
5697
|
+
const urlObj = new URL(argv.url);
|
|
5698
|
+
if (urlObj.hostname.toLowerCase() === scmCloudHostname.Bitbucket && !argv.username) {
|
|
5699
|
+
throw new CliError("\nError: --username flag is required for Bitbucket");
|
|
5700
|
+
}
|
|
5701
|
+
}
|
|
5702
|
+
function validateGithub(argv) {
|
|
5202
5703
|
const urlObj = new URL(argv.url);
|
|
5203
|
-
if (urlObj.hostname.toLowerCase() ===
|
|
5704
|
+
if (urlObj.hostname.toLowerCase() === scmCloudHostname.GitHub && !argv.username) {
|
|
5204
5705
|
throw new CliError("\nError: --username flag is required for GitHub");
|
|
5205
5706
|
}
|
|
5206
|
-
|
|
5707
|
+
}
|
|
5708
|
+
function validateAdo(argv) {
|
|
5709
|
+
const urlObj = new URL(argv.url);
|
|
5710
|
+
if ((urlObj.hostname.toLowerCase() === scmCloudHostname.Ado || urlObj.hostname.toLowerCase().endsWith(".visualstudio.com")) && !argv.organization) {
|
|
5207
5711
|
throw new CliError(
|
|
5208
5712
|
"\nError: --organization flag is required for Azure DevOps"
|
|
5209
5713
|
);
|