mobbdev 0.0.108 → 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 +1673 -1156
- package/package.json +7 -6
package/dist/index.mjs
CHANGED
|
@@ -360,9 +360,16 @@ var SubmitVulnerabilityReportDocument = `
|
|
|
360
360
|
var CreateCommunityUserDocument = `
|
|
361
361
|
mutation CreateCommunityUser {
|
|
362
362
|
initOrganizationAndProject {
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
363
|
+
__typename
|
|
364
|
+
... on InitOrganizationAndProjectGoodResponse {
|
|
365
|
+
projectId
|
|
366
|
+
userId
|
|
367
|
+
organizationId
|
|
368
|
+
}
|
|
369
|
+
... on UserAlreadyInProjectError {
|
|
370
|
+
error
|
|
371
|
+
status
|
|
372
|
+
}
|
|
366
373
|
}
|
|
367
374
|
}
|
|
368
375
|
`;
|
|
@@ -517,7 +524,7 @@ import fetch3 from "node-fetch";
|
|
|
517
524
|
import open2 from "open";
|
|
518
525
|
import semver from "semver";
|
|
519
526
|
import tmp2 from "tmp";
|
|
520
|
-
import { z as
|
|
527
|
+
import { z as z12 } from "zod";
|
|
521
528
|
|
|
522
529
|
// src/features/analysis/git.ts
|
|
523
530
|
import Debug2 from "debug";
|
|
@@ -945,35 +952,46 @@ var GQLClient = class {
|
|
|
945
952
|
import { Octokit as Octokit3 } from "@octokit/core";
|
|
946
953
|
import Debug5 from "debug";
|
|
947
954
|
import parseDiff2 from "parse-diff";
|
|
948
|
-
import { z as
|
|
955
|
+
import { z as z11 } from "zod";
|
|
949
956
|
|
|
950
957
|
// src/features/analysis/scm/ado.ts
|
|
951
|
-
import
|
|
958
|
+
import querystring from "node:querystring";
|
|
952
959
|
import * as api from "azure-devops-node-api";
|
|
953
|
-
import { z as z9 } from "zod";
|
|
954
|
-
|
|
955
|
-
// src/features/analysis/scm/scm.ts
|
|
956
|
-
import { Octokit as Octokit2 } from "@octokit/core";
|
|
957
|
-
import { z as z8 } from "zod";
|
|
958
|
-
|
|
959
|
-
// src/features/analysis/scm/github/encryptSecret.ts
|
|
960
|
-
import sodium from "libsodium-wrappers";
|
|
961
|
-
async function encryptSecret(secret, key) {
|
|
962
|
-
await sodium.ready;
|
|
963
|
-
const binkey = sodium.from_base64(key, sodium.base64_variants.ORIGINAL);
|
|
964
|
-
const binsec = sodium.from_string(secret);
|
|
965
|
-
const encBytes = sodium.crypto_box_seal(binsec, binkey);
|
|
966
|
-
return sodium.to_base64(encBytes, sodium.base64_variants.ORIGINAL);
|
|
967
|
-
}
|
|
968
|
-
|
|
969
|
-
// src/features/analysis/scm/github/github.ts
|
|
970
|
-
import { RequestError } from "@octokit/request-error";
|
|
971
|
-
import { Octokit } from "octokit";
|
|
972
960
|
import { z as z3 } from "zod";
|
|
973
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
|
+
|
|
974
990
|
// src/features/analysis/scm/urlParser.ts
|
|
975
|
-
function
|
|
991
|
+
function detectAdoUrl(args) {
|
|
992
|
+
const { pathname, hostname, scmType } = args;
|
|
976
993
|
const hostnameParts = hostname.split(".");
|
|
994
|
+
const adoHostname = new URL(scmCloudUrl.Ado).hostname;
|
|
977
995
|
if (hostnameParts.length === 3 && hostnameParts[1] === "visualstudio" && hostnameParts[2] === "com") {
|
|
978
996
|
if (pathname.length === 2 && pathname[0] === "_git") {
|
|
979
997
|
return {
|
|
@@ -990,7 +1008,7 @@ function getRepoInfo(pathname, hostname, scmType) {
|
|
|
990
1008
|
};
|
|
991
1009
|
}
|
|
992
1010
|
}
|
|
993
|
-
if (hostname ===
|
|
1011
|
+
if (hostname === adoHostname || scmType === "Ado" /* Ado */) {
|
|
994
1012
|
if (pathname.length === 3 && pathname[1] === "_git") {
|
|
995
1013
|
return {
|
|
996
1014
|
organization: pathname[0],
|
|
@@ -1006,7 +1024,12 @@ function getRepoInfo(pathname, hostname, scmType) {
|
|
|
1006
1024
|
};
|
|
1007
1025
|
}
|
|
1008
1026
|
}
|
|
1009
|
-
|
|
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 */) {
|
|
1010
1033
|
if (pathname.length === 2) {
|
|
1011
1034
|
return {
|
|
1012
1035
|
organization: pathname[0],
|
|
@@ -1015,7 +1038,12 @@ function getRepoInfo(pathname, hostname, scmType) {
|
|
|
1015
1038
|
};
|
|
1016
1039
|
}
|
|
1017
1040
|
}
|
|
1018
|
-
|
|
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 */) {
|
|
1019
1047
|
if (pathname.length >= 2) {
|
|
1020
1048
|
return {
|
|
1021
1049
|
organization: pathname[0],
|
|
@@ -1026,13 +1054,46 @@ function getRepoInfo(pathname, hostname, scmType) {
|
|
|
1026
1054
|
}
|
|
1027
1055
|
return null;
|
|
1028
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
|
+
}
|
|
1029
1086
|
var NAME_REGEX = /[a-z0-9\-_.+]+/i;
|
|
1030
1087
|
var parseScmURL = (scmURL, scmType) => {
|
|
1031
1088
|
try {
|
|
1032
1089
|
const url = new URL(scmURL);
|
|
1033
1090
|
const hostname = url.hostname.toLowerCase();
|
|
1034
1091
|
const projectPath = url.pathname.substring(1).replace(/.git$/i, "");
|
|
1035
|
-
const repo = getRepoInfo(
|
|
1092
|
+
const repo = getRepoInfo({
|
|
1093
|
+
pathname: projectPath.split("/"),
|
|
1094
|
+
hostname,
|
|
1095
|
+
scmType
|
|
1096
|
+
});
|
|
1036
1097
|
if (!repo)
|
|
1037
1098
|
return null;
|
|
1038
1099
|
const { organization, repoName, projectName } = repo;
|
|
@@ -1069,247 +1130,886 @@ var sanityRepoURL = (scmURL) => {
|
|
|
1069
1130
|
}
|
|
1070
1131
|
};
|
|
1071
1132
|
|
|
1072
|
-
// src/features/analysis/scm/
|
|
1133
|
+
// src/features/analysis/scm/ado.ts
|
|
1073
1134
|
function removeTrailingSlash(str) {
|
|
1074
1135
|
return str.trim().replace(/\/+$/, "");
|
|
1075
1136
|
}
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
authoredDate
|
|
1103
|
-
}
|
|
1104
|
-
startingLine
|
|
1105
|
-
endingLine
|
|
1106
|
-
age
|
|
1107
|
-
}
|
|
1108
|
-
}
|
|
1109
|
-
}
|
|
1110
|
-
|
|
1111
|
-
}
|
|
1112
|
-
}
|
|
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}`
|
|
1113
1163
|
}
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
const
|
|
1117
|
-
|
|
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;
|
|
1118
1181
|
}
|
|
1119
|
-
|
|
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
|
+
}) {
|
|
1120
1220
|
try {
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1221
|
+
if (!url && accessToken && getAdoTokenType(accessToken) === "OAUTH" /* OAUTH */) {
|
|
1222
|
+
await _getOrgsForOauthToken({ oauthToken: accessToken });
|
|
1223
|
+
return;
|
|
1124
1224
|
}
|
|
1225
|
+
let org = tokenOrg;
|
|
1125
1226
|
if (url) {
|
|
1126
|
-
const { owner
|
|
1127
|
-
|
|
1227
|
+
const { owner } = parseAdoOwnerAndRepo(url);
|
|
1228
|
+
org = owner;
|
|
1128
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();
|
|
1129
1239
|
} catch (e) {
|
|
1130
1240
|
const error = e;
|
|
1131
|
-
const code = error.status || error.statusCode || error.response?.status || error.response?.statusCode || error.response?.code;
|
|
1132
|
-
|
|
1133
|
-
|
|
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`);
|
|
1134
1245
|
}
|
|
1135
|
-
if (code === 404) {
|
|
1136
|
-
throw new InvalidRepoUrlError(`invalid
|
|
1246
|
+
if (code === 404 || description.includes("404") || description.includes("Not Found")) {
|
|
1247
|
+
throw new InvalidRepoUrlError(`invalid ADO repo URL ${url}`);
|
|
1137
1248
|
}
|
|
1138
1249
|
throw e;
|
|
1139
1250
|
}
|
|
1140
1251
|
}
|
|
1141
|
-
async function
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
}
|
|
1146
|
-
async function getGithubIsUserCollaborator(username, accessToken, repoUrl) {
|
|
1252
|
+
async function getAdoIsUserCollaborator({
|
|
1253
|
+
accessToken,
|
|
1254
|
+
tokenOrg,
|
|
1255
|
+
repoUrl
|
|
1256
|
+
}) {
|
|
1147
1257
|
try {
|
|
1148
|
-
const { owner, repo } =
|
|
1149
|
-
const
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
username
|
|
1258
|
+
const { owner, repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
|
|
1259
|
+
const api2 = await getAdoApiClient({
|
|
1260
|
+
accessToken,
|
|
1261
|
+
tokenOrg,
|
|
1262
|
+
orgName: owner
|
|
1154
1263
|
});
|
|
1155
|
-
|
|
1156
|
-
|
|
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");
|
|
1157
1268
|
}
|
|
1269
|
+
return true;
|
|
1158
1270
|
} catch (e) {
|
|
1159
1271
|
return false;
|
|
1160
1272
|
}
|
|
1161
|
-
return false;
|
|
1162
1273
|
}
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
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
|
|
1170
1291
|
});
|
|
1171
|
-
|
|
1172
|
-
|
|
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");
|
|
1173
1296
|
}
|
|
1174
|
-
|
|
1175
|
-
return "draft";
|
|
1176
|
-
}
|
|
1177
|
-
return res.data.state;
|
|
1297
|
+
return adoStatusNumberToEnumMap[res.status];
|
|
1178
1298
|
}
|
|
1179
|
-
async function
|
|
1180
|
-
|
|
1181
|
-
|
|
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();
|
|
1182
1312
|
try {
|
|
1183
|
-
const
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
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;
|
|
1189
1318
|
} catch (e) {
|
|
1190
1319
|
return false;
|
|
1191
1320
|
}
|
|
1192
1321
|
}
|
|
1193
|
-
async function
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
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);
|
|
1202
1371
|
}
|
|
1203
|
-
return
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
};
|
|
1211
|
-
}
|
|
1212
|
-
);
|
|
1213
|
-
} catch (e) {
|
|
1214
|
-
if (e instanceof RequestError && e.status === 401) {
|
|
1215
|
-
return [];
|
|
1216
|
-
}
|
|
1217
|
-
if (e instanceof RequestError && e.status === 404) {
|
|
1218
|
-
return [];
|
|
1372
|
+
return acc;
|
|
1373
|
+
}, []);
|
|
1374
|
+
return repoInfoList;
|
|
1375
|
+
})
|
|
1376
|
+
)).reduce((acc, res) => {
|
|
1377
|
+
if (res.status === "fulfilled") {
|
|
1378
|
+
return acc.concat(res.value);
|
|
1219
1379
|
}
|
|
1220
|
-
|
|
1221
|
-
}
|
|
1222
|
-
|
|
1223
|
-
async function getGithubBranchList(accessToken, repoUrl) {
|
|
1224
|
-
const { owner, repo } = parseGithubOwnerAndRepo(repoUrl);
|
|
1225
|
-
const oktoKit = getOktoKit({ githubAuthToken: accessToken });
|
|
1226
|
-
const res = await oktoKit.rest.repos.listBranches({
|
|
1227
|
-
owner,
|
|
1228
|
-
repo,
|
|
1229
|
-
per_page: 1e3,
|
|
1230
|
-
page: 1
|
|
1231
|
-
});
|
|
1232
|
-
return res.data.map((branch) => branch.name);
|
|
1380
|
+
return acc;
|
|
1381
|
+
}, []);
|
|
1382
|
+
return repos;
|
|
1233
1383
|
}
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
repo,
|
|
1240
|
-
title: options.title,
|
|
1241
|
-
body: options.body,
|
|
1242
|
-
head: options.sourceBranchName,
|
|
1243
|
-
base: options.targetBranchName,
|
|
1244
|
-
draft: false,
|
|
1245
|
-
maintainer_can_modify: true
|
|
1246
|
-
});
|
|
1247
|
-
return res.data.number;
|
|
1384
|
+
function getAdoPrUrl({
|
|
1385
|
+
url,
|
|
1386
|
+
prNumber
|
|
1387
|
+
}) {
|
|
1388
|
+
return `${url}/pullrequest/${prNumber}`;
|
|
1248
1389
|
}
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
}
|
|
1257
|
-
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`;
|
|
1258
1398
|
}
|
|
1259
|
-
async function
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
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
|
|
1265
1409
|
});
|
|
1266
|
-
|
|
1267
|
-
}
|
|
1268
|
-
async function getGithubRepoDefaultBranch(repoUrl, options) {
|
|
1269
|
-
const oktoKit = getOktoKit(options);
|
|
1270
|
-
const { owner, repo } = parseGithubOwnerAndRepo(repoUrl);
|
|
1271
|
-
return (await oktoKit.rest.repos.get({ repo, owner })).data.default_branch;
|
|
1272
|
-
}
|
|
1273
|
-
async function getGithubReferenceData({ ref, gitHubUrl }, options) {
|
|
1274
|
-
const { owner, repo } = parseGithubOwnerAndRepo(gitHubUrl);
|
|
1275
|
-
let res;
|
|
1410
|
+
const git = await api2.getGitApi();
|
|
1276
1411
|
try {
|
|
1277
|
-
const
|
|
1278
|
-
res
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
type: "TAG" /* TAG */,
|
|
1292
|
-
sha: data.sha
|
|
1293
|
-
}))
|
|
1294
|
-
]);
|
|
1295
|
-
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
|
+
}, []);
|
|
1296
1426
|
} catch (e) {
|
|
1297
|
-
|
|
1298
|
-
throw new RefNotFoundError(`ref: ${ref} does not exist`);
|
|
1299
|
-
}
|
|
1300
|
-
throw e;
|
|
1427
|
+
return [];
|
|
1301
1428
|
}
|
|
1302
1429
|
}
|
|
1303
|
-
async function
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
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
|
|
1308
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;
|
|
1309
1449
|
}
|
|
1310
|
-
async function
|
|
1311
|
-
|
|
1312
|
-
|
|
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}`,
|
|
1313
2013
|
owner,
|
|
1314
2014
|
repo
|
|
1315
2015
|
});
|
|
@@ -1347,7 +2047,7 @@ async function getCommit({
|
|
|
1347
2047
|
});
|
|
1348
2048
|
}
|
|
1349
2049
|
function parseGithubOwnerAndRepo(gitHubUrl) {
|
|
1350
|
-
gitHubUrl =
|
|
2050
|
+
gitHubUrl = removeTrailingSlash2(gitHubUrl);
|
|
1351
2051
|
const parsingResult = parseScmURL(gitHubUrl, "GitHub" /* GitHub */);
|
|
1352
2052
|
if (!parsingResult || parsingResult.hostname !== "github.com") {
|
|
1353
2053
|
throw new InvalidUrlPatternError(`invalid github repo Url ${gitHubUrl}`);
|
|
@@ -1551,30 +2251,30 @@ function deleteGeneralPrComment(client, params) {
|
|
|
1551
2251
|
}
|
|
1552
2252
|
|
|
1553
2253
|
// src/features/analysis/scm/gitlab/gitlab.ts
|
|
1554
|
-
import
|
|
2254
|
+
import querystring2 from "node:querystring";
|
|
1555
2255
|
import {
|
|
1556
2256
|
Gitlab
|
|
1557
2257
|
} from "@gitbeaker/rest";
|
|
1558
2258
|
import { ProxyAgent } from "undici";
|
|
1559
|
-
import { z as
|
|
2259
|
+
import { z as z6 } from "zod";
|
|
1560
2260
|
|
|
1561
2261
|
// src/features/analysis/scm/gitlab/types.ts
|
|
1562
|
-
import { z as
|
|
1563
|
-
var GitlabAuthResultZ =
|
|
1564
|
-
access_token:
|
|
1565
|
-
token_type:
|
|
1566
|
-
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()
|
|
1567
2267
|
});
|
|
1568
2268
|
|
|
1569
2269
|
// src/features/analysis/scm/gitlab/gitlab.ts
|
|
1570
|
-
var EnvVariablesZod2 =
|
|
1571
|
-
GITLAB_API_TOKEN:
|
|
1572
|
-
BROKERED_HOSTS:
|
|
2270
|
+
var EnvVariablesZod2 = z6.object({
|
|
2271
|
+
GITLAB_API_TOKEN: z6.string().optional(),
|
|
2272
|
+
BROKERED_HOSTS: z6.string().toLowerCase().transform(
|
|
1573
2273
|
(x) => x.split(",").map((url) => url.trim(), []).filter(Boolean)
|
|
1574
2274
|
).default("")
|
|
1575
2275
|
});
|
|
1576
2276
|
var { GITLAB_API_TOKEN, BROKERED_HOSTS } = EnvVariablesZod2.parse(process.env);
|
|
1577
|
-
function
|
|
2277
|
+
function removeTrailingSlash3(str) {
|
|
1578
2278
|
return str.trim().replace(/\/+$/, "");
|
|
1579
2279
|
}
|
|
1580
2280
|
function getGitBeaker(options) {
|
|
@@ -1634,6 +2334,11 @@ async function getGitlabIsUserCollaborator({
|
|
|
1634
2334
|
return false;
|
|
1635
2335
|
}
|
|
1636
2336
|
}
|
|
2337
|
+
var gitlabMergeRequestStatus = {
|
|
2338
|
+
merged: "merged",
|
|
2339
|
+
opened: "opened",
|
|
2340
|
+
closed: "closed"
|
|
2341
|
+
};
|
|
1637
2342
|
async function getGitlabMergeRequestStatus({
|
|
1638
2343
|
accessToken,
|
|
1639
2344
|
repoUrl,
|
|
@@ -1643,9 +2348,9 @@ async function getGitlabMergeRequestStatus({
|
|
|
1643
2348
|
const api2 = getGitBeaker({ url: repoUrl, gitlabAuthToken: accessToken });
|
|
1644
2349
|
const res = await api2.MergeRequests.show(projectPath, mrNumber);
|
|
1645
2350
|
switch (res.state) {
|
|
1646
|
-
case
|
|
1647
|
-
case
|
|
1648
|
-
case
|
|
2351
|
+
case gitlabMergeRequestStatus.merged:
|
|
2352
|
+
case gitlabMergeRequestStatus.opened:
|
|
2353
|
+
case gitlabMergeRequestStatus.closed:
|
|
1649
2354
|
return res.state;
|
|
1650
2355
|
default:
|
|
1651
2356
|
throw new Error(`unknown merge request state ${res.state}`);
|
|
@@ -1798,7 +2503,7 @@ async function getGitlabReferenceData({ ref, gitlabUrl }, options) {
|
|
|
1798
2503
|
throw new RefNotFoundError(`ref: ${ref} does not exist`);
|
|
1799
2504
|
}
|
|
1800
2505
|
function parseGitlabOwnerAndRepo(gitlabUrl) {
|
|
1801
|
-
gitlabUrl =
|
|
2506
|
+
gitlabUrl = removeTrailingSlash3(gitlabUrl);
|
|
1802
2507
|
const parsingResult = parseScmURL(gitlabUrl, "GitLab" /* GitLab */);
|
|
1803
2508
|
if (!parsingResult || !parsingResult.repoName) {
|
|
1804
2509
|
throw new InvalidUrlPatternError(`invalid gitlab repo Url ${gitlabUrl}`);
|
|
@@ -1864,84 +2569,84 @@ import parseDiff from "parse-diff";
|
|
|
1864
2569
|
import path3 from "path";
|
|
1865
2570
|
import { simpleGit as simpleGit2 } from "simple-git";
|
|
1866
2571
|
import tmp from "tmp";
|
|
1867
|
-
import { z as
|
|
2572
|
+
import { z as z8 } from "zod";
|
|
1868
2573
|
|
|
1869
2574
|
// src/features/analysis/scm/scmSubmit/types.ts
|
|
1870
|
-
import { z as
|
|
1871
|
-
var BaseSubmitToScmMessageZ =
|
|
1872
|
-
submitFixRequestId:
|
|
1873
|
-
fixes:
|
|
1874
|
-
|
|
1875
|
-
fixId:
|
|
1876
|
-
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()
|
|
1877
2582
|
})
|
|
1878
2583
|
),
|
|
1879
|
-
commitHash:
|
|
1880
|
-
repoUrl:
|
|
2584
|
+
commitHash: z7.string(),
|
|
2585
|
+
repoUrl: z7.string()
|
|
1881
2586
|
});
|
|
1882
2587
|
var submitToScmMessageType = {
|
|
1883
2588
|
commitToSameBranch: "commitToSameBranch",
|
|
1884
2589
|
submitFixesForDifferentBranch: "submitFixesForDifferentBranch"
|
|
1885
2590
|
};
|
|
1886
2591
|
var CommitToSameBranchParamsZ = BaseSubmitToScmMessageZ.merge(
|
|
1887
|
-
|
|
1888
|
-
type:
|
|
1889
|
-
branch:
|
|
1890
|
-
commitMessage:
|
|
1891
|
-
commitDescription:
|
|
1892
|
-
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()
|
|
1893
2598
|
})
|
|
1894
2599
|
);
|
|
1895
|
-
var SubmitFixesToDifferentBranchParamsZ =
|
|
1896
|
-
type:
|
|
1897
|
-
submitBranch:
|
|
1898
|
-
baseBranch:
|
|
2600
|
+
var SubmitFixesToDifferentBranchParamsZ = z7.object({
|
|
2601
|
+
type: z7.literal(submitToScmMessageType.submitFixesForDifferentBranch),
|
|
2602
|
+
submitBranch: z7.string(),
|
|
2603
|
+
baseBranch: z7.string()
|
|
1899
2604
|
}).merge(BaseSubmitToScmMessageZ);
|
|
1900
|
-
var SubmitFixesMessageZ =
|
|
2605
|
+
var SubmitFixesMessageZ = z7.union([
|
|
1901
2606
|
CommitToSameBranchParamsZ,
|
|
1902
2607
|
SubmitFixesToDifferentBranchParamsZ
|
|
1903
2608
|
]);
|
|
1904
|
-
var FixResponseArrayZ =
|
|
1905
|
-
|
|
1906
|
-
fixId:
|
|
2609
|
+
var FixResponseArrayZ = z7.array(
|
|
2610
|
+
z7.object({
|
|
2611
|
+
fixId: z7.string().uuid()
|
|
1907
2612
|
})
|
|
1908
2613
|
);
|
|
1909
|
-
var SubmitFixesBaseResponseMessageZ =
|
|
1910
|
-
submitFixRequestId:
|
|
1911
|
-
submitBranches:
|
|
1912
|
-
|
|
1913
|
-
branchName:
|
|
2614
|
+
var SubmitFixesBaseResponseMessageZ = z7.object({
|
|
2615
|
+
submitFixRequestId: z7.string().uuid(),
|
|
2616
|
+
submitBranches: z7.array(
|
|
2617
|
+
z7.object({
|
|
2618
|
+
branchName: z7.string(),
|
|
1914
2619
|
fixes: FixResponseArrayZ
|
|
1915
2620
|
})
|
|
1916
2621
|
),
|
|
1917
|
-
error:
|
|
1918
|
-
type:
|
|
2622
|
+
error: z7.object({
|
|
2623
|
+
type: z7.enum([
|
|
1919
2624
|
"InitialRepoAccessError",
|
|
1920
2625
|
"PushBranchError",
|
|
1921
2626
|
"UnknownError"
|
|
1922
2627
|
]),
|
|
1923
|
-
info:
|
|
1924
|
-
message:
|
|
1925
|
-
pushBranchName:
|
|
2628
|
+
info: z7.object({
|
|
2629
|
+
message: z7.string(),
|
|
2630
|
+
pushBranchName: z7.string().optional()
|
|
1926
2631
|
})
|
|
1927
2632
|
}).optional()
|
|
1928
2633
|
});
|
|
1929
|
-
var SubmitFixesToSameBranchResponseMessageZ =
|
|
1930
|
-
type:
|
|
1931
|
-
githubCommentId:
|
|
2634
|
+
var SubmitFixesToSameBranchResponseMessageZ = z7.object({
|
|
2635
|
+
type: z7.literal(submitToScmMessageType.commitToSameBranch),
|
|
2636
|
+
githubCommentId: z7.number().nullish()
|
|
1932
2637
|
}).merge(SubmitFixesBaseResponseMessageZ);
|
|
1933
|
-
var SubmitFixesToDifferentBranchResponseMessageZ =
|
|
1934
|
-
type:
|
|
1935
|
-
githubCommentId:
|
|
2638
|
+
var SubmitFixesToDifferentBranchResponseMessageZ = z7.object({
|
|
2639
|
+
type: z7.literal(submitToScmMessageType.submitFixesForDifferentBranch),
|
|
2640
|
+
githubCommentId: z7.number().optional()
|
|
1936
2641
|
}).merge(SubmitFixesBaseResponseMessageZ);
|
|
1937
|
-
var SubmitFixesResponseMessageZ =
|
|
2642
|
+
var SubmitFixesResponseMessageZ = z7.discriminatedUnion("type", [
|
|
1938
2643
|
SubmitFixesToSameBranchResponseMessageZ,
|
|
1939
2644
|
SubmitFixesToDifferentBranchResponseMessageZ
|
|
1940
2645
|
]);
|
|
1941
2646
|
|
|
1942
2647
|
// src/features/analysis/scm/scmSubmit/index.ts
|
|
1943
|
-
var EnvVariablesZod3 =
|
|
1944
|
-
BROKERED_HOSTS:
|
|
2648
|
+
var EnvVariablesZod3 = z8.object({
|
|
2649
|
+
BROKERED_HOSTS: z8.string().toLowerCase().transform(
|
|
1945
2650
|
(x) => x.split(",").map((url) => url.trim(), []).filter(Boolean)
|
|
1946
2651
|
).default("")
|
|
1947
2652
|
});
|
|
@@ -1958,49 +2663,59 @@ var isValidBranchName = async (branchName) => {
|
|
|
1958
2663
|
return false;
|
|
1959
2664
|
}
|
|
1960
2665
|
};
|
|
1961
|
-
var FixesZ =
|
|
2666
|
+
var FixesZ = z8.array(z8.object({ fixId: z8.string(), diff: z8.string() })).nonempty();
|
|
1962
2667
|
|
|
1963
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
|
+
});
|
|
1964
2674
|
function getCloudScmLibTypeFromUrl(url) {
|
|
1965
2675
|
if (!url) {
|
|
1966
2676
|
return void 0;
|
|
1967
2677
|
}
|
|
1968
2678
|
const urlObject = new URL(url);
|
|
1969
2679
|
const hostname = urlObject.hostname.toLowerCase();
|
|
1970
|
-
if (hostname ===
|
|
2680
|
+
if (hostname === scmCloudHostname.GitLab) {
|
|
1971
2681
|
return "GITLAB" /* GITLAB */;
|
|
1972
2682
|
}
|
|
1973
|
-
if (hostname ===
|
|
2683
|
+
if (hostname === scmCloudHostname.GitHub) {
|
|
1974
2684
|
return "GITHUB" /* GITHUB */;
|
|
1975
2685
|
}
|
|
1976
|
-
if (hostname ===
|
|
2686
|
+
if (hostname === scmCloudHostname.Ado || hostname.endsWith(".visualstudio.com")) {
|
|
1977
2687
|
return "ADO" /* ADO */;
|
|
1978
2688
|
}
|
|
2689
|
+
if (hostname === scmCloudHostname.Bitbucket) {
|
|
2690
|
+
return "BITBUCKET" /* BITBUCKET */;
|
|
2691
|
+
}
|
|
1979
2692
|
return void 0;
|
|
1980
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
|
+
};
|
|
1981
2712
|
function getScmTypeFromScmLibType(scmLibType) {
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
}
|
|
1985
|
-
if (scmLibType === "GITHUB" /* GITHUB */) {
|
|
1986
|
-
return "GitHub" /* GitHub */;
|
|
1987
|
-
}
|
|
1988
|
-
if (scmLibType === "ADO" /* ADO */) {
|
|
1989
|
-
return "Ado" /* Ado */;
|
|
1990
|
-
}
|
|
1991
|
-
throw new Error(`unknown scm lib type: ${scmLibType}`);
|
|
2713
|
+
const parsedScmLibType = z9.nativeEnum(ScmLibScmType).parse(scmLibType);
|
|
2714
|
+
return scmLibScmTypeToScmType[parsedScmLibType];
|
|
1992
2715
|
}
|
|
1993
2716
|
function getScmLibTypeFromScmType(scmType) {
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
}
|
|
1997
|
-
if (scmType === "GitHub" /* GitHub */) {
|
|
1998
|
-
return "GITHUB" /* GITHUB */;
|
|
1999
|
-
}
|
|
2000
|
-
if (scmType === "Ado" /* Ado */) {
|
|
2001
|
-
return "ADO" /* ADO */;
|
|
2002
|
-
}
|
|
2003
|
-
throw new Error(`unknown scm type: ${scmType}`);
|
|
2717
|
+
const parsedScmType = z9.nativeEnum(ScmType).parse(scmType);
|
|
2718
|
+
return scmTypeToScmLibScmType[parsedScmType];
|
|
2004
2719
|
}
|
|
2005
2720
|
function getScmConfig({
|
|
2006
2721
|
url,
|
|
@@ -2096,6 +2811,19 @@ var RepoNoTokenAccessError = class extends Error {
|
|
|
2096
2811
|
super(m);
|
|
2097
2812
|
}
|
|
2098
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
|
+
}
|
|
2099
2827
|
var SCMLib = class {
|
|
2100
2828
|
constructor(url, accessToken, scmOrg) {
|
|
2101
2829
|
__publicField(this, "url");
|
|
@@ -2111,24 +2839,45 @@ var SCMLib = class {
|
|
|
2111
2839
|
throw new Error("no url");
|
|
2112
2840
|
}
|
|
2113
2841
|
const trimmedUrl = this.url.trim().replace(/\/$/, "");
|
|
2114
|
-
|
|
2842
|
+
const accessToken = this.getAccessToken();
|
|
2843
|
+
if (!accessToken) {
|
|
2115
2844
|
return trimmedUrl;
|
|
2116
2845
|
}
|
|
2846
|
+
console.log(
|
|
2847
|
+
"this instanceof BitbucketSCMLib",
|
|
2848
|
+
this instanceof BitbucketSCMLib
|
|
2849
|
+
);
|
|
2117
2850
|
const scmLibType = this.getScmLibType();
|
|
2118
2851
|
if (scmLibType === "ADO" /* ADO */) {
|
|
2119
|
-
return `https://${
|
|
2852
|
+
return `https://${accessToken}@${trimmedUrl.toLowerCase().replace("https://", "")}`;
|
|
2120
2853
|
}
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
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
|
+
}
|
|
2131
2874
|
}
|
|
2875
|
+
const username = await this._getUsernameForAuthUrl();
|
|
2876
|
+
return buildAuthrizedRepoUrl({
|
|
2877
|
+
url: trimmedUrl,
|
|
2878
|
+
username,
|
|
2879
|
+
password: accessToken
|
|
2880
|
+
});
|
|
2132
2881
|
}
|
|
2133
2882
|
getAccessToken() {
|
|
2134
2883
|
return this.accessToken || "";
|
|
@@ -2142,6 +2891,12 @@ var SCMLib = class {
|
|
|
2142
2891
|
}
|
|
2143
2892
|
return this.url.split("/").at(-1) || "";
|
|
2144
2893
|
}
|
|
2894
|
+
_validateToken() {
|
|
2895
|
+
if (!this.accessToken) {
|
|
2896
|
+
console.error("no access token");
|
|
2897
|
+
throw new Error("no access token");
|
|
2898
|
+
}
|
|
2899
|
+
}
|
|
2145
2900
|
static async getIsValidBranchName(branchName) {
|
|
2146
2901
|
return isValidBranchName(branchName);
|
|
2147
2902
|
}
|
|
@@ -2156,20 +2911,27 @@ var SCMLib = class {
|
|
|
2156
2911
|
trimmedUrl = url.trim().replace(/\/$/, "").replace(/.git$/i, "");
|
|
2157
2912
|
}
|
|
2158
2913
|
try {
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
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
|
+
}
|
|
2173
2935
|
}
|
|
2174
2936
|
} catch (e) {
|
|
2175
2937
|
if (e instanceof InvalidRepoUrlError && url) {
|
|
@@ -2180,36 +2942,24 @@ var SCMLib = class {
|
|
|
2180
2942
|
}
|
|
2181
2943
|
_validateAccessTokenAndUrl() {
|
|
2182
2944
|
if (!this.accessToken) {
|
|
2945
|
+
console.error("no access token");
|
|
2183
2946
|
throw new InvalidAccessTokenError("no access token");
|
|
2184
2947
|
}
|
|
2948
|
+
this._validateUrl();
|
|
2949
|
+
}
|
|
2950
|
+
_validateUrl() {
|
|
2185
2951
|
if (!this.url) {
|
|
2952
|
+
console.error("no url");
|
|
2186
2953
|
throw new InvalidRepoUrlError("no url");
|
|
2187
2954
|
}
|
|
2188
2955
|
}
|
|
2189
2956
|
};
|
|
2190
2957
|
var AdoSCMLib = class extends SCMLib {
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
getPrComment(_commentId) {
|
|
2195
|
-
throw new Error("getPrComment not implemented.");
|
|
2196
|
-
}
|
|
2197
|
-
async forkRepo() {
|
|
2198
|
-
throw new Error("forkRepo not supported yet");
|
|
2199
|
-
}
|
|
2200
|
-
async createOrUpdateRepositorySecret() {
|
|
2201
|
-
throw new Error("createOrUpdateRepositorySecret not supported yet");
|
|
2202
|
-
}
|
|
2203
|
-
async createPullRequestWithNewFile(_sourceRepoUrl, _filesPaths, _userRepoUrl, _title, _body) {
|
|
2204
|
-
throw new Error("createPullRequestWithNewFile not supported yet");
|
|
2205
|
-
}
|
|
2206
|
-
async createSubmitRequest(targetBranchName, sourceBranchName, title, body) {
|
|
2207
|
-
if (!this.accessToken || !this.url) {
|
|
2208
|
-
console.error("no access token or no url");
|
|
2209
|
-
throw new Error("no access token or no url");
|
|
2210
|
-
}
|
|
2958
|
+
async createSubmitRequest(params) {
|
|
2959
|
+
this._validateAccessTokenAndUrl();
|
|
2960
|
+
const { targetBranchName, sourceBranchName, title, body } = params;
|
|
2211
2961
|
return String(
|
|
2212
|
-
await createAdoPullRequest({
|
|
2962
|
+
await AdoSdk.createAdoPullRequest({
|
|
2213
2963
|
title,
|
|
2214
2964
|
body,
|
|
2215
2965
|
targetBranchName,
|
|
@@ -2221,7 +2971,7 @@ var AdoSCMLib = class extends SCMLib {
|
|
|
2221
2971
|
);
|
|
2222
2972
|
}
|
|
2223
2973
|
async validateParams() {
|
|
2224
|
-
return adoValidateParams({
|
|
2974
|
+
return AdoSdk.adoValidateParams({
|
|
2225
2975
|
url: this.url,
|
|
2226
2976
|
accessToken: this.accessToken,
|
|
2227
2977
|
tokenOrg: this.scmOrg
|
|
@@ -2232,18 +2982,15 @@ var AdoSCMLib = class extends SCMLib {
|
|
|
2232
2982
|
console.error("no access token");
|
|
2233
2983
|
throw new Error("no access token");
|
|
2234
2984
|
}
|
|
2235
|
-
return getAdoRepoList({
|
|
2985
|
+
return AdoSdk.getAdoRepoList({
|
|
2236
2986
|
orgName: scmOrg,
|
|
2237
2987
|
tokenOrg: this.scmOrg,
|
|
2238
2988
|
accessToken: this.accessToken
|
|
2239
2989
|
});
|
|
2240
2990
|
}
|
|
2241
2991
|
async getBranchList() {
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
throw new Error("no access token or no url");
|
|
2245
|
-
}
|
|
2246
|
-
return getAdoBranchList({
|
|
2992
|
+
this._validateAccessTokenAndUrl();
|
|
2993
|
+
return AdoSdk.getAdoBranchList({
|
|
2247
2994
|
accessToken: this.accessToken,
|
|
2248
2995
|
tokenOrg: this.scmOrg,
|
|
2249
2996
|
repoUrl: this.url
|
|
@@ -2254,7 +3001,7 @@ var AdoSCMLib = class extends SCMLib {
|
|
|
2254
3001
|
}
|
|
2255
3002
|
getAuthHeaders() {
|
|
2256
3003
|
if (this.accessToken) {
|
|
2257
|
-
if (getAdoTokenType(this.accessToken) === "OAUTH" /* OAUTH */) {
|
|
3004
|
+
if (AdoSdk.getAdoTokenType(this.accessToken) === "OAUTH" /* OAUTH */) {
|
|
2258
3005
|
return {
|
|
2259
3006
|
authorization: `Bearer ${this.accessToken}`
|
|
2260
3007
|
};
|
|
@@ -2269,21 +3016,17 @@ var AdoSCMLib = class extends SCMLib {
|
|
|
2269
3016
|
return {};
|
|
2270
3017
|
}
|
|
2271
3018
|
getDownloadUrl(sha) {
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
return getAdoDownloadUrl({ repoUrl: this.url, branch: sha });
|
|
3019
|
+
this._validateUrl();
|
|
3020
|
+
return Promise.resolve(
|
|
3021
|
+
AdoSdk.getAdoDownloadUrl({ repoUrl: this.url, branch: sha })
|
|
3022
|
+
);
|
|
2277
3023
|
}
|
|
2278
3024
|
async _getUsernameForAuthUrl() {
|
|
2279
3025
|
throw new Error("_getUsernameForAuthUrl() is not relevant for ADO");
|
|
2280
3026
|
}
|
|
2281
3027
|
async getIsRemoteBranch(branch) {
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
throw new Error("no access token or no url");
|
|
2285
|
-
}
|
|
2286
|
-
return getAdoIsRemoteBranch({
|
|
3028
|
+
this._validateAccessTokenAndUrl();
|
|
3029
|
+
return AdoSdk.getAdoIsRemoteBranch({
|
|
2287
3030
|
accessToken: this.accessToken,
|
|
2288
3031
|
tokenOrg: this.scmOrg,
|
|
2289
3032
|
repoUrl: this.url,
|
|
@@ -2291,11 +3034,8 @@ var AdoSCMLib = class extends SCMLib {
|
|
|
2291
3034
|
});
|
|
2292
3035
|
}
|
|
2293
3036
|
async getUserHasAccessToRepo() {
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
throw new Error("no access token or no url");
|
|
2297
|
-
}
|
|
2298
|
-
return getAdoIsUserCollaborator({
|
|
3037
|
+
this._validateAccessTokenAndUrl();
|
|
3038
|
+
return AdoSdk.getAdoIsUserCollaborator({
|
|
2299
3039
|
accessToken: this.accessToken,
|
|
2300
3040
|
tokenOrg: this.scmOrg,
|
|
2301
3041
|
repoUrl: this.url
|
|
@@ -2305,11 +3045,8 @@ var AdoSCMLib = class extends SCMLib {
|
|
|
2305
3045
|
throw new Error("getUsername() is not relevant for ADO");
|
|
2306
3046
|
}
|
|
2307
3047
|
async getSubmitRequestStatus(scmSubmitRequestId) {
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
throw new Error("no access token or no url");
|
|
2311
|
-
}
|
|
2312
|
-
const state = await getAdoPullRequestStatus({
|
|
3048
|
+
this._validateAccessTokenAndUrl();
|
|
3049
|
+
const state = await AdoSdk.getAdoPullRequestStatus({
|
|
2313
3050
|
accessToken: this.accessToken,
|
|
2314
3051
|
tokenOrg: this.scmOrg,
|
|
2315
3052
|
repoUrl: this.url,
|
|
@@ -2317,24 +3054,21 @@ var AdoSCMLib = class extends SCMLib {
|
|
|
2317
3054
|
});
|
|
2318
3055
|
switch (state) {
|
|
2319
3056
|
case "completed" /* completed */:
|
|
2320
|
-
return "
|
|
3057
|
+
return "merged";
|
|
2321
3058
|
case "active" /* active */:
|
|
2322
|
-
return "
|
|
3059
|
+
return "open";
|
|
2323
3060
|
case "abandoned" /* abandoned */:
|
|
2324
|
-
return "
|
|
3061
|
+
return "closed";
|
|
2325
3062
|
default:
|
|
2326
3063
|
throw new Error(`unknown state ${state}`);
|
|
2327
3064
|
}
|
|
2328
3065
|
}
|
|
2329
3066
|
async getRepoBlameRanges(_ref, _path) {
|
|
2330
|
-
return await getAdoBlameRanges();
|
|
3067
|
+
return await AdoSdk.getAdoBlameRanges();
|
|
2331
3068
|
}
|
|
2332
3069
|
async getReferenceData(ref) {
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
throw new Error("no url");
|
|
2336
|
-
}
|
|
2337
|
-
return await getAdoReferenceData({
|
|
3070
|
+
this._validateUrl();
|
|
3071
|
+
return await AdoSdk.getAdoReferenceData({
|
|
2338
3072
|
ref,
|
|
2339
3073
|
repoUrl: this.url,
|
|
2340
3074
|
accessToken: this.accessToken,
|
|
@@ -2342,11 +3076,8 @@ var AdoSCMLib = class extends SCMLib {
|
|
|
2342
3076
|
});
|
|
2343
3077
|
}
|
|
2344
3078
|
async getRepoDefaultBranch() {
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
throw new Error("no url");
|
|
2348
|
-
}
|
|
2349
|
-
return await getAdoRepoDefaultBranch({
|
|
3079
|
+
this._validateUrl();
|
|
3080
|
+
return await AdoSdk.getAdoRepoDefaultBranch({
|
|
2350
3081
|
repoUrl: this.url,
|
|
2351
3082
|
tokenOrg: this.scmOrg,
|
|
2352
3083
|
accessToken: this.accessToken
|
|
@@ -2356,22 +3087,11 @@ var AdoSCMLib = class extends SCMLib {
|
|
|
2356
3087
|
this._validateAccessTokenAndUrl();
|
|
2357
3088
|
return Promise.resolve(getAdoPrUrl({ prNumber, url: this.url }));
|
|
2358
3089
|
}
|
|
2359
|
-
postGeneralPrComment() {
|
|
2360
|
-
throw new Error("Method not implemented.");
|
|
2361
|
-
}
|
|
2362
|
-
getGeneralPrComments() {
|
|
2363
|
-
throw new Error("Method not implemented.");
|
|
2364
|
-
}
|
|
2365
|
-
deleteGeneralPrComment() {
|
|
2366
|
-
throw new Error("Method not implemented.");
|
|
2367
|
-
}
|
|
2368
3090
|
};
|
|
2369
3091
|
var GitlabSCMLib = class extends SCMLib {
|
|
2370
|
-
async createSubmitRequest(
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
throw new Error("no access token or no url");
|
|
2374
|
-
}
|
|
3092
|
+
async createSubmitRequest(params) {
|
|
3093
|
+
this._validateAccessTokenAndUrl();
|
|
3094
|
+
const { targetBranchName, sourceBranchName, title, body } = params;
|
|
2375
3095
|
return String(
|
|
2376
3096
|
await createMergeRequest({
|
|
2377
3097
|
title,
|
|
@@ -2389,23 +3109,6 @@ var GitlabSCMLib = class extends SCMLib {
|
|
|
2389
3109
|
accessToken: this.accessToken
|
|
2390
3110
|
});
|
|
2391
3111
|
}
|
|
2392
|
-
async forkRepo() {
|
|
2393
|
-
if (!this.accessToken) {
|
|
2394
|
-
console.error("no access token");
|
|
2395
|
-
throw new Error("no access token");
|
|
2396
|
-
}
|
|
2397
|
-
throw new Error("not supported yet");
|
|
2398
|
-
}
|
|
2399
|
-
async createOrUpdateRepositorySecret() {
|
|
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 createPullRequestWithNewFile(_sourceRepoUrl, _filesPaths, _userRepoUrl, _title, _body) {
|
|
2407
|
-
throw new Error("not implemented");
|
|
2408
|
-
}
|
|
2409
3112
|
async getRepoList(_scmOrg) {
|
|
2410
3113
|
if (!this.accessToken) {
|
|
2411
3114
|
console.error("no access token");
|
|
@@ -2414,10 +3117,7 @@ var GitlabSCMLib = class extends SCMLib {
|
|
|
2414
3117
|
return getGitlabRepoList(this.url, this.accessToken);
|
|
2415
3118
|
}
|
|
2416
3119
|
async getBranchList() {
|
|
2417
|
-
|
|
2418
|
-
console.error("no access token or no url");
|
|
2419
|
-
throw new Error("no access token or no url");
|
|
2420
|
-
}
|
|
3120
|
+
this._validateAccessTokenAndUrl();
|
|
2421
3121
|
return getGitlabBranchList({
|
|
2422
3122
|
accessToken: this.accessToken,
|
|
2423
3123
|
repoUrl: this.url
|
|
@@ -2438,7 +3138,9 @@ var GitlabSCMLib = class extends SCMLib {
|
|
|
2438
3138
|
getDownloadUrl(sha) {
|
|
2439
3139
|
const urlSplit = this.url?.split("/") || [];
|
|
2440
3140
|
const repoName = urlSplit[urlSplit?.length - 1];
|
|
2441
|
-
return
|
|
3141
|
+
return Promise.resolve(
|
|
3142
|
+
`${this.url}/-/archive/${sha}/${repoName}-${sha}.zip`
|
|
3143
|
+
);
|
|
2442
3144
|
}
|
|
2443
3145
|
async _getUsernameForAuthUrl() {
|
|
2444
3146
|
if (this?.accessToken?.startsWith("glpat-")) {
|
|
@@ -2448,10 +3150,7 @@ var GitlabSCMLib = class extends SCMLib {
|
|
|
2448
3150
|
}
|
|
2449
3151
|
}
|
|
2450
3152
|
async getIsRemoteBranch(branch) {
|
|
2451
|
-
|
|
2452
|
-
console.error("no access token or no url");
|
|
2453
|
-
throw new Error("no access token or no url");
|
|
2454
|
-
}
|
|
3153
|
+
this._validateAccessTokenAndUrl();
|
|
2455
3154
|
return getGitlabIsRemoteBranch({
|
|
2456
3155
|
accessToken: this.accessToken,
|
|
2457
3156
|
repoUrl: this.url,
|
|
@@ -2459,10 +3158,7 @@ var GitlabSCMLib = class extends SCMLib {
|
|
|
2459
3158
|
});
|
|
2460
3159
|
}
|
|
2461
3160
|
async getUserHasAccessToRepo() {
|
|
2462
|
-
|
|
2463
|
-
console.error("no access token or no url");
|
|
2464
|
-
throw new Error("no access token or no url");
|
|
2465
|
-
}
|
|
3161
|
+
this._validateAccessTokenAndUrl();
|
|
2466
3162
|
const username = await this.getUsername();
|
|
2467
3163
|
return getGitlabIsUserCollaborator({
|
|
2468
3164
|
username,
|
|
@@ -2471,38 +3167,29 @@ var GitlabSCMLib = class extends SCMLib {
|
|
|
2471
3167
|
});
|
|
2472
3168
|
}
|
|
2473
3169
|
async getUsername() {
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
}
|
|
2480
|
-
async getSubmitRequestStatus(scmSubmitRequestId) {
|
|
2481
|
-
if (!this.accessToken || !this.url) {
|
|
2482
|
-
console.error("no access token or no url");
|
|
2483
|
-
throw new Error("no access token or no url");
|
|
2484
|
-
}
|
|
3170
|
+
this._validateAccessTokenAndUrl();
|
|
3171
|
+
return getGitlabUsername(this.url, this.accessToken);
|
|
3172
|
+
}
|
|
3173
|
+
async getSubmitRequestStatus(scmSubmitRequestId) {
|
|
3174
|
+
this._validateAccessTokenAndUrl();
|
|
2485
3175
|
const state = await getGitlabMergeRequestStatus({
|
|
2486
3176
|
accessToken: this.accessToken,
|
|
2487
3177
|
repoUrl: this.url,
|
|
2488
3178
|
mrNumber: Number(scmSubmitRequestId)
|
|
2489
3179
|
});
|
|
2490
3180
|
switch (state) {
|
|
2491
|
-
case
|
|
2492
|
-
return "
|
|
2493
|
-
case
|
|
2494
|
-
return "
|
|
2495
|
-
case
|
|
2496
|
-
return "
|
|
3181
|
+
case gitlabMergeRequestStatus.merged:
|
|
3182
|
+
return "merged";
|
|
3183
|
+
case gitlabMergeRequestStatus.opened:
|
|
3184
|
+
return "open";
|
|
3185
|
+
case gitlabMergeRequestStatus.closed:
|
|
3186
|
+
return "closed";
|
|
2497
3187
|
default:
|
|
2498
3188
|
throw new Error(`unknown state ${state}`);
|
|
2499
3189
|
}
|
|
2500
3190
|
}
|
|
2501
3191
|
async getRepoBlameRanges(ref, path9) {
|
|
2502
|
-
|
|
2503
|
-
console.error("no url");
|
|
2504
|
-
throw new Error("no url");
|
|
2505
|
-
}
|
|
3192
|
+
this._validateUrl();
|
|
2506
3193
|
return await getGitlabBlameRanges(
|
|
2507
3194
|
{ ref, path: path9, gitlabUrl: this.url },
|
|
2508
3195
|
{
|
|
@@ -2512,10 +3199,7 @@ var GitlabSCMLib = class extends SCMLib {
|
|
|
2512
3199
|
);
|
|
2513
3200
|
}
|
|
2514
3201
|
async getReferenceData(ref) {
|
|
2515
|
-
|
|
2516
|
-
console.error("no url");
|
|
2517
|
-
throw new Error("no url");
|
|
2518
|
-
}
|
|
3202
|
+
this._validateUrl();
|
|
2519
3203
|
return await getGitlabReferenceData(
|
|
2520
3204
|
{ ref, gitlabUrl: this.url },
|
|
2521
3205
|
{
|
|
@@ -2525,21 +3209,12 @@ var GitlabSCMLib = class extends SCMLib {
|
|
|
2525
3209
|
);
|
|
2526
3210
|
}
|
|
2527
3211
|
async getRepoDefaultBranch() {
|
|
2528
|
-
|
|
2529
|
-
console.error("no url");
|
|
2530
|
-
throw new Error("no url");
|
|
2531
|
-
}
|
|
3212
|
+
this._validateUrl();
|
|
2532
3213
|
return await getGitlabRepoDefaultBranch(this.url, {
|
|
2533
3214
|
url: this.url,
|
|
2534
3215
|
gitlabAuthToken: this.accessToken
|
|
2535
3216
|
});
|
|
2536
3217
|
}
|
|
2537
|
-
getPrComment(_commentId) {
|
|
2538
|
-
throw new Error("getPrComment not implemented.");
|
|
2539
|
-
}
|
|
2540
|
-
updatePrComment(_params, _oktokit) {
|
|
2541
|
-
throw new Error("updatePrComment not implemented.");
|
|
2542
|
-
}
|
|
2543
3218
|
async getPrUrl(prNumber) {
|
|
2544
3219
|
this._validateAccessTokenAndUrl();
|
|
2545
3220
|
const res = await getGitlabMergeRequest({
|
|
@@ -2549,15 +3224,6 @@ var GitlabSCMLib = class extends SCMLib {
|
|
|
2549
3224
|
});
|
|
2550
3225
|
return res.web_url;
|
|
2551
3226
|
}
|
|
2552
|
-
postGeneralPrComment() {
|
|
2553
|
-
throw new Error("Method not implemented.");
|
|
2554
|
-
}
|
|
2555
|
-
getGeneralPrComments() {
|
|
2556
|
-
throw new Error("Method not implemented.");
|
|
2557
|
-
}
|
|
2558
|
-
deleteGeneralPrComment() {
|
|
2559
|
-
throw new Error("Method not implemented.");
|
|
2560
|
-
}
|
|
2561
3227
|
};
|
|
2562
3228
|
var GithubSCMLib = class extends SCMLib {
|
|
2563
3229
|
// we don't always need a url, what's important is that we have an access token
|
|
@@ -2566,11 +3232,9 @@ var GithubSCMLib = class extends SCMLib {
|
|
|
2566
3232
|
__publicField(this, "oktokit");
|
|
2567
3233
|
this.oktokit = new Octokit2({ auth: accessToken });
|
|
2568
3234
|
}
|
|
2569
|
-
async createSubmitRequest(
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
throw new Error("no access token or no url");
|
|
2573
|
-
}
|
|
3235
|
+
async createSubmitRequest(params) {
|
|
3236
|
+
this._validateAccessTokenAndUrl();
|
|
3237
|
+
const { targetBranchName, sourceBranchName, title, body } = params;
|
|
2574
3238
|
return String(
|
|
2575
3239
|
await createPullRequest({
|
|
2576
3240
|
title,
|
|
@@ -2583,10 +3247,7 @@ var GithubSCMLib = class extends SCMLib {
|
|
|
2583
3247
|
);
|
|
2584
3248
|
}
|
|
2585
3249
|
async forkRepo(repoUrl) {
|
|
2586
|
-
|
|
2587
|
-
console.error("no access token");
|
|
2588
|
-
throw new Error("no access token");
|
|
2589
|
-
}
|
|
3250
|
+
this._validateToken();
|
|
2590
3251
|
return forkRepo({
|
|
2591
3252
|
repoUrl,
|
|
2592
3253
|
accessToken: this.accessToken
|
|
@@ -2692,7 +3353,7 @@ var GithubSCMLib = class extends SCMLib {
|
|
|
2692
3353
|
owner,
|
|
2693
3354
|
repo
|
|
2694
3355
|
});
|
|
2695
|
-
return
|
|
3356
|
+
return z9.string().parse(prRes.data);
|
|
2696
3357
|
}
|
|
2697
3358
|
async getRepoList(_scmOrg) {
|
|
2698
3359
|
if (!this.accessToken) {
|
|
@@ -2702,10 +3363,7 @@ var GithubSCMLib = class extends SCMLib {
|
|
|
2702
3363
|
return getGithubRepoList(this.accessToken);
|
|
2703
3364
|
}
|
|
2704
3365
|
async getBranchList() {
|
|
2705
|
-
|
|
2706
|
-
console.error("no access token or no url");
|
|
2707
|
-
throw new Error("no access token or no url");
|
|
2708
|
-
}
|
|
3366
|
+
this._validateAccessTokenAndUrl();
|
|
2709
3367
|
return getGithubBranchList(this.accessToken, this.url);
|
|
2710
3368
|
}
|
|
2711
3369
|
getScmLibType() {
|
|
@@ -2718,16 +3376,13 @@ var GithubSCMLib = class extends SCMLib {
|
|
|
2718
3376
|
return {};
|
|
2719
3377
|
}
|
|
2720
3378
|
getDownloadUrl(sha) {
|
|
2721
|
-
return `${this.url}/zipball/${sha}
|
|
3379
|
+
return Promise.resolve(`${this.url}/zipball/${sha}`);
|
|
2722
3380
|
}
|
|
2723
3381
|
async _getUsernameForAuthUrl() {
|
|
2724
3382
|
return this.getUsername();
|
|
2725
3383
|
}
|
|
2726
3384
|
async getIsRemoteBranch(branch) {
|
|
2727
|
-
|
|
2728
|
-
console.error("no access token or no url");
|
|
2729
|
-
throw new Error("no access token or no url");
|
|
2730
|
-
}
|
|
3385
|
+
this._validateAccessTokenAndUrl();
|
|
2731
3386
|
return getGithubIsRemoteBranch(this.accessToken, this.url, branch);
|
|
2732
3387
|
}
|
|
2733
3388
|
async getUserHasAccessToRepo() {
|
|
@@ -2755,25 +3410,10 @@ var GithubSCMLib = class extends SCMLib {
|
|
|
2755
3410
|
this.url,
|
|
2756
3411
|
Number(scmSubmitRequestId)
|
|
2757
3412
|
);
|
|
2758
|
-
|
|
2759
|
-
return "MERGED" /* MERGED */;
|
|
2760
|
-
}
|
|
2761
|
-
if (state === "open") {
|
|
2762
|
-
return "OPEN" /* OPEN */;
|
|
2763
|
-
}
|
|
2764
|
-
if (state === "draft") {
|
|
2765
|
-
return "DRAFT" /* DRAFT */;
|
|
2766
|
-
}
|
|
2767
|
-
if (state === "closed") {
|
|
2768
|
-
return "CLOSED" /* CLOSED */;
|
|
2769
|
-
}
|
|
2770
|
-
throw new Error(`unknown state ${state}`);
|
|
3413
|
+
return state;
|
|
2771
3414
|
}
|
|
2772
3415
|
async getRepoBlameRanges(ref, path9) {
|
|
2773
|
-
|
|
2774
|
-
console.error("no url");
|
|
2775
|
-
throw new Error("no url");
|
|
2776
|
-
}
|
|
3416
|
+
this._validateUrl();
|
|
2777
3417
|
return await getGithubBlameRanges(
|
|
2778
3418
|
{ ref, path: path9, gitHubUrl: this.url },
|
|
2779
3419
|
{
|
|
@@ -2782,10 +3422,7 @@ var GithubSCMLib = class extends SCMLib {
|
|
|
2782
3422
|
);
|
|
2783
3423
|
}
|
|
2784
3424
|
async getReferenceData(ref) {
|
|
2785
|
-
|
|
2786
|
-
console.error("no url");
|
|
2787
|
-
throw new Error("no url");
|
|
2788
|
-
}
|
|
3425
|
+
this._validateUrl();
|
|
2789
3426
|
return await getGithubReferenceData(
|
|
2790
3427
|
{ ref, gitHubUrl: this.url },
|
|
2791
3428
|
{
|
|
@@ -2794,10 +3431,7 @@ var GithubSCMLib = class extends SCMLib {
|
|
|
2794
3431
|
);
|
|
2795
3432
|
}
|
|
2796
3433
|
async getPrComment(commentId) {
|
|
2797
|
-
|
|
2798
|
-
console.error("no url");
|
|
2799
|
-
throw new Error("no url");
|
|
2800
|
-
}
|
|
3434
|
+
this._validateUrl();
|
|
2801
3435
|
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
2802
3436
|
return await getPrComment(this.oktokit, {
|
|
2803
3437
|
repo,
|
|
@@ -2806,10 +3440,7 @@ var GithubSCMLib = class extends SCMLib {
|
|
|
2806
3440
|
});
|
|
2807
3441
|
}
|
|
2808
3442
|
async getRepoDefaultBranch() {
|
|
2809
|
-
|
|
2810
|
-
console.error("no url");
|
|
2811
|
-
throw new Error("no url");
|
|
2812
|
-
}
|
|
3443
|
+
this._validateUrl();
|
|
2813
3444
|
return await getGithubRepoDefaultBranch(this.url, {
|
|
2814
3445
|
githubAuthToken: this.accessToken
|
|
2815
3446
|
});
|
|
@@ -2829,10 +3460,7 @@ var GithubSCMLib = class extends SCMLib {
|
|
|
2829
3460
|
}
|
|
2830
3461
|
async postGeneralPrComment(params, auth) {
|
|
2831
3462
|
const { prNumber, body } = params;
|
|
2832
|
-
|
|
2833
|
-
console.error("no url");
|
|
2834
|
-
throw new Error("no url");
|
|
2835
|
-
}
|
|
3463
|
+
this._validateUrl();
|
|
2836
3464
|
const oktoKit = auth ? new Octokit2({ auth: auth.authToken }) : this.oktokit;
|
|
2837
3465
|
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
2838
3466
|
return await postGeneralPrComment(oktoKit, {
|
|
@@ -2844,10 +3472,7 @@ var GithubSCMLib = class extends SCMLib {
|
|
|
2844
3472
|
}
|
|
2845
3473
|
async getGeneralPrComments(params, auth) {
|
|
2846
3474
|
const { prNumber } = params;
|
|
2847
|
-
|
|
2848
|
-
console.error("no url");
|
|
2849
|
-
throw new Error("no url");
|
|
2850
|
-
}
|
|
3475
|
+
this._validateUrl();
|
|
2851
3476
|
const oktoKit = auth ? new Octokit2({ auth: auth.authToken }) : this.oktokit;
|
|
2852
3477
|
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
2853
3478
|
return await getGeneralPrComments(oktoKit, {
|
|
@@ -2857,10 +3482,7 @@ var GithubSCMLib = class extends SCMLib {
|
|
|
2857
3482
|
});
|
|
2858
3483
|
}
|
|
2859
3484
|
async deleteGeneralPrComment({ commentId }, auth) {
|
|
2860
|
-
|
|
2861
|
-
console.error("no url");
|
|
2862
|
-
throw new Error("no url");
|
|
2863
|
-
}
|
|
3485
|
+
this._validateUrl();
|
|
2864
3486
|
const oktoKit = auth ? new Octokit2({ auth: auth.authToken }) : this.oktokit;
|
|
2865
3487
|
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
2866
3488
|
return deleteGeneralPrComment(oktoKit, {
|
|
@@ -2871,7 +3493,7 @@ var GithubSCMLib = class extends SCMLib {
|
|
|
2871
3493
|
}
|
|
2872
3494
|
};
|
|
2873
3495
|
var StubSCMLib = class extends SCMLib {
|
|
2874
|
-
async createSubmitRequest(
|
|
3496
|
+
async createSubmitRequest(_params) {
|
|
2875
3497
|
console.error("createSubmitRequest() not implemented");
|
|
2876
3498
|
throw new Error("createSubmitRequest() not implemented");
|
|
2877
3499
|
}
|
|
@@ -2887,10 +3509,6 @@ var StubSCMLib = class extends SCMLib {
|
|
|
2887
3509
|
console.error("getDownloadUrl() not implemented");
|
|
2888
3510
|
throw new Error("getDownloadUrl() not implemented");
|
|
2889
3511
|
}
|
|
2890
|
-
async _getUsernameForAuthUrl() {
|
|
2891
|
-
console.error("_getUsernameForAuthUrl() not implemented");
|
|
2892
|
-
throw new Error("_getUsernameForAuthUrl() not implemented");
|
|
2893
|
-
}
|
|
2894
3512
|
async getIsRemoteBranch(_branch) {
|
|
2895
3513
|
console.error("getIsRemoteBranch() not implemented");
|
|
2896
3514
|
throw new Error("getIsRemoteBranch() not implemented");
|
|
@@ -2899,18 +3517,6 @@ var StubSCMLib = class extends SCMLib {
|
|
|
2899
3517
|
console.error("validateParams() not implemented");
|
|
2900
3518
|
throw new Error("validateParams() not implemented");
|
|
2901
3519
|
}
|
|
2902
|
-
async forkRepo() {
|
|
2903
|
-
console.error("forkRepo() not implemented");
|
|
2904
|
-
throw new Error("forkRepo() not implemented");
|
|
2905
|
-
}
|
|
2906
|
-
async createOrUpdateRepositorySecret() {
|
|
2907
|
-
console.error("forkRepo() not implemented");
|
|
2908
|
-
throw new Error("forkRepo() not implemented");
|
|
2909
|
-
}
|
|
2910
|
-
async createPullRequestWithNewFile(_sourceRepoUrl, _filesPaths, _userRepoUrl, _title, _body) {
|
|
2911
|
-
console.error("createPullRequestWithNewFile() not implemented");
|
|
2912
|
-
throw new Error("createPullRequestWithNewFile() not implemented");
|
|
2913
|
-
}
|
|
2914
3520
|
async getRepoList(_scmOrg) {
|
|
2915
3521
|
console.error("getRepoList() not implemented");
|
|
2916
3522
|
throw new Error("getRepoList() not implemented");
|
|
@@ -2943,607 +3549,496 @@ var StubSCMLib = class extends SCMLib {
|
|
|
2943
3549
|
console.error("getRepoDefaultBranch() not implemented");
|
|
2944
3550
|
throw new Error("getRepoDefaultBranch() not implemented");
|
|
2945
3551
|
}
|
|
2946
|
-
async getPrComment(_commentId) {
|
|
2947
|
-
console.error("getPrComment() not implemented");
|
|
2948
|
-
throw new Error("getPrComment() not implemented");
|
|
2949
|
-
}
|
|
2950
|
-
async updatePrComment() {
|
|
2951
|
-
console.error("updatePrComment() not implemented");
|
|
2952
|
-
throw new Error("updatePrComment() not implemented");
|
|
2953
|
-
}
|
|
2954
3552
|
async getPrUrl(_prNumber) {
|
|
2955
3553
|
console.error("getPr() not implemented");
|
|
2956
3554
|
throw new Error("getPr() not implemented");
|
|
2957
3555
|
}
|
|
2958
|
-
|
|
2959
|
-
throw new Error("Method not implemented.");
|
|
2960
|
-
}
|
|
2961
|
-
getGeneralPrComments() {
|
|
2962
|
-
throw new Error("Method not implemented.");
|
|
2963
|
-
}
|
|
2964
|
-
deleteGeneralPrComment() {
|
|
3556
|
+
_getUsernameForAuthUrl() {
|
|
2965
3557
|
throw new Error("Method not implemented.");
|
|
2966
3558
|
}
|
|
2967
3559
|
};
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
return
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
const profileZ = z9.object({
|
|
2975
|
-
displayName: z9.string(),
|
|
2976
|
-
publicAlias: z9.string().min(1),
|
|
2977
|
-
emailAddress: z9.string(),
|
|
2978
|
-
coreRevision: z9.number(),
|
|
2979
|
-
timeStamp: z9.string(),
|
|
2980
|
-
id: z9.string(),
|
|
2981
|
-
revision: z9.number()
|
|
2982
|
-
});
|
|
2983
|
-
const accountsZ = z9.object({
|
|
2984
|
-
count: z9.number(),
|
|
2985
|
-
value: z9.array(
|
|
2986
|
-
z9.object({
|
|
2987
|
-
accountId: z9.string(),
|
|
2988
|
-
accountUri: z9.string(),
|
|
2989
|
-
accountName: z9.string()
|
|
2990
|
-
})
|
|
2991
|
-
)
|
|
2992
|
-
});
|
|
2993
|
-
const profileRes = await fetch(
|
|
2994
|
-
"https://app.vssps.visualstudio.com/_apis/profile/profiles/me?api-version=6.0",
|
|
2995
|
-
{
|
|
2996
|
-
method: "GET",
|
|
2997
|
-
headers: {
|
|
2998
|
-
Authorization: `Bearer ${oauthToken}`
|
|
2999
|
-
}
|
|
3000
|
-
}
|
|
3001
|
-
);
|
|
3002
|
-
const profileJson = await profileRes.json();
|
|
3003
|
-
const profile = profileZ.parse(profileJson);
|
|
3004
|
-
const accountsRes = await fetch(
|
|
3005
|
-
`https://app.vssps.visualstudio.com/_apis/accounts?memberId=${profile.publicAlias}&api-version=6.0`,
|
|
3006
|
-
{
|
|
3007
|
-
method: "GET",
|
|
3008
|
-
headers: {
|
|
3009
|
-
Authorization: `Bearer ${oauthToken}`
|
|
3010
|
-
}
|
|
3011
|
-
}
|
|
3012
|
-
);
|
|
3013
|
-
const accountsJson = await accountsRes.json();
|
|
3014
|
-
const accounts = accountsZ.parse(accountsJson);
|
|
3015
|
-
const orgs = accounts.value.map((account) => account.accountName).filter((value, index, array) => array.indexOf(value) === index);
|
|
3016
|
-
return orgs;
|
|
3017
|
-
}
|
|
3018
|
-
function _getPublicAdoClient({ orgName }) {
|
|
3019
|
-
const orgUrl = `https://dev.azure.com/${orgName}`;
|
|
3020
|
-
const authHandler = api.getPersonalAccessTokenHandler("");
|
|
3021
|
-
authHandler.canHandleAuthentication = () => false;
|
|
3022
|
-
authHandler.prepareRequest = (_options) => {
|
|
3023
|
-
return;
|
|
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
|
|
3024
3566
|
};
|
|
3025
|
-
const connection = new api.WebApi(orgUrl, authHandler);
|
|
3026
|
-
return connection;
|
|
3027
|
-
}
|
|
3028
|
-
function getAdoTokenType(token) {
|
|
3029
|
-
if (token.includes(".")) {
|
|
3030
|
-
return "OAUTH" /* OAUTH */;
|
|
3031
|
-
}
|
|
3032
|
-
return "PAT" /* PAT */;
|
|
3033
3567
|
}
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
orgName
|
|
3038
|
-
}) {
|
|
3039
|
-
if (!accessToken || tokenOrg && tokenOrg !== orgName) {
|
|
3040
|
-
return _getPublicAdoClient({ orgName });
|
|
3041
|
-
}
|
|
3042
|
-
const orgUrl = `https://dev.azure.com/${orgName}`;
|
|
3043
|
-
if (getAdoTokenType(accessToken) === "OAUTH" /* OAUTH */) {
|
|
3044
|
-
const connection2 = new api.WebApi(orgUrl, api.getBearerHandler(accessToken));
|
|
3045
|
-
return connection2;
|
|
3568
|
+
function createBitbucketSdk(token) {
|
|
3569
|
+
if (!token) {
|
|
3570
|
+
return getBitbucketSdk({ authType: "public" });
|
|
3046
3571
|
}
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
accessToken,
|
|
3054
|
-
tokenOrg
|
|
3055
|
-
}) {
|
|
3056
|
-
try {
|
|
3057
|
-
if (!url && accessToken && getAdoTokenType(accessToken) === "OAUTH" /* OAUTH */) {
|
|
3058
|
-
await _getOrgsForOauthToken({ oauthToken: accessToken });
|
|
3059
|
-
return;
|
|
3060
|
-
}
|
|
3061
|
-
let org = tokenOrg;
|
|
3062
|
-
if (url) {
|
|
3063
|
-
const { owner } = parseAdoOwnerAndRepo(url);
|
|
3064
|
-
org = owner;
|
|
3065
|
-
}
|
|
3066
|
-
if (!org) {
|
|
3067
|
-
throw new InvalidRepoUrlError(`invalid ADO ORG ${org}`);
|
|
3068
|
-
}
|
|
3069
|
-
const api2 = await getAdoApiClient({
|
|
3070
|
-
accessToken,
|
|
3071
|
-
tokenOrg,
|
|
3072
|
-
orgName: org
|
|
3572
|
+
if (token.includes(":")) {
|
|
3573
|
+
const { password, username } = getUserAndPassword(token);
|
|
3574
|
+
return getBitbucketSdk({
|
|
3575
|
+
authType: "basic",
|
|
3576
|
+
username,
|
|
3577
|
+
password
|
|
3073
3578
|
});
|
|
3074
|
-
await api2.connect();
|
|
3075
|
-
} catch (e) {
|
|
3076
|
-
const error = e;
|
|
3077
|
-
const code = error.code || error.status || error.statusCode || error.response?.status || error.response?.statusCode || error.response?.code;
|
|
3078
|
-
const description = error.description || `${e}`;
|
|
3079
|
-
if (code === 401 || code === 403 || description.includes("401") || description.includes("403")) {
|
|
3080
|
-
throw new InvalidAccessTokenError(`invalid ADO access token`);
|
|
3081
|
-
}
|
|
3082
|
-
if (code === 404 || description.includes("404") || description.includes("Not Found")) {
|
|
3083
|
-
throw new InvalidRepoUrlError(`invalid ADO repo URL ${url}`);
|
|
3084
|
-
}
|
|
3085
|
-
throw e;
|
|
3086
3579
|
}
|
|
3580
|
+
return getBitbucketSdk({ authType: "token", token });
|
|
3087
3581
|
}
|
|
3088
|
-
|
|
3089
|
-
accessToken,
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
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 };
|
|
3596
|
+
}
|
|
3597
|
+
case "token": {
|
|
3598
|
+
return { authType, token: z9.string().parse(this.accessToken) };
|
|
3599
|
+
}
|
|
3600
|
+
case "public":
|
|
3601
|
+
return { authType };
|
|
3104
3602
|
}
|
|
3105
|
-
return true;
|
|
3106
|
-
} catch (e) {
|
|
3107
|
-
return false;
|
|
3108
3603
|
}
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
async function getAdoPullRequestStatus({
|
|
3117
|
-
accessToken,
|
|
3118
|
-
tokenOrg,
|
|
3119
|
-
repoUrl,
|
|
3120
|
-
prNumber
|
|
3121
|
-
}) {
|
|
3122
|
-
const { owner, repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
|
|
3123
|
-
const api2 = await getAdoApiClient({
|
|
3124
|
-
accessToken,
|
|
3125
|
-
tokenOrg,
|
|
3126
|
-
orgName: owner
|
|
3127
|
-
});
|
|
3128
|
-
const git = await api2.getGitApi();
|
|
3129
|
-
const res = await git.getPullRequest(repo, prNumber, projectName);
|
|
3130
|
-
if (!res.status || res.status < 1 || res.status > 3) {
|
|
3131
|
-
throw new Error("bad pr status for ADO");
|
|
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));
|
|
3132
3611
|
}
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3612
|
+
async validateParams() {
|
|
3613
|
+
return validateBitbucketParams({
|
|
3614
|
+
bitbucketClient: this.bitbucketSdk,
|
|
3615
|
+
url: this.url
|
|
3616
|
+
});
|
|
3617
|
+
}
|
|
3618
|
+
async getRepoList(scmOrg) {
|
|
3619
|
+
this._validateToken();
|
|
3620
|
+
return this.bitbucketSdk.getRepos({
|
|
3621
|
+
workspaceSlug: scmOrg
|
|
3622
|
+
});
|
|
3623
|
+
}
|
|
3624
|
+
async getBranchList() {
|
|
3625
|
+
this._validateAccessTokenAndUrl();
|
|
3626
|
+
return this.bitbucketSdk.getBranchList({
|
|
3627
|
+
repoUrl: this.url
|
|
3628
|
+
});
|
|
3629
|
+
}
|
|
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
|
+
}
|
|
3152
3649
|
}
|
|
3153
|
-
return branchStatus.name === branch;
|
|
3154
|
-
} catch (e) {
|
|
3155
|
-
return false;
|
|
3156
3650
|
}
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
tokenOrg,
|
|
3161
|
-
accessToken
|
|
3162
|
-
}) {
|
|
3163
|
-
let orgs = [];
|
|
3164
|
-
if (getAdoTokenType(accessToken) === "OAUTH" /* OAUTH */) {
|
|
3165
|
-
orgs = await _getOrgsForOauthToken({ oauthToken: accessToken });
|
|
3651
|
+
async getDownloadUrl(sha) {
|
|
3652
|
+
this._validateUrl();
|
|
3653
|
+
return this.bitbucketSdk.getDownloadUrl({ url: this.url, sha });
|
|
3166
3654
|
}
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
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;
|
|
3171
3662
|
}
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
|
|
3663
|
+
async getIsRemoteBranch(branch) {
|
|
3664
|
+
this._validateAccessTokenAndUrl();
|
|
3665
|
+
try {
|
|
3666
|
+
const res = await this.bitbucketSdk.getBranch({
|
|
3667
|
+
branchName: branch,
|
|
3668
|
+
repoUrl: this.url
|
|
3178
3669
|
});
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
orgRepos.map(async (repo) => {
|
|
3183
|
-
if (!repo.name || !repo.remoteUrl || !repo.defaultBranch) {
|
|
3184
|
-
throw new InvalidRepoUrlError("bad repo");
|
|
3185
|
-
}
|
|
3186
|
-
const branch = await gitOrg.getBranch(
|
|
3187
|
-
repo.name,
|
|
3188
|
-
repo.defaultBranch.replace(/^refs\/heads\//, ""),
|
|
3189
|
-
repo.project?.name
|
|
3190
|
-
);
|
|
3191
|
-
return {
|
|
3192
|
-
repoName: repo.name,
|
|
3193
|
-
repoUrl: repo.remoteUrl.replace(
|
|
3194
|
-
/^[hH][tT][tT][pP][sS]:\/\/[^/]+@/,
|
|
3195
|
-
"https://"
|
|
3196
|
-
),
|
|
3197
|
-
repoOwner: org,
|
|
3198
|
-
repoIsPublic: repo.project?.visibility === 2,
|
|
3199
|
-
//2 is public in the ADO API
|
|
3200
|
-
repoLanguages: [],
|
|
3201
|
-
repoUpdatedAt: branch.commit?.committer?.date?.toDateString() || repo.project?.lastUpdateTime?.toDateString() || (/* @__PURE__ */ new Date()).toDateString()
|
|
3202
|
-
};
|
|
3203
|
-
})
|
|
3204
|
-
)).reduce((acc, res) => {
|
|
3205
|
-
if (res.status === "fulfilled") {
|
|
3206
|
-
acc.push(res.value);
|
|
3207
|
-
}
|
|
3208
|
-
return acc;
|
|
3209
|
-
}, []);
|
|
3210
|
-
return repoInfoList;
|
|
3211
|
-
})
|
|
3212
|
-
)).reduce((acc, res) => {
|
|
3213
|
-
if (res.status === "fulfilled") {
|
|
3214
|
-
return acc.concat(res.value);
|
|
3670
|
+
return res.name === branch;
|
|
3671
|
+
} catch (e) {
|
|
3672
|
+
return false;
|
|
3215
3673
|
}
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
}
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
}
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
const url = new URL(repoUrl);
|
|
3232
|
-
const origin = url.origin.toLowerCase().endsWith(".visualstudio.com") ? "https://dev.azure.com" : url.origin.toLowerCase();
|
|
3233
|
-
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`;
|
|
3234
|
-
}
|
|
3235
|
-
async function getAdoBranchList({
|
|
3236
|
-
accessToken,
|
|
3237
|
-
tokenOrg,
|
|
3238
|
-
repoUrl
|
|
3239
|
-
}) {
|
|
3240
|
-
const { owner, repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
|
|
3241
|
-
const api2 = await getAdoApiClient({
|
|
3242
|
-
accessToken,
|
|
3243
|
-
tokenOrg,
|
|
3244
|
-
orgName: owner
|
|
3245
|
-
});
|
|
3246
|
-
const git = await api2.getGitApi();
|
|
3247
|
-
try {
|
|
3248
|
-
const res = await git.getBranches(repo, projectName);
|
|
3249
|
-
res.sort((a, b) => {
|
|
3250
|
-
if (!a.commit?.committer?.date || !b.commit?.committer?.date) {
|
|
3251
|
-
return 0;
|
|
3252
|
-
}
|
|
3253
|
-
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
|
|
3254
3689
|
});
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
return
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
|
|
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) {
|
|
3263
3702
|
return [];
|
|
3264
3703
|
}
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
const api2 = await getAdoApiClient({
|
|
3269
|
-
accessToken: options.accessToken,
|
|
3270
|
-
tokenOrg: options.tokenOrg,
|
|
3271
|
-
orgName: owner
|
|
3272
|
-
});
|
|
3273
|
-
const git = await api2.getGitApi();
|
|
3274
|
-
const res = await git.createPullRequest(
|
|
3275
|
-
{
|
|
3276
|
-
sourceRefName: `refs/heads/${options.sourceBranchName}`,
|
|
3277
|
-
targetRefName: `refs/heads/${options.targetBranchName}`,
|
|
3278
|
-
title: options.title,
|
|
3279
|
-
description: options.body
|
|
3280
|
-
},
|
|
3281
|
-
repo,
|
|
3282
|
-
projectName
|
|
3283
|
-
);
|
|
3284
|
-
return res.pullRequestId;
|
|
3285
|
-
}
|
|
3286
|
-
async function getAdoRepoDefaultBranch({
|
|
3287
|
-
repoUrl,
|
|
3288
|
-
tokenOrg,
|
|
3289
|
-
accessToken
|
|
3290
|
-
}) {
|
|
3291
|
-
const { owner, repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
|
|
3292
|
-
const api2 = await getAdoApiClient({
|
|
3293
|
-
accessToken,
|
|
3294
|
-
tokenOrg,
|
|
3295
|
-
orgName: owner
|
|
3296
|
-
});
|
|
3297
|
-
const git = await api2.getGitApi();
|
|
3298
|
-
const branches = await git.getBranches(repo, projectName);
|
|
3299
|
-
if (!branches || branches.length === 0) {
|
|
3300
|
-
throw new InvalidRepoUrlError("no branches");
|
|
3704
|
+
async getReferenceData(ref) {
|
|
3705
|
+
this._validateUrl();
|
|
3706
|
+
return this.bitbucketSdk.getReferenceData({ url: this.url, ref });
|
|
3301
3707
|
}
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3708
|
+
async getRepoDefaultBranch() {
|
|
3709
|
+
this._validateUrl();
|
|
3710
|
+
const repoRes = await this.bitbucketSdk.getRepo({ repoUrl: this.url });
|
|
3711
|
+
return z9.string().parse(repoRes.mainbranch?.name);
|
|
3305
3712
|
}
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
tokenOrg
|
|
3313
|
-
}) {
|
|
3314
|
-
const { owner, repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
|
|
3315
|
-
const api2 = await getAdoApiClient({
|
|
3316
|
-
accessToken,
|
|
3317
|
-
tokenOrg,
|
|
3318
|
-
orgName: owner
|
|
3319
|
-
});
|
|
3320
|
-
if (!projectName) {
|
|
3321
|
-
throw new InvalidUrlPatternError("no project name");
|
|
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
|
+
);
|
|
3322
3719
|
}
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
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
|
+
};
|
|
3763
|
+
}
|
|
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
|
|
3349
3779
|
}
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
|
|
3780
|
+
)
|
|
3781
|
+
});
|
|
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
|
+
});
|
|
3798
|
+
}
|
|
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
|
|
3823
|
+
);
|
|
3824
|
+
const res = await bitbucketClient.refs.listBranches({
|
|
3825
|
+
repo_slug: repoSlug,
|
|
3826
|
+
workspace
|
|
3827
|
+
});
|
|
3828
|
+
if (!res.data.values) {
|
|
3829
|
+
return [];
|
|
3360
3830
|
}
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
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
|
+
}
|
|
3366
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
|
+
]);
|
|
3367
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;
|
|
3368
3933
|
}
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
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
|
|
3377
3974
|
);
|
|
3378
|
-
const
|
|
3379
|
-
|
|
3380
|
-
|
|
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);
|
|
3381
4005
|
}
|
|
3382
|
-
|
|
3383
|
-
|
|
3384
|
-
type: "TAG" /* TAG */,
|
|
3385
|
-
date: commit.committer?.date || /* @__PURE__ */ new Date()
|
|
3386
|
-
};
|
|
3387
|
-
})()
|
|
3388
|
-
]);
|
|
3389
|
-
const [branchRes, commitRes, tagRes] = results;
|
|
3390
|
-
if (tagRes.status === "fulfilled") {
|
|
3391
|
-
return tagRes.value;
|
|
3392
|
-
}
|
|
3393
|
-
if (branchRes.status === "fulfilled") {
|
|
3394
|
-
return branchRes.value;
|
|
3395
|
-
}
|
|
3396
|
-
if (commitRes.status === "fulfilled") {
|
|
3397
|
-
return commitRes.value;
|
|
4006
|
+
}
|
|
4007
|
+
throw e;
|
|
3398
4008
|
}
|
|
3399
|
-
throw new RefNotFoundError(`ref: ${ref} does not exist`);
|
|
3400
4009
|
}
|
|
3401
|
-
function
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
|
|
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 [];
|
|
3406
4018
|
}
|
|
3407
|
-
const
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
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;
|
|
3415
4030
|
}
|
|
3416
|
-
async function
|
|
3417
|
-
|
|
4031
|
+
async function getRepositoriesByWorkspace(bitbucketClient, { workspaceSlug }) {
|
|
4032
|
+
const res = await bitbucketClient.repositories.list({
|
|
4033
|
+
workspace: workspaceSlug
|
|
4034
|
+
});
|
|
4035
|
+
return res.data.values ?? [];
|
|
3418
4036
|
}
|
|
3419
|
-
var AdoAuthResultZ = z9.object({
|
|
3420
|
-
access_token: z9.string().min(1),
|
|
3421
|
-
token_type: z9.string().min(1),
|
|
3422
|
-
refresh_token: z9.string().min(1)
|
|
3423
|
-
});
|
|
3424
4037
|
|
|
3425
4038
|
// src/features/analysis/scm/constants.ts
|
|
3426
4039
|
var MOBB_ICON_IMG = "https://app.mobb.ai/gh-action/Logo_Rounded_Icon.svg";
|
|
3427
4040
|
var COMMIT_FIX_SVG = `https://app.mobb.ai/gh-action/commit-button.svg`;
|
|
3428
4041
|
|
|
3429
|
-
// src/features/analysis/scm/utils/get_issue_type.ts
|
|
3430
|
-
var getIssueType = (issueType) => {
|
|
3431
|
-
switch (issueType) {
|
|
3432
|
-
case "SQL_Injection" /* SqlInjection */:
|
|
3433
|
-
return "SQL Injection";
|
|
3434
|
-
case "CMDi_relative_path_command" /* CmDiRelativePathCommand */:
|
|
3435
|
-
return "Relative Path Command Injection";
|
|
3436
|
-
case "CMDi" /* CmDi */:
|
|
3437
|
-
return "Command Injection";
|
|
3438
|
-
case "XXE" /* Xxe */:
|
|
3439
|
-
return "XXE";
|
|
3440
|
-
case "XSS" /* Xss */:
|
|
3441
|
-
return "XSS";
|
|
3442
|
-
case "PT" /* Pt */:
|
|
3443
|
-
return "Path Traversal";
|
|
3444
|
-
case "ZIP_SLIP" /* ZipSlip */:
|
|
3445
|
-
return "Zip Slip";
|
|
3446
|
-
case "INSECURE_RANDOMNESS" /* InsecureRandomness */:
|
|
3447
|
-
return "Insecure Randomness";
|
|
3448
|
-
case "SSRF" /* Ssrf */:
|
|
3449
|
-
return "Server Side Request Forgery";
|
|
3450
|
-
case "TYPE_CONFUSION" /* TypeConfusion */:
|
|
3451
|
-
return "Type Confusion";
|
|
3452
|
-
case "REGEX_INJECTION" /* RegexInjection */:
|
|
3453
|
-
return "Regular Expression Injection";
|
|
3454
|
-
case "INCOMPLETE_URL_SANITIZATION" /* IncompleteUrlSanitization */:
|
|
3455
|
-
return "Incomplete URL Sanitization";
|
|
3456
|
-
case "LOG_FORGING" /* LogForging */:
|
|
3457
|
-
return "Log Forging";
|
|
3458
|
-
case "LOCALE_DEPENDENT_COMPARISON" /* LocaleDependentComparison */:
|
|
3459
|
-
return "Locale Dependent Comparison";
|
|
3460
|
-
case "MISSING_CHECK_AGAINST_NULL" /* MissingCheckAgainstNull */:
|
|
3461
|
-
return "Missing Check against Null";
|
|
3462
|
-
case "PASSWORD_IN_COMMENT" /* PasswordInComment */:
|
|
3463
|
-
return "Password in Comment";
|
|
3464
|
-
case "OVERLY_BROAD_CATCH" /* OverlyBroadCatch */:
|
|
3465
|
-
return "Poor Error Handling: Overly Broad Catch";
|
|
3466
|
-
case "USE_OF_SYSTEM_OUTPUT_STREAM" /* UseOfSystemOutputStream */:
|
|
3467
|
-
return "Use of System.out/System.err";
|
|
3468
|
-
case "DANGEROUS_FUNCTION_OVERFLOW" /* DangerousFunctionOverflow */:
|
|
3469
|
-
return "Use of dangerous function";
|
|
3470
|
-
case "DOS_STRING_BUILDER" /* DosStringBuilder */:
|
|
3471
|
-
return "Denial of Service: StringBuilder";
|
|
3472
|
-
case "OPEN_REDIRECT" /* OpenRedirect */:
|
|
3473
|
-
return "Open Redirect";
|
|
3474
|
-
case "WEAK_XML_SCHEMA_UNBOUNDED_OCCURRENCES" /* WeakXmlSchemaUnboundedOccurrences */:
|
|
3475
|
-
return "Weak XML Schema: Unbounded Occurrences";
|
|
3476
|
-
case "SYSTEM_INFORMATION_LEAK" /* SystemInformationLeak */:
|
|
3477
|
-
return "System Information Leak";
|
|
3478
|
-
case "HTTP_RESPONSE_SPLITTING" /* HttpResponseSplitting */:
|
|
3479
|
-
return "HTTP response splitting";
|
|
3480
|
-
case "HTTP_ONLY_COOKIE" /* HttpOnlyCookie */:
|
|
3481
|
-
return "Cookie is not HttpOnly";
|
|
3482
|
-
case "INSECURE_COOKIE" /* InsecureCookie */:
|
|
3483
|
-
return "Insecure Cookie";
|
|
3484
|
-
case "TRUST_BOUNDARY_VIOLATION" /* TrustBoundaryViolation */:
|
|
3485
|
-
return "Trust Boundary Violation";
|
|
3486
|
-
case "MISSING_EQUALS_OR_HASHCODE" /* MissingEqualsOrHashcode */:
|
|
3487
|
-
return "Missing equals or hashcode method";
|
|
3488
|
-
default: {
|
|
3489
|
-
return issueType ? issueType.replaceAll("_", " ") : "Other";
|
|
3490
|
-
}
|
|
3491
|
-
}
|
|
3492
|
-
};
|
|
3493
|
-
|
|
3494
|
-
// src/features/analysis/scm/utils/index.ts
|
|
3495
|
-
function getFixUrlWithRedirect(params) {
|
|
3496
|
-
const {
|
|
3497
|
-
fixId,
|
|
3498
|
-
projectId,
|
|
3499
|
-
organizationId,
|
|
3500
|
-
analysisId,
|
|
3501
|
-
redirectUrl,
|
|
3502
|
-
appBaseUrl,
|
|
3503
|
-
commentId
|
|
3504
|
-
} = params;
|
|
3505
|
-
const searchParams = new URLSearchParams();
|
|
3506
|
-
searchParams.append("commit_redirect_url", redirectUrl);
|
|
3507
|
-
searchParams.append("comment_id", commentId.toString());
|
|
3508
|
-
return `${getFixUrl({
|
|
3509
|
-
appBaseUrl,
|
|
3510
|
-
fixId,
|
|
3511
|
-
projectId,
|
|
3512
|
-
organizationId,
|
|
3513
|
-
analysisId
|
|
3514
|
-
})}?${searchParams.toString()}`;
|
|
3515
|
-
}
|
|
3516
|
-
function getFixUrl({
|
|
3517
|
-
appBaseUrl,
|
|
3518
|
-
fixId,
|
|
3519
|
-
projectId,
|
|
3520
|
-
organizationId,
|
|
3521
|
-
analysisId
|
|
3522
|
-
}) {
|
|
3523
|
-
return `${appBaseUrl}/organization/${organizationId}/project/${projectId}/report/${analysisId}/fix/${fixId}`;
|
|
3524
|
-
}
|
|
3525
|
-
function getCommitUrl(params) {
|
|
3526
|
-
const {
|
|
3527
|
-
fixId,
|
|
3528
|
-
projectId,
|
|
3529
|
-
organizationId,
|
|
3530
|
-
analysisId,
|
|
3531
|
-
redirectUrl,
|
|
3532
|
-
appBaseUrl,
|
|
3533
|
-
commentId
|
|
3534
|
-
} = params;
|
|
3535
|
-
const searchParams = new URLSearchParams();
|
|
3536
|
-
searchParams.append("redirect_url", redirectUrl);
|
|
3537
|
-
searchParams.append("comment_id", commentId.toString());
|
|
3538
|
-
return `${getFixUrl({
|
|
3539
|
-
appBaseUrl,
|
|
3540
|
-
fixId,
|
|
3541
|
-
projectId,
|
|
3542
|
-
organizationId,
|
|
3543
|
-
analysisId
|
|
3544
|
-
})}/commit?${searchParams.toString()}`;
|
|
3545
|
-
}
|
|
3546
|
-
|
|
3547
4042
|
// src/features/analysis/utils/by_key.ts
|
|
3548
4043
|
function keyBy(array, keyBy2) {
|
|
3549
4044
|
return array.reduce((acc, item) => {
|
|
@@ -3613,6 +4108,16 @@ async function sendReport({
|
|
|
3613
4108
|
}
|
|
3614
4109
|
}
|
|
3615
4110
|
|
|
4111
|
+
// src/features/analysis/utils/index.ts
|
|
4112
|
+
function getFromArraySafe(array) {
|
|
4113
|
+
return array.reduce((acc, nullableItem) => {
|
|
4114
|
+
if (nullableItem) {
|
|
4115
|
+
acc.push(nullableItem);
|
|
4116
|
+
}
|
|
4117
|
+
return acc;
|
|
4118
|
+
}, []);
|
|
4119
|
+
}
|
|
4120
|
+
|
|
3616
4121
|
// src/features/analysis/handle_finished_analysis.ts
|
|
3617
4122
|
var debug5 = Debug5("mobbdev:handle-finished-analysis");
|
|
3618
4123
|
var contactUsMarkdown = `For specific requests [contact us](https://mobb.ai/contact) and we'll do the most to answer your need quickly.`;
|
|
@@ -3641,7 +4146,7 @@ async function getRelevantVulenrabilitiesFromDiff(params) {
|
|
|
3641
4146
|
});
|
|
3642
4147
|
const lineAddedRanges = calculateRanges(fileNumbers);
|
|
3643
4148
|
const fileFilter = {
|
|
3644
|
-
path:
|
|
4149
|
+
path: z11.string().parse(file.to),
|
|
3645
4150
|
ranges: lineAddedRanges.map(([startLine, endLine]) => ({
|
|
3646
4151
|
endLine,
|
|
3647
4152
|
startLine
|
|
@@ -4439,9 +4944,7 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
4439
4944
|
apiKey: apiKey || config2.get("apiToken")
|
|
4440
4945
|
});
|
|
4441
4946
|
await handleMobbLogin();
|
|
4442
|
-
const { projectId, organizationId } = await gqlClient.getOrgAndProjectId(
|
|
4443
|
-
mobbProjectName
|
|
4444
|
-
);
|
|
4947
|
+
const { projectId, organizationId } = await gqlClient.getOrgAndProjectId(mobbProjectName);
|
|
4445
4948
|
const {
|
|
4446
4949
|
uploadS3BucketInfo: { repoUploadInfo, reportUploadInfo }
|
|
4447
4950
|
} = await gqlClient.uploadS3BucketInfo();
|
|
@@ -4456,12 +4959,10 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
4456
4959
|
throw new Error("repo is required in case srcPath is not provided");
|
|
4457
4960
|
}
|
|
4458
4961
|
const userInfo = await gqlClient.getUserInfo();
|
|
4459
|
-
|
|
4460
|
-
|
|
4461
|
-
if (scmConfig?.__typename === "ScmConfig") {
|
|
4462
|
-
scmConfigs.push(scmConfig);
|
|
4463
|
-
}
|
|
4962
|
+
if (!userInfo) {
|
|
4963
|
+
throw new Error("userInfo is null");
|
|
4464
4964
|
}
|
|
4965
|
+
const scmConfigs = getFromArraySafe(userInfo.scmConfigs);
|
|
4465
4966
|
const tokenInfo = getScmConfig({
|
|
4466
4967
|
url: repo,
|
|
4467
4968
|
scmConfigs,
|
|
@@ -4506,6 +5007,7 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
4506
5007
|
});
|
|
4507
5008
|
const reference = ref ?? await scm.getRepoDefaultBranch();
|
|
4508
5009
|
const { sha } = await scm.getReferenceData(reference);
|
|
5010
|
+
const downloadUrl = await scm.getDownloadUrl(sha);
|
|
4509
5011
|
debug10("org id %s", organizationId);
|
|
4510
5012
|
debug10("project id %s", projectId);
|
|
4511
5013
|
debug10("default branch %s", reference);
|
|
@@ -4514,7 +5016,7 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
4514
5016
|
dirname,
|
|
4515
5017
|
ci,
|
|
4516
5018
|
authHeaders: scm.getAuthHeaders(),
|
|
4517
|
-
downloadUrl
|
|
5019
|
+
downloadUrl
|
|
4518
5020
|
});
|
|
4519
5021
|
if (command === "scan") {
|
|
4520
5022
|
reportPath = await getReport(SupportedScannersZ.parse(scanner));
|
|
@@ -4541,7 +5043,7 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
4541
5043
|
spinner: mobbSpinner,
|
|
4542
5044
|
submitVulnerabilityReportVariables: {
|
|
4543
5045
|
fixReportId: reportUploadInfo.fixReportId,
|
|
4544
|
-
repoUrl:
|
|
5046
|
+
repoUrl: z12.string().parse(repo),
|
|
4545
5047
|
reference,
|
|
4546
5048
|
projectId,
|
|
4547
5049
|
vulnerabilityReportFileName: "report.json",
|
|
@@ -4563,8 +5065,8 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
4563
5065
|
analysisId,
|
|
4564
5066
|
gqlClient,
|
|
4565
5067
|
scm,
|
|
4566
|
-
githubActionToken:
|
|
4567
|
-
scanner:
|
|
5068
|
+
githubActionToken: z12.string().parse(githubActionToken),
|
|
5069
|
+
scanner: z12.nativeEnum(SCANNERS).parse(scanner)
|
|
4568
5070
|
}),
|
|
4569
5071
|
callbackStates: ["Finished" /* Finished */]
|
|
4570
5072
|
});
|
|
@@ -4693,12 +5195,10 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
4693
5195
|
await open2(scmAuthUrl2);
|
|
4694
5196
|
for (let i = 0; i < LOGIN_MAX_WAIT / LOGIN_CHECK_DELAY; i++) {
|
|
4695
5197
|
const userInfo2 = await gqlClient.getUserInfo();
|
|
4696
|
-
|
|
4697
|
-
|
|
4698
|
-
if (scmConfig?.__typename === "ScmConfig") {
|
|
4699
|
-
scmConfigs2.push(scmConfig);
|
|
4700
|
-
}
|
|
5198
|
+
if (!userInfo2) {
|
|
5199
|
+
throw new CliError2("User info not found");
|
|
4701
5200
|
}
|
|
5201
|
+
const scmConfigs2 = getFromArraySafe(userInfo2.scmConfigs);
|
|
4702
5202
|
const tokenInfo2 = getScmConfig({
|
|
4703
5203
|
url: repoUrl,
|
|
4704
5204
|
scmConfigs: scmConfigs2,
|
|
@@ -4974,21 +5474,22 @@ var commitHashOption = {
|
|
|
4974
5474
|
};
|
|
4975
5475
|
var scmTypeOption = {
|
|
4976
5476
|
demandOption: true,
|
|
4977
|
-
describe: chalk5.bold("SCM type (GitHub, GitLab, Ado)"),
|
|
5477
|
+
describe: chalk5.bold("SCM type (GitHub, GitLab, Ado, Bitbucket)"),
|
|
4978
5478
|
type: "string"
|
|
4979
5479
|
};
|
|
4980
5480
|
var urlOption = {
|
|
4981
5481
|
describe: chalk5.bold(
|
|
4982
|
-
"URL of the repository (used in GitHub, GitLab, Azure DevOps)"
|
|
5482
|
+
"URL of the repository (used in GitHub, GitLab, Azure DevOps, Bitbucket)"
|
|
4983
5483
|
),
|
|
4984
|
-
type: "string"
|
|
5484
|
+
type: "string",
|
|
5485
|
+
demandOption: true
|
|
4985
5486
|
};
|
|
4986
5487
|
var scmOrgOption = {
|
|
4987
5488
|
describe: chalk5.bold("Organization name in SCM (used in Azure DevOps)"),
|
|
4988
5489
|
type: "string"
|
|
4989
5490
|
};
|
|
4990
5491
|
var scmUsernameOption = {
|
|
4991
|
-
describe: chalk5.bold("Username in SCM (used in GitHub)"),
|
|
5492
|
+
describe: chalk5.bold("Username in SCM (used in GitHub, Bitbucket)"),
|
|
4992
5493
|
type: "string"
|
|
4993
5494
|
};
|
|
4994
5495
|
var scmRefreshTokenOption = {
|
|
@@ -4997,13 +5498,14 @@ var scmRefreshTokenOption = {
|
|
|
4997
5498
|
};
|
|
4998
5499
|
var scmTokenOption = {
|
|
4999
5500
|
describe: chalk5.bold("SCM API token"),
|
|
5000
|
-
type: "string"
|
|
5501
|
+
type: "string",
|
|
5502
|
+
demandOption: true
|
|
5001
5503
|
};
|
|
5002
5504
|
|
|
5003
5505
|
// src/args/validation.ts
|
|
5004
5506
|
import chalk6 from "chalk";
|
|
5005
5507
|
import path8 from "path";
|
|
5006
|
-
import { z as
|
|
5508
|
+
import { z as z13 } from "zod";
|
|
5007
5509
|
function throwRepoUrlErrorMessage({
|
|
5008
5510
|
error,
|
|
5009
5511
|
repoUrl,
|
|
@@ -5020,7 +5522,7 @@ Example:
|
|
|
5020
5522
|
)}`;
|
|
5021
5523
|
throw new CliError(formattedErrorMessage);
|
|
5022
5524
|
}
|
|
5023
|
-
var UrlZ =
|
|
5525
|
+
var UrlZ = z13.string({
|
|
5024
5526
|
invalid_type_error: "is not a valid GitHub / GitLab / ADO URL"
|
|
5025
5527
|
}).refine((data) => !!sanityRepoURL(data), {
|
|
5026
5528
|
message: "is not a valid GitHub / GitLab / ADO URL"
|
|
@@ -5168,6 +5670,7 @@ async function scanHandler(args) {
|
|
|
5168
5670
|
}
|
|
5169
5671
|
|
|
5170
5672
|
// src/args/commands/token.ts
|
|
5673
|
+
import { z as z14 } from "zod";
|
|
5171
5674
|
function addScmTokenBuilder(args) {
|
|
5172
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(
|
|
5173
5676
|
"$0 add-scm-token --scm-type Ado --url https://dev.azure.com/adoorg/test/_git/repo --token abcdef0123456 --organization myOrg",
|
|
@@ -5175,22 +5678,36 @@ function addScmTokenBuilder(args) {
|
|
|
5175
5678
|
).help().demandOption(["url", "token"]);
|
|
5176
5679
|
}
|
|
5177
5680
|
function validateAddScmTokenOptions(argv) {
|
|
5178
|
-
if (!argv.
|
|
5179
|
-
throw new CliError(errorMessages.missingUrl);
|
|
5180
|
-
}
|
|
5181
|
-
if (!argv.token) {
|
|
5182
|
-
throw new CliError(errorMessages.missingToken);
|
|
5183
|
-
}
|
|
5184
|
-
if ("GitHub" /* GitHub */ !== argv.scmType && "Ado" /* Ado */ !== argv.scmType && "GitLab" /* GitLab */ !== argv.scmType) {
|
|
5681
|
+
if (!z14.nativeEnum(ScmType).safeParse(argv.scmType).success) {
|
|
5185
5682
|
throw new CliError(
|
|
5186
|
-
"\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)"
|
|
5187
5684
|
);
|
|
5188
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) {
|
|
5189
5703
|
const urlObj = new URL(argv.url);
|
|
5190
|
-
if (urlObj.hostname.toLowerCase() ===
|
|
5704
|
+
if (urlObj.hostname.toLowerCase() === scmCloudHostname.GitHub && !argv.username) {
|
|
5191
5705
|
throw new CliError("\nError: --username flag is required for GitHub");
|
|
5192
5706
|
}
|
|
5193
|
-
|
|
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) {
|
|
5194
5711
|
throw new CliError(
|
|
5195
5712
|
"\nError: --organization flag is required for Azure DevOps"
|
|
5196
5713
|
);
|