mobbdev 1.0.58 → 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.
Files changed (2) hide show
  1. package/dist/index.mjs +919 -599
  2. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -145,6 +145,7 @@ var IssueType_Enum = /* @__PURE__ */ ((IssueType_Enum2) => {
145
145
  IssueType_Enum2["InsecureBinderConfiguration"] = "INSECURE_BINDER_CONFIGURATION";
146
146
  IssueType_Enum2["InsecureCookie"] = "INSECURE_COOKIE";
147
147
  IssueType_Enum2["InsecureRandomness"] = "INSECURE_RANDOMNESS";
148
+ IssueType_Enum2["InsecureUuidVersion"] = "INSECURE_UUID_VERSION";
148
149
  IssueType_Enum2["InsufficientLogging"] = "INSUFFICIENT_LOGGING";
149
150
  IssueType_Enum2["JqueryDeprecatedSymbols"] = "JQUERY_DEPRECATED_SYMBOLS";
150
151
  IssueType_Enum2["LeftoverDebugCode"] = "LEFTOVER_DEBUG_CODE";
@@ -222,19 +223,20 @@ var Vulnerability_Report_Issue_State_Enum = /* @__PURE__ */ ((Vulnerability_Repo
222
223
  Vulnerability_Report_Issue_State_Enum2["Unsupported"] = "Unsupported";
223
224
  return Vulnerability_Report_Issue_State_Enum2;
224
225
  })(Vulnerability_Report_Issue_State_Enum || {});
225
- var Vulnerability_Report_Issue_Tag_Enum = /* @__PURE__ */ ((Vulnerability_Report_Issue_Tag_Enum2) => {
226
- Vulnerability_Report_Issue_Tag_Enum2["AutogeneratedCode"] = "AUTOGENERATED_CODE";
227
- Vulnerability_Report_Issue_Tag_Enum2["AuxiliaryCode"] = "AUXILIARY_CODE";
228
- Vulnerability_Report_Issue_Tag_Enum2["FalsePositive"] = "FALSE_POSITIVE";
229
- Vulnerability_Report_Issue_Tag_Enum2["TestCode"] = "TEST_CODE";
230
- Vulnerability_Report_Issue_Tag_Enum2["VendorCode"] = "VENDOR_CODE";
231
- return Vulnerability_Report_Issue_Tag_Enum2;
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;
232
233
  })(Vulnerability_Report_Issue_Tag_Enum || {});
233
234
  var Vulnerability_Report_Vendor_Enum = /* @__PURE__ */ ((Vulnerability_Report_Vendor_Enum3) => {
234
235
  Vulnerability_Report_Vendor_Enum3["Checkmarx"] = "checkmarx";
235
236
  Vulnerability_Report_Vendor_Enum3["CheckmarxXml"] = "checkmarxXml";
236
237
  Vulnerability_Report_Vendor_Enum3["Codeql"] = "codeql";
237
238
  Vulnerability_Report_Vendor_Enum3["Fortify"] = "fortify";
239
+ Vulnerability_Report_Vendor_Enum3["Opengrep"] = "opengrep";
238
240
  Vulnerability_Report_Vendor_Enum3["Semgrep"] = "semgrep";
239
241
  Vulnerability_Report_Vendor_Enum3["Snyk"] = "snyk";
240
242
  Vulnerability_Report_Vendor_Enum3["Sonarqube"] = "sonarqube";
@@ -412,8 +414,12 @@ var GetVulByNodesMetadataDocument = `
412
414
  path
413
415
  startLine
414
416
  vulnerabilityReportIssue {
415
- issueType
417
+ parsedIssueType
416
418
  fixId
419
+ category
420
+ vulnerabilityReportIssueTags {
421
+ tag: vulnerability_report_issue_tag_value
422
+ }
417
423
  }
418
424
  }
419
425
  fixablePrVuls: vulnerability_report_issue_aggregate(
@@ -437,6 +443,25 @@ var GetVulByNodesMetadataDocument = `
437
443
  count
438
444
  }
439
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
+ }
440
465
  }
441
466
  `;
442
467
  var UpdateScmTokenDocument = `
@@ -899,7 +924,7 @@ var FixPageFixReportZ = z3.object({
899
924
 
900
925
  // src/features/analysis/scm/shared/src/types/issue.ts
901
926
  var MAX_SOURCE_CODE_FILE_SIZE_IN_BYTES = 1e5;
902
- var category = {
927
+ var CATEGORY = {
903
928
  NoFix: "NoFix",
904
929
  Unsupported: "Unsupported",
905
930
  Irrelevant: "Irrelevant",
@@ -907,11 +932,11 @@ var category = {
907
932
  Fixable: "Fixable"
908
933
  };
909
934
  var ValidCategoriesZ = z4.union([
910
- z4.literal(category.NoFix),
911
- z4.literal(category.Unsupported),
912
- z4.literal(category.Irrelevant),
913
- z4.literal(category.FalsePositive),
914
- z4.literal(category.Fixable)
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)
915
940
  ]);
916
941
  var BaseIssuePartsZ = z4.object({
917
942
  id: z4.string().uuid(),
@@ -972,13 +997,13 @@ var FalsePositivePartsZ = z4.object({
972
997
  });
973
998
  var IssuePartsWithFixZ = BaseIssuePartsZ.merge(
974
999
  z4.object({
975
- category: z4.literal(category.Irrelevant),
1000
+ category: z4.literal(CATEGORY.Irrelevant),
976
1001
  fix: FixPartsForFixScreenZ.nullish()
977
1002
  })
978
1003
  );
979
1004
  var IssuePartsFpZ = BaseIssuePartsZ.merge(
980
1005
  z4.object({
981
- category: z4.literal(category.FalsePositive),
1006
+ category: z4.literal(CATEGORY.FalsePositive),
982
1007
  fpId: z4.string().uuid(),
983
1008
  getFalsePositive: FalsePositivePartsZ
984
1009
  })
@@ -986,9 +1011,9 @@ var IssuePartsFpZ = BaseIssuePartsZ.merge(
986
1011
  var GeneralIssueZ = BaseIssuePartsZ.merge(
987
1012
  z4.object({
988
1013
  category: z4.union([
989
- z4.literal(category.NoFix),
990
- z4.literal(category.Unsupported),
991
- z4.literal(category.Fixable)
1014
+ z4.literal(CATEGORY.NoFix),
1015
+ z4.literal(CATEGORY.Unsupported),
1016
+ z4.literal(CATEGORY.Fixable)
992
1017
  ])
993
1018
  })
994
1019
  );
@@ -1013,6 +1038,13 @@ var GetIssueScreenDataZ = z4.object({
1013
1038
  issueIndexes: GetIssueIndexesZ
1014
1039
  });
1015
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
+ };
1016
1048
 
1017
1049
  // src/features/analysis/scm/shared/src/types/types.ts
1018
1050
  import { z as z7 } from "zod";
@@ -1108,7 +1140,8 @@ var issueTypeMap = {
1108
1140
  ["USE_OF_HARD_CODED_CRYPTOGRAPHIC_KEY" /* UseOfHardCodedCryptographicKey */]: "Use of Hardcoded Cryptographic Key",
1109
1141
  ["MISSING_SSL_MINVERSION" /* MissingSslMinversion */]: "Missing SSL MinVersion",
1110
1142
  ["WEBSOCKET_MISSING_ORIGIN_CHECK" /* WebsocketMissingOriginCheck */]: "Missing Websocket Origin Check",
1111
- ["DUPLICATED_STRINGS" /* DuplicatedStrings */]: "String Literals Should not Be Duplicated"
1143
+ ["DUPLICATED_STRINGS" /* DuplicatedStrings */]: "String Literals Should not Be Duplicated",
1144
+ ["INSECURE_UUID_VERSION" /* InsecureUuidVersion */]: "Insecure UUID Version"
1112
1145
  };
1113
1146
  var issueTypeZ = z5.nativeEnum(IssueType_Enum);
1114
1147
  var getIssueTypeFriendlyString = (issueType) => {
@@ -1118,6 +1151,29 @@ var getIssueTypeFriendlyString = (issueType) => {
1118
1151
  }
1119
1152
  return issueTypeMap[issueTypeZParseRes.data];
1120
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
+ };
1121
1177
 
1122
1178
  // src/features/analysis/scm/shared/src/validations.ts
1123
1179
  var IssueTypeSettingZ = z6.object({
@@ -1733,12 +1789,8 @@ import { z as z29 } from "zod";
1733
1789
  // src/features/analysis/add_fix_comments_for_pr/add_fix_comments_for_pr.ts
1734
1790
  import Debug8 from "debug";
1735
1791
 
1736
- // src/features/analysis/scm/github/github.ts
1737
- import { RequestError } from "@octokit/request-error";
1738
-
1739
- // src/features/analysis/scm/constants.ts
1740
- var MOBB_ICON_IMG = "https://app.mobb.ai/gh-action/Logo_Rounded_Icon.svg";
1741
- var MAX_BRANCHES_FETCH = 1e3;
1792
+ // src/features/analysis/scm/github/GithubSCMLib.ts
1793
+ import { z as z24 } from "zod";
1742
1794
 
1743
1795
  // src/features/analysis/scm/errors.ts
1744
1796
  var InvalidRepoUrlError = class extends Error {
@@ -1768,6 +1820,21 @@ var RepoNoTokenAccessError = class extends Error {
1768
1820
  }
1769
1821
  };
1770
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
+
1771
1838
  // src/features/analysis/scm/types.ts
1772
1839
  import { z as z14 } from "zod";
1773
1840
 
@@ -2014,13 +2081,19 @@ var fixDetailsData = {
2014
2081
  ["USE_OF_HARD_CODED_CRYPTOGRAPHIC_KEY" /* UseOfHardCodedCryptographicKey */]: void 0,
2015
2082
  ["MISSING_SSL_MINVERSION" /* MissingSslMinversion */]: void 0,
2016
2083
  ["WEBSOCKET_MISSING_ORIGIN_CHECK" /* WebsocketMissingOriginCheck */]: void 0,
2017
- ["DUPLICATED_STRINGS" /* DuplicatedStrings */]: void 0
2084
+ ["DUPLICATED_STRINGS" /* DuplicatedStrings */]: void 0,
2085
+ ["INSECURE_UUID_VERSION" /* InsecureUuidVersion */]: void 0
2018
2086
  };
2019
2087
 
2020
2088
  // src/features/analysis/scm/shared/src/commitDescriptionMarkup.ts
2021
2089
  function capitalizeFirstLetter(str) {
2022
2090
  return str?.length ? str[0].toUpperCase() + str.slice(1) : "";
2023
2091
  }
2092
+ function lowercaseFirstLetter(str) {
2093
+ if (!str)
2094
+ return str;
2095
+ return `${str.charAt(0).toLowerCase()}${str.slice(1)}`;
2096
+ }
2024
2097
  var severityToEmoji = {
2025
2098
  ["critical" /* Critical */]: "\u{1F6A8}",
2026
2099
  ["high" /* High */]: "\u{1F6A9}",
@@ -2032,7 +2105,8 @@ var getCommitDescription = ({
2032
2105
  issueType,
2033
2106
  severity,
2034
2107
  guidances,
2035
- fixUrl
2108
+ fixUrl,
2109
+ irrelevantIssueWithTags
2036
2110
  }) => {
2037
2111
  const issueTypeString = getIssueTypeFriendlyString(issueType);
2038
2112
  let description = `This change fixes a **${severity} severity** (${severityToEmoji[severity]}) **${issueTypeString}** issue reported by **${capitalizeFirstLetter(
@@ -2042,6 +2116,17 @@ var getCommitDescription = ({
2042
2116
  `;
2043
2117
  const parseIssueTypeRes = z9.nativeEnum(IssueType_Enum).safeParse(issueType);
2044
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
+ }
2045
2130
  const staticData = fixDetailsData[parseIssueTypeRes.data];
2046
2131
  if (staticData) {
2047
2132
  description += `## Issue description
@@ -2063,6 +2148,36 @@ ${guidances.map(({ guidance }) => `## Additional actions required
2063
2148
  }
2064
2149
  return description;
2065
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
+ };
2066
2181
 
2067
2182
  // src/features/analysis/scm/shared/src/guidances.ts
2068
2183
  import { z as z12 } from "zod";
@@ -3766,6 +3881,15 @@ function getFixUrl({
3766
3881
  }) {
3767
3882
  return `${appBaseUrl}/organization/${organizationId}/project/${projectId}/report/${analysisId}/fix/${fixId}`;
3768
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
+ }
3769
3893
 
3770
3894
  // src/features/analysis/scm/types.ts
3771
3895
  var ReferenceType = /* @__PURE__ */ ((ReferenceType2) => {
@@ -3805,92 +3929,8 @@ var GetRefererenceResultZ = z14.object({
3805
3929
  type: z14.nativeEnum(ReferenceType)
3806
3930
  });
3807
3931
 
3808
- // src/features/analysis/scm/github/consts.ts
3809
- var POST_COMMENT_PATH = "POST /repos/{owner}/{repo}/pulls/{pull_number}/comments";
3810
- var DELETE_COMMENT_PATH = "DELETE /repos/{owner}/{repo}/pulls/comments/{comment_id}";
3811
- var UPDATE_COMMENT_PATH = "PATCH /repos/{owner}/{repo}/pulls/comments/{comment_id}";
3812
- var GET_PR_COMMENTS_PATH = "GET /repos/{owner}/{repo}/pulls/{pull_number}/comments";
3813
- var GET_PR_COMMENT_PATH = "GET /repos/{owner}/{repo}/pulls/comments/{comment_id}";
3814
- var REPLY_TO_CODE_REVIEW_COMMENT_PATH = "POST /repos/{owner}/{repo}/pulls/{pull_number}/comments/{comment_id}/replies";
3815
- var GET_PR = "GET /repos/{owner}/{repo}/pulls/{pull_number}";
3816
- var POST_GENERAL_PR_COMMENT = "POST /repos/{owner}/{repo}/issues/{issue_number}/comments";
3817
- var GET_GENERAL_PR_COMMENTS = "GET /repos/{owner}/{repo}/issues/{issue_number}/comments";
3818
- var DELETE_GENERAL_PR_COMMENT = "DELETE /repos/{owner}/{repo}/issues/comments/{comment_id}";
3819
- var CREATE_OR_UPDATE_A_REPOSITORY_SECRET = "PUT /repos/{owner}/{repo}/actions/secrets/{secret_name}";
3820
- var GET_A_REPOSITORY_PUBLIC_KEY = "GET /repos/{owner}/{repo}/actions/secrets/public-key";
3821
- var GET_USER = "GET /user";
3822
- var GET_USER_REPOS = "GET /user/repos";
3823
- var GET_REPO_BRANCHES = "GET /repos/{owner}/{repo}/branches";
3824
- var GET_BLAME_DOCUMENT = `
3825
- query GetBlame(
3826
- $owner: String!
3827
- $repo: String!
3828
- $ref: String!
3829
- $path: String!
3830
- ) {
3831
- repository(name: $repo, owner: $owner) {
3832
- # branch name
3833
- object(expression: $ref) {
3834
- # cast Target to a Commit
3835
- ... on Commit {
3836
- # full repo-relative path to blame file
3837
- blame(path: $path) {
3838
- ranges {
3839
- commit {
3840
- author {
3841
- user {
3842
- name
3843
- login
3844
- }
3845
- }
3846
- authoredDate
3847
- }
3848
- startingLine
3849
- endingLine
3850
- age
3851
- }
3852
- }
3853
- }
3854
-
3855
- }
3856
- }
3857
- }
3858
- `;
3859
-
3860
- // src/features/analysis/scm/github/utils/encrypt_secret.ts
3861
- import sodium from "libsodium-wrappers";
3862
- async function encryptSecret(secret, key) {
3863
- await sodium.ready;
3864
- const binkey = sodium.from_base64(key, sodium.base64_variants.ORIGINAL);
3865
- const binsec = sodium.from_string(secret);
3866
- const encBytes = sodium.crypto_box_seal(binsec, binkey);
3867
- return sodium.to_base64(encBytes, sodium.base64_variants.ORIGINAL);
3868
- }
3869
-
3870
- // src/features/analysis/scm/github/utils/utils.ts
3871
- import { Octokit } from "octokit";
3872
- import { fetch as fetch2, ProxyAgent as ProxyAgent2 } from "undici";
3873
-
3874
- // src/features/analysis/scm/ado/constants.ts
3875
- var DEFUALT_ADO_ORIGIN = scmCloudUrl.Ado;
3876
-
3877
- // src/features/analysis/scm/ado/utils.ts
3878
- import querystring from "node:querystring";
3879
- import * as api from "azure-devops-node-api";
3880
- import Debug2 from "debug";
3881
- import { z as z18 } from "zod";
3882
-
3883
- // src/features/analysis/scm/env.ts
3884
- import { z as z15 } from "zod";
3885
- var EnvVariablesZod = z15.object({
3886
- GITLAB_API_TOKEN: z15.string().optional(),
3887
- GITHUB_API_TOKEN: z15.string().optional(),
3888
- GIT_PROXY_HOST: z15.string()
3889
- });
3890
- var { GITLAB_API_TOKEN, GITHUB_API_TOKEN, GIT_PROXY_HOST } = EnvVariablesZod.parse(process.env);
3891
-
3892
3932
  // src/features/analysis/scm/utils/index.ts
3893
- import { z as z16 } from "zod";
3933
+ import { z as z15 } from "zod";
3894
3934
  function getFixUrlWithRedirect(params) {
3895
3935
  const {
3896
3936
  fixId,
@@ -3912,6 +3952,27 @@ function getFixUrlWithRedirect(params) {
3912
3952
  analysisId
3913
3953
  })}?${searchParams.toString()}`;
3914
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
+ }
3915
3976
  function getCommitUrl(params) {
3916
3977
  const {
3917
3978
  fixId,
@@ -3933,6 +3994,27 @@ function getCommitUrl(params) {
3933
3994
  analysisId
3934
3995
  })}/commit?${searchParams.toString()}`;
3935
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
+ }
3936
4018
  var userNamePattern = /^(https?:\/\/)([^@]+@)?([^/]+\/.+)$/;
3937
4019
  var sshPattern = /^git@([\w.-]+):([\w./-]+)$/;
3938
4020
  function normalizeUrl(repoUrl) {
@@ -3959,7 +4041,7 @@ function shouldValidateUrl(repoUrl) {
3959
4041
  return repoUrl && isUrlHasPath(repoUrl);
3960
4042
  }
3961
4043
  function isBrokerUrl(url) {
3962
- return z16.string().uuid().safeParse(new URL(url).host).success;
4044
+ return z15.string().uuid().safeParse(new URL(url).host).success;
3963
4045
  }
3964
4046
  function buildAuthorizedRepoUrl(args) {
3965
4047
  const { url, username, password } = args;
@@ -3995,7 +4077,7 @@ function getCloudScmLibTypeFromUrl(url) {
3995
4077
  return void 0;
3996
4078
  }
3997
4079
  function getScmLibTypeFromScmType(scmType) {
3998
- const parsedScmType = z16.nativeEnum(ScmType).parse(scmType);
4080
+ const parsedScmType = z15.nativeEnum(ScmType).parse(scmType);
3999
4081
  return scmTypeToScmLibScmType[parsedScmType];
4000
4082
  }
4001
4083
  function getScmConfig({
@@ -4061,70 +4143,226 @@ function getScmConfig({
4061
4143
  };
4062
4144
  }
4063
4145
 
4064
- // src/features/analysis/scm/ado/validation.ts
4065
- import { z as z17 } from "zod";
4066
- var ValidPullRequestStatusZ = z17.union([
4067
- z17.literal(1 /* Active */),
4068
- z17.literal(2 /* Abandoned */),
4069
- z17.literal(3 /* Completed */)
4070
- ]);
4071
- var AdoAuthResultZ = z17.object({
4072
- access_token: z17.string().min(1),
4073
- token_type: z17.string().min(1),
4074
- refresh_token: z17.string().min(1)
4075
- });
4076
- var AdoAuthResultWithOrgsZ = AdoAuthResultZ.extend({
4077
- scmOrgs: z17.array(z17.string())
4078
- });
4079
- var profileZ = z17.object({
4080
- displayName: z17.string(),
4081
- publicAlias: z17.string().min(1),
4082
- emailAddress: z17.string(),
4083
- coreRevision: z17.number(),
4084
- timeStamp: z17.string(),
4085
- id: z17.string(),
4086
- revision: z17.number()
4087
- });
4088
- var accountsZ = z17.object({
4089
- count: z17.number(),
4090
- value: z17.array(
4091
- z17.object({
4092
- accountId: z17.string(),
4093
- accountUri: z17.string(),
4094
- accountName: z17.string()
4095
- })
4096
- )
4097
- });
4098
-
4099
- // src/features/analysis/scm/ado/utils.ts
4100
- var debug2 = Debug2("mobbdev:scm:ado");
4101
- function _getPublicAdoClient({
4102
- orgName,
4103
- origin: origin2
4104
- }) {
4105
- const orgUrl = `${origin2}/${orgName}`;
4106
- const authHandler = api.getPersonalAccessTokenHandler("");
4107
- authHandler.canHandleAuthentication = () => false;
4108
- authHandler.prepareRequest = (_options) => {
4109
- return;
4110
- };
4111
- const connection = new api.WebApi(orgUrl, authHandler);
4112
- return connection;
4113
- }
4114
- function removeTrailingSlash(str) {
4115
- return str.trim().replace(/\/+$/, "");
4116
- }
4117
- function parseAdoOwnerAndRepo(adoUrl) {
4118
- adoUrl = removeTrailingSlash(adoUrl);
4119
- const parsingResult = parseScmURL(adoUrl, "Ado" /* Ado */);
4120
- if (!parsingResult || parsingResult.scmType !== "Ado" /* Ado */) {
4121
- throw new InvalidUrlPatternError(`
4122
- : ${adoUrl}`);
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;
4123
4155
  }
4124
- const {
4125
- organization,
4126
- repoName,
4127
- projectName,
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 {
4363
+ organization,
4364
+ repoName,
4365
+ projectName,
4128
4366
  projectPath,
4129
4367
  pathElements,
4130
4368
  hostname,
@@ -4671,88 +4909,6 @@ async function getAdoRepoList({
4671
4909
 
4672
4910
  // src/features/analysis/scm/ado/AdoSCMLib.ts
4673
4911
  import { setTimeout as setTimeout2 } from "node:timers/promises";
4674
-
4675
- // src/features/analysis/scm/scmSubmit/index.ts
4676
- import { simpleGit } from "simple-git";
4677
- var isValidBranchName = async (branchName) => {
4678
- const git = simpleGit();
4679
- try {
4680
- const res = await git.raw(["check-ref-format", "--branch", branchName]);
4681
- if (res) {
4682
- return true;
4683
- }
4684
- return false;
4685
- } catch (e) {
4686
- return false;
4687
- }
4688
- };
4689
-
4690
- // src/features/analysis/scm/scm.ts
4691
- var SCMLib = class {
4692
- constructor(url, accessToken, scmOrg) {
4693
- __publicField(this, "url");
4694
- __publicField(this, "accessToken");
4695
- __publicField(this, "scmOrg");
4696
- this.accessToken = accessToken;
4697
- this.url = url;
4698
- this.scmOrg = scmOrg;
4699
- }
4700
- async getUrlWithCredentials() {
4701
- if (!this.url) {
4702
- console.error("no url for getUrlWithCredentials()");
4703
- throw new Error("no url");
4704
- }
4705
- const trimmedUrl = this.url.trim().replace(/\/$/, "");
4706
- const accessToken = this.getAccessToken();
4707
- if (!accessToken) {
4708
- return trimmedUrl;
4709
- }
4710
- if (this.scmLibType === "ADO" /* ADO */) {
4711
- const { host, protocol, pathname } = new URL(trimmedUrl);
4712
- return `${protocol}//${accessToken}@${host}${pathname}`;
4713
- }
4714
- const finalUrl = this.scmLibType === "GITLAB" /* GITLAB */ ? `${trimmedUrl}.git` : trimmedUrl;
4715
- const username = await this._getUsernameForAuthUrl();
4716
- return buildAuthorizedRepoUrl({
4717
- url: finalUrl,
4718
- username,
4719
- password: accessToken
4720
- });
4721
- }
4722
- getAccessToken() {
4723
- return this.accessToken || "";
4724
- }
4725
- getUrl() {
4726
- return this.url;
4727
- }
4728
- getName() {
4729
- if (!this.url) {
4730
- return "";
4731
- }
4732
- return this.url.split("/").at(-1) || "";
4733
- }
4734
- _validateAccessToken() {
4735
- if (!this.accessToken) {
4736
- console.error("no access token");
4737
- throw new Error("no access token");
4738
- }
4739
- }
4740
- static async getIsValidBranchName(branchName) {
4741
- return isValidBranchName(branchName);
4742
- }
4743
- _validateAccessTokenAndUrl() {
4744
- this._validateAccessToken();
4745
- this._validateUrl();
4746
- }
4747
- _validateUrl() {
4748
- if (!this.url) {
4749
- console.error("no url");
4750
- throw new InvalidRepoUrlError("no url");
4751
- }
4752
- }
4753
- };
4754
-
4755
- // src/features/analysis/scm/ado/AdoSCMLib.ts
4756
4912
  async function initAdoSdk(params) {
4757
4913
  const { url, accessToken, scmOrg } = params;
4758
4914
  const adoClientParams = await getAdoClientParams({
@@ -5395,353 +5551,104 @@ var BitbucketSCMLib = class extends SCMLib {
5395
5551
  case "public":
5396
5552
  return {};
5397
5553
  case "token":
5398
- return { authorization: `Bearer ${this.accessToken}` };
5399
- case "basic": {
5400
- this._validateAccessToken();
5401
- const { username, password } = getUserAndPassword(this.accessToken);
5402
- return {
5403
- authorization: `Basic ${Buffer.from(
5404
- username + ":" + password
5405
- ).toString("base64")}`
5406
- };
5407
- }
5408
- }
5409
- }
5410
- async getDownloadUrl(sha) {
5411
- this._validateUrl();
5412
- return this.bitbucketSdk.getDownloadUrl({ url: this.url, sha });
5413
- }
5414
- async _getUsernameForAuthUrl() {
5415
- this._validateAccessTokenAndUrl();
5416
- const user = await this.bitbucketSdk.getUser();
5417
- if (!user.username) {
5418
- throw new Error("no username found");
5419
- }
5420
- return user.username;
5421
- }
5422
- async getIsRemoteBranch(branch) {
5423
- this._validateAccessTokenAndUrl();
5424
- try {
5425
- const res = await this.bitbucketSdk.getBranch({
5426
- branchName: branch,
5427
- repoUrl: this.url
5428
- });
5429
- return res.name === branch;
5430
- } catch (e) {
5431
- return false;
5432
- }
5433
- }
5434
- async getUserHasAccessToRepo() {
5435
- this._validateAccessTokenAndUrl();
5436
- return this.bitbucketSdk.getIsUserCollaborator({ repoUrl: this.url });
5437
- }
5438
- async getUsername() {
5439
- this._validateAccessToken();
5440
- const res = await this.bitbucketSdk.getUser();
5441
- return z21.string().parse(res.username);
5442
- }
5443
- async getSubmitRequestStatus(_scmSubmitRequestId) {
5444
- this._validateAccessTokenAndUrl();
5445
- const pullRequestRes = await this.bitbucketSdk.getPullRequest({
5446
- prNumber: Number(_scmSubmitRequestId),
5447
- url: this.url
5448
- });
5449
- switch (pullRequestRes.state) {
5450
- case "OPEN":
5451
- return "open";
5452
- case "MERGED":
5453
- return "merged";
5454
- case "DECLINED":
5455
- return "closed";
5456
- default:
5457
- throw new Error(`unknown state ${pullRequestRes.state} `);
5458
- }
5459
- }
5460
- async getRepoBlameRanges(_ref, _path) {
5461
- return [];
5462
- }
5463
- async getReferenceData(ref) {
5464
- this._validateUrl();
5465
- return this.bitbucketSdk.getReferenceData({ url: this.url, ref });
5466
- }
5467
- async getRepoDefaultBranch() {
5468
- this._validateUrl();
5469
- const repoRes = await this.bitbucketSdk.getRepo({ repoUrl: this.url });
5470
- return z21.string().parse(repoRes.mainbranch?.name);
5471
- }
5472
- getSubmitRequestUrl(submitRequestId) {
5473
- this._validateUrl();
5474
- const { repo_slug, workspace } = parseBitbucketOrganizationAndRepo(this.url);
5475
- return Promise.resolve(
5476
- `https://bitbucket.org/${workspace}/${repo_slug}/pull-requests/${submitRequestId}`
5477
- );
5478
- }
5479
- async getSubmitRequestId(submitRequestUrl) {
5480
- const match = submitRequestUrl.match(/\/pull-requests\/(\d+)/);
5481
- return match?.[1] || "";
5482
- }
5483
- getCommitUrl(commitId) {
5484
- this._validateUrl();
5485
- const { repo_slug, workspace } = parseBitbucketOrganizationAndRepo(this.url);
5486
- return Promise.resolve(
5487
- `https://bitbucket.org/${workspace}/${repo_slug}/commits/${commitId}`
5488
- );
5489
- }
5490
- async addCommentToSubmitRequest(submitRequestId, comment) {
5491
- this._validateUrl();
5492
- await this.bitbucketSdk.addCommentToPullRequest({
5493
- prNumber: Number(submitRequestId),
5494
- url: this.url,
5495
- markdownComment: comment
5496
- });
5497
- }
5498
- };
5499
-
5500
- // src/features/analysis/scm/github/GithubSCMLib.ts
5501
- import { z as z22 } from "zod";
5502
- var GithubSCMLib = class extends SCMLib {
5503
- // we don't always need a url, what's important is that we have an access token
5504
- constructor(url, accessToken, scmOrg) {
5505
- super(url, accessToken, scmOrg);
5506
- __publicField(this, "githubSdk");
5507
- this.githubSdk = getGithubSdk({
5508
- auth: accessToken,
5509
- url
5510
- });
5511
- }
5512
- async createSubmitRequest(params) {
5513
- this._validateAccessTokenAndUrl();
5514
- const { targetBranchName, sourceBranchName, title, body } = params;
5515
- const pullRequestResult = await this.githubSdk.createPullRequest({
5516
- title,
5517
- body,
5518
- targetBranchName,
5519
- sourceBranchName,
5520
- repoUrl: this.url
5521
- });
5522
- return String(pullRequestResult.data.number);
5523
- }
5524
- async forkRepo(repoUrl) {
5525
- this._validateAccessToken();
5526
- return this.githubSdk.forkRepo({
5527
- repoUrl
5528
- });
5529
- }
5530
- async createOrUpdateRepositorySecret(params) {
5531
- this._validateAccessTokenAndUrl();
5532
- const { owner, repo } = parseGithubOwnerAndRepo(this.url);
5533
- const { data: repositoryPublicKeyResponse } = await this.githubSdk.getRepositoryPublicKey({ owner, repo });
5534
- const { key_id, key } = repositoryPublicKeyResponse;
5535
- const encryptedValue = await encryptSecret(params.value, key);
5536
- return this.githubSdk.createOrUpdateRepositorySecret({
5537
- encrypted_value: encryptedValue,
5538
- secret_name: params.name,
5539
- key_id,
5540
- owner,
5541
- repo
5542
- });
5543
- }
5544
- async createPullRequestWithNewFile(sourceRepoUrl, filesPaths, userRepoUrl, title, body) {
5545
- const { pull_request_url } = await this.githubSdk.createPr({
5546
- sourceRepoUrl,
5547
- filesPaths,
5548
- userRepoUrl,
5549
- title,
5550
- body
5551
- });
5552
- return { pull_request_url };
5553
- }
5554
- async validateParams() {
5555
- return githubValidateParams(this.url, this.accessToken);
5556
- }
5557
- async postPrComment(params) {
5558
- this._validateAccessTokenAndUrl();
5559
- const { owner, repo } = parseGithubOwnerAndRepo(this.url);
5560
- return this.githubSdk.postPrComment({
5561
- ...params,
5562
- owner,
5563
- repo
5564
- });
5565
- }
5566
- async updatePrComment(params) {
5567
- this._validateAccessTokenAndUrl();
5568
- const { owner, repo } = parseGithubOwnerAndRepo(this.url);
5569
- return this.githubSdk.updatePrComment({
5570
- ...params,
5571
- owner,
5572
- repo
5573
- });
5574
- }
5575
- async deleteComment(params) {
5576
- this._validateAccessTokenAndUrl();
5577
- const { owner, repo } = parseGithubOwnerAndRepo(this.url);
5578
- return this.githubSdk.deleteComment({
5579
- ...params,
5580
- owner,
5581
- repo
5582
- });
5583
- }
5584
- async getPrComments(params) {
5585
- this._validateAccessTokenAndUrl();
5586
- const { owner, repo } = parseGithubOwnerAndRepo(this.url);
5587
- return this.githubSdk.getPrComments({
5588
- per_page: 100,
5589
- ...params,
5590
- owner,
5591
- repo
5592
- });
5593
- }
5594
- async getPrDiff(params) {
5595
- this._validateAccessTokenAndUrl();
5596
- const { owner, repo } = parseGithubOwnerAndRepo(this.url);
5597
- const prRes = await this.githubSdk.getPrDiff({
5598
- ...params,
5599
- owner,
5600
- repo
5601
- });
5602
- return z22.string().parse(prRes.data);
5603
- }
5604
- async getRepoList(_scmOrg) {
5605
- this._validateAccessToken();
5606
- return this.githubSdk.getGithubRepoList();
5607
- }
5608
- async getBranchList() {
5609
- this._validateAccessTokenAndUrl();
5610
- const branches = await this.githubSdk.getGithubBranchList(this.url);
5611
- return branches.data.map((branch) => branch.name);
5612
- }
5613
- get scmLibType() {
5614
- return "GITHUB" /* GITHUB */;
5615
- }
5616
- getAuthHeaders() {
5617
- if (this.accessToken) {
5618
- return { authorization: `Bearer ${this.accessToken}` };
5554
+ return { authorization: `Bearer ${this.accessToken}` };
5555
+ case "basic": {
5556
+ this._validateAccessToken();
5557
+ const { username, password } = getUserAndPassword(this.accessToken);
5558
+ return {
5559
+ authorization: `Basic ${Buffer.from(
5560
+ username + ":" + password
5561
+ ).toString("base64")}`
5562
+ };
5563
+ }
5619
5564
  }
5620
- return {};
5621
5565
  }
5622
- getDownloadUrl(sha) {
5566
+ async getDownloadUrl(sha) {
5623
5567
  this._validateUrl();
5624
- const res = parseScmURL(this.url, "GitHub" /* GitHub */);
5625
- if (!res) {
5626
- throw new InvalidRepoUrlError("invalid repo url");
5627
- }
5628
- const { protocol, hostname, organization, repoName } = res;
5629
- const downloadUrl = isGithubOnPrem(this.url) ? `${protocol}//${hostname}/api/v3/repos/${organization}/${repoName}/zipball/${sha}` : `https://api.${hostname}/repos/${organization}/${repoName}/zipball/${sha}`;
5630
- return Promise.resolve(downloadUrl);
5568
+ return this.bitbucketSdk.getDownloadUrl({ url: this.url, sha });
5631
5569
  }
5632
5570
  async _getUsernameForAuthUrl() {
5633
- return this.getUsername();
5571
+ this._validateAccessTokenAndUrl();
5572
+ const user = await this.bitbucketSdk.getUser();
5573
+ if (!user.username) {
5574
+ throw new Error("no username found");
5575
+ }
5576
+ return user.username;
5634
5577
  }
5635
5578
  async getIsRemoteBranch(branch) {
5636
- this._validateUrl();
5637
- return this.githubSdk.getGithubIsRemoteBranch({ branch, repoUrl: this.url });
5579
+ this._validateAccessTokenAndUrl();
5580
+ try {
5581
+ const res = await this.bitbucketSdk.getBranch({
5582
+ branchName: branch,
5583
+ repoUrl: this.url
5584
+ });
5585
+ return res.name === branch;
5586
+ } catch (e) {
5587
+ return false;
5588
+ }
5638
5589
  }
5639
5590
  async getUserHasAccessToRepo() {
5640
5591
  this._validateAccessTokenAndUrl();
5641
- const username = await this.getUsername();
5642
- return this.githubSdk.getGithubIsUserCollaborator({
5643
- repoUrl: this.url,
5644
- username
5645
- });
5592
+ return this.bitbucketSdk.getIsUserCollaborator({ repoUrl: this.url });
5646
5593
  }
5647
5594
  async getUsername() {
5648
5595
  this._validateAccessToken();
5649
- return this.githubSdk.getGithubUsername();
5650
- }
5651
- async getSubmitRequestStatus(scmSubmitRequestId) {
5652
- this._validateAccessTokenAndUrl();
5653
- return this.githubSdk.getGithubPullRequestStatus({
5654
- repoUrl: this.url,
5655
- prNumber: Number(scmSubmitRequestId)
5656
- });
5596
+ const res = await this.bitbucketSdk.getUser();
5597
+ return z21.string().parse(res.username);
5657
5598
  }
5658
- async addCommentToSubmitRequest(submitRequestId, comment) {
5599
+ async getSubmitRequestStatus(_scmSubmitRequestId) {
5659
5600
  this._validateAccessTokenAndUrl();
5660
- await this.githubSdk.createMarkdownCommentOnPullRequest({
5661
- repoUrl: this.url,
5662
- prNumber: Number(submitRequestId),
5663
- markdownComment: comment
5601
+ const pullRequestRes = await this.bitbucketSdk.getPullRequest({
5602
+ prNumber: Number(_scmSubmitRequestId),
5603
+ url: this.url
5664
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
+ }
5665
5615
  }
5666
- async getRepoBlameRanges(ref, path8) {
5667
- this._validateUrl();
5668
- return await this.githubSdk.getGithubBlameRanges({
5669
- ref,
5670
- path: path8,
5671
- gitHubUrl: this.url
5672
- });
5616
+ async getRepoBlameRanges(_ref, _path) {
5617
+ return [];
5673
5618
  }
5674
5619
  async getReferenceData(ref) {
5675
5620
  this._validateUrl();
5676
- return this.githubSdk.getGithubReferenceData({ ref, gitHubUrl: this.url });
5677
- }
5678
- async getPrComment(commentId) {
5679
- this._validateUrl();
5680
- const { owner, repo } = parseGithubOwnerAndRepo(this.url);
5681
- return await this.githubSdk.getPrComment({
5682
- repo,
5683
- owner,
5684
- comment_id: commentId
5685
- });
5621
+ return this.bitbucketSdk.getReferenceData({ url: this.url, ref });
5686
5622
  }
5687
5623
  async getRepoDefaultBranch() {
5688
5624
  this._validateUrl();
5689
- return await this.githubSdk.getGithubRepoDefaultBranch(this.url);
5625
+ const repoRes = await this.bitbucketSdk.getRepo({ repoUrl: this.url });
5626
+ return z21.string().parse(repoRes.mainbranch?.name);
5690
5627
  }
5691
- async getSubmitRequestUrl(submitRequestUrl) {
5692
- this._validateAccessTokenAndUrl();
5693
- const { owner, repo } = parseGithubOwnerAndRepo(this.url);
5694
- const getPrRes = await this.githubSdk.getPr({
5695
- owner,
5696
- repo,
5697
- pull_number: submitRequestUrl
5698
- });
5699
- 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
+ );
5700
5634
  }
5701
5635
  async getSubmitRequestId(submitRequestUrl) {
5702
- const match = submitRequestUrl.match(/\/pull\/(\d+)/);
5636
+ const match = submitRequestUrl.match(/\/pull-requests\/(\d+)/);
5703
5637
  return match?.[1] || "";
5704
5638
  }
5705
- async getCommitUrl(commitId) {
5706
- this._validateAccessTokenAndUrl();
5707
- const { owner, repo } = parseGithubOwnerAndRepo(this.url);
5708
- const getCommitRes = await this.githubSdk.getCommit({
5709
- owner,
5710
- repo,
5711
- commitSha: commitId
5712
- });
5713
- return getCommitRes.data.html_url;
5714
- }
5715
- async postGeneralPrComment(params) {
5716
- const { prNumber, body } = params;
5717
- this._validateAccessTokenAndUrl();
5718
- const { owner, repo } = parseGithubOwnerAndRepo(this.url);
5719
- return await this.githubSdk.postGeneralPrComment({
5720
- issue_number: prNumber,
5721
- owner,
5722
- repo,
5723
- body
5724
- });
5725
- }
5726
- async getGeneralPrComments(params) {
5727
- const { prNumber } = params;
5728
- this._validateAccessTokenAndUrl();
5729
- const { owner, repo } = parseGithubOwnerAndRepo(this.url);
5730
- return await this.githubSdk.getGeneralPrComments({
5731
- issue_number: prNumber,
5732
- owner,
5733
- repo
5734
- });
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
+ );
5735
5645
  }
5736
- async deleteGeneralPrComment({
5737
- commentId
5738
- }) {
5739
- this._validateAccessTokenAndUrl();
5740
- const { owner, repo } = parseGithubOwnerAndRepo(this.url);
5741
- return this.githubSdk.deleteGeneralPrComment({
5742
- owner,
5743
- repo,
5744
- 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
5745
5652
  });
5746
5653
  }
5747
5654
  };
@@ -5761,11 +5668,11 @@ import {
5761
5668
  } from "undici";
5762
5669
 
5763
5670
  // src/features/analysis/scm/gitlab/types.ts
5764
- import { z as z23 } from "zod";
5765
- var GitlabAuthResultZ = z23.object({
5766
- access_token: z23.string(),
5767
- token_type: z23.string(),
5768
- refresh_token: z23.string()
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()
5769
5676
  });
5770
5677
 
5771
5678
  // src/features/analysis/scm/gitlab/gitlab.ts
@@ -6307,7 +6214,7 @@ var GitlabSCMLib = class extends SCMLib {
6307
6214
  };
6308
6215
 
6309
6216
  // src/features/analysis/scm/scmFactory.ts
6310
- import { z as z24 } from "zod";
6217
+ import { z as z23 } from "zod";
6311
6218
 
6312
6219
  // src/features/analysis/scm/StubSCMLib.ts
6313
6220
  var StubSCMLib = class extends SCMLib {
@@ -6429,7 +6336,7 @@ async function createScmLib({ url, accessToken, scmType, scmOrg }, { propagateEx
6429
6336
  if (e instanceof InvalidRepoUrlError && url) {
6430
6337
  throw new RepoNoTokenAccessError(
6431
6338
  "no access to repo",
6432
- scmLibScmTypeToScmType[z24.nativeEnum(ScmLibScmType).parse(scmType)]
6339
+ scmLibScmTypeToScmType[z23.nativeEnum(ScmLibScmType).parse(scmType)]
6433
6340
  );
6434
6341
  }
6435
6342
  console.error(`error validating scm: ${scmType} `, e);
@@ -6905,8 +6812,256 @@ function getGithubSdk(params = {}) {
6905
6812
  async getUserInfo() {
6906
6813
  return octokit.request(GET_USER);
6907
6814
  }
6908
- };
6909
- }
6815
+ };
6816
+ }
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
+ };
6910
7065
 
6911
7066
  // src/features/analysis/add_fix_comments_for_pr/utils/utils.ts
6912
7067
  import Debug7 from "debug";
@@ -6986,8 +7141,9 @@ import Debug6 from "debug";
6986
7141
  import { z as z25 } from "zod";
6987
7142
  var debug6 = Debug6("mobbdev:handle-finished-analysis");
6988
7143
  var getCommitFixButton = (commitUrl) => `<a href="${commitUrl}"><img src=${COMMIT_FIX_SVG}></a>`;
6989
- function buildCommentBody({
7144
+ function buildFixCommentBody({
6990
7145
  fix,
7146
+ issueId,
6991
7147
  commentId,
6992
7148
  commentUrl,
6993
7149
  scanner,
@@ -6995,9 +7151,19 @@ function buildCommentBody({
6995
7151
  projectId,
6996
7152
  analysisId,
6997
7153
  organizationId,
6998
- patch
7154
+ patch,
7155
+ irrelevantIssueWithTags
6999
7156
  }) {
7000
- const commitUrl = getCommitUrl({
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({
7001
7167
  appBaseUrl: WEB_APP_URL,
7002
7168
  fixId,
7003
7169
  projectId,
@@ -7006,7 +7172,15 @@ function buildCommentBody({
7006
7172
  redirectUrl: commentUrl,
7007
7173
  commentId
7008
7174
  });
7009
- const fixUrl = getFixUrlWithRedirect({
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({
7010
7184
  appBaseUrl: WEB_APP_URL,
7011
7185
  fixId,
7012
7186
  projectId,
@@ -7038,7 +7212,8 @@ function buildCommentBody({
7038
7212
  issueType: validFixParseRes.data.safeIssueType,
7039
7213
  issueLanguage: validFixParseRes.data.safeIssueLanguage,
7040
7214
  fixExtraContext: validFixParseRes.data.patchAndQuestions.extraContext
7041
- })
7215
+ }),
7216
+ irrelevantIssueWithTags
7042
7217
  }) : "";
7043
7218
  const diff = `\`\`\`diff
7044
7219
  ${patch}
@@ -7052,6 +7227,37 @@ ${getCommitFixButton(
7052
7227
  )}
7053
7228
  ${fixPageLink}`;
7054
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
+ }
7055
7261
 
7056
7262
  // src/features/analysis/add_fix_comments_for_pr/utils/utils.ts
7057
7263
  var debug7 = Debug7("mobbdev:handle-finished-analysis");
@@ -7109,6 +7315,53 @@ function deleteAllPreviousGeneralPrComments(params) {
7109
7315
  }
7110
7316
  });
7111
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
+ }
7112
7365
  async function postFixComment(params) {
7113
7366
  const {
7114
7367
  vulnerabilityReportIssueCodeNode,
@@ -7124,8 +7377,10 @@ async function postFixComment(params) {
7124
7377
  const {
7125
7378
  path: path8,
7126
7379
  startLine,
7127
- vulnerabilityReportIssue: { fixId }
7380
+ vulnerabilityReportIssue: { fixId, vulnerabilityReportIssueTags, category },
7381
+ vulnerabilityReportIssueId
7128
7382
  } = vulnerabilityReportIssueCodeNode;
7383
+ const irrelevantIssueWithTags = mapCategoryToBucket[category] === "irrelevant" && vulnerabilityReportIssueTags?.length > 0 ? vulnerabilityReportIssueTags : [];
7129
7384
  const fix = fixesById[fixId];
7130
7385
  if (!fix || fix.patchAndQuestions.__typename !== "FixData") {
7131
7386
  throw new Error(`fix ${fixId} not found`);
@@ -7142,8 +7397,10 @@ Refresh the page in order to see the changes.`,
7142
7397
  line: startLine
7143
7398
  });
7144
7399
  const commentId = commentRes.data.id;
7145
- const commentBody = buildCommentBody({
7400
+ const commentBody = buildFixCommentBody({
7146
7401
  fix,
7402
+ issueId: vulnerabilityReportIssueId,
7403
+ irrelevantIssueWithTags,
7147
7404
  commentId,
7148
7405
  commentUrl: commentRes.data.html_url,
7149
7406
  scanner,
@@ -7297,7 +7554,7 @@ async function addFixCommentsForPr({
7297
7554
  gqlClient,
7298
7555
  scanner
7299
7556
  }) {
7300
- if (_scm instanceof GithubSCMLib === false) {
7557
+ if (!(_scm instanceof GithubSCMLib)) {
7301
7558
  return;
7302
7559
  }
7303
7560
  const scm = _scm;
@@ -7319,7 +7576,10 @@ async function addFixCommentsForPr({
7319
7576
  gqlClient,
7320
7577
  vulnerabilityReportId: getAnalysisRes.vulnerabilityReportId
7321
7578
  });
7322
- const { vulnerabilityReportIssueCodeNodes } = prVulenrabilities;
7579
+ const {
7580
+ vulnerabilityReportIssueCodeNodes,
7581
+ irrelevantVulnerabilityReportIssues
7582
+ } = prVulenrabilities;
7323
7583
  const fixesId = vulnerabilityReportIssueCodeNodes.map(
7324
7584
  ({ vulnerabilityReportIssue: { fixId } }) => fixId
7325
7585
  );
@@ -7348,6 +7608,33 @@ async function addFixCommentsForPr({
7348
7608
  });
7349
7609
  }
7350
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
+ }),
7351
7638
  postAnalysisInsightComment({
7352
7639
  prVulenrabilities,
7353
7640
  pullRequest,
@@ -7552,9 +7839,37 @@ var VulnerabilityReportIssueCodeNodeZ = z27.object({
7552
7839
  path: z27.string(),
7553
7840
  startLine: z27.number(),
7554
7841
  vulnerabilityReportIssue: z27.object({
7555
- fixId: z27.string()
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
+ )
7556
7850
  })
7557
7851
  });
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
+ });
7558
7873
  var GetVulByNodesMetadataZ = z27.object({
7559
7874
  vulnerabilityReportIssueCodeNodes: z27.array(VulnerabilityReportIssueCodeNodeZ),
7560
7875
  nonFixablePrVuls: z27.object({
@@ -7571,7 +7886,10 @@ var GetVulByNodesMetadataZ = z27.object({
7571
7886
  aggregate: z27.object({
7572
7887
  count: z27.number()
7573
7888
  })
7574
- })
7889
+ }),
7890
+ irrelevantVulnerabilityReportIssue: z27.array(
7891
+ VulnerabilityReportIssueNoFixCodeNodeZ
7892
+ )
7575
7893
  });
7576
7894
 
7577
7895
  // src/features/analysis/graphql/gql.ts
@@ -7723,6 +8041,7 @@ var GQLClient = class {
7723
8041
  const totalScanVulnerabilities = parsedGetVulByNodesMetadataRes.totalScanVulnerabilities.aggregate.count;
7724
8042
  const vulnerabilitiesOutsidePr = totalScanVulnerabilities - nonFixablePrVuls - fixablePrVuls;
7725
8043
  const totalPrVulnerabilities = nonFixablePrVuls + fixablePrVuls;
8044
+ const irrelevantVulnerabilityReportIssues = parsedGetVulByNodesMetadataRes.irrelevantVulnerabilityReportIssue?.[0]?.vulnerabilityReportIssues ?? [];
7726
8045
  return {
7727
8046
  vulnerabilityReportIssueCodeNodes: Object.values(
7728
8047
  uniqueVulByNodesMetadata
@@ -7731,7 +8050,8 @@ var GQLClient = class {
7731
8050
  fixablePrVuls,
7732
8051
  totalScanVulnerabilities,
7733
8052
  vulnerabilitiesOutsidePr,
7734
- totalPrVulnerabilities
8053
+ totalPrVulnerabilities,
8054
+ irrelevantVulnerabilityReportIssues
7735
8055
  };
7736
8056
  }
7737
8057
  async digestVulnerabilityReport({