mobbdev 1.0.53 → 1.0.59
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 +1104 -862
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -25,7 +25,7 @@ import chalk10 from "chalk";
|
|
|
25
25
|
import yargs from "yargs/yargs";
|
|
26
26
|
|
|
27
27
|
// src/args/commands/analyze.ts
|
|
28
|
-
import
|
|
28
|
+
import fs4 from "node:fs";
|
|
29
29
|
|
|
30
30
|
// src/commands/index.ts
|
|
31
31
|
import crypto from "node:crypto";
|
|
@@ -123,6 +123,7 @@ var IssueType_Enum = /* @__PURE__ */ ((IssueType_Enum2) => {
|
|
|
123
123
|
IssueType_Enum2["DefaultRightsInObjDefinition"] = "DEFAULT_RIGHTS_IN_OBJ_DEFINITION";
|
|
124
124
|
IssueType_Enum2["DeprecatedFunction"] = "DEPRECATED_FUNCTION";
|
|
125
125
|
IssueType_Enum2["DosStringBuilder"] = "DOS_STRING_BUILDER";
|
|
126
|
+
IssueType_Enum2["DuplicatedStrings"] = "DUPLICATED_STRINGS";
|
|
126
127
|
IssueType_Enum2["ErroneousStringCompare"] = "ERRONEOUS_STRING_COMPARE";
|
|
127
128
|
IssueType_Enum2["ErrorCondtionWithoutAction"] = "ERROR_CONDTION_WITHOUT_ACTION";
|
|
128
129
|
IssueType_Enum2["FrameableLoginPage"] = "FRAMEABLE_LOGIN_PAGE";
|
|
@@ -144,6 +145,7 @@ var IssueType_Enum = /* @__PURE__ */ ((IssueType_Enum2) => {
|
|
|
144
145
|
IssueType_Enum2["InsecureBinderConfiguration"] = "INSECURE_BINDER_CONFIGURATION";
|
|
145
146
|
IssueType_Enum2["InsecureCookie"] = "INSECURE_COOKIE";
|
|
146
147
|
IssueType_Enum2["InsecureRandomness"] = "INSECURE_RANDOMNESS";
|
|
148
|
+
IssueType_Enum2["InsecureUuidVersion"] = "INSECURE_UUID_VERSION";
|
|
147
149
|
IssueType_Enum2["InsufficientLogging"] = "INSUFFICIENT_LOGGING";
|
|
148
150
|
IssueType_Enum2["JqueryDeprecatedSymbols"] = "JQUERY_DEPRECATED_SYMBOLS";
|
|
149
151
|
IssueType_Enum2["LeftoverDebugCode"] = "LEFTOVER_DEBUG_CODE";
|
|
@@ -221,19 +223,20 @@ var Vulnerability_Report_Issue_State_Enum = /* @__PURE__ */ ((Vulnerability_Repo
|
|
|
221
223
|
Vulnerability_Report_Issue_State_Enum2["Unsupported"] = "Unsupported";
|
|
222
224
|
return Vulnerability_Report_Issue_State_Enum2;
|
|
223
225
|
})(Vulnerability_Report_Issue_State_Enum || {});
|
|
224
|
-
var Vulnerability_Report_Issue_Tag_Enum = /* @__PURE__ */ ((
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
return
|
|
226
|
+
var Vulnerability_Report_Issue_Tag_Enum = /* @__PURE__ */ ((Vulnerability_Report_Issue_Tag_Enum3) => {
|
|
227
|
+
Vulnerability_Report_Issue_Tag_Enum3["AutogeneratedCode"] = "AUTOGENERATED_CODE";
|
|
228
|
+
Vulnerability_Report_Issue_Tag_Enum3["AuxiliaryCode"] = "AUXILIARY_CODE";
|
|
229
|
+
Vulnerability_Report_Issue_Tag_Enum3["FalsePositive"] = "FALSE_POSITIVE";
|
|
230
|
+
Vulnerability_Report_Issue_Tag_Enum3["TestCode"] = "TEST_CODE";
|
|
231
|
+
Vulnerability_Report_Issue_Tag_Enum3["VendorCode"] = "VENDOR_CODE";
|
|
232
|
+
return Vulnerability_Report_Issue_Tag_Enum3;
|
|
231
233
|
})(Vulnerability_Report_Issue_Tag_Enum || {});
|
|
232
234
|
var Vulnerability_Report_Vendor_Enum = /* @__PURE__ */ ((Vulnerability_Report_Vendor_Enum3) => {
|
|
233
235
|
Vulnerability_Report_Vendor_Enum3["Checkmarx"] = "checkmarx";
|
|
234
236
|
Vulnerability_Report_Vendor_Enum3["CheckmarxXml"] = "checkmarxXml";
|
|
235
237
|
Vulnerability_Report_Vendor_Enum3["Codeql"] = "codeql";
|
|
236
238
|
Vulnerability_Report_Vendor_Enum3["Fortify"] = "fortify";
|
|
239
|
+
Vulnerability_Report_Vendor_Enum3["Opengrep"] = "opengrep";
|
|
237
240
|
Vulnerability_Report_Vendor_Enum3["Semgrep"] = "semgrep";
|
|
238
241
|
Vulnerability_Report_Vendor_Enum3["Snyk"] = "snyk";
|
|
239
242
|
Vulnerability_Report_Vendor_Enum3["Sonarqube"] = "sonarqube";
|
|
@@ -411,8 +414,12 @@ var GetVulByNodesMetadataDocument = `
|
|
|
411
414
|
path
|
|
412
415
|
startLine
|
|
413
416
|
vulnerabilityReportIssue {
|
|
414
|
-
|
|
417
|
+
parsedIssueType
|
|
415
418
|
fixId
|
|
419
|
+
category
|
|
420
|
+
vulnerabilityReportIssueTags {
|
|
421
|
+
tag: vulnerability_report_issue_tag_value
|
|
422
|
+
}
|
|
416
423
|
}
|
|
417
424
|
}
|
|
418
425
|
fixablePrVuls: vulnerability_report_issue_aggregate(
|
|
@@ -436,6 +443,25 @@ var GetVulByNodesMetadataDocument = `
|
|
|
436
443
|
count
|
|
437
444
|
}
|
|
438
445
|
}
|
|
446
|
+
irrelevantVulnerabilityReportIssue: vulnerability_report(
|
|
447
|
+
where: {id: {_eq: $vulnerabilityReportId}}
|
|
448
|
+
) {
|
|
449
|
+
vulnerabilityReportIssues(
|
|
450
|
+
where: {fixId: {_is_null: true}, _or: [{category: {_eq: "Irrelevant"}}, {category: {_eq: "FalsePositive"}}]}
|
|
451
|
+
) {
|
|
452
|
+
id
|
|
453
|
+
parsedIssueType
|
|
454
|
+
fixId
|
|
455
|
+
category
|
|
456
|
+
vulnerabilityReportIssueTags {
|
|
457
|
+
tag: vulnerability_report_issue_tag_value
|
|
458
|
+
}
|
|
459
|
+
codeNodes(order_by: {index: desc}, where: {_or: $filters}) {
|
|
460
|
+
path
|
|
461
|
+
startLine
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
}
|
|
439
465
|
}
|
|
440
466
|
`;
|
|
441
467
|
var UpdateScmTokenDocument = `
|
|
@@ -898,7 +924,7 @@ var FixPageFixReportZ = z3.object({
|
|
|
898
924
|
|
|
899
925
|
// src/features/analysis/scm/shared/src/types/issue.ts
|
|
900
926
|
var MAX_SOURCE_CODE_FILE_SIZE_IN_BYTES = 1e5;
|
|
901
|
-
var
|
|
927
|
+
var CATEGORY = {
|
|
902
928
|
NoFix: "NoFix",
|
|
903
929
|
Unsupported: "Unsupported",
|
|
904
930
|
Irrelevant: "Irrelevant",
|
|
@@ -906,11 +932,11 @@ var category = {
|
|
|
906
932
|
Fixable: "Fixable"
|
|
907
933
|
};
|
|
908
934
|
var ValidCategoriesZ = z4.union([
|
|
909
|
-
z4.literal(
|
|
910
|
-
z4.literal(
|
|
911
|
-
z4.literal(
|
|
912
|
-
z4.literal(
|
|
913
|
-
z4.literal(
|
|
935
|
+
z4.literal(CATEGORY.NoFix),
|
|
936
|
+
z4.literal(CATEGORY.Unsupported),
|
|
937
|
+
z4.literal(CATEGORY.Irrelevant),
|
|
938
|
+
z4.literal(CATEGORY.FalsePositive),
|
|
939
|
+
z4.literal(CATEGORY.Fixable)
|
|
914
940
|
]);
|
|
915
941
|
var BaseIssuePartsZ = z4.object({
|
|
916
942
|
id: z4.string().uuid(),
|
|
@@ -919,6 +945,10 @@ var BaseIssuePartsZ = z4.object({
|
|
|
919
945
|
createdAt: z4.string(),
|
|
920
946
|
parsedSeverity: ParsedSeverityZ,
|
|
921
947
|
category: ValidCategoriesZ,
|
|
948
|
+
extraData: z4.object({
|
|
949
|
+
missing_files: z4.string().array().nullish(),
|
|
950
|
+
error_files: z4.string().array().nullish()
|
|
951
|
+
}),
|
|
922
952
|
vulnerabilityReportIssueTags: z4.array(
|
|
923
953
|
z4.object({
|
|
924
954
|
tag: z4.nativeEnum(Vulnerability_Report_Issue_Tag_Enum)
|
|
@@ -967,13 +997,13 @@ var FalsePositivePartsZ = z4.object({
|
|
|
967
997
|
});
|
|
968
998
|
var IssuePartsWithFixZ = BaseIssuePartsZ.merge(
|
|
969
999
|
z4.object({
|
|
970
|
-
category: z4.literal(
|
|
1000
|
+
category: z4.literal(CATEGORY.Irrelevant),
|
|
971
1001
|
fix: FixPartsForFixScreenZ.nullish()
|
|
972
1002
|
})
|
|
973
1003
|
);
|
|
974
1004
|
var IssuePartsFpZ = BaseIssuePartsZ.merge(
|
|
975
1005
|
z4.object({
|
|
976
|
-
category: z4.literal(
|
|
1006
|
+
category: z4.literal(CATEGORY.FalsePositive),
|
|
977
1007
|
fpId: z4.string().uuid(),
|
|
978
1008
|
getFalsePositive: FalsePositivePartsZ
|
|
979
1009
|
})
|
|
@@ -981,9 +1011,9 @@ var IssuePartsFpZ = BaseIssuePartsZ.merge(
|
|
|
981
1011
|
var GeneralIssueZ = BaseIssuePartsZ.merge(
|
|
982
1012
|
z4.object({
|
|
983
1013
|
category: z4.union([
|
|
984
|
-
z4.literal(
|
|
985
|
-
z4.literal(
|
|
986
|
-
z4.literal(
|
|
1014
|
+
z4.literal(CATEGORY.NoFix),
|
|
1015
|
+
z4.literal(CATEGORY.Unsupported),
|
|
1016
|
+
z4.literal(CATEGORY.Fixable)
|
|
987
1017
|
])
|
|
988
1018
|
})
|
|
989
1019
|
);
|
|
@@ -1008,6 +1038,13 @@ var GetIssueScreenDataZ = z4.object({
|
|
|
1008
1038
|
issueIndexes: GetIssueIndexesZ
|
|
1009
1039
|
});
|
|
1010
1040
|
var IssueBucketZ = z4.enum(["fixable", "irrelevant", "remaining"]);
|
|
1041
|
+
var mapCategoryToBucket = {
|
|
1042
|
+
FalsePositive: "irrelevant",
|
|
1043
|
+
Irrelevant: "irrelevant",
|
|
1044
|
+
NoFix: "remaining",
|
|
1045
|
+
Unsupported: "remaining",
|
|
1046
|
+
Fixable: "fixable"
|
|
1047
|
+
};
|
|
1011
1048
|
|
|
1012
1049
|
// src/features/analysis/scm/shared/src/types/types.ts
|
|
1013
1050
|
import { z as z7 } from "zod";
|
|
@@ -1102,7 +1139,9 @@ var issueTypeMap = {
|
|
|
1102
1139
|
["FRAMEABLE_LOGIN_PAGE" /* FrameableLoginPage */]: "Frameable Login Page",
|
|
1103
1140
|
["USE_OF_HARD_CODED_CRYPTOGRAPHIC_KEY" /* UseOfHardCodedCryptographicKey */]: "Use of Hardcoded Cryptographic Key",
|
|
1104
1141
|
["MISSING_SSL_MINVERSION" /* MissingSslMinversion */]: "Missing SSL MinVersion",
|
|
1105
|
-
["WEBSOCKET_MISSING_ORIGIN_CHECK" /* WebsocketMissingOriginCheck */]: "Missing Websocket Origin Check"
|
|
1142
|
+
["WEBSOCKET_MISSING_ORIGIN_CHECK" /* WebsocketMissingOriginCheck */]: "Missing Websocket Origin Check",
|
|
1143
|
+
["DUPLICATED_STRINGS" /* DuplicatedStrings */]: "String Literals Should not Be Duplicated",
|
|
1144
|
+
["INSECURE_UUID_VERSION" /* InsecureUuidVersion */]: "Insecure UUID Version"
|
|
1106
1145
|
};
|
|
1107
1146
|
var issueTypeZ = z5.nativeEnum(IssueType_Enum);
|
|
1108
1147
|
var getIssueTypeFriendlyString = (issueType) => {
|
|
@@ -1112,6 +1151,29 @@ var getIssueTypeFriendlyString = (issueType) => {
|
|
|
1112
1151
|
}
|
|
1113
1152
|
return issueTypeMap[issueTypeZParseRes.data];
|
|
1114
1153
|
};
|
|
1154
|
+
function getTagTooltip(tag) {
|
|
1155
|
+
switch (tag) {
|
|
1156
|
+
case "FALSE_POSITIVE":
|
|
1157
|
+
return "Issue was found to be a false positive";
|
|
1158
|
+
case "TEST_CODE":
|
|
1159
|
+
return "Issue found in test files, not production code";
|
|
1160
|
+
case "VENDOR_CODE":
|
|
1161
|
+
return "Issue is in external libraries or dependencies not owned or maintained by your team";
|
|
1162
|
+
case "AUTOGENERATED_CODE":
|
|
1163
|
+
return "Code created by tools or frameworks, not manually written";
|
|
1164
|
+
case "AUXILIARY_CODE":
|
|
1165
|
+
return "Issue found in supporting files that don\u2019t impact core functionality";
|
|
1166
|
+
default:
|
|
1167
|
+
return tag;
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1170
|
+
var issueDescription = {
|
|
1171
|
+
["AUTOGENERATED_CODE" /* AutogeneratedCode */]: "The flagged code is generated automatically by tools or frameworks as part of the build or runtime process. This categorization highlights that **the issue resides in non-manual code**, which often requires tool-specific solutions or exemptions.",
|
|
1172
|
+
["AUXILIARY_CODE" /* AuxiliaryCode */]: "The flagged code is auxiliary or supporting code, such as configuration files, build scripts, or other non-application logic. This categorization indicates that the issue is not directly related to the application\u2019s core functionality.",
|
|
1173
|
+
["FALSE_POSITIVE" /* FalsePositive */]: "The flagged code **does not represent an actual vulnerability within the application\u2019s context.** This categorization indicates that the issue is either misidentified by the scanner or deemed irrelevant to the application\u2019s functionality.",
|
|
1174
|
+
["TEST_CODE" /* TestCode */]: "The flagged code resides in a test-specific path or context. This categorization indicates that **it supports testing scenarios and is isolated from production use**.",
|
|
1175
|
+
["VENDOR_CODE" /* VendorCode */]: "The flagged code originates from a third-party library or dependency maintained externally. This categorization suggests that **the issue lies outside the application\u2019s direct control** and should be addressed by the vendor if necessary."
|
|
1176
|
+
};
|
|
1115
1177
|
|
|
1116
1178
|
// src/features/analysis/scm/shared/src/validations.ts
|
|
1117
1179
|
var IssueTypeSettingZ = z6.object({
|
|
@@ -1605,9 +1667,9 @@ var progressMassages = {
|
|
|
1605
1667
|
var VUL_REPORT_DIGEST_TIMEOUT_MS = 1e3 * 60 * 30;
|
|
1606
1668
|
|
|
1607
1669
|
// src/features/analysis/index.ts
|
|
1608
|
-
import
|
|
1670
|
+
import fs3 from "node:fs";
|
|
1609
1671
|
import fsPromises from "node:fs/promises";
|
|
1610
|
-
import
|
|
1672
|
+
import path6 from "node:path";
|
|
1611
1673
|
import { env as env2 } from "node:process";
|
|
1612
1674
|
import { pipeline } from "node:stream/promises";
|
|
1613
1675
|
|
|
@@ -1721,18 +1783,14 @@ import extract from "extract-zip";
|
|
|
1721
1783
|
import { createSpinner as createSpinner4 } from "nanospinner";
|
|
1722
1784
|
import fetch4 from "node-fetch";
|
|
1723
1785
|
import open2 from "open";
|
|
1724
|
-
import
|
|
1725
|
-
import { z as
|
|
1786
|
+
import tmp from "tmp";
|
|
1787
|
+
import { z as z29 } from "zod";
|
|
1726
1788
|
|
|
1727
1789
|
// src/features/analysis/add_fix_comments_for_pr/add_fix_comments_for_pr.ts
|
|
1728
1790
|
import Debug8 from "debug";
|
|
1729
1791
|
|
|
1730
|
-
// src/features/analysis/scm/github/
|
|
1731
|
-
import {
|
|
1732
|
-
|
|
1733
|
-
// src/features/analysis/scm/constants.ts
|
|
1734
|
-
var MOBB_ICON_IMG = "https://app.mobb.ai/gh-action/Logo_Rounded_Icon.svg";
|
|
1735
|
-
var MAX_BRANCHES_FETCH = 1e3;
|
|
1792
|
+
// src/features/analysis/scm/github/GithubSCMLib.ts
|
|
1793
|
+
import { z as z24 } from "zod";
|
|
1736
1794
|
|
|
1737
1795
|
// src/features/analysis/scm/errors.ts
|
|
1738
1796
|
var InvalidRepoUrlError = class extends Error {
|
|
@@ -1762,6 +1820,21 @@ var RepoNoTokenAccessError = class extends Error {
|
|
|
1762
1820
|
}
|
|
1763
1821
|
};
|
|
1764
1822
|
|
|
1823
|
+
// src/features/analysis/scm/scmSubmit/index.ts
|
|
1824
|
+
import { simpleGit } from "simple-git";
|
|
1825
|
+
var isValidBranchName = async (branchName) => {
|
|
1826
|
+
const git = simpleGit();
|
|
1827
|
+
try {
|
|
1828
|
+
const res = await git.raw(["check-ref-format", "--branch", branchName]);
|
|
1829
|
+
if (res) {
|
|
1830
|
+
return true;
|
|
1831
|
+
}
|
|
1832
|
+
return false;
|
|
1833
|
+
} catch (e) {
|
|
1834
|
+
return false;
|
|
1835
|
+
}
|
|
1836
|
+
};
|
|
1837
|
+
|
|
1765
1838
|
// src/features/analysis/scm/types.ts
|
|
1766
1839
|
import { z as z14 } from "zod";
|
|
1767
1840
|
|
|
@@ -2007,13 +2080,20 @@ var fixDetailsData = {
|
|
|
2007
2080
|
["FRAMEABLE_LOGIN_PAGE" /* FrameableLoginPage */]: void 0,
|
|
2008
2081
|
["USE_OF_HARD_CODED_CRYPTOGRAPHIC_KEY" /* UseOfHardCodedCryptographicKey */]: void 0,
|
|
2009
2082
|
["MISSING_SSL_MINVERSION" /* MissingSslMinversion */]: void 0,
|
|
2010
|
-
["WEBSOCKET_MISSING_ORIGIN_CHECK" /* WebsocketMissingOriginCheck */]: void 0
|
|
2083
|
+
["WEBSOCKET_MISSING_ORIGIN_CHECK" /* WebsocketMissingOriginCheck */]: void 0,
|
|
2084
|
+
["DUPLICATED_STRINGS" /* DuplicatedStrings */]: void 0,
|
|
2085
|
+
["INSECURE_UUID_VERSION" /* InsecureUuidVersion */]: void 0
|
|
2011
2086
|
};
|
|
2012
2087
|
|
|
2013
2088
|
// src/features/analysis/scm/shared/src/commitDescriptionMarkup.ts
|
|
2014
2089
|
function capitalizeFirstLetter(str) {
|
|
2015
2090
|
return str?.length ? str[0].toUpperCase() + str.slice(1) : "";
|
|
2016
2091
|
}
|
|
2092
|
+
function lowercaseFirstLetter(str) {
|
|
2093
|
+
if (!str)
|
|
2094
|
+
return str;
|
|
2095
|
+
return `${str.charAt(0).toLowerCase()}${str.slice(1)}`;
|
|
2096
|
+
}
|
|
2017
2097
|
var severityToEmoji = {
|
|
2018
2098
|
["critical" /* Critical */]: "\u{1F6A8}",
|
|
2019
2099
|
["high" /* High */]: "\u{1F6A9}",
|
|
@@ -2025,7 +2105,8 @@ var getCommitDescription = ({
|
|
|
2025
2105
|
issueType,
|
|
2026
2106
|
severity,
|
|
2027
2107
|
guidances,
|
|
2028
|
-
fixUrl
|
|
2108
|
+
fixUrl,
|
|
2109
|
+
irrelevantIssueWithTags
|
|
2029
2110
|
}) => {
|
|
2030
2111
|
const issueTypeString = getIssueTypeFriendlyString(issueType);
|
|
2031
2112
|
let description = `This change fixes a **${severity} severity** (${severityToEmoji[severity]}) **${issueTypeString}** issue reported by **${capitalizeFirstLetter(
|
|
@@ -2035,6 +2116,17 @@ var getCommitDescription = ({
|
|
|
2035
2116
|
`;
|
|
2036
2117
|
const parseIssueTypeRes = z9.nativeEnum(IssueType_Enum).safeParse(issueType);
|
|
2037
2118
|
if (issueType && parseIssueTypeRes.success) {
|
|
2119
|
+
if (irrelevantIssueWithTags?.[0]?.tag) {
|
|
2120
|
+
description += `
|
|
2121
|
+
> [!tip]
|
|
2122
|
+
> This issue was found to be irrelevant to your project - ${lowercaseFirstLetter(getTagTooltip(irrelevantIssueWithTags[0].tag))}.
|
|
2123
|
+
> Mobb recommends to ignore this issue, however fix is available if you think differently.
|
|
2124
|
+
|
|
2125
|
+
|
|
2126
|
+
## Justification
|
|
2127
|
+
${issueDescription[irrelevantIssueWithTags[0].tag]}
|
|
2128
|
+
`;
|
|
2129
|
+
}
|
|
2038
2130
|
const staticData = fixDetailsData[parseIssueTypeRes.data];
|
|
2039
2131
|
if (staticData) {
|
|
2040
2132
|
description += `## Issue description
|
|
@@ -2056,6 +2148,36 @@ ${guidances.map(({ guidance }) => `## Additional actions required
|
|
|
2056
2148
|
}
|
|
2057
2149
|
return description;
|
|
2058
2150
|
};
|
|
2151
|
+
var getCommitIssueDescription = ({
|
|
2152
|
+
vendor,
|
|
2153
|
+
issueType,
|
|
2154
|
+
irrelevantIssueWithTags
|
|
2155
|
+
}) => {
|
|
2156
|
+
const issueTypeString = getIssueTypeFriendlyString(issueType);
|
|
2157
|
+
let description = `The following issues reported by ${capitalizeFirstLetter(vendor)} on this PR were found to be irrelevant to your project:
|
|
2158
|
+
`;
|
|
2159
|
+
const parseIssueTypeRes = z9.nativeEnum(IssueType_Enum).safeParse(issueType);
|
|
2160
|
+
if (issueType && parseIssueTypeRes.success) {
|
|
2161
|
+
if (irrelevantIssueWithTags?.[0]?.tag) {
|
|
2162
|
+
description += `
|
|
2163
|
+
> [!tip]
|
|
2164
|
+
> ${issueTypeString} - ${lowercaseFirstLetter(getTagTooltip(irrelevantIssueWithTags[0].tag))}.
|
|
2165
|
+
> Mobb recommends to ignore this issue, however fix is available if you think differently.
|
|
2166
|
+
|
|
2167
|
+
|
|
2168
|
+
## Justification
|
|
2169
|
+
${issueDescription[irrelevantIssueWithTags[0].tag]}
|
|
2170
|
+
`;
|
|
2171
|
+
}
|
|
2172
|
+
const staticData = fixDetailsData[parseIssueTypeRes.data];
|
|
2173
|
+
if (staticData) {
|
|
2174
|
+
description += `## Issue description
|
|
2175
|
+
${staticData.issueDescription}
|
|
2176
|
+
`;
|
|
2177
|
+
}
|
|
2178
|
+
}
|
|
2179
|
+
return description;
|
|
2180
|
+
};
|
|
2059
2181
|
|
|
2060
2182
|
// src/features/analysis/scm/shared/src/guidances.ts
|
|
2061
2183
|
import { z as z12 } from "zod";
|
|
@@ -2655,6 +2777,15 @@ var confusingNaming = {
|
|
|
2655
2777
|
}
|
|
2656
2778
|
};
|
|
2657
2779
|
|
|
2780
|
+
// src/features/analysis/scm/shared/src/storedQuestionData/java/duplicatedStrings.ts
|
|
2781
|
+
var duplicatedStrings = {
|
|
2782
|
+
constantName: {
|
|
2783
|
+
content: () => "New constant name",
|
|
2784
|
+
description: () => "",
|
|
2785
|
+
guidance: () => ""
|
|
2786
|
+
}
|
|
2787
|
+
};
|
|
2788
|
+
|
|
2658
2789
|
// src/features/analysis/scm/shared/src/storedQuestionData/java/erroneousStringCompare.ts
|
|
2659
2790
|
var erroneousStringCompare = {
|
|
2660
2791
|
javaVersionGreaterOrEqual17: {
|
|
@@ -3051,7 +3182,8 @@ var vulnerabilities11 = {
|
|
|
3051
3182
|
["INSECURE_COOKIE" /* InsecureCookie */]: insecureCookie2,
|
|
3052
3183
|
["TRUST_BOUNDARY_VIOLATION" /* TrustBoundaryViolation */]: trustBoundaryViolation2,
|
|
3053
3184
|
["LEFTOVER_DEBUG_CODE" /* LeftoverDebugCode */]: leftoverDebugCode,
|
|
3054
|
-
["ERRONEOUS_STRING_COMPARE" /* ErroneousStringCompare */]: erroneousStringCompare
|
|
3185
|
+
["ERRONEOUS_STRING_COMPARE" /* ErroneousStringCompare */]: erroneousStringCompare,
|
|
3186
|
+
["DUPLICATED_STRINGS" /* DuplicatedStrings */]: duplicatedStrings
|
|
3055
3187
|
};
|
|
3056
3188
|
var java_default2 = vulnerabilities11;
|
|
3057
3189
|
|
|
@@ -3749,6 +3881,15 @@ function getFixUrl({
|
|
|
3749
3881
|
}) {
|
|
3750
3882
|
return `${appBaseUrl}/organization/${organizationId}/project/${projectId}/report/${analysisId}/fix/${fixId}`;
|
|
3751
3883
|
}
|
|
3884
|
+
function getIssueUrl({
|
|
3885
|
+
appBaseUrl,
|
|
3886
|
+
issueId,
|
|
3887
|
+
projectId,
|
|
3888
|
+
organizationId,
|
|
3889
|
+
analysisId
|
|
3890
|
+
}) {
|
|
3891
|
+
return `${appBaseUrl}/organization/${organizationId}/project/${projectId}/report/${analysisId}/issue/${issueId}`;
|
|
3892
|
+
}
|
|
3752
3893
|
|
|
3753
3894
|
// src/features/analysis/scm/types.ts
|
|
3754
3895
|
var ReferenceType = /* @__PURE__ */ ((ReferenceType2) => {
|
|
@@ -3788,100 +3929,8 @@ var GetRefererenceResultZ = z14.object({
|
|
|
3788
3929
|
type: z14.nativeEnum(ReferenceType)
|
|
3789
3930
|
});
|
|
3790
3931
|
|
|
3791
|
-
// src/features/analysis/scm/github/consts.ts
|
|
3792
|
-
var POST_COMMENT_PATH = "POST /repos/{owner}/{repo}/pulls/{pull_number}/comments";
|
|
3793
|
-
var DELETE_COMMENT_PATH = "DELETE /repos/{owner}/{repo}/pulls/comments/{comment_id}";
|
|
3794
|
-
var UPDATE_COMMENT_PATH = "PATCH /repos/{owner}/{repo}/pulls/comments/{comment_id}";
|
|
3795
|
-
var GET_PR_COMMENTS_PATH = "GET /repos/{owner}/{repo}/pulls/{pull_number}/comments";
|
|
3796
|
-
var GET_PR_COMMENT_PATH = "GET /repos/{owner}/{repo}/pulls/comments/{comment_id}";
|
|
3797
|
-
var REPLY_TO_CODE_REVIEW_COMMENT_PATH = "POST /repos/{owner}/{repo}/pulls/{pull_number}/comments/{comment_id}/replies";
|
|
3798
|
-
var GET_PR = "GET /repos/{owner}/{repo}/pulls/{pull_number}";
|
|
3799
|
-
var POST_GENERAL_PR_COMMENT = "POST /repos/{owner}/{repo}/issues/{issue_number}/comments";
|
|
3800
|
-
var GET_GENERAL_PR_COMMENTS = "GET /repos/{owner}/{repo}/issues/{issue_number}/comments";
|
|
3801
|
-
var DELETE_GENERAL_PR_COMMENT = "DELETE /repos/{owner}/{repo}/issues/comments/{comment_id}";
|
|
3802
|
-
var CREATE_OR_UPDATE_A_REPOSITORY_SECRET = "PUT /repos/{owner}/{repo}/actions/secrets/{secret_name}";
|
|
3803
|
-
var GET_A_REPOSITORY_PUBLIC_KEY = "GET /repos/{owner}/{repo}/actions/secrets/public-key";
|
|
3804
|
-
var GET_USER = "GET /user";
|
|
3805
|
-
var GET_USER_REPOS = "GET /user/repos";
|
|
3806
|
-
var GET_REPO_BRANCHES = "GET /repos/{owner}/{repo}/branches";
|
|
3807
|
-
var GET_BLAME_DOCUMENT = `
|
|
3808
|
-
query GetBlame(
|
|
3809
|
-
$owner: String!
|
|
3810
|
-
$repo: String!
|
|
3811
|
-
$ref: String!
|
|
3812
|
-
$path: String!
|
|
3813
|
-
) {
|
|
3814
|
-
repository(name: $repo, owner: $owner) {
|
|
3815
|
-
# branch name
|
|
3816
|
-
object(expression: $ref) {
|
|
3817
|
-
# cast Target to a Commit
|
|
3818
|
-
... on Commit {
|
|
3819
|
-
# full repo-relative path to blame file
|
|
3820
|
-
blame(path: $path) {
|
|
3821
|
-
ranges {
|
|
3822
|
-
commit {
|
|
3823
|
-
author {
|
|
3824
|
-
user {
|
|
3825
|
-
name
|
|
3826
|
-
login
|
|
3827
|
-
}
|
|
3828
|
-
}
|
|
3829
|
-
authoredDate
|
|
3830
|
-
}
|
|
3831
|
-
startingLine
|
|
3832
|
-
endingLine
|
|
3833
|
-
age
|
|
3834
|
-
}
|
|
3835
|
-
}
|
|
3836
|
-
}
|
|
3837
|
-
|
|
3838
|
-
}
|
|
3839
|
-
}
|
|
3840
|
-
}
|
|
3841
|
-
`;
|
|
3842
|
-
|
|
3843
|
-
// src/features/analysis/scm/github/utils/encrypt_secret.ts
|
|
3844
|
-
import sodium from "libsodium-wrappers";
|
|
3845
|
-
async function encryptSecret(secret, key) {
|
|
3846
|
-
await sodium.ready;
|
|
3847
|
-
const binkey = sodium.from_base64(key, sodium.base64_variants.ORIGINAL);
|
|
3848
|
-
const binsec = sodium.from_string(secret);
|
|
3849
|
-
const encBytes = sodium.crypto_box_seal(binsec, binkey);
|
|
3850
|
-
return sodium.to_base64(encBytes, sodium.base64_variants.ORIGINAL);
|
|
3851
|
-
}
|
|
3852
|
-
|
|
3853
|
-
// src/features/analysis/scm/github/utils/utils.ts
|
|
3854
|
-
import { Octokit } from "octokit";
|
|
3855
|
-
import { fetch as fetch2, ProxyAgent as ProxyAgent2 } from "undici";
|
|
3856
|
-
|
|
3857
|
-
// src/features/analysis/scm/ado/constants.ts
|
|
3858
|
-
var DEFUALT_ADO_ORIGIN = scmCloudUrl.Ado;
|
|
3859
|
-
|
|
3860
|
-
// src/features/analysis/scm/ado/utils.ts
|
|
3861
|
-
import querystring from "node:querystring";
|
|
3862
|
-
import * as api from "azure-devops-node-api";
|
|
3863
|
-
import Debug2 from "debug";
|
|
3864
|
-
import { z as z18 } from "zod";
|
|
3865
|
-
|
|
3866
|
-
// src/features/analysis/scm/env.ts
|
|
3867
|
-
import { z as z15 } from "zod";
|
|
3868
|
-
var EnvVariablesZod = z15.object({
|
|
3869
|
-
GITLAB_API_TOKEN: z15.string().optional(),
|
|
3870
|
-
GITHUB_API_TOKEN: z15.string().optional(),
|
|
3871
|
-
GIT_COMMITTER_EMAIL: z15.string().optional(),
|
|
3872
|
-
GIT_COMMITTER_NAME: z15.string().optional(),
|
|
3873
|
-
GIT_PROXY_HOST: z15.string()
|
|
3874
|
-
});
|
|
3875
|
-
var {
|
|
3876
|
-
GITLAB_API_TOKEN,
|
|
3877
|
-
GITHUB_API_TOKEN,
|
|
3878
|
-
GIT_PROXY_HOST,
|
|
3879
|
-
GIT_COMMITTER_EMAIL,
|
|
3880
|
-
GIT_COMMITTER_NAME
|
|
3881
|
-
} = EnvVariablesZod.parse(process.env);
|
|
3882
|
-
|
|
3883
3932
|
// src/features/analysis/scm/utils/index.ts
|
|
3884
|
-
import { z as
|
|
3933
|
+
import { z as z15 } from "zod";
|
|
3885
3934
|
function getFixUrlWithRedirect(params) {
|
|
3886
3935
|
const {
|
|
3887
3936
|
fixId,
|
|
@@ -3903,6 +3952,27 @@ function getFixUrlWithRedirect(params) {
|
|
|
3903
3952
|
analysisId
|
|
3904
3953
|
})}?${searchParams.toString()}`;
|
|
3905
3954
|
}
|
|
3955
|
+
function getIssueUrlWithRedirect(params) {
|
|
3956
|
+
const {
|
|
3957
|
+
issueId,
|
|
3958
|
+
projectId,
|
|
3959
|
+
organizationId,
|
|
3960
|
+
analysisId,
|
|
3961
|
+
redirectUrl,
|
|
3962
|
+
appBaseUrl,
|
|
3963
|
+
commentId
|
|
3964
|
+
} = params;
|
|
3965
|
+
const searchParams = new URLSearchParams();
|
|
3966
|
+
searchParams.append("commit_redirect_url", redirectUrl);
|
|
3967
|
+
searchParams.append("comment_id", commentId.toString());
|
|
3968
|
+
return `${getIssueUrl({
|
|
3969
|
+
appBaseUrl,
|
|
3970
|
+
issueId,
|
|
3971
|
+
projectId,
|
|
3972
|
+
organizationId,
|
|
3973
|
+
analysisId
|
|
3974
|
+
})}?${searchParams.toString()}`;
|
|
3975
|
+
}
|
|
3906
3976
|
function getCommitUrl(params) {
|
|
3907
3977
|
const {
|
|
3908
3978
|
fixId,
|
|
@@ -3924,6 +3994,27 @@ function getCommitUrl(params) {
|
|
|
3924
3994
|
analysisId
|
|
3925
3995
|
})}/commit?${searchParams.toString()}`;
|
|
3926
3996
|
}
|
|
3997
|
+
function getCommitIssueUrl(params) {
|
|
3998
|
+
const {
|
|
3999
|
+
issueId,
|
|
4000
|
+
projectId,
|
|
4001
|
+
organizationId,
|
|
4002
|
+
analysisId,
|
|
4003
|
+
redirectUrl,
|
|
4004
|
+
appBaseUrl,
|
|
4005
|
+
commentId
|
|
4006
|
+
} = params;
|
|
4007
|
+
const searchParams = new URLSearchParams();
|
|
4008
|
+
searchParams.append("redirect_url", redirectUrl);
|
|
4009
|
+
searchParams.append("comment_id", commentId.toString());
|
|
4010
|
+
return `${getIssueUrl({
|
|
4011
|
+
appBaseUrl,
|
|
4012
|
+
issueId,
|
|
4013
|
+
projectId,
|
|
4014
|
+
organizationId,
|
|
4015
|
+
analysisId
|
|
4016
|
+
})}/commit?${searchParams.toString()}`;
|
|
4017
|
+
}
|
|
3927
4018
|
var userNamePattern = /^(https?:\/\/)([^@]+@)?([^/]+\/.+)$/;
|
|
3928
4019
|
var sshPattern = /^git@([\w.-]+):([\w./-]+)$/;
|
|
3929
4020
|
function normalizeUrl(repoUrl) {
|
|
@@ -3950,7 +4041,7 @@ function shouldValidateUrl(repoUrl) {
|
|
|
3950
4041
|
return repoUrl && isUrlHasPath(repoUrl);
|
|
3951
4042
|
}
|
|
3952
4043
|
function isBrokerUrl(url) {
|
|
3953
|
-
return
|
|
4044
|
+
return z15.string().uuid().safeParse(new URL(url).host).success;
|
|
3954
4045
|
}
|
|
3955
4046
|
function buildAuthorizedRepoUrl(args) {
|
|
3956
4047
|
const { url, username, password } = args;
|
|
@@ -3986,7 +4077,7 @@ function getCloudScmLibTypeFromUrl(url) {
|
|
|
3986
4077
|
return void 0;
|
|
3987
4078
|
}
|
|
3988
4079
|
function getScmLibTypeFromScmType(scmType) {
|
|
3989
|
-
const parsedScmType =
|
|
4080
|
+
const parsedScmType = z15.nativeEnum(ScmType).parse(scmType);
|
|
3990
4081
|
return scmTypeToScmLibScmType[parsedScmType];
|
|
3991
4082
|
}
|
|
3992
4083
|
function getScmConfig({
|
|
@@ -4052,67 +4143,223 @@ function getScmConfig({
|
|
|
4052
4143
|
};
|
|
4053
4144
|
}
|
|
4054
4145
|
|
|
4055
|
-
// src/features/analysis/scm/
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
4063
|
-
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
}
|
|
4070
|
-
|
|
4071
|
-
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
|
|
4075
|
-
|
|
4076
|
-
|
|
4077
|
-
|
|
4078
|
-
}
|
|
4079
|
-
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
|
|
4083
|
-
|
|
4084
|
-
|
|
4085
|
-
|
|
4086
|
-
|
|
4087
|
-
)
|
|
4088
|
-
|
|
4089
|
-
|
|
4090
|
-
|
|
4091
|
-
|
|
4092
|
-
|
|
4093
|
-
|
|
4094
|
-
|
|
4095
|
-
|
|
4096
|
-
|
|
4097
|
-
|
|
4098
|
-
|
|
4099
|
-
|
|
4100
|
-
|
|
4101
|
-
|
|
4102
|
-
|
|
4103
|
-
|
|
4104
|
-
}
|
|
4105
|
-
|
|
4106
|
-
|
|
4107
|
-
}
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
|
|
4115
|
-
|
|
4146
|
+
// src/features/analysis/scm/scm.ts
|
|
4147
|
+
var SCMLib = class {
|
|
4148
|
+
constructor(url, accessToken, scmOrg) {
|
|
4149
|
+
__publicField(this, "url");
|
|
4150
|
+
__publicField(this, "accessToken");
|
|
4151
|
+
__publicField(this, "scmOrg");
|
|
4152
|
+
this.accessToken = accessToken;
|
|
4153
|
+
this.url = url;
|
|
4154
|
+
this.scmOrg = scmOrg;
|
|
4155
|
+
}
|
|
4156
|
+
async getUrlWithCredentials() {
|
|
4157
|
+
if (!this.url) {
|
|
4158
|
+
console.error("no url for getUrlWithCredentials()");
|
|
4159
|
+
throw new Error("no url");
|
|
4160
|
+
}
|
|
4161
|
+
const trimmedUrl = this.url.trim().replace(/\/$/, "");
|
|
4162
|
+
const accessToken = this.getAccessToken();
|
|
4163
|
+
if (!accessToken) {
|
|
4164
|
+
return trimmedUrl;
|
|
4165
|
+
}
|
|
4166
|
+
if (this.scmLibType === "ADO" /* ADO */) {
|
|
4167
|
+
const { host, protocol, pathname } = new URL(trimmedUrl);
|
|
4168
|
+
return `${protocol}//${accessToken}@${host}${pathname}`;
|
|
4169
|
+
}
|
|
4170
|
+
const finalUrl = this.scmLibType === "GITLAB" /* GITLAB */ ? `${trimmedUrl}.git` : trimmedUrl;
|
|
4171
|
+
const username = await this._getUsernameForAuthUrl();
|
|
4172
|
+
return buildAuthorizedRepoUrl({
|
|
4173
|
+
url: finalUrl,
|
|
4174
|
+
username,
|
|
4175
|
+
password: accessToken
|
|
4176
|
+
});
|
|
4177
|
+
}
|
|
4178
|
+
getAccessToken() {
|
|
4179
|
+
return this.accessToken || "";
|
|
4180
|
+
}
|
|
4181
|
+
getUrl() {
|
|
4182
|
+
return this.url;
|
|
4183
|
+
}
|
|
4184
|
+
getName() {
|
|
4185
|
+
if (!this.url) {
|
|
4186
|
+
return "";
|
|
4187
|
+
}
|
|
4188
|
+
return this.url.split("/").at(-1) || "";
|
|
4189
|
+
}
|
|
4190
|
+
_validateAccessToken() {
|
|
4191
|
+
if (!this.accessToken) {
|
|
4192
|
+
console.error("no access token");
|
|
4193
|
+
throw new Error("no access token");
|
|
4194
|
+
}
|
|
4195
|
+
}
|
|
4196
|
+
static async getIsValidBranchName(branchName) {
|
|
4197
|
+
return isValidBranchName(branchName);
|
|
4198
|
+
}
|
|
4199
|
+
_validateAccessTokenAndUrl() {
|
|
4200
|
+
this._validateAccessToken();
|
|
4201
|
+
this._validateUrl();
|
|
4202
|
+
}
|
|
4203
|
+
_validateUrl() {
|
|
4204
|
+
if (!this.url) {
|
|
4205
|
+
console.error("no url");
|
|
4206
|
+
throw new InvalidRepoUrlError("no url");
|
|
4207
|
+
}
|
|
4208
|
+
}
|
|
4209
|
+
};
|
|
4210
|
+
|
|
4211
|
+
// src/features/analysis/scm/github/github.ts
|
|
4212
|
+
import { RequestError } from "@octokit/request-error";
|
|
4213
|
+
|
|
4214
|
+
// src/features/analysis/scm/constants.ts
|
|
4215
|
+
var MOBB_ICON_IMG = "https://app.mobb.ai/gh-action/Logo_Rounded_Icon.svg";
|
|
4216
|
+
var MAX_BRANCHES_FETCH = 1e3;
|
|
4217
|
+
|
|
4218
|
+
// src/features/analysis/scm/github/consts.ts
|
|
4219
|
+
var POST_COMMENT_PATH = "POST /repos/{owner}/{repo}/pulls/{pull_number}/comments";
|
|
4220
|
+
var DELETE_COMMENT_PATH = "DELETE /repos/{owner}/{repo}/pulls/comments/{comment_id}";
|
|
4221
|
+
var UPDATE_COMMENT_PATH = "PATCH /repos/{owner}/{repo}/pulls/comments/{comment_id}";
|
|
4222
|
+
var GET_PR_COMMENTS_PATH = "GET /repos/{owner}/{repo}/pulls/{pull_number}/comments";
|
|
4223
|
+
var GET_PR_COMMENT_PATH = "GET /repos/{owner}/{repo}/pulls/comments/{comment_id}";
|
|
4224
|
+
var REPLY_TO_CODE_REVIEW_COMMENT_PATH = "POST /repos/{owner}/{repo}/pulls/{pull_number}/comments/{comment_id}/replies";
|
|
4225
|
+
var GET_PR = "GET /repos/{owner}/{repo}/pulls/{pull_number}";
|
|
4226
|
+
var POST_GENERAL_PR_COMMENT = "POST /repos/{owner}/{repo}/issues/{issue_number}/comments";
|
|
4227
|
+
var GET_GENERAL_PR_COMMENTS = "GET /repos/{owner}/{repo}/issues/{issue_number}/comments";
|
|
4228
|
+
var DELETE_GENERAL_PR_COMMENT = "DELETE /repos/{owner}/{repo}/issues/comments/{comment_id}";
|
|
4229
|
+
var CREATE_OR_UPDATE_A_REPOSITORY_SECRET = "PUT /repos/{owner}/{repo}/actions/secrets/{secret_name}";
|
|
4230
|
+
var GET_A_REPOSITORY_PUBLIC_KEY = "GET /repos/{owner}/{repo}/actions/secrets/public-key";
|
|
4231
|
+
var GET_USER = "GET /user";
|
|
4232
|
+
var GET_USER_REPOS = "GET /user/repos";
|
|
4233
|
+
var GET_REPO_BRANCHES = "GET /repos/{owner}/{repo}/branches";
|
|
4234
|
+
var GET_BLAME_DOCUMENT = `
|
|
4235
|
+
query GetBlame(
|
|
4236
|
+
$owner: String!
|
|
4237
|
+
$repo: String!
|
|
4238
|
+
$ref: String!
|
|
4239
|
+
$path: String!
|
|
4240
|
+
) {
|
|
4241
|
+
repository(name: $repo, owner: $owner) {
|
|
4242
|
+
# branch name
|
|
4243
|
+
object(expression: $ref) {
|
|
4244
|
+
# cast Target to a Commit
|
|
4245
|
+
... on Commit {
|
|
4246
|
+
# full repo-relative path to blame file
|
|
4247
|
+
blame(path: $path) {
|
|
4248
|
+
ranges {
|
|
4249
|
+
commit {
|
|
4250
|
+
author {
|
|
4251
|
+
user {
|
|
4252
|
+
name
|
|
4253
|
+
login
|
|
4254
|
+
}
|
|
4255
|
+
}
|
|
4256
|
+
authoredDate
|
|
4257
|
+
}
|
|
4258
|
+
startingLine
|
|
4259
|
+
endingLine
|
|
4260
|
+
age
|
|
4261
|
+
}
|
|
4262
|
+
}
|
|
4263
|
+
}
|
|
4264
|
+
|
|
4265
|
+
}
|
|
4266
|
+
}
|
|
4267
|
+
}
|
|
4268
|
+
`;
|
|
4269
|
+
|
|
4270
|
+
// src/features/analysis/scm/github/utils/encrypt_secret.ts
|
|
4271
|
+
import sodium from "libsodium-wrappers";
|
|
4272
|
+
async function encryptSecret(secret, key) {
|
|
4273
|
+
await sodium.ready;
|
|
4274
|
+
const binkey = sodium.from_base64(key, sodium.base64_variants.ORIGINAL);
|
|
4275
|
+
const binsec = sodium.from_string(secret);
|
|
4276
|
+
const encBytes = sodium.crypto_box_seal(binsec, binkey);
|
|
4277
|
+
return sodium.to_base64(encBytes, sodium.base64_variants.ORIGINAL);
|
|
4278
|
+
}
|
|
4279
|
+
|
|
4280
|
+
// src/features/analysis/scm/github/utils/utils.ts
|
|
4281
|
+
import { Octokit } from "octokit";
|
|
4282
|
+
import { fetch as fetch2, ProxyAgent as ProxyAgent2 } from "undici";
|
|
4283
|
+
|
|
4284
|
+
// src/features/analysis/scm/ado/constants.ts
|
|
4285
|
+
var DEFUALT_ADO_ORIGIN = scmCloudUrl.Ado;
|
|
4286
|
+
|
|
4287
|
+
// src/features/analysis/scm/ado/utils.ts
|
|
4288
|
+
import querystring from "node:querystring";
|
|
4289
|
+
import * as api from "azure-devops-node-api";
|
|
4290
|
+
import Debug2 from "debug";
|
|
4291
|
+
import { z as z18 } from "zod";
|
|
4292
|
+
|
|
4293
|
+
// src/features/analysis/scm/env.ts
|
|
4294
|
+
import { z as z16 } from "zod";
|
|
4295
|
+
var EnvVariablesZod = z16.object({
|
|
4296
|
+
GITLAB_API_TOKEN: z16.string().optional(),
|
|
4297
|
+
GITHUB_API_TOKEN: z16.string().optional(),
|
|
4298
|
+
GIT_PROXY_HOST: z16.string()
|
|
4299
|
+
});
|
|
4300
|
+
var { GITLAB_API_TOKEN, GITHUB_API_TOKEN, GIT_PROXY_HOST } = EnvVariablesZod.parse(process.env);
|
|
4301
|
+
|
|
4302
|
+
// src/features/analysis/scm/ado/validation.ts
|
|
4303
|
+
import { z as z17 } from "zod";
|
|
4304
|
+
var ValidPullRequestStatusZ = z17.union([
|
|
4305
|
+
z17.literal(1 /* Active */),
|
|
4306
|
+
z17.literal(2 /* Abandoned */),
|
|
4307
|
+
z17.literal(3 /* Completed */)
|
|
4308
|
+
]);
|
|
4309
|
+
var AdoAuthResultZ = z17.object({
|
|
4310
|
+
access_token: z17.string().min(1),
|
|
4311
|
+
token_type: z17.string().min(1),
|
|
4312
|
+
refresh_token: z17.string().min(1)
|
|
4313
|
+
});
|
|
4314
|
+
var AdoAuthResultWithOrgsZ = AdoAuthResultZ.extend({
|
|
4315
|
+
scmOrgs: z17.array(z17.string())
|
|
4316
|
+
});
|
|
4317
|
+
var profileZ = z17.object({
|
|
4318
|
+
displayName: z17.string(),
|
|
4319
|
+
publicAlias: z17.string().min(1),
|
|
4320
|
+
emailAddress: z17.string(),
|
|
4321
|
+
coreRevision: z17.number(),
|
|
4322
|
+
timeStamp: z17.string(),
|
|
4323
|
+
id: z17.string(),
|
|
4324
|
+
revision: z17.number()
|
|
4325
|
+
});
|
|
4326
|
+
var accountsZ = z17.object({
|
|
4327
|
+
count: z17.number(),
|
|
4328
|
+
value: z17.array(
|
|
4329
|
+
z17.object({
|
|
4330
|
+
accountId: z17.string(),
|
|
4331
|
+
accountUri: z17.string(),
|
|
4332
|
+
accountName: z17.string()
|
|
4333
|
+
})
|
|
4334
|
+
)
|
|
4335
|
+
});
|
|
4336
|
+
|
|
4337
|
+
// src/features/analysis/scm/ado/utils.ts
|
|
4338
|
+
var debug2 = Debug2("mobbdev:scm:ado");
|
|
4339
|
+
function _getPublicAdoClient({
|
|
4340
|
+
orgName,
|
|
4341
|
+
origin: origin2
|
|
4342
|
+
}) {
|
|
4343
|
+
const orgUrl = `${origin2}/${orgName}`;
|
|
4344
|
+
const authHandler = api.getPersonalAccessTokenHandler("");
|
|
4345
|
+
authHandler.canHandleAuthentication = () => false;
|
|
4346
|
+
authHandler.prepareRequest = (_options) => {
|
|
4347
|
+
return;
|
|
4348
|
+
};
|
|
4349
|
+
const connection = new api.WebApi(orgUrl, authHandler);
|
|
4350
|
+
return connection;
|
|
4351
|
+
}
|
|
4352
|
+
function removeTrailingSlash(str) {
|
|
4353
|
+
return str.trim().replace(/\/+$/, "");
|
|
4354
|
+
}
|
|
4355
|
+
function parseAdoOwnerAndRepo(adoUrl) {
|
|
4356
|
+
adoUrl = removeTrailingSlash(adoUrl);
|
|
4357
|
+
const parsingResult = parseScmURL(adoUrl, "Ado" /* Ado */);
|
|
4358
|
+
if (!parsingResult || parsingResult.scmType !== "Ado" /* Ado */) {
|
|
4359
|
+
throw new InvalidUrlPatternError(`
|
|
4360
|
+
: ${adoUrl}`);
|
|
4361
|
+
}
|
|
4362
|
+
const {
|
|
4116
4363
|
organization,
|
|
4117
4364
|
repoName,
|
|
4118
4365
|
projectName,
|
|
@@ -4429,7 +4676,7 @@ async function getAdoSdk(params) {
|
|
|
4429
4676
|
const url = new URL(repoUrl);
|
|
4430
4677
|
const origin2 = url.origin.toLowerCase().endsWith(".visualstudio.com") ? DEFUALT_ADO_ORIGIN : url.origin.toLowerCase();
|
|
4431
4678
|
const params2 = `path=/&versionDescriptor[versionOptions]=0&versionDescriptor[versionType]=commit&versionDescriptor[version]=${branch}&resolveLfs=true&$format=zip&api-version=5.0&download=true`;
|
|
4432
|
-
const
|
|
4679
|
+
const path8 = [
|
|
4433
4680
|
prefixPath,
|
|
4434
4681
|
owner,
|
|
4435
4682
|
projectName,
|
|
@@ -4440,7 +4687,7 @@ async function getAdoSdk(params) {
|
|
|
4440
4687
|
"items",
|
|
4441
4688
|
"items"
|
|
4442
4689
|
].filter(Boolean).join("/");
|
|
4443
|
-
return new URL(`${
|
|
4690
|
+
return new URL(`${path8}?${params2}`, origin2).toString();
|
|
4444
4691
|
},
|
|
4445
4692
|
async getAdoBranchList({ repoUrl }) {
|
|
4446
4693
|
try {
|
|
@@ -4615,246 +4862,53 @@ async function getAdoRepoList({
|
|
|
4615
4862
|
...await getAdoClientParams({
|
|
4616
4863
|
accessToken,
|
|
4617
4864
|
tokenOrg: tokenOrg || org,
|
|
4618
|
-
url: void 0
|
|
4619
|
-
}),
|
|
4620
|
-
orgName: org
|
|
4621
|
-
});
|
|
4622
|
-
const gitOrg = await orgApi.getGitApi();
|
|
4623
|
-
const orgRepos = await gitOrg.getRepositories();
|
|
4624
|
-
const repoInfoList = (await Promise.allSettled(
|
|
4625
|
-
orgRepos.map(async (repo) => {
|
|
4626
|
-
if (!repo.name || !repo.remoteUrl || !repo.defaultBranch) {
|
|
4627
|
-
throw new InvalidRepoUrlError("bad repo");
|
|
4628
|
-
}
|
|
4629
|
-
const branch = await gitOrg.getBranch(
|
|
4630
|
-
repo.name,
|
|
4631
|
-
repo.defaultBranch.replace(/^refs\/heads\//, ""),
|
|
4632
|
-
repo.project?.name
|
|
4633
|
-
);
|
|
4634
|
-
return {
|
|
4635
|
-
repoName: repo.name,
|
|
4636
|
-
repoUrl: repo.remoteUrl.replace(
|
|
4637
|
-
/^[hH][tT][tT][pP][sS]:\/\/[^/]+@/,
|
|
4638
|
-
"https://"
|
|
4639
|
-
),
|
|
4640
|
-
repoOwner: org,
|
|
4641
|
-
repoIsPublic: repo.project?.visibility === 2 /* Public */,
|
|
4642
|
-
repoLanguages: [],
|
|
4643
|
-
repoUpdatedAt: branch.commit?.committer?.date?.toDateString() || repo.project?.lastUpdateTime?.toDateString() || (/* @__PURE__ */ new Date()).toDateString()
|
|
4644
|
-
};
|
|
4645
|
-
})
|
|
4646
|
-
)).reduce((acc, res) => {
|
|
4647
|
-
if (res.status === "fulfilled") {
|
|
4648
|
-
acc.push(res.value);
|
|
4649
|
-
}
|
|
4650
|
-
return acc;
|
|
4651
|
-
}, []);
|
|
4652
|
-
return repoInfoList;
|
|
4653
|
-
})
|
|
4654
|
-
)).reduce((acc, res) => {
|
|
4655
|
-
if (res.status === "fulfilled") {
|
|
4656
|
-
return acc.concat(res.value);
|
|
4657
|
-
}
|
|
4658
|
-
return acc;
|
|
4659
|
-
}, []);
|
|
4660
|
-
return repos;
|
|
4661
|
-
}
|
|
4662
|
-
|
|
4663
|
-
// src/features/analysis/scm/ado/AdoSCMLib.ts
|
|
4664
|
-
import { setTimeout as setTimeout2 } from "node:timers/promises";
|
|
4665
|
-
|
|
4666
|
-
// src/features/analysis/scm/scmSubmit/index.ts
|
|
4667
|
-
import fs2 from "node:fs/promises";
|
|
4668
|
-
import parseDiff from "parse-diff";
|
|
4669
|
-
import path4 from "path";
|
|
4670
|
-
import { simpleGit } from "simple-git";
|
|
4671
|
-
import tmp from "tmp";
|
|
4672
|
-
import { z as z20 } from "zod";
|
|
4673
|
-
|
|
4674
|
-
// src/features/analysis/scm/scmSubmit/types.ts
|
|
4675
|
-
import { z as z19 } from "zod";
|
|
4676
|
-
var BaseSubmitToScmMessageZ = z19.object({
|
|
4677
|
-
submitFixRequestId: z19.string().uuid(),
|
|
4678
|
-
fixes: z19.array(
|
|
4679
|
-
z19.object({
|
|
4680
|
-
fixId: z19.string().uuid(),
|
|
4681
|
-
patchesOriginalEncodingBase64: z19.array(z19.string()),
|
|
4682
|
-
patches: z19.array(z19.string())
|
|
4683
|
-
})
|
|
4684
|
-
),
|
|
4685
|
-
commitHash: z19.string(),
|
|
4686
|
-
repoUrl: z19.string(),
|
|
4687
|
-
mobbUserEmail: z19.string(),
|
|
4688
|
-
extraHeaders: z19.record(z19.string(), z19.string()).default({})
|
|
4689
|
-
});
|
|
4690
|
-
var submitToScmMessageType = {
|
|
4691
|
-
commitToSameBranch: "commitToSameBranch",
|
|
4692
|
-
submitFixesForDifferentBranch: "submitFixesForDifferentBranch"
|
|
4693
|
-
};
|
|
4694
|
-
var CommitToSameBranchParamsZ = BaseSubmitToScmMessageZ.merge(
|
|
4695
|
-
z19.object({
|
|
4696
|
-
type: z19.literal(submitToScmMessageType.commitToSameBranch),
|
|
4697
|
-
branch: z19.string(),
|
|
4698
|
-
commitMessages: z19.array(z19.string()),
|
|
4699
|
-
commitDescriptions: z19.array(z19.string().nullish()),
|
|
4700
|
-
githubCommentId: z19.number().nullish(),
|
|
4701
|
-
prId: z19.number().nullish()
|
|
4702
|
-
})
|
|
4703
|
-
);
|
|
4704
|
-
var SubmitFixesToDifferentBranchParamsZ = z19.object({
|
|
4705
|
-
type: z19.literal(submitToScmMessageType.submitFixesForDifferentBranch),
|
|
4706
|
-
submitBranch: z19.string(),
|
|
4707
|
-
baseBranch: z19.string()
|
|
4708
|
-
}).merge(BaseSubmitToScmMessageZ);
|
|
4709
|
-
var SubmitFixesMessageZ = z19.union([
|
|
4710
|
-
CommitToSameBranchParamsZ,
|
|
4711
|
-
SubmitFixesToDifferentBranchParamsZ
|
|
4712
|
-
]);
|
|
4713
|
-
var FixResponseArrayZ = z19.array(
|
|
4714
|
-
z19.object({
|
|
4715
|
-
fixId: z19.string().uuid()
|
|
4716
|
-
})
|
|
4717
|
-
);
|
|
4718
|
-
var SubmitFixesBaseResponseMessageZ = z19.object({
|
|
4719
|
-
mobbUserEmail: z19.string(),
|
|
4720
|
-
submitFixRequestId: z19.string().uuid(),
|
|
4721
|
-
submitBranches: z19.array(
|
|
4722
|
-
z19.object({
|
|
4723
|
-
branchName: z19.string(),
|
|
4724
|
-
fixes: FixResponseArrayZ
|
|
4725
|
-
})
|
|
4726
|
-
),
|
|
4727
|
-
error: z19.object({
|
|
4728
|
-
type: z19.enum([
|
|
4729
|
-
"InitialRepoAccessError",
|
|
4730
|
-
"PushBranchError",
|
|
4731
|
-
"AllFixesConflictWithTargetBranchError",
|
|
4732
|
-
"InternalFixConflictError",
|
|
4733
|
-
"UnknownError"
|
|
4734
|
-
]),
|
|
4735
|
-
info: z19.object({
|
|
4736
|
-
message: z19.string(),
|
|
4737
|
-
pushBranchName: z19.string().optional()
|
|
4738
|
-
})
|
|
4739
|
-
}).optional()
|
|
4740
|
-
});
|
|
4741
|
-
var authorSchemaZ = z19.object({
|
|
4742
|
-
email: z19.string(),
|
|
4743
|
-
name: z19.string()
|
|
4744
|
-
}).nullable();
|
|
4745
|
-
var summarySchemaZ = z19.object({
|
|
4746
|
-
changes: z19.number(),
|
|
4747
|
-
insertions: z19.number(),
|
|
4748
|
-
deletions: z19.number()
|
|
4749
|
-
});
|
|
4750
|
-
var GitCommitZ = z19.object({
|
|
4751
|
-
author: authorSchemaZ,
|
|
4752
|
-
branch: z19.string(),
|
|
4753
|
-
commit: z19.string(),
|
|
4754
|
-
root: z19.boolean(),
|
|
4755
|
-
summary: summarySchemaZ
|
|
4756
|
-
});
|
|
4757
|
-
var SubmitFixesToSameBranchResponseMessageZ = z19.object({
|
|
4758
|
-
type: z19.literal(submitToScmMessageType.commitToSameBranch),
|
|
4759
|
-
githubCommentId: z19.number().nullish(),
|
|
4760
|
-
commits: z19.array(GitCommitZ),
|
|
4761
|
-
prId: z19.number().nullish()
|
|
4762
|
-
}).merge(SubmitFixesBaseResponseMessageZ);
|
|
4763
|
-
var SubmitFixesToDifferentBranchResponseMessageZ = z19.object({
|
|
4764
|
-
type: z19.literal(submitToScmMessageType.submitFixesForDifferentBranch),
|
|
4765
|
-
githubCommentId: z19.number().optional()
|
|
4766
|
-
}).merge(SubmitFixesBaseResponseMessageZ);
|
|
4767
|
-
var SubmitFixesResponseMessageZ = z19.discriminatedUnion("type", [
|
|
4768
|
-
SubmitFixesToSameBranchResponseMessageZ,
|
|
4769
|
-
SubmitFixesToDifferentBranchResponseMessageZ
|
|
4770
|
-
]);
|
|
4771
|
-
|
|
4772
|
-
// src/features/analysis/scm/scmSubmit/index.ts
|
|
4773
|
-
var isValidBranchName = async (branchName) => {
|
|
4774
|
-
const git = simpleGit();
|
|
4775
|
-
try {
|
|
4776
|
-
const res = await git.raw(["check-ref-format", "--branch", branchName]);
|
|
4777
|
-
if (res) {
|
|
4778
|
-
return true;
|
|
4779
|
-
}
|
|
4780
|
-
return false;
|
|
4781
|
-
} catch (e) {
|
|
4782
|
-
return false;
|
|
4783
|
-
}
|
|
4784
|
-
};
|
|
4785
|
-
var FixesZ = z20.array(
|
|
4786
|
-
z20.object({
|
|
4787
|
-
fixId: z20.string(),
|
|
4788
|
-
patchesOriginalEncodingBase64: z20.array(z20.string())
|
|
4789
|
-
})
|
|
4790
|
-
).nonempty();
|
|
4791
|
-
|
|
4792
|
-
// src/features/analysis/scm/scm.ts
|
|
4793
|
-
var SCMLib = class {
|
|
4794
|
-
constructor(url, accessToken, scmOrg) {
|
|
4795
|
-
__publicField(this, "url");
|
|
4796
|
-
__publicField(this, "accessToken");
|
|
4797
|
-
__publicField(this, "scmOrg");
|
|
4798
|
-
this.accessToken = accessToken;
|
|
4799
|
-
this.url = url;
|
|
4800
|
-
this.scmOrg = scmOrg;
|
|
4801
|
-
}
|
|
4802
|
-
async getUrlWithCredentials() {
|
|
4803
|
-
if (!this.url) {
|
|
4804
|
-
console.error("no url for getUrlWithCredentials()");
|
|
4805
|
-
throw new Error("no url");
|
|
4806
|
-
}
|
|
4807
|
-
const trimmedUrl = this.url.trim().replace(/\/$/, "");
|
|
4808
|
-
const accessToken = this.getAccessToken();
|
|
4809
|
-
if (!accessToken) {
|
|
4810
|
-
return trimmedUrl;
|
|
4811
|
-
}
|
|
4812
|
-
if (this.scmLibType === "ADO" /* ADO */) {
|
|
4813
|
-
const { host, protocol, pathname } = new URL(trimmedUrl);
|
|
4814
|
-
return `${protocol}//${accessToken}@${host}${pathname}`;
|
|
4815
|
-
}
|
|
4816
|
-
const finalUrl = this.scmLibType === "GITLAB" /* GITLAB */ ? `${trimmedUrl}.git` : trimmedUrl;
|
|
4817
|
-
const username = await this._getUsernameForAuthUrl();
|
|
4818
|
-
return buildAuthorizedRepoUrl({
|
|
4819
|
-
url: finalUrl,
|
|
4820
|
-
username,
|
|
4821
|
-
password: accessToken
|
|
4822
|
-
});
|
|
4823
|
-
}
|
|
4824
|
-
getAccessToken() {
|
|
4825
|
-
return this.accessToken || "";
|
|
4826
|
-
}
|
|
4827
|
-
getUrl() {
|
|
4828
|
-
return this.url;
|
|
4829
|
-
}
|
|
4830
|
-
getName() {
|
|
4831
|
-
if (!this.url) {
|
|
4832
|
-
return "";
|
|
4833
|
-
}
|
|
4834
|
-
return this.url.split("/").at(-1) || "";
|
|
4835
|
-
}
|
|
4836
|
-
_validateAccessToken() {
|
|
4837
|
-
if (!this.accessToken) {
|
|
4838
|
-
console.error("no access token");
|
|
4839
|
-
throw new Error("no access token");
|
|
4840
|
-
}
|
|
4841
|
-
}
|
|
4842
|
-
static async getIsValidBranchName(branchName) {
|
|
4843
|
-
return isValidBranchName(branchName);
|
|
4844
|
-
}
|
|
4845
|
-
_validateAccessTokenAndUrl() {
|
|
4846
|
-
this._validateAccessToken();
|
|
4847
|
-
this._validateUrl();
|
|
4848
|
-
}
|
|
4849
|
-
_validateUrl() {
|
|
4850
|
-
if (!this.url) {
|
|
4851
|
-
console.error("no url");
|
|
4852
|
-
throw new InvalidRepoUrlError("no url");
|
|
4865
|
+
url: void 0
|
|
4866
|
+
}),
|
|
4867
|
+
orgName: org
|
|
4868
|
+
});
|
|
4869
|
+
const gitOrg = await orgApi.getGitApi();
|
|
4870
|
+
const orgRepos = await gitOrg.getRepositories();
|
|
4871
|
+
const repoInfoList = (await Promise.allSettled(
|
|
4872
|
+
orgRepos.map(async (repo) => {
|
|
4873
|
+
if (!repo.name || !repo.remoteUrl || !repo.defaultBranch) {
|
|
4874
|
+
throw new InvalidRepoUrlError("bad repo");
|
|
4875
|
+
}
|
|
4876
|
+
const branch = await gitOrg.getBranch(
|
|
4877
|
+
repo.name,
|
|
4878
|
+
repo.defaultBranch.replace(/^refs\/heads\//, ""),
|
|
4879
|
+
repo.project?.name
|
|
4880
|
+
);
|
|
4881
|
+
return {
|
|
4882
|
+
repoName: repo.name,
|
|
4883
|
+
repoUrl: repo.remoteUrl.replace(
|
|
4884
|
+
/^[hH][tT][tT][pP][sS]:\/\/[^/]+@/,
|
|
4885
|
+
"https://"
|
|
4886
|
+
),
|
|
4887
|
+
repoOwner: org,
|
|
4888
|
+
repoIsPublic: repo.project?.visibility === 2 /* Public */,
|
|
4889
|
+
repoLanguages: [],
|
|
4890
|
+
repoUpdatedAt: branch.commit?.committer?.date?.toDateString() || repo.project?.lastUpdateTime?.toDateString() || (/* @__PURE__ */ new Date()).toDateString()
|
|
4891
|
+
};
|
|
4892
|
+
})
|
|
4893
|
+
)).reduce((acc, res) => {
|
|
4894
|
+
if (res.status === "fulfilled") {
|
|
4895
|
+
acc.push(res.value);
|
|
4896
|
+
}
|
|
4897
|
+
return acc;
|
|
4898
|
+
}, []);
|
|
4899
|
+
return repoInfoList;
|
|
4900
|
+
})
|
|
4901
|
+
)).reduce((acc, res) => {
|
|
4902
|
+
if (res.status === "fulfilled") {
|
|
4903
|
+
return acc.concat(res.value);
|
|
4853
4904
|
}
|
|
4854
|
-
|
|
4855
|
-
};
|
|
4905
|
+
return acc;
|
|
4906
|
+
}, []);
|
|
4907
|
+
return repos;
|
|
4908
|
+
}
|
|
4856
4909
|
|
|
4857
4910
|
// src/features/analysis/scm/ado/AdoSCMLib.ts
|
|
4911
|
+
import { setTimeout as setTimeout2 } from "node:timers/promises";
|
|
4858
4912
|
async function initAdoSdk(params) {
|
|
4859
4913
|
const { url, accessToken, scmOrg } = params;
|
|
4860
4914
|
const adoClientParams = await getAdoClientParams({
|
|
@@ -5049,33 +5103,33 @@ import querystring2 from "node:querystring";
|
|
|
5049
5103
|
import * as bitbucketPkgNode from "bitbucket";
|
|
5050
5104
|
import bitbucketPkg from "bitbucket";
|
|
5051
5105
|
import Debug3 from "debug";
|
|
5052
|
-
import { z as
|
|
5106
|
+
import { z as z20 } from "zod";
|
|
5053
5107
|
|
|
5054
5108
|
// src/features/analysis/scm/bitbucket/validation.ts
|
|
5055
|
-
import { z as
|
|
5056
|
-
var BitbucketAuthResultZ =
|
|
5057
|
-
access_token:
|
|
5058
|
-
token_type:
|
|
5059
|
-
refresh_token:
|
|
5109
|
+
import { z as z19 } from "zod";
|
|
5110
|
+
var BitbucketAuthResultZ = z19.object({
|
|
5111
|
+
access_token: z19.string(),
|
|
5112
|
+
token_type: z19.string(),
|
|
5113
|
+
refresh_token: z19.string()
|
|
5060
5114
|
});
|
|
5061
5115
|
|
|
5062
5116
|
// src/features/analysis/scm/bitbucket/bitbucket.ts
|
|
5063
5117
|
var debug3 = Debug3("scm:bitbucket");
|
|
5064
5118
|
var BITBUCKET_HOSTNAME = "bitbucket.org";
|
|
5065
|
-
var TokenExpiredErrorZ =
|
|
5066
|
-
status:
|
|
5067
|
-
error:
|
|
5068
|
-
type:
|
|
5069
|
-
error:
|
|
5070
|
-
message:
|
|
5119
|
+
var TokenExpiredErrorZ = z20.object({
|
|
5120
|
+
status: z20.number(),
|
|
5121
|
+
error: z20.object({
|
|
5122
|
+
type: z20.string(),
|
|
5123
|
+
error: z20.object({
|
|
5124
|
+
message: z20.string()
|
|
5071
5125
|
})
|
|
5072
5126
|
})
|
|
5073
5127
|
});
|
|
5074
5128
|
var BITBUCKET_ACCESS_TOKEN_URL = `https://${BITBUCKET_HOSTNAME}/site/oauth2/access_token`;
|
|
5075
|
-
var BitbucketParseResultZ =
|
|
5076
|
-
organization:
|
|
5077
|
-
repoName:
|
|
5078
|
-
hostname:
|
|
5129
|
+
var BitbucketParseResultZ = z20.object({
|
|
5130
|
+
organization: z20.string(),
|
|
5131
|
+
repoName: z20.string(),
|
|
5132
|
+
hostname: z20.literal(BITBUCKET_HOSTNAME)
|
|
5079
5133
|
});
|
|
5080
5134
|
function parseBitbucketOrganizationAndRepo(bitbucketUrl) {
|
|
5081
5135
|
const parsedGitHubUrl = normalizeUrl(bitbucketUrl);
|
|
@@ -5136,7 +5190,7 @@ function getBitbucketSdk(params) {
|
|
|
5136
5190
|
if (!res.data.values) {
|
|
5137
5191
|
return [];
|
|
5138
5192
|
}
|
|
5139
|
-
return res.data.values.filter((branch) => !!branch.name).map((branch) =>
|
|
5193
|
+
return res.data.values.filter((branch) => !!branch.name).map((branch) => z20.string().parse(branch.name));
|
|
5140
5194
|
},
|
|
5141
5195
|
async getIsUserCollaborator(params2) {
|
|
5142
5196
|
const { repoUrl } = params2;
|
|
@@ -5251,7 +5305,7 @@ function getBitbucketSdk(params) {
|
|
|
5251
5305
|
return GetRefererenceResultZ.parse({
|
|
5252
5306
|
sha: tagRes.data.target?.hash,
|
|
5253
5307
|
type: "TAG" /* TAG */,
|
|
5254
|
-
date: new Date(
|
|
5308
|
+
date: new Date(z20.string().parse(tagRes.data.target?.date))
|
|
5255
5309
|
});
|
|
5256
5310
|
},
|
|
5257
5311
|
async getBranchRef(params2) {
|
|
@@ -5259,7 +5313,7 @@ function getBitbucketSdk(params) {
|
|
|
5259
5313
|
return GetRefererenceResultZ.parse({
|
|
5260
5314
|
sha: getBranchRes.target?.hash,
|
|
5261
5315
|
type: "BRANCH" /* BRANCH */,
|
|
5262
|
-
date: new Date(
|
|
5316
|
+
date: new Date(z20.string().parse(getBranchRes.target?.date))
|
|
5263
5317
|
});
|
|
5264
5318
|
},
|
|
5265
5319
|
async getCommitRef(params2) {
|
|
@@ -5267,13 +5321,13 @@ function getBitbucketSdk(params) {
|
|
|
5267
5321
|
return GetRefererenceResultZ.parse({
|
|
5268
5322
|
sha: getCommitRes.hash,
|
|
5269
5323
|
type: "COMMIT" /* COMMIT */,
|
|
5270
|
-
date: new Date(
|
|
5324
|
+
date: new Date(z20.string().parse(getCommitRes.date))
|
|
5271
5325
|
});
|
|
5272
5326
|
},
|
|
5273
5327
|
async getDownloadUrl({ url, sha }) {
|
|
5274
5328
|
this.getReferenceData({ ref: sha, url });
|
|
5275
5329
|
const repoRes = await this.getRepo({ repoUrl: url });
|
|
5276
|
-
const parsedRepoUrl =
|
|
5330
|
+
const parsedRepoUrl = z20.string().url().parse(repoRes.links?.html?.href);
|
|
5277
5331
|
return `${parsedRepoUrl}/get/${sha}.zip`;
|
|
5278
5332
|
},
|
|
5279
5333
|
async getPullRequest(params2) {
|
|
@@ -5338,7 +5392,7 @@ async function validateBitbucketParams(params) {
|
|
|
5338
5392
|
}
|
|
5339
5393
|
async function getUsersworkspacesSlugs(bitbucketClient) {
|
|
5340
5394
|
const res = await bitbucketClient.workspaces.getWorkspaces({});
|
|
5341
|
-
return res.data.values?.map((v) =>
|
|
5395
|
+
return res.data.values?.map((v) => z20.string().parse(v.slug));
|
|
5342
5396
|
}
|
|
5343
5397
|
async function getllUsersrepositories(bitbucketClient) {
|
|
5344
5398
|
const userWorspacesSlugs = await getUsersworkspacesSlugs(bitbucketClient);
|
|
@@ -5366,10 +5420,10 @@ async function getRepositoriesByWorkspace(bitbucketClient, { workspaceSlug }) {
|
|
|
5366
5420
|
|
|
5367
5421
|
// src/features/analysis/scm/bitbucket/BitbucketSCMLib.ts
|
|
5368
5422
|
import { setTimeout as setTimeout3 } from "node:timers/promises";
|
|
5369
|
-
import { z as
|
|
5423
|
+
import { z as z21 } from "zod";
|
|
5370
5424
|
function getUserAndPassword(token) {
|
|
5371
5425
|
const [username, password] = token.split(":");
|
|
5372
|
-
const safePasswordAndUsername =
|
|
5426
|
+
const safePasswordAndUsername = z21.object({ username: z21.string(), password: z21.string() }).parse({ username, password });
|
|
5373
5427
|
return {
|
|
5374
5428
|
username: safePasswordAndUsername.username,
|
|
5375
5429
|
password: safePasswordAndUsername.password
|
|
@@ -5441,7 +5495,7 @@ var BitbucketSCMLib = class extends SCMLib {
|
|
|
5441
5495
|
return { username, password, authType };
|
|
5442
5496
|
}
|
|
5443
5497
|
case "token": {
|
|
5444
|
-
return { authType, token:
|
|
5498
|
+
return { authType, token: z21.string().parse(this.accessToken) };
|
|
5445
5499
|
}
|
|
5446
5500
|
case "public":
|
|
5447
5501
|
return { authType };
|
|
@@ -5455,7 +5509,7 @@ var BitbucketSCMLib = class extends SCMLib {
|
|
|
5455
5509
|
...params,
|
|
5456
5510
|
repoUrl: this.url
|
|
5457
5511
|
});
|
|
5458
|
-
return String(
|
|
5512
|
+
return String(z21.number().parse(pullRequestRes.id));
|
|
5459
5513
|
} catch (e) {
|
|
5460
5514
|
console.warn(
|
|
5461
5515
|
`error creating pull request for BB. Try number ${i + 1}`,
|
|
@@ -5531,319 +5585,70 @@ var BitbucketSCMLib = class extends SCMLib {
|
|
|
5531
5585
|
return res.name === branch;
|
|
5532
5586
|
} catch (e) {
|
|
5533
5587
|
return false;
|
|
5534
|
-
}
|
|
5535
|
-
}
|
|
5536
|
-
async getUserHasAccessToRepo() {
|
|
5537
|
-
this._validateAccessTokenAndUrl();
|
|
5538
|
-
return this.bitbucketSdk.getIsUserCollaborator({ repoUrl: this.url });
|
|
5539
|
-
}
|
|
5540
|
-
async getUsername() {
|
|
5541
|
-
this._validateAccessToken();
|
|
5542
|
-
const res = await this.bitbucketSdk.getUser();
|
|
5543
|
-
return z23.string().parse(res.username);
|
|
5544
|
-
}
|
|
5545
|
-
async getSubmitRequestStatus(_scmSubmitRequestId) {
|
|
5546
|
-
this._validateAccessTokenAndUrl();
|
|
5547
|
-
const pullRequestRes = await this.bitbucketSdk.getPullRequest({
|
|
5548
|
-
prNumber: Number(_scmSubmitRequestId),
|
|
5549
|
-
url: this.url
|
|
5550
|
-
});
|
|
5551
|
-
switch (pullRequestRes.state) {
|
|
5552
|
-
case "OPEN":
|
|
5553
|
-
return "open";
|
|
5554
|
-
case "MERGED":
|
|
5555
|
-
return "merged";
|
|
5556
|
-
case "DECLINED":
|
|
5557
|
-
return "closed";
|
|
5558
|
-
default:
|
|
5559
|
-
throw new Error(`unknown state ${pullRequestRes.state} `);
|
|
5560
|
-
}
|
|
5561
|
-
}
|
|
5562
|
-
async getRepoBlameRanges(_ref, _path) {
|
|
5563
|
-
return [];
|
|
5564
|
-
}
|
|
5565
|
-
async getReferenceData(ref) {
|
|
5566
|
-
this._validateUrl();
|
|
5567
|
-
return this.bitbucketSdk.getReferenceData({ url: this.url, ref });
|
|
5568
|
-
}
|
|
5569
|
-
async getRepoDefaultBranch() {
|
|
5570
|
-
this._validateUrl();
|
|
5571
|
-
const repoRes = await this.bitbucketSdk.getRepo({ repoUrl: this.url });
|
|
5572
|
-
return z23.string().parse(repoRes.mainbranch?.name);
|
|
5573
|
-
}
|
|
5574
|
-
getSubmitRequestUrl(submitRequestId) {
|
|
5575
|
-
this._validateUrl();
|
|
5576
|
-
const { repo_slug, workspace } = parseBitbucketOrganizationAndRepo(this.url);
|
|
5577
|
-
return Promise.resolve(
|
|
5578
|
-
`https://bitbucket.org/${workspace}/${repo_slug}/pull-requests/${submitRequestId}`
|
|
5579
|
-
);
|
|
5580
|
-
}
|
|
5581
|
-
async getSubmitRequestId(submitRequestUrl) {
|
|
5582
|
-
const match = submitRequestUrl.match(/\/pull-requests\/(\d+)/);
|
|
5583
|
-
return match?.[1] || "";
|
|
5584
|
-
}
|
|
5585
|
-
getCommitUrl(commitId) {
|
|
5586
|
-
this._validateUrl();
|
|
5587
|
-
const { repo_slug, workspace } = parseBitbucketOrganizationAndRepo(this.url);
|
|
5588
|
-
return Promise.resolve(
|
|
5589
|
-
`https://bitbucket.org/${workspace}/${repo_slug}/commits/${commitId}`
|
|
5590
|
-
);
|
|
5591
|
-
}
|
|
5592
|
-
async addCommentToSubmitRequest(submitRequestId, comment) {
|
|
5593
|
-
this._validateUrl();
|
|
5594
|
-
await this.bitbucketSdk.addCommentToPullRequest({
|
|
5595
|
-
prNumber: Number(submitRequestId),
|
|
5596
|
-
url: this.url,
|
|
5597
|
-
markdownComment: comment
|
|
5598
|
-
});
|
|
5599
|
-
}
|
|
5600
|
-
};
|
|
5601
|
-
|
|
5602
|
-
// src/features/analysis/scm/github/GithubSCMLib.ts
|
|
5603
|
-
import { z as z24 } from "zod";
|
|
5604
|
-
var GithubSCMLib = class extends SCMLib {
|
|
5605
|
-
// we don't always need a url, what's important is that we have an access token
|
|
5606
|
-
constructor(url, accessToken, scmOrg) {
|
|
5607
|
-
super(url, accessToken, scmOrg);
|
|
5608
|
-
__publicField(this, "githubSdk");
|
|
5609
|
-
this.githubSdk = getGithubSdk({
|
|
5610
|
-
auth: accessToken,
|
|
5611
|
-
url
|
|
5612
|
-
});
|
|
5613
|
-
}
|
|
5614
|
-
async createSubmitRequest(params) {
|
|
5615
|
-
this._validateAccessTokenAndUrl();
|
|
5616
|
-
const { targetBranchName, sourceBranchName, title, body } = params;
|
|
5617
|
-
const pullRequestResult = await this.githubSdk.createPullRequest({
|
|
5618
|
-
title,
|
|
5619
|
-
body,
|
|
5620
|
-
targetBranchName,
|
|
5621
|
-
sourceBranchName,
|
|
5622
|
-
repoUrl: this.url
|
|
5623
|
-
});
|
|
5624
|
-
return String(pullRequestResult.data.number);
|
|
5625
|
-
}
|
|
5626
|
-
async forkRepo(repoUrl) {
|
|
5627
|
-
this._validateAccessToken();
|
|
5628
|
-
return this.githubSdk.forkRepo({
|
|
5629
|
-
repoUrl
|
|
5630
|
-
});
|
|
5631
|
-
}
|
|
5632
|
-
async createOrUpdateRepositorySecret(params) {
|
|
5633
|
-
this._validateAccessTokenAndUrl();
|
|
5634
|
-
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
5635
|
-
const { data: repositoryPublicKeyResponse } = await this.githubSdk.getRepositoryPublicKey({ owner, repo });
|
|
5636
|
-
const { key_id, key } = repositoryPublicKeyResponse;
|
|
5637
|
-
const encryptedValue = await encryptSecret(params.value, key);
|
|
5638
|
-
return this.githubSdk.createOrUpdateRepositorySecret({
|
|
5639
|
-
encrypted_value: encryptedValue,
|
|
5640
|
-
secret_name: params.name,
|
|
5641
|
-
key_id,
|
|
5642
|
-
owner,
|
|
5643
|
-
repo
|
|
5644
|
-
});
|
|
5645
|
-
}
|
|
5646
|
-
async createPullRequestWithNewFile(sourceRepoUrl, filesPaths, userRepoUrl, title, body) {
|
|
5647
|
-
const { pull_request_url } = await this.githubSdk.createPr({
|
|
5648
|
-
sourceRepoUrl,
|
|
5649
|
-
filesPaths,
|
|
5650
|
-
userRepoUrl,
|
|
5651
|
-
title,
|
|
5652
|
-
body
|
|
5653
|
-
});
|
|
5654
|
-
return { pull_request_url };
|
|
5655
|
-
}
|
|
5656
|
-
async validateParams() {
|
|
5657
|
-
return githubValidateParams(this.url, this.accessToken);
|
|
5658
|
-
}
|
|
5659
|
-
async postPrComment(params) {
|
|
5660
|
-
this._validateAccessTokenAndUrl();
|
|
5661
|
-
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
5662
|
-
return this.githubSdk.postPrComment({
|
|
5663
|
-
...params,
|
|
5664
|
-
owner,
|
|
5665
|
-
repo
|
|
5666
|
-
});
|
|
5667
|
-
}
|
|
5668
|
-
async updatePrComment(params) {
|
|
5669
|
-
this._validateAccessTokenAndUrl();
|
|
5670
|
-
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
5671
|
-
return this.githubSdk.updatePrComment({
|
|
5672
|
-
...params,
|
|
5673
|
-
owner,
|
|
5674
|
-
repo
|
|
5675
|
-
});
|
|
5676
|
-
}
|
|
5677
|
-
async deleteComment(params) {
|
|
5678
|
-
this._validateAccessTokenAndUrl();
|
|
5679
|
-
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
5680
|
-
return this.githubSdk.deleteComment({
|
|
5681
|
-
...params,
|
|
5682
|
-
owner,
|
|
5683
|
-
repo
|
|
5684
|
-
});
|
|
5685
|
-
}
|
|
5686
|
-
async getPrComments(params) {
|
|
5687
|
-
this._validateAccessTokenAndUrl();
|
|
5688
|
-
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
5689
|
-
return this.githubSdk.getPrComments({
|
|
5690
|
-
per_page: 100,
|
|
5691
|
-
...params,
|
|
5692
|
-
owner,
|
|
5693
|
-
repo
|
|
5694
|
-
});
|
|
5695
|
-
}
|
|
5696
|
-
async getPrDiff(params) {
|
|
5697
|
-
this._validateAccessTokenAndUrl();
|
|
5698
|
-
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
5699
|
-
const prRes = await this.githubSdk.getPrDiff({
|
|
5700
|
-
...params,
|
|
5701
|
-
owner,
|
|
5702
|
-
repo
|
|
5703
|
-
});
|
|
5704
|
-
return z24.string().parse(prRes.data);
|
|
5705
|
-
}
|
|
5706
|
-
async getRepoList(_scmOrg) {
|
|
5707
|
-
this._validateAccessToken();
|
|
5708
|
-
return this.githubSdk.getGithubRepoList();
|
|
5709
|
-
}
|
|
5710
|
-
async getBranchList() {
|
|
5711
|
-
this._validateAccessTokenAndUrl();
|
|
5712
|
-
const branches = await this.githubSdk.getGithubBranchList(this.url);
|
|
5713
|
-
return branches.data.map((branch) => branch.name);
|
|
5714
|
-
}
|
|
5715
|
-
get scmLibType() {
|
|
5716
|
-
return "GITHUB" /* GITHUB */;
|
|
5717
|
-
}
|
|
5718
|
-
getAuthHeaders() {
|
|
5719
|
-
if (this.accessToken) {
|
|
5720
|
-
return { authorization: `Bearer ${this.accessToken}` };
|
|
5721
|
-
}
|
|
5722
|
-
return {};
|
|
5723
|
-
}
|
|
5724
|
-
getDownloadUrl(sha) {
|
|
5725
|
-
this._validateUrl();
|
|
5726
|
-
const res = parseScmURL(this.url, "GitHub" /* GitHub */);
|
|
5727
|
-
if (!res) {
|
|
5728
|
-
throw new InvalidRepoUrlError("invalid repo url");
|
|
5729
|
-
}
|
|
5730
|
-
const { protocol, hostname, organization, repoName } = res;
|
|
5731
|
-
const downloadUrl = isGithubOnPrem(this.url) ? `${protocol}//${hostname}/api/v3/repos/${organization}/${repoName}/zipball/${sha}` : `https://api.${hostname}/repos/${organization}/${repoName}/zipball/${sha}`;
|
|
5732
|
-
return Promise.resolve(downloadUrl);
|
|
5733
|
-
}
|
|
5734
|
-
async _getUsernameForAuthUrl() {
|
|
5735
|
-
return this.getUsername();
|
|
5736
|
-
}
|
|
5737
|
-
async getIsRemoteBranch(branch) {
|
|
5738
|
-
this._validateUrl();
|
|
5739
|
-
return this.githubSdk.getGithubIsRemoteBranch({ branch, repoUrl: this.url });
|
|
5588
|
+
}
|
|
5740
5589
|
}
|
|
5741
5590
|
async getUserHasAccessToRepo() {
|
|
5742
5591
|
this._validateAccessTokenAndUrl();
|
|
5743
|
-
|
|
5744
|
-
return this.githubSdk.getGithubIsUserCollaborator({
|
|
5745
|
-
repoUrl: this.url,
|
|
5746
|
-
username
|
|
5747
|
-
});
|
|
5592
|
+
return this.bitbucketSdk.getIsUserCollaborator({ repoUrl: this.url });
|
|
5748
5593
|
}
|
|
5749
5594
|
async getUsername() {
|
|
5750
5595
|
this._validateAccessToken();
|
|
5751
|
-
|
|
5752
|
-
|
|
5753
|
-
async getSubmitRequestStatus(scmSubmitRequestId) {
|
|
5754
|
-
this._validateAccessTokenAndUrl();
|
|
5755
|
-
return this.githubSdk.getGithubPullRequestStatus({
|
|
5756
|
-
repoUrl: this.url,
|
|
5757
|
-
prNumber: Number(scmSubmitRequestId)
|
|
5758
|
-
});
|
|
5596
|
+
const res = await this.bitbucketSdk.getUser();
|
|
5597
|
+
return z21.string().parse(res.username);
|
|
5759
5598
|
}
|
|
5760
|
-
async
|
|
5599
|
+
async getSubmitRequestStatus(_scmSubmitRequestId) {
|
|
5761
5600
|
this._validateAccessTokenAndUrl();
|
|
5762
|
-
await this.
|
|
5763
|
-
|
|
5764
|
-
|
|
5765
|
-
markdownComment: comment
|
|
5601
|
+
const pullRequestRes = await this.bitbucketSdk.getPullRequest({
|
|
5602
|
+
prNumber: Number(_scmSubmitRequestId),
|
|
5603
|
+
url: this.url
|
|
5766
5604
|
});
|
|
5605
|
+
switch (pullRequestRes.state) {
|
|
5606
|
+
case "OPEN":
|
|
5607
|
+
return "open";
|
|
5608
|
+
case "MERGED":
|
|
5609
|
+
return "merged";
|
|
5610
|
+
case "DECLINED":
|
|
5611
|
+
return "closed";
|
|
5612
|
+
default:
|
|
5613
|
+
throw new Error(`unknown state ${pullRequestRes.state} `);
|
|
5614
|
+
}
|
|
5767
5615
|
}
|
|
5768
|
-
async getRepoBlameRanges(
|
|
5769
|
-
|
|
5770
|
-
return await this.githubSdk.getGithubBlameRanges({
|
|
5771
|
-
ref,
|
|
5772
|
-
path: path9,
|
|
5773
|
-
gitHubUrl: this.url
|
|
5774
|
-
});
|
|
5616
|
+
async getRepoBlameRanges(_ref, _path) {
|
|
5617
|
+
return [];
|
|
5775
5618
|
}
|
|
5776
5619
|
async getReferenceData(ref) {
|
|
5777
5620
|
this._validateUrl();
|
|
5778
|
-
return this.
|
|
5779
|
-
}
|
|
5780
|
-
async getPrComment(commentId) {
|
|
5781
|
-
this._validateUrl();
|
|
5782
|
-
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
5783
|
-
return await this.githubSdk.getPrComment({
|
|
5784
|
-
repo,
|
|
5785
|
-
owner,
|
|
5786
|
-
comment_id: commentId
|
|
5787
|
-
});
|
|
5621
|
+
return this.bitbucketSdk.getReferenceData({ url: this.url, ref });
|
|
5788
5622
|
}
|
|
5789
5623
|
async getRepoDefaultBranch() {
|
|
5790
5624
|
this._validateUrl();
|
|
5791
|
-
|
|
5625
|
+
const repoRes = await this.bitbucketSdk.getRepo({ repoUrl: this.url });
|
|
5626
|
+
return z21.string().parse(repoRes.mainbranch?.name);
|
|
5792
5627
|
}
|
|
5793
|
-
|
|
5794
|
-
this.
|
|
5795
|
-
const {
|
|
5796
|
-
|
|
5797
|
-
|
|
5798
|
-
|
|
5799
|
-
pull_number: submitRequestUrl
|
|
5800
|
-
});
|
|
5801
|
-
return getPrRes.data.html_url;
|
|
5628
|
+
getSubmitRequestUrl(submitRequestId) {
|
|
5629
|
+
this._validateUrl();
|
|
5630
|
+
const { repo_slug, workspace } = parseBitbucketOrganizationAndRepo(this.url);
|
|
5631
|
+
return Promise.resolve(
|
|
5632
|
+
`https://bitbucket.org/${workspace}/${repo_slug}/pull-requests/${submitRequestId}`
|
|
5633
|
+
);
|
|
5802
5634
|
}
|
|
5803
5635
|
async getSubmitRequestId(submitRequestUrl) {
|
|
5804
|
-
const match = submitRequestUrl.match(/\/pull\/(\d+)/);
|
|
5636
|
+
const match = submitRequestUrl.match(/\/pull-requests\/(\d+)/);
|
|
5805
5637
|
return match?.[1] || "";
|
|
5806
5638
|
}
|
|
5807
|
-
|
|
5808
|
-
this.
|
|
5809
|
-
const {
|
|
5810
|
-
|
|
5811
|
-
|
|
5812
|
-
|
|
5813
|
-
commitSha: commitId
|
|
5814
|
-
});
|
|
5815
|
-
return getCommitRes.data.html_url;
|
|
5816
|
-
}
|
|
5817
|
-
async postGeneralPrComment(params) {
|
|
5818
|
-
const { prNumber, body } = params;
|
|
5819
|
-
this._validateAccessTokenAndUrl();
|
|
5820
|
-
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
5821
|
-
return await this.githubSdk.postGeneralPrComment({
|
|
5822
|
-
issue_number: prNumber,
|
|
5823
|
-
owner,
|
|
5824
|
-
repo,
|
|
5825
|
-
body
|
|
5826
|
-
});
|
|
5827
|
-
}
|
|
5828
|
-
async getGeneralPrComments(params) {
|
|
5829
|
-
const { prNumber } = params;
|
|
5830
|
-
this._validateAccessTokenAndUrl();
|
|
5831
|
-
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
5832
|
-
return await this.githubSdk.getGeneralPrComments({
|
|
5833
|
-
issue_number: prNumber,
|
|
5834
|
-
owner,
|
|
5835
|
-
repo
|
|
5836
|
-
});
|
|
5639
|
+
getCommitUrl(commitId) {
|
|
5640
|
+
this._validateUrl();
|
|
5641
|
+
const { repo_slug, workspace } = parseBitbucketOrganizationAndRepo(this.url);
|
|
5642
|
+
return Promise.resolve(
|
|
5643
|
+
`https://bitbucket.org/${workspace}/${repo_slug}/commits/${commitId}`
|
|
5644
|
+
);
|
|
5837
5645
|
}
|
|
5838
|
-
async
|
|
5839
|
-
|
|
5840
|
-
|
|
5841
|
-
|
|
5842
|
-
|
|
5843
|
-
|
|
5844
|
-
owner,
|
|
5845
|
-
repo,
|
|
5846
|
-
comment_id: commentId
|
|
5646
|
+
async addCommentToSubmitRequest(submitRequestId, comment) {
|
|
5647
|
+
this._validateUrl();
|
|
5648
|
+
await this.bitbucketSdk.addCommentToPullRequest({
|
|
5649
|
+
prNumber: Number(submitRequestId),
|
|
5650
|
+
url: this.url,
|
|
5651
|
+
markdownComment: comment
|
|
5847
5652
|
});
|
|
5848
5653
|
}
|
|
5849
5654
|
};
|
|
@@ -5863,11 +5668,11 @@ import {
|
|
|
5863
5668
|
} from "undici";
|
|
5864
5669
|
|
|
5865
5670
|
// src/features/analysis/scm/gitlab/types.ts
|
|
5866
|
-
import { z as
|
|
5867
|
-
var GitlabAuthResultZ =
|
|
5868
|
-
access_token:
|
|
5869
|
-
token_type:
|
|
5870
|
-
refresh_token:
|
|
5671
|
+
import { z as z22 } from "zod";
|
|
5672
|
+
var GitlabAuthResultZ = z22.object({
|
|
5673
|
+
access_token: z22.string(),
|
|
5674
|
+
token_type: z22.string(),
|
|
5675
|
+
refresh_token: z22.string()
|
|
5871
5676
|
});
|
|
5872
5677
|
|
|
5873
5678
|
// src/features/analysis/scm/gitlab/gitlab.ts
|
|
@@ -6165,13 +5970,13 @@ function parseGitlabOwnerAndRepo(gitlabUrl) {
|
|
|
6165
5970
|
const { organization, repoName, projectPath } = parsingResult;
|
|
6166
5971
|
return { owner: organization, repo: repoName, projectPath };
|
|
6167
5972
|
}
|
|
6168
|
-
async function getGitlabBlameRanges({ ref, gitlabUrl, path:
|
|
5973
|
+
async function getGitlabBlameRanges({ ref, gitlabUrl, path: path8 }, options) {
|
|
6169
5974
|
const { projectPath } = parseGitlabOwnerAndRepo(gitlabUrl);
|
|
6170
5975
|
const api2 = getGitBeaker({
|
|
6171
5976
|
url: gitlabUrl,
|
|
6172
5977
|
gitlabAuthToken: options?.gitlabAuthToken
|
|
6173
5978
|
});
|
|
6174
|
-
const resp = await api2.RepositoryFiles.allFileBlames(projectPath,
|
|
5979
|
+
const resp = await api2.RepositoryFiles.allFileBlames(projectPath, path8, ref);
|
|
6175
5980
|
let lineNumber = 1;
|
|
6176
5981
|
return resp.filter((range) => range.lines).map((range) => {
|
|
6177
5982
|
const oldLineNumber = lineNumber;
|
|
@@ -6357,10 +6162,10 @@ var GitlabSCMLib = class extends SCMLib {
|
|
|
6357
6162
|
markdownComment: comment
|
|
6358
6163
|
});
|
|
6359
6164
|
}
|
|
6360
|
-
async getRepoBlameRanges(ref,
|
|
6165
|
+
async getRepoBlameRanges(ref, path8) {
|
|
6361
6166
|
this._validateUrl();
|
|
6362
6167
|
return await getGitlabBlameRanges(
|
|
6363
|
-
{ ref, path:
|
|
6168
|
+
{ ref, path: path8, gitlabUrl: this.url },
|
|
6364
6169
|
{
|
|
6365
6170
|
url: this.url,
|
|
6366
6171
|
gitlabAuthToken: this.accessToken
|
|
@@ -6409,7 +6214,7 @@ var GitlabSCMLib = class extends SCMLib {
|
|
|
6409
6214
|
};
|
|
6410
6215
|
|
|
6411
6216
|
// src/features/analysis/scm/scmFactory.ts
|
|
6412
|
-
import { z as
|
|
6217
|
+
import { z as z23 } from "zod";
|
|
6413
6218
|
|
|
6414
6219
|
// src/features/analysis/scm/StubSCMLib.ts
|
|
6415
6220
|
var StubSCMLib = class extends SCMLib {
|
|
@@ -6531,7 +6336,7 @@ async function createScmLib({ url, accessToken, scmType, scmOrg }, { propagateEx
|
|
|
6531
6336
|
if (e instanceof InvalidRepoUrlError && url) {
|
|
6532
6337
|
throw new RepoNoTokenAccessError(
|
|
6533
6338
|
"no access to repo",
|
|
6534
|
-
scmLibScmTypeToScmType[
|
|
6339
|
+
scmLibScmTypeToScmType[z23.nativeEnum(ScmLibScmType).parse(scmType)]
|
|
6535
6340
|
);
|
|
6536
6341
|
}
|
|
6537
6342
|
console.error(`error validating scm: ${scmType} `, e);
|
|
@@ -6862,14 +6667,14 @@ function getGithubSdk(params = {}) {
|
|
|
6862
6667
|
};
|
|
6863
6668
|
},
|
|
6864
6669
|
async getGithubBlameRanges(params2) {
|
|
6865
|
-
const { ref, gitHubUrl, path:
|
|
6670
|
+
const { ref, gitHubUrl, path: path8 } = params2;
|
|
6866
6671
|
const { owner, repo } = parseGithubOwnerAndRepo(gitHubUrl);
|
|
6867
6672
|
const res = await octokit.graphql(
|
|
6868
6673
|
GET_BLAME_DOCUMENT,
|
|
6869
6674
|
{
|
|
6870
6675
|
owner,
|
|
6871
6676
|
repo,
|
|
6872
|
-
path:
|
|
6677
|
+
path: path8,
|
|
6873
6678
|
ref
|
|
6874
6679
|
}
|
|
6875
6680
|
);
|
|
@@ -7010,10 +6815,258 @@ function getGithubSdk(params = {}) {
|
|
|
7010
6815
|
};
|
|
7011
6816
|
}
|
|
7012
6817
|
|
|
6818
|
+
// src/features/analysis/scm/github/GithubSCMLib.ts
|
|
6819
|
+
var GithubSCMLib = class extends SCMLib {
|
|
6820
|
+
// we don't always need a url, what's important is that we have an access token
|
|
6821
|
+
constructor(url, accessToken, scmOrg) {
|
|
6822
|
+
super(url, accessToken, scmOrg);
|
|
6823
|
+
__publicField(this, "githubSdk");
|
|
6824
|
+
this.githubSdk = getGithubSdk({
|
|
6825
|
+
auth: accessToken,
|
|
6826
|
+
url
|
|
6827
|
+
});
|
|
6828
|
+
}
|
|
6829
|
+
async createSubmitRequest(params) {
|
|
6830
|
+
this._validateAccessTokenAndUrl();
|
|
6831
|
+
const { targetBranchName, sourceBranchName, title, body } = params;
|
|
6832
|
+
const pullRequestResult = await this.githubSdk.createPullRequest({
|
|
6833
|
+
title,
|
|
6834
|
+
body,
|
|
6835
|
+
targetBranchName,
|
|
6836
|
+
sourceBranchName,
|
|
6837
|
+
repoUrl: this.url
|
|
6838
|
+
});
|
|
6839
|
+
return String(pullRequestResult.data.number);
|
|
6840
|
+
}
|
|
6841
|
+
async forkRepo(repoUrl) {
|
|
6842
|
+
this._validateAccessToken();
|
|
6843
|
+
return this.githubSdk.forkRepo({
|
|
6844
|
+
repoUrl
|
|
6845
|
+
});
|
|
6846
|
+
}
|
|
6847
|
+
async createOrUpdateRepositorySecret(params) {
|
|
6848
|
+
this._validateAccessTokenAndUrl();
|
|
6849
|
+
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
6850
|
+
const { data: repositoryPublicKeyResponse } = await this.githubSdk.getRepositoryPublicKey({ owner, repo });
|
|
6851
|
+
const { key_id, key } = repositoryPublicKeyResponse;
|
|
6852
|
+
const encryptedValue = await encryptSecret(params.value, key);
|
|
6853
|
+
return this.githubSdk.createOrUpdateRepositorySecret({
|
|
6854
|
+
encrypted_value: encryptedValue,
|
|
6855
|
+
secret_name: params.name,
|
|
6856
|
+
key_id,
|
|
6857
|
+
owner,
|
|
6858
|
+
repo
|
|
6859
|
+
});
|
|
6860
|
+
}
|
|
6861
|
+
async createPullRequestWithNewFile(sourceRepoUrl, filesPaths, userRepoUrl, title, body) {
|
|
6862
|
+
const { pull_request_url } = await this.githubSdk.createPr({
|
|
6863
|
+
sourceRepoUrl,
|
|
6864
|
+
filesPaths,
|
|
6865
|
+
userRepoUrl,
|
|
6866
|
+
title,
|
|
6867
|
+
body
|
|
6868
|
+
});
|
|
6869
|
+
return { pull_request_url };
|
|
6870
|
+
}
|
|
6871
|
+
async validateParams() {
|
|
6872
|
+
return githubValidateParams(this.url, this.accessToken);
|
|
6873
|
+
}
|
|
6874
|
+
async postPrComment(params) {
|
|
6875
|
+
this._validateAccessTokenAndUrl();
|
|
6876
|
+
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
6877
|
+
return this.githubSdk.postPrComment({
|
|
6878
|
+
...params,
|
|
6879
|
+
owner,
|
|
6880
|
+
repo
|
|
6881
|
+
});
|
|
6882
|
+
}
|
|
6883
|
+
async updatePrComment(params) {
|
|
6884
|
+
this._validateAccessTokenAndUrl();
|
|
6885
|
+
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
6886
|
+
return this.githubSdk.updatePrComment({
|
|
6887
|
+
...params,
|
|
6888
|
+
owner,
|
|
6889
|
+
repo
|
|
6890
|
+
});
|
|
6891
|
+
}
|
|
6892
|
+
async deleteComment(params) {
|
|
6893
|
+
this._validateAccessTokenAndUrl();
|
|
6894
|
+
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
6895
|
+
return this.githubSdk.deleteComment({
|
|
6896
|
+
...params,
|
|
6897
|
+
owner,
|
|
6898
|
+
repo
|
|
6899
|
+
});
|
|
6900
|
+
}
|
|
6901
|
+
async getPrComments(params) {
|
|
6902
|
+
this._validateAccessTokenAndUrl();
|
|
6903
|
+
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
6904
|
+
return this.githubSdk.getPrComments({
|
|
6905
|
+
per_page: 100,
|
|
6906
|
+
...params,
|
|
6907
|
+
owner,
|
|
6908
|
+
repo
|
|
6909
|
+
});
|
|
6910
|
+
}
|
|
6911
|
+
async getPrDiff(params) {
|
|
6912
|
+
this._validateAccessTokenAndUrl();
|
|
6913
|
+
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
6914
|
+
const prRes = await this.githubSdk.getPrDiff({
|
|
6915
|
+
...params,
|
|
6916
|
+
owner,
|
|
6917
|
+
repo
|
|
6918
|
+
});
|
|
6919
|
+
return z24.string().parse(prRes.data);
|
|
6920
|
+
}
|
|
6921
|
+
async getRepoList(_scmOrg) {
|
|
6922
|
+
this._validateAccessToken();
|
|
6923
|
+
return this.githubSdk.getGithubRepoList();
|
|
6924
|
+
}
|
|
6925
|
+
async getBranchList() {
|
|
6926
|
+
this._validateAccessTokenAndUrl();
|
|
6927
|
+
const branches = await this.githubSdk.getGithubBranchList(this.url);
|
|
6928
|
+
return branches.data.map((branch) => branch.name);
|
|
6929
|
+
}
|
|
6930
|
+
get scmLibType() {
|
|
6931
|
+
return "GITHUB" /* GITHUB */;
|
|
6932
|
+
}
|
|
6933
|
+
getAuthHeaders() {
|
|
6934
|
+
if (this.accessToken) {
|
|
6935
|
+
return { authorization: `Bearer ${this.accessToken}` };
|
|
6936
|
+
}
|
|
6937
|
+
return {};
|
|
6938
|
+
}
|
|
6939
|
+
getDownloadUrl(sha) {
|
|
6940
|
+
this._validateUrl();
|
|
6941
|
+
const res = parseScmURL(this.url, "GitHub" /* GitHub */);
|
|
6942
|
+
if (!res) {
|
|
6943
|
+
throw new InvalidRepoUrlError("invalid repo url");
|
|
6944
|
+
}
|
|
6945
|
+
const { protocol, hostname, organization, repoName } = res;
|
|
6946
|
+
const downloadUrl = isGithubOnPrem(this.url) ? `${protocol}//${hostname}/api/v3/repos/${organization}/${repoName}/zipball/${sha}` : `https://api.${hostname}/repos/${organization}/${repoName}/zipball/${sha}`;
|
|
6947
|
+
return Promise.resolve(downloadUrl);
|
|
6948
|
+
}
|
|
6949
|
+
async _getUsernameForAuthUrl() {
|
|
6950
|
+
return this.getUsername();
|
|
6951
|
+
}
|
|
6952
|
+
async getIsRemoteBranch(branch) {
|
|
6953
|
+
this._validateUrl();
|
|
6954
|
+
return this.githubSdk.getGithubIsRemoteBranch({ branch, repoUrl: this.url });
|
|
6955
|
+
}
|
|
6956
|
+
async getUserHasAccessToRepo() {
|
|
6957
|
+
this._validateAccessTokenAndUrl();
|
|
6958
|
+
const username = await this.getUsername();
|
|
6959
|
+
return this.githubSdk.getGithubIsUserCollaborator({
|
|
6960
|
+
repoUrl: this.url,
|
|
6961
|
+
username
|
|
6962
|
+
});
|
|
6963
|
+
}
|
|
6964
|
+
async getUsername() {
|
|
6965
|
+
this._validateAccessToken();
|
|
6966
|
+
return this.githubSdk.getGithubUsername();
|
|
6967
|
+
}
|
|
6968
|
+
async getSubmitRequestStatus(scmSubmitRequestId) {
|
|
6969
|
+
this._validateAccessTokenAndUrl();
|
|
6970
|
+
return this.githubSdk.getGithubPullRequestStatus({
|
|
6971
|
+
repoUrl: this.url,
|
|
6972
|
+
prNumber: Number(scmSubmitRequestId)
|
|
6973
|
+
});
|
|
6974
|
+
}
|
|
6975
|
+
async addCommentToSubmitRequest(submitRequestId, comment) {
|
|
6976
|
+
this._validateAccessTokenAndUrl();
|
|
6977
|
+
await this.githubSdk.createMarkdownCommentOnPullRequest({
|
|
6978
|
+
repoUrl: this.url,
|
|
6979
|
+
prNumber: Number(submitRequestId),
|
|
6980
|
+
markdownComment: comment
|
|
6981
|
+
});
|
|
6982
|
+
}
|
|
6983
|
+
async getRepoBlameRanges(ref, path8) {
|
|
6984
|
+
this._validateUrl();
|
|
6985
|
+
return await this.githubSdk.getGithubBlameRanges({
|
|
6986
|
+
ref,
|
|
6987
|
+
path: path8,
|
|
6988
|
+
gitHubUrl: this.url
|
|
6989
|
+
});
|
|
6990
|
+
}
|
|
6991
|
+
async getReferenceData(ref) {
|
|
6992
|
+
this._validateUrl();
|
|
6993
|
+
return this.githubSdk.getGithubReferenceData({ ref, gitHubUrl: this.url });
|
|
6994
|
+
}
|
|
6995
|
+
async getPrComment(commentId) {
|
|
6996
|
+
this._validateUrl();
|
|
6997
|
+
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
6998
|
+
return await this.githubSdk.getPrComment({
|
|
6999
|
+
repo,
|
|
7000
|
+
owner,
|
|
7001
|
+
comment_id: commentId
|
|
7002
|
+
});
|
|
7003
|
+
}
|
|
7004
|
+
async getRepoDefaultBranch() {
|
|
7005
|
+
this._validateUrl();
|
|
7006
|
+
return await this.githubSdk.getGithubRepoDefaultBranch(this.url);
|
|
7007
|
+
}
|
|
7008
|
+
async getSubmitRequestUrl(submitRequestUrl) {
|
|
7009
|
+
this._validateAccessTokenAndUrl();
|
|
7010
|
+
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
7011
|
+
const getPrRes = await this.githubSdk.getPr({
|
|
7012
|
+
owner,
|
|
7013
|
+
repo,
|
|
7014
|
+
pull_number: submitRequestUrl
|
|
7015
|
+
});
|
|
7016
|
+
return getPrRes.data.html_url;
|
|
7017
|
+
}
|
|
7018
|
+
async getSubmitRequestId(submitRequestUrl) {
|
|
7019
|
+
const match = submitRequestUrl.match(/\/pull\/(\d+)/);
|
|
7020
|
+
return match?.[1] || "";
|
|
7021
|
+
}
|
|
7022
|
+
async getCommitUrl(commitId) {
|
|
7023
|
+
this._validateAccessTokenAndUrl();
|
|
7024
|
+
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
7025
|
+
const getCommitRes = await this.githubSdk.getCommit({
|
|
7026
|
+
owner,
|
|
7027
|
+
repo,
|
|
7028
|
+
commitSha: commitId
|
|
7029
|
+
});
|
|
7030
|
+
return getCommitRes.data.html_url;
|
|
7031
|
+
}
|
|
7032
|
+
async postGeneralPrComment(params) {
|
|
7033
|
+
const { prNumber, body } = params;
|
|
7034
|
+
this._validateAccessTokenAndUrl();
|
|
7035
|
+
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
7036
|
+
return await this.githubSdk.postGeneralPrComment({
|
|
7037
|
+
issue_number: prNumber,
|
|
7038
|
+
owner,
|
|
7039
|
+
repo,
|
|
7040
|
+
body
|
|
7041
|
+
});
|
|
7042
|
+
}
|
|
7043
|
+
async getGeneralPrComments(params) {
|
|
7044
|
+
const { prNumber } = params;
|
|
7045
|
+
this._validateAccessTokenAndUrl();
|
|
7046
|
+
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
7047
|
+
return await this.githubSdk.getGeneralPrComments({
|
|
7048
|
+
issue_number: prNumber,
|
|
7049
|
+
owner,
|
|
7050
|
+
repo
|
|
7051
|
+
});
|
|
7052
|
+
}
|
|
7053
|
+
async deleteGeneralPrComment({
|
|
7054
|
+
commentId
|
|
7055
|
+
}) {
|
|
7056
|
+
this._validateAccessTokenAndUrl();
|
|
7057
|
+
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
7058
|
+
return this.githubSdk.deleteGeneralPrComment({
|
|
7059
|
+
owner,
|
|
7060
|
+
repo,
|
|
7061
|
+
comment_id: commentId
|
|
7062
|
+
});
|
|
7063
|
+
}
|
|
7064
|
+
};
|
|
7065
|
+
|
|
7013
7066
|
// src/features/analysis/add_fix_comments_for_pr/utils/utils.ts
|
|
7014
7067
|
import Debug7 from "debug";
|
|
7015
|
-
import
|
|
7016
|
-
import { z as
|
|
7068
|
+
import parseDiff from "parse-diff";
|
|
7069
|
+
import { z as z26 } from "zod";
|
|
7017
7070
|
|
|
7018
7071
|
// src/features/analysis/utils/by_key.ts
|
|
7019
7072
|
function keyBy(array, keyBy2) {
|
|
@@ -7085,11 +7138,12 @@ var scannerToFriendlyString = {
|
|
|
7085
7138
|
|
|
7086
7139
|
// src/features/analysis/add_fix_comments_for_pr/utils/buildCommentBody.ts
|
|
7087
7140
|
import Debug6 from "debug";
|
|
7088
|
-
import { z as
|
|
7141
|
+
import { z as z25 } from "zod";
|
|
7089
7142
|
var debug6 = Debug6("mobbdev:handle-finished-analysis");
|
|
7090
7143
|
var getCommitFixButton = (commitUrl) => `<a href="${commitUrl}"><img src=${COMMIT_FIX_SVG}></a>`;
|
|
7091
|
-
function
|
|
7144
|
+
function buildFixCommentBody({
|
|
7092
7145
|
fix,
|
|
7146
|
+
issueId,
|
|
7093
7147
|
commentId,
|
|
7094
7148
|
commentUrl,
|
|
7095
7149
|
scanner,
|
|
@@ -7097,9 +7151,19 @@ function buildCommentBody({
|
|
|
7097
7151
|
projectId,
|
|
7098
7152
|
analysisId,
|
|
7099
7153
|
organizationId,
|
|
7100
|
-
patch
|
|
7154
|
+
patch,
|
|
7155
|
+
irrelevantIssueWithTags
|
|
7101
7156
|
}) {
|
|
7102
|
-
const
|
|
7157
|
+
const isIrrelevantIssueWithTags = irrelevantIssueWithTags?.[0]?.tag;
|
|
7158
|
+
const commitUrl = isIrrelevantIssueWithTags ? getCommitIssueUrl({
|
|
7159
|
+
appBaseUrl: WEB_APP_URL,
|
|
7160
|
+
issueId,
|
|
7161
|
+
projectId,
|
|
7162
|
+
analysisId,
|
|
7163
|
+
organizationId,
|
|
7164
|
+
redirectUrl: commentUrl,
|
|
7165
|
+
commentId
|
|
7166
|
+
}) : getCommitUrl({
|
|
7103
7167
|
appBaseUrl: WEB_APP_URL,
|
|
7104
7168
|
fixId,
|
|
7105
7169
|
projectId,
|
|
@@ -7108,7 +7172,15 @@ function buildCommentBody({
|
|
|
7108
7172
|
redirectUrl: commentUrl,
|
|
7109
7173
|
commentId
|
|
7110
7174
|
});
|
|
7111
|
-
const fixUrl =
|
|
7175
|
+
const fixUrl = isIrrelevantIssueWithTags ? getIssueUrlWithRedirect({
|
|
7176
|
+
appBaseUrl: WEB_APP_URL,
|
|
7177
|
+
issueId,
|
|
7178
|
+
projectId,
|
|
7179
|
+
analysisId,
|
|
7180
|
+
organizationId,
|
|
7181
|
+
redirectUrl: commentUrl,
|
|
7182
|
+
commentId
|
|
7183
|
+
}) : getFixUrlWithRedirect({
|
|
7112
7184
|
appBaseUrl: WEB_APP_URL,
|
|
7113
7185
|
fixId,
|
|
7114
7186
|
projectId,
|
|
@@ -7119,11 +7191,11 @@ function buildCommentBody({
|
|
|
7119
7191
|
});
|
|
7120
7192
|
const issueType = getIssueTypeFriendlyString(fix.safeIssueType);
|
|
7121
7193
|
const title = `# ${MobbIconMarkdown} ${issueType} fix is ready`;
|
|
7122
|
-
const validFixParseRes =
|
|
7194
|
+
const validFixParseRes = z25.object({
|
|
7123
7195
|
patchAndQuestions: PatchAndQuestionsZ,
|
|
7124
|
-
safeIssueLanguage:
|
|
7125
|
-
severityText:
|
|
7126
|
-
safeIssueType:
|
|
7196
|
+
safeIssueLanguage: z25.nativeEnum(IssueLanguage_Enum),
|
|
7197
|
+
severityText: z25.nativeEnum(Vulnerability_Severity_Enum),
|
|
7198
|
+
safeIssueType: z25.nativeEnum(IssueType_Enum)
|
|
7127
7199
|
}).safeParse(fix);
|
|
7128
7200
|
if (!validFixParseRes.success) {
|
|
7129
7201
|
debug6(
|
|
@@ -7140,7 +7212,8 @@ function buildCommentBody({
|
|
|
7140
7212
|
issueType: validFixParseRes.data.safeIssueType,
|
|
7141
7213
|
issueLanguage: validFixParseRes.data.safeIssueLanguage,
|
|
7142
7214
|
fixExtraContext: validFixParseRes.data.patchAndQuestions.extraContext
|
|
7143
|
-
})
|
|
7215
|
+
}),
|
|
7216
|
+
irrelevantIssueWithTags
|
|
7144
7217
|
}) : "";
|
|
7145
7218
|
const diff = `\`\`\`diff
|
|
7146
7219
|
${patch}
|
|
@@ -7154,6 +7227,37 @@ ${getCommitFixButton(
|
|
|
7154
7227
|
)}
|
|
7155
7228
|
${fixPageLink}`;
|
|
7156
7229
|
}
|
|
7230
|
+
function buildIssueCommentBody({
|
|
7231
|
+
issueId,
|
|
7232
|
+
commentId,
|
|
7233
|
+
commentUrl,
|
|
7234
|
+
scanner,
|
|
7235
|
+
issueType,
|
|
7236
|
+
projectId,
|
|
7237
|
+
analysisId,
|
|
7238
|
+
organizationId,
|
|
7239
|
+
irrelevantIssueWithTags
|
|
7240
|
+
}) {
|
|
7241
|
+
const issueUrl = getIssueUrlWithRedirect({
|
|
7242
|
+
appBaseUrl: WEB_APP_URL,
|
|
7243
|
+
issueId,
|
|
7244
|
+
projectId,
|
|
7245
|
+
analysisId,
|
|
7246
|
+
organizationId,
|
|
7247
|
+
redirectUrl: commentUrl,
|
|
7248
|
+
commentId
|
|
7249
|
+
});
|
|
7250
|
+
const title = `# ${MobbIconMarkdown} Irrelevant issues were spotted - no action required \u{1F9F9}`;
|
|
7251
|
+
const subTitle = getCommitIssueDescription({
|
|
7252
|
+
issueType,
|
|
7253
|
+
vendor: scannerToVulnerability_Report_Vendor_Enum[scanner],
|
|
7254
|
+
irrelevantIssueWithTags
|
|
7255
|
+
});
|
|
7256
|
+
const issuePageLink = `[Learn more and fine tune the issue](${issueUrl})`;
|
|
7257
|
+
return `${title}
|
|
7258
|
+
${subTitle}
|
|
7259
|
+
${issuePageLink}`;
|
|
7260
|
+
}
|
|
7157
7261
|
|
|
7158
7262
|
// src/features/analysis/add_fix_comments_for_pr/utils/utils.ts
|
|
7159
7263
|
var debug7 = Debug7("mobbdev:handle-finished-analysis");
|
|
@@ -7211,6 +7315,53 @@ function deleteAllPreviousGeneralPrComments(params) {
|
|
|
7211
7315
|
}
|
|
7212
7316
|
});
|
|
7213
7317
|
}
|
|
7318
|
+
async function postIssueComment(params) {
|
|
7319
|
+
const {
|
|
7320
|
+
vulnerabilityReportIssueCodeNode,
|
|
7321
|
+
projectId,
|
|
7322
|
+
analysisId,
|
|
7323
|
+
organizationId,
|
|
7324
|
+
scm,
|
|
7325
|
+
commitSha,
|
|
7326
|
+
pullRequest,
|
|
7327
|
+
scanner
|
|
7328
|
+
} = params;
|
|
7329
|
+
const {
|
|
7330
|
+
path: path8,
|
|
7331
|
+
startLine,
|
|
7332
|
+
vulnerabilityReportIssue: {
|
|
7333
|
+
vulnerabilityReportIssueTags,
|
|
7334
|
+
category,
|
|
7335
|
+
parsedIssueType
|
|
7336
|
+
},
|
|
7337
|
+
vulnerabilityReportIssueId
|
|
7338
|
+
} = vulnerabilityReportIssueCodeNode;
|
|
7339
|
+
const irrelevantIssueWithTags = mapCategoryToBucket[category] === "irrelevant" && vulnerabilityReportIssueTags?.length > 0 ? vulnerabilityReportIssueTags : [];
|
|
7340
|
+
const commentRes = await scm.postPrComment({
|
|
7341
|
+
body: `# ${MobbIconMarkdown} Your fix is ready!
|
|
7342
|
+
Refresh the page in order to see the changes.`,
|
|
7343
|
+
pull_number: pullRequest,
|
|
7344
|
+
commit_id: commitSha,
|
|
7345
|
+
path: path8,
|
|
7346
|
+
line: startLine
|
|
7347
|
+
});
|
|
7348
|
+
const commentId = commentRes.data.id;
|
|
7349
|
+
const commentBody = buildIssueCommentBody({
|
|
7350
|
+
issueId: vulnerabilityReportIssueId,
|
|
7351
|
+
issueType: parsedIssueType,
|
|
7352
|
+
irrelevantIssueWithTags,
|
|
7353
|
+
commentId,
|
|
7354
|
+
commentUrl: commentRes.data.html_url,
|
|
7355
|
+
scanner,
|
|
7356
|
+
projectId,
|
|
7357
|
+
analysisId,
|
|
7358
|
+
organizationId
|
|
7359
|
+
});
|
|
7360
|
+
return await scm.updatePrComment({
|
|
7361
|
+
body: commentBody,
|
|
7362
|
+
comment_id: commentId
|
|
7363
|
+
});
|
|
7364
|
+
}
|
|
7214
7365
|
async function postFixComment(params) {
|
|
7215
7366
|
const {
|
|
7216
7367
|
vulnerabilityReportIssueCodeNode,
|
|
@@ -7224,10 +7375,12 @@ async function postFixComment(params) {
|
|
|
7224
7375
|
scanner
|
|
7225
7376
|
} = params;
|
|
7226
7377
|
const {
|
|
7227
|
-
path:
|
|
7378
|
+
path: path8,
|
|
7228
7379
|
startLine,
|
|
7229
|
-
vulnerabilityReportIssue: { fixId }
|
|
7380
|
+
vulnerabilityReportIssue: { fixId, vulnerabilityReportIssueTags, category },
|
|
7381
|
+
vulnerabilityReportIssueId
|
|
7230
7382
|
} = vulnerabilityReportIssueCodeNode;
|
|
7383
|
+
const irrelevantIssueWithTags = mapCategoryToBucket[category] === "irrelevant" && vulnerabilityReportIssueTags?.length > 0 ? vulnerabilityReportIssueTags : [];
|
|
7231
7384
|
const fix = fixesById[fixId];
|
|
7232
7385
|
if (!fix || fix.patchAndQuestions.__typename !== "FixData") {
|
|
7233
7386
|
throw new Error(`fix ${fixId} not found`);
|
|
@@ -7240,12 +7393,14 @@ async function postFixComment(params) {
|
|
|
7240
7393
|
Refresh the page in order to see the changes.`,
|
|
7241
7394
|
pull_number: pullRequest,
|
|
7242
7395
|
commit_id: commitSha,
|
|
7243
|
-
path:
|
|
7396
|
+
path: path8,
|
|
7244
7397
|
line: startLine
|
|
7245
7398
|
});
|
|
7246
7399
|
const commentId = commentRes.data.id;
|
|
7247
|
-
const commentBody =
|
|
7400
|
+
const commentBody = buildFixCommentBody({
|
|
7248
7401
|
fix,
|
|
7402
|
+
issueId: vulnerabilityReportIssueId,
|
|
7403
|
+
irrelevantIssueWithTags,
|
|
7249
7404
|
commentId,
|
|
7250
7405
|
commentUrl: commentRes.data.html_url,
|
|
7251
7406
|
scanner,
|
|
@@ -7288,7 +7443,7 @@ ${summary.join("\n")}`;
|
|
|
7288
7443
|
}
|
|
7289
7444
|
async function getRelevantVulenrabilitiesFromDiff(params) {
|
|
7290
7445
|
const { gqlClient, diff, vulnerabilityReportId } = params;
|
|
7291
|
-
const parsedDiff =
|
|
7446
|
+
const parsedDiff = parseDiff(diff);
|
|
7292
7447
|
const fileHunks = parsedDiff.map((file) => {
|
|
7293
7448
|
const fileNumbers = file.chunks.flatMap((chunk) => chunk.changes).filter((change) => change.type === "add").map((_change) => {
|
|
7294
7449
|
const change = _change;
|
|
@@ -7296,7 +7451,7 @@ async function getRelevantVulenrabilitiesFromDiff(params) {
|
|
|
7296
7451
|
});
|
|
7297
7452
|
const lineAddedRanges = calculateRanges(fileNumbers);
|
|
7298
7453
|
const fileFilter = {
|
|
7299
|
-
path:
|
|
7454
|
+
path: z26.string().parse(file.to),
|
|
7300
7455
|
ranges: lineAddedRanges.map(([startLine, endLine]) => ({
|
|
7301
7456
|
endLine,
|
|
7302
7457
|
startLine
|
|
@@ -7399,7 +7554,7 @@ async function addFixCommentsForPr({
|
|
|
7399
7554
|
gqlClient,
|
|
7400
7555
|
scanner
|
|
7401
7556
|
}) {
|
|
7402
|
-
if (_scm instanceof GithubSCMLib
|
|
7557
|
+
if (!(_scm instanceof GithubSCMLib)) {
|
|
7403
7558
|
return;
|
|
7404
7559
|
}
|
|
7405
7560
|
const scm = _scm;
|
|
@@ -7421,7 +7576,10 @@ async function addFixCommentsForPr({
|
|
|
7421
7576
|
gqlClient,
|
|
7422
7577
|
vulnerabilityReportId: getAnalysisRes.vulnerabilityReportId
|
|
7423
7578
|
});
|
|
7424
|
-
const {
|
|
7579
|
+
const {
|
|
7580
|
+
vulnerabilityReportIssueCodeNodes,
|
|
7581
|
+
irrelevantVulnerabilityReportIssues
|
|
7582
|
+
} = prVulenrabilities;
|
|
7425
7583
|
const fixesId = vulnerabilityReportIssueCodeNodes.map(
|
|
7426
7584
|
({ vulnerabilityReportIssue: { fixId } }) => fixId
|
|
7427
7585
|
);
|
|
@@ -7450,6 +7608,33 @@ async function addFixCommentsForPr({
|
|
|
7450
7608
|
});
|
|
7451
7609
|
}
|
|
7452
7610
|
),
|
|
7611
|
+
...irrelevantVulnerabilityReportIssues.map((vulnerabilityReportIssue) => {
|
|
7612
|
+
return vulnerabilityReportIssue.codeNodes.map(
|
|
7613
|
+
(vulnerabilityReportIssueCodeNode) => {
|
|
7614
|
+
return postIssueComment({
|
|
7615
|
+
vulnerabilityReportIssueCodeNode: {
|
|
7616
|
+
path: vulnerabilityReportIssueCodeNode.path,
|
|
7617
|
+
startLine: vulnerabilityReportIssueCodeNode.startLine,
|
|
7618
|
+
vulnerabilityReportIssue: {
|
|
7619
|
+
fixId: "",
|
|
7620
|
+
parsedIssueType: vulnerabilityReportIssue.parsedIssueType,
|
|
7621
|
+
vulnerabilityReportIssueTags: vulnerabilityReportIssue.vulnerabilityReportIssueTags,
|
|
7622
|
+
category: vulnerabilityReportIssue.category
|
|
7623
|
+
},
|
|
7624
|
+
vulnerabilityReportIssueId: vulnerabilityReportIssue.id
|
|
7625
|
+
},
|
|
7626
|
+
projectId,
|
|
7627
|
+
analysisId,
|
|
7628
|
+
organizationId,
|
|
7629
|
+
fixesById,
|
|
7630
|
+
scm,
|
|
7631
|
+
pullRequest,
|
|
7632
|
+
scanner,
|
|
7633
|
+
commitSha
|
|
7634
|
+
});
|
|
7635
|
+
}
|
|
7636
|
+
);
|
|
7637
|
+
}),
|
|
7453
7638
|
postAnalysisInsightComment({
|
|
7454
7639
|
prVulenrabilities,
|
|
7455
7640
|
pullRequest,
|
|
@@ -7648,32 +7833,63 @@ function subscribe(query, variables, callback, wsClientOptions) {
|
|
|
7648
7833
|
}
|
|
7649
7834
|
|
|
7650
7835
|
// src/features/analysis/graphql/types.ts
|
|
7651
|
-
import { z as
|
|
7652
|
-
var VulnerabilityReportIssueCodeNodeZ =
|
|
7653
|
-
vulnerabilityReportIssueId:
|
|
7654
|
-
path:
|
|
7655
|
-
startLine:
|
|
7656
|
-
vulnerabilityReportIssue:
|
|
7657
|
-
fixId:
|
|
7836
|
+
import { z as z27 } from "zod";
|
|
7837
|
+
var VulnerabilityReportIssueCodeNodeZ = z27.object({
|
|
7838
|
+
vulnerabilityReportIssueId: z27.string(),
|
|
7839
|
+
path: z27.string(),
|
|
7840
|
+
startLine: z27.number(),
|
|
7841
|
+
vulnerabilityReportIssue: z27.object({
|
|
7842
|
+
fixId: z27.string(),
|
|
7843
|
+
category: ValidCategoriesZ,
|
|
7844
|
+
parsedIssueType: z27.string(),
|
|
7845
|
+
vulnerabilityReportIssueTags: z27.array(
|
|
7846
|
+
z27.object({
|
|
7847
|
+
tag: z27.nativeEnum(Vulnerability_Report_Issue_Tag_Enum)
|
|
7848
|
+
})
|
|
7849
|
+
)
|
|
7658
7850
|
})
|
|
7659
7851
|
});
|
|
7660
|
-
var
|
|
7661
|
-
|
|
7662
|
-
|
|
7663
|
-
|
|
7664
|
-
|
|
7852
|
+
var VulnerabilityReportIssueNoFixCodeNodeZ = z27.object({
|
|
7853
|
+
vulnerabilityReportIssues: z27.array(
|
|
7854
|
+
z27.object({
|
|
7855
|
+
id: z27.string(),
|
|
7856
|
+
fixId: z27.string().nullable(),
|
|
7857
|
+
category: ValidCategoriesZ,
|
|
7858
|
+
parsedIssueType: z27.string(),
|
|
7859
|
+
codeNodes: z27.array(
|
|
7860
|
+
z27.object({
|
|
7861
|
+
path: z27.string(),
|
|
7862
|
+
startLine: z27.number()
|
|
7863
|
+
})
|
|
7864
|
+
),
|
|
7865
|
+
vulnerabilityReportIssueTags: z27.array(
|
|
7866
|
+
z27.object({
|
|
7867
|
+
tag: z27.nativeEnum(Vulnerability_Report_Issue_Tag_Enum)
|
|
7868
|
+
})
|
|
7869
|
+
)
|
|
7870
|
+
})
|
|
7871
|
+
)
|
|
7872
|
+
});
|
|
7873
|
+
var GetVulByNodesMetadataZ = z27.object({
|
|
7874
|
+
vulnerabilityReportIssueCodeNodes: z27.array(VulnerabilityReportIssueCodeNodeZ),
|
|
7875
|
+
nonFixablePrVuls: z27.object({
|
|
7876
|
+
aggregate: z27.object({
|
|
7877
|
+
count: z27.number()
|
|
7665
7878
|
})
|
|
7666
7879
|
}),
|
|
7667
|
-
fixablePrVuls:
|
|
7668
|
-
aggregate:
|
|
7669
|
-
count:
|
|
7880
|
+
fixablePrVuls: z27.object({
|
|
7881
|
+
aggregate: z27.object({
|
|
7882
|
+
count: z27.number()
|
|
7670
7883
|
})
|
|
7671
7884
|
}),
|
|
7672
|
-
totalScanVulnerabilities:
|
|
7673
|
-
aggregate:
|
|
7674
|
-
count:
|
|
7885
|
+
totalScanVulnerabilities: z27.object({
|
|
7886
|
+
aggregate: z27.object({
|
|
7887
|
+
count: z27.number()
|
|
7675
7888
|
})
|
|
7676
|
-
})
|
|
7889
|
+
}),
|
|
7890
|
+
irrelevantVulnerabilityReportIssue: z27.array(
|
|
7891
|
+
VulnerabilityReportIssueNoFixCodeNodeZ
|
|
7892
|
+
)
|
|
7677
7893
|
});
|
|
7678
7894
|
|
|
7679
7895
|
// src/features/analysis/graphql/gql.ts
|
|
@@ -7825,6 +8041,7 @@ var GQLClient = class {
|
|
|
7825
8041
|
const totalScanVulnerabilities = parsedGetVulByNodesMetadataRes.totalScanVulnerabilities.aggregate.count;
|
|
7826
8042
|
const vulnerabilitiesOutsidePr = totalScanVulnerabilities - nonFixablePrVuls - fixablePrVuls;
|
|
7827
8043
|
const totalPrVulnerabilities = nonFixablePrVuls + fixablePrVuls;
|
|
8044
|
+
const irrelevantVulnerabilityReportIssues = parsedGetVulByNodesMetadataRes.irrelevantVulnerabilityReportIssue?.[0]?.vulnerabilityReportIssues ?? [];
|
|
7828
8045
|
return {
|
|
7829
8046
|
vulnerabilityReportIssueCodeNodes: Object.values(
|
|
7830
8047
|
uniqueVulByNodesMetadata
|
|
@@ -7833,7 +8050,8 @@ var GQLClient = class {
|
|
|
7833
8050
|
fixablePrVuls,
|
|
7834
8051
|
totalScanVulnerabilities,
|
|
7835
8052
|
vulnerabilitiesOutsidePr,
|
|
7836
|
-
totalPrVulnerabilities
|
|
8053
|
+
totalPrVulnerabilities,
|
|
8054
|
+
irrelevantVulnerabilityReportIssues
|
|
7837
8055
|
};
|
|
7838
8056
|
}
|
|
7839
8057
|
async digestVulnerabilityReport({
|
|
@@ -7961,24 +8179,24 @@ var GQLClient = class {
|
|
|
7961
8179
|
};
|
|
7962
8180
|
|
|
7963
8181
|
// src/features/analysis/pack.ts
|
|
7964
|
-
import
|
|
7965
|
-
import
|
|
8182
|
+
import fs2 from "node:fs";
|
|
8183
|
+
import path4 from "node:path";
|
|
7966
8184
|
import AdmZip from "adm-zip";
|
|
7967
8185
|
import Debug12 from "debug";
|
|
7968
8186
|
import { globby } from "globby";
|
|
7969
8187
|
import { isBinary } from "istextorbinary";
|
|
7970
8188
|
import { simpleGit as simpleGit3 } from "simple-git";
|
|
7971
8189
|
import { parseStringPromise } from "xml2js";
|
|
7972
|
-
import { z as
|
|
8190
|
+
import { z as z28 } from "zod";
|
|
7973
8191
|
var debug12 = Debug12("mobbdev:pack");
|
|
7974
8192
|
var MAX_FILE_SIZE = 1024 * 1024 * 5;
|
|
7975
|
-
var FPR_SOURCE_CODE_FILE_MAPPING_SCHEMA =
|
|
7976
|
-
properties:
|
|
7977
|
-
entry:
|
|
7978
|
-
|
|
7979
|
-
_:
|
|
7980
|
-
$:
|
|
7981
|
-
key:
|
|
8193
|
+
var FPR_SOURCE_CODE_FILE_MAPPING_SCHEMA = z28.object({
|
|
8194
|
+
properties: z28.object({
|
|
8195
|
+
entry: z28.array(
|
|
8196
|
+
z28.object({
|
|
8197
|
+
_: z28.string(),
|
|
8198
|
+
$: z28.object({
|
|
8199
|
+
key: z28.string()
|
|
7982
8200
|
})
|
|
7983
8201
|
})
|
|
7984
8202
|
)
|
|
@@ -8028,20 +8246,20 @@ async function pack(srcDirPath, vulnFiles) {
|
|
|
8028
8246
|
const zip = new AdmZip();
|
|
8029
8247
|
debug12("compressing files");
|
|
8030
8248
|
for (const filepath of filepaths) {
|
|
8031
|
-
const absFilepath =
|
|
8249
|
+
const absFilepath = path4.join(srcDirPath, filepath.toString());
|
|
8032
8250
|
vulnFiles = vulnFiles.concat(_get_manifest_files_suffixes());
|
|
8033
8251
|
if (!endsWithAny(
|
|
8034
|
-
absFilepath.toString().replaceAll(
|
|
8252
|
+
absFilepath.toString().replaceAll(path4.win32.sep, path4.posix.sep),
|
|
8035
8253
|
vulnFiles
|
|
8036
8254
|
)) {
|
|
8037
8255
|
debug12("ignoring %s because it is not a vulnerability file", filepath);
|
|
8038
8256
|
continue;
|
|
8039
8257
|
}
|
|
8040
|
-
if (
|
|
8258
|
+
if (fs2.lstatSync(absFilepath).size > MAX_FILE_SIZE) {
|
|
8041
8259
|
debug12("ignoring %s because the size is > 5MB", filepath);
|
|
8042
8260
|
continue;
|
|
8043
8261
|
}
|
|
8044
|
-
const data = git ? await git.showBuffer([`HEAD:./${filepath}`]) :
|
|
8262
|
+
const data = git ? await git.showBuffer([`HEAD:./${filepath}`]) : fs2.readFileSync(absFilepath);
|
|
8045
8263
|
if (isBinary(null, data)) {
|
|
8046
8264
|
debug12("ignoring %s because is seems to be a binary file", filepath);
|
|
8047
8265
|
continue;
|
|
@@ -8198,7 +8416,7 @@ import Debug14 from "debug";
|
|
|
8198
8416
|
import { existsSync } from "fs";
|
|
8199
8417
|
import { createSpinner as createSpinner2 } from "nanospinner";
|
|
8200
8418
|
import { type } from "os";
|
|
8201
|
-
import
|
|
8419
|
+
import path5 from "path";
|
|
8202
8420
|
var debug13 = Debug14("mobbdev:checkmarx");
|
|
8203
8421
|
var require2 = createRequire(import.meta.url);
|
|
8204
8422
|
var getCheckmarxPath = () => {
|
|
@@ -8258,9 +8476,9 @@ async function getCheckmarxReport({ reportPath, repositoryRoot, branch, projectN
|
|
|
8258
8476
|
await startCheckmarxConfigationPrompt();
|
|
8259
8477
|
await validateCheckamxCredentials();
|
|
8260
8478
|
}
|
|
8261
|
-
const extension =
|
|
8262
|
-
const filePath =
|
|
8263
|
-
const fileName =
|
|
8479
|
+
const extension = path5.extname(reportPath);
|
|
8480
|
+
const filePath = path5.dirname(reportPath);
|
|
8481
|
+
const fileName = path5.basename(reportPath, extension);
|
|
8264
8482
|
const checkmarxCommandArgs = getCheckmarxCommandArgs({
|
|
8265
8483
|
repoPath: repositoryRoot,
|
|
8266
8484
|
branch,
|
|
@@ -8442,7 +8660,7 @@ async function downloadRepo({
|
|
|
8442
8660
|
const { createSpinner: createSpinner5 } = Spinner2({ ci });
|
|
8443
8661
|
const repoSpinner = createSpinner5("\u{1F4BE} Downloading Repo").start();
|
|
8444
8662
|
debug16("download repo %s %s %s", repoUrl, dirname);
|
|
8445
|
-
const zipFilePath =
|
|
8663
|
+
const zipFilePath = path6.join(dirname, "repo.zip");
|
|
8446
8664
|
debug16("download URL: %s auth headers: %o", downloadUrl, authHeaders);
|
|
8447
8665
|
const response = await fetch4(downloadUrl, {
|
|
8448
8666
|
method: "GET",
|
|
@@ -8455,19 +8673,19 @@ async function downloadRepo({
|
|
|
8455
8673
|
repoSpinner.error({ text: "\u{1F4BE} Repo download failed" });
|
|
8456
8674
|
throw new Error(`Can't access ${chalk4.bold(repoUrl)}`);
|
|
8457
8675
|
}
|
|
8458
|
-
const fileWriterStream =
|
|
8676
|
+
const fileWriterStream = fs3.createWriteStream(zipFilePath);
|
|
8459
8677
|
if (!response.body) {
|
|
8460
8678
|
throw new Error("Response body is empty");
|
|
8461
8679
|
}
|
|
8462
8680
|
await pipeline(response.body, fileWriterStream);
|
|
8463
8681
|
await extract(zipFilePath, { dir: dirname });
|
|
8464
|
-
const repoRoot =
|
|
8682
|
+
const repoRoot = fs3.readdirSync(dirname, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name)[0];
|
|
8465
8683
|
if (!repoRoot) {
|
|
8466
8684
|
throw new Error("Repo root not found");
|
|
8467
8685
|
}
|
|
8468
8686
|
debug16("repo root %s", repoRoot);
|
|
8469
8687
|
repoSpinner.success({ text: "\u{1F4BE} Repo downloaded successfully" });
|
|
8470
|
-
return
|
|
8688
|
+
return path6.join(dirname, repoRoot);
|
|
8471
8689
|
}
|
|
8472
8690
|
var getReportUrl = ({
|
|
8473
8691
|
organizationId,
|
|
@@ -8478,7 +8696,7 @@ var debug16 = Debug17("mobbdev:index");
|
|
|
8478
8696
|
var config2 = new Configstore(packageJson.name, { apiToken: "" });
|
|
8479
8697
|
debug16("config %o", config2);
|
|
8480
8698
|
async function runAnalysis(params, options) {
|
|
8481
|
-
const tmpObj =
|
|
8699
|
+
const tmpObj = tmp.dirSync({
|
|
8482
8700
|
unsafeCleanup: true
|
|
8483
8701
|
});
|
|
8484
8702
|
try {
|
|
@@ -8577,7 +8795,7 @@ async function getReport(params, { skipPrompts }) {
|
|
|
8577
8795
|
authHeaders: scm.getAuthHeaders(),
|
|
8578
8796
|
downloadUrl
|
|
8579
8797
|
});
|
|
8580
|
-
const reportPath =
|
|
8798
|
+
const reportPath = path6.join(dirname, "report.json");
|
|
8581
8799
|
switch (scanner) {
|
|
8582
8800
|
case "snyk":
|
|
8583
8801
|
await getSnykReport(reportPath, repositoryRoot, { skipPrompts });
|
|
@@ -8737,7 +8955,7 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
8737
8955
|
spinner: mobbSpinner,
|
|
8738
8956
|
submitVulnerabilityReportVariables: {
|
|
8739
8957
|
fixReportId: reportUploadInfo.fixReportId,
|
|
8740
|
-
repoUrl:
|
|
8958
|
+
repoUrl: z29.string().parse(repo),
|
|
8741
8959
|
reference,
|
|
8742
8960
|
projectId,
|
|
8743
8961
|
vulnerabilityReportFileName: "report.json",
|
|
@@ -8764,6 +8982,15 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
8764
8982
|
});
|
|
8765
8983
|
}
|
|
8766
8984
|
await askToOpenAnalysis();
|
|
8985
|
+
if (command === "review") {
|
|
8986
|
+
await waitForAnaysisAndReviewPr({
|
|
8987
|
+
repo,
|
|
8988
|
+
githubActionToken,
|
|
8989
|
+
analysisId: reportUploadInfo.fixReportId,
|
|
8990
|
+
scanner,
|
|
8991
|
+
gqlClient
|
|
8992
|
+
});
|
|
8993
|
+
}
|
|
8767
8994
|
return reportUploadInfo.fixReportId;
|
|
8768
8995
|
async function askToOpenAnalysis() {
|
|
8769
8996
|
if (!repoUploadInfo || !reportUploadInfo) {
|
|
@@ -8856,7 +9083,7 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
8856
9083
|
const zippingSpinner = createSpinner5("\u{1F4E6} Zipping repo").start();
|
|
8857
9084
|
let zipBuffer;
|
|
8858
9085
|
let gitInfo = { success: false };
|
|
8859
|
-
if (srcFileStatus.isFile() &&
|
|
9086
|
+
if (srcFileStatus.isFile() && path6.extname(srcPath).toLowerCase() === ".fpr") {
|
|
8860
9087
|
zipBuffer = await repackFpr(srcPath);
|
|
8861
9088
|
} else {
|
|
8862
9089
|
gitInfo = await getGitInfo(srcPath);
|
|
@@ -8892,34 +9119,12 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
8892
9119
|
}
|
|
8893
9120
|
});
|
|
8894
9121
|
if (command === "review") {
|
|
8895
|
-
|
|
8896
|
-
repo
|
|
8897
|
-
githubActionToken
|
|
8898
|
-
|
|
8899
|
-
|
|
8900
|
-
|
|
8901
|
-
url: params2.repo,
|
|
8902
|
-
accessToken: params2.githubActionToken,
|
|
8903
|
-
scmOrg: "",
|
|
8904
|
-
scmType: "GITHUB" /* GITHUB */
|
|
8905
|
-
},
|
|
8906
|
-
{
|
|
8907
|
-
propagateExceptions: true
|
|
8908
|
-
}
|
|
8909
|
-
);
|
|
8910
|
-
await gqlClient.subscribeToAnalysis({
|
|
8911
|
-
subscribeToAnalysisParams: {
|
|
8912
|
-
analysisId: reportUploadInfo.fixReportId
|
|
8913
|
-
},
|
|
8914
|
-
callback: (analysisId) => {
|
|
8915
|
-
return addFixCommentsForPr({
|
|
8916
|
-
analysisId,
|
|
8917
|
-
gqlClient,
|
|
8918
|
-
scm,
|
|
8919
|
-
scanner: z31.nativeEnum(SCANNERS).parse(scanner)
|
|
8920
|
-
});
|
|
8921
|
-
},
|
|
8922
|
-
callbackStates: ["Finished" /* Finished */]
|
|
9122
|
+
await waitForAnaysisAndReviewPr({
|
|
9123
|
+
repo,
|
|
9124
|
+
githubActionToken,
|
|
9125
|
+
analysisId: reportUploadInfo.fixReportId,
|
|
9126
|
+
scanner,
|
|
9127
|
+
gqlClient
|
|
8923
9128
|
});
|
|
8924
9129
|
}
|
|
8925
9130
|
} catch (e) {
|
|
@@ -8991,6 +9196,43 @@ async function _digestReport({
|
|
|
8991
9196
|
throw e;
|
|
8992
9197
|
}
|
|
8993
9198
|
}
|
|
9199
|
+
async function waitForAnaysisAndReviewPr({
|
|
9200
|
+
repo,
|
|
9201
|
+
githubActionToken,
|
|
9202
|
+
analysisId,
|
|
9203
|
+
scanner,
|
|
9204
|
+
gqlClient
|
|
9205
|
+
}) {
|
|
9206
|
+
const params = z29.object({
|
|
9207
|
+
repo: z29.string().url(),
|
|
9208
|
+
githubActionToken: z29.string()
|
|
9209
|
+
}).parse({ repo, githubActionToken });
|
|
9210
|
+
const scm = await createScmLib(
|
|
9211
|
+
{
|
|
9212
|
+
url: params.repo,
|
|
9213
|
+
accessToken: params.githubActionToken,
|
|
9214
|
+
scmOrg: "",
|
|
9215
|
+
scmType: "GITHUB" /* GITHUB */
|
|
9216
|
+
},
|
|
9217
|
+
{
|
|
9218
|
+
propagateExceptions: true
|
|
9219
|
+
}
|
|
9220
|
+
);
|
|
9221
|
+
await gqlClient.subscribeToAnalysis({
|
|
9222
|
+
subscribeToAnalysisParams: {
|
|
9223
|
+
analysisId
|
|
9224
|
+
},
|
|
9225
|
+
callback: (analysisId2) => {
|
|
9226
|
+
return addFixCommentsForPr({
|
|
9227
|
+
analysisId: analysisId2,
|
|
9228
|
+
gqlClient,
|
|
9229
|
+
scm,
|
|
9230
|
+
scanner: z29.nativeEnum(SCANNERS).parse(scanner)
|
|
9231
|
+
});
|
|
9232
|
+
},
|
|
9233
|
+
callbackStates: ["Finished" /* Finished */]
|
|
9234
|
+
});
|
|
9235
|
+
}
|
|
8994
9236
|
|
|
8995
9237
|
// src/commands/index.ts
|
|
8996
9238
|
import chalk5 from "chalk";
|
|
@@ -9302,8 +9544,8 @@ var scmTokenOption = {
|
|
|
9302
9544
|
|
|
9303
9545
|
// src/args/validation.ts
|
|
9304
9546
|
import chalk7 from "chalk";
|
|
9305
|
-
import
|
|
9306
|
-
import { z as
|
|
9547
|
+
import path7 from "path";
|
|
9548
|
+
import { z as z30 } from "zod";
|
|
9307
9549
|
function throwRepoUrlErrorMessage({
|
|
9308
9550
|
error,
|
|
9309
9551
|
repoUrl,
|
|
@@ -9320,11 +9562,11 @@ Example:
|
|
|
9320
9562
|
)}`;
|
|
9321
9563
|
throw new CliError(formattedErrorMessage);
|
|
9322
9564
|
}
|
|
9323
|
-
var UrlZ =
|
|
9565
|
+
var UrlZ = z30.string({
|
|
9324
9566
|
invalid_type_error: `is not a valid ${Object.values(ScmType).join("/ ")} URL`
|
|
9325
9567
|
});
|
|
9326
9568
|
function validateOrganizationId(organizationId) {
|
|
9327
|
-
const orgIdValidation =
|
|
9569
|
+
const orgIdValidation = z30.string().uuid().nullish().safeParse(organizationId);
|
|
9328
9570
|
if (!orgIdValidation.success) {
|
|
9329
9571
|
throw new CliError(`organizationId: ${organizationId} is not a valid UUID`);
|
|
9330
9572
|
}
|
|
@@ -9346,7 +9588,7 @@ function validateRepoUrl(args) {
|
|
|
9346
9588
|
}
|
|
9347
9589
|
var supportExtensions = [".json", ".xml", ".fpr", ".sarif"];
|
|
9348
9590
|
function validateReportFileFormat(reportFile) {
|
|
9349
|
-
if (!supportExtensions.includes(
|
|
9591
|
+
if (!supportExtensions.includes(path7.extname(reportFile))) {
|
|
9350
9592
|
throw new CliError(
|
|
9351
9593
|
`
|
|
9352
9594
|
${chalk7.bold(
|
|
@@ -9389,7 +9631,7 @@ function analyzeBuilder(yargs2) {
|
|
|
9389
9631
|
).help();
|
|
9390
9632
|
}
|
|
9391
9633
|
function validateAnalyzeOptions(argv) {
|
|
9392
|
-
if (!
|
|
9634
|
+
if (!fs4.existsSync(argv.f)) {
|
|
9393
9635
|
throw new CliError(`
|
|
9394
9636
|
Can't access ${chalk8.bold(argv.f)}`);
|
|
9395
9637
|
}
|
|
@@ -9421,7 +9663,7 @@ async function analyzeHandler(args) {
|
|
|
9421
9663
|
}
|
|
9422
9664
|
|
|
9423
9665
|
// src/args/commands/review.ts
|
|
9424
|
-
import
|
|
9666
|
+
import fs5 from "node:fs";
|
|
9425
9667
|
import chalk9 from "chalk";
|
|
9426
9668
|
function reviewBuilder(yargs2) {
|
|
9427
9669
|
return yargs2.option("f", {
|
|
@@ -9451,14 +9693,14 @@ function reviewBuilder(yargs2) {
|
|
|
9451
9693
|
"Path to the repository folder with the source code"
|
|
9452
9694
|
),
|
|
9453
9695
|
type: "string",
|
|
9454
|
-
demandOption:
|
|
9696
|
+
demandOption: false
|
|
9455
9697
|
}).example(
|
|
9456
9698
|
"npx mobbdev@latest review -r https://github.com/WebGoat/WebGoat -f <your_vulnerability_report_path> --ch <pr_last_commit> --pr <pr_number> --ref <pr_branch_name> --api-key <api_key> --src-path <your_repo_path>",
|
|
9457
9699
|
"add fixes to your pr"
|
|
9458
9700
|
).help();
|
|
9459
9701
|
}
|
|
9460
9702
|
function validateReviewOptions(argv) {
|
|
9461
|
-
if (!
|
|
9703
|
+
if (!fs5.existsSync(argv.f)) {
|
|
9462
9704
|
throw new CliError(`
|
|
9463
9705
|
Can't access ${chalk9.bold(argv.f)}`);
|
|
9464
9706
|
}
|