mobbdev 1.0.65 → 1.0.74

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 +1559 -1473
  2. package/package.json +13 -13
package/dist/index.mjs CHANGED
@@ -7,7 +7,7 @@ var __export = (target, all) => {
7
7
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
8
8
 
9
9
  // src/index.ts
10
- import Debug19 from "debug";
10
+ import Debug20 from "debug";
11
11
  import { hideBin } from "yargs/helpers";
12
12
 
13
13
  // src/types.ts
@@ -111,6 +111,7 @@ var IssueLanguage_Enum = /* @__PURE__ */ ((IssueLanguage_Enum2) => {
111
111
  })(IssueLanguage_Enum || {});
112
112
  var IssueType_Enum = /* @__PURE__ */ ((IssueType_Enum2) => {
113
113
  IssueType_Enum2["AutoEscapeFalse"] = "AUTO_ESCAPE_FALSE";
114
+ IssueType_Enum2["AvoidIdentityComparisonCachedTypes"] = "AVOID_IDENTITY_COMPARISON_CACHED_TYPES";
114
115
  IssueType_Enum2["ClientDomStoredCodeInjection"] = "CLIENT_DOM_STORED_CODE_INJECTION";
115
116
  IssueType_Enum2["CmDi"] = "CMDi";
116
117
  IssueType_Enum2["CmDiRelativePathCommand"] = "CMDi_relative_path_command";
@@ -146,6 +147,7 @@ var IssueType_Enum = /* @__PURE__ */ ((IssueType_Enum2) => {
146
147
  IssueType_Enum2["InsecureBinderConfiguration"] = "INSECURE_BINDER_CONFIGURATION";
147
148
  IssueType_Enum2["InsecureCookie"] = "INSECURE_COOKIE";
148
149
  IssueType_Enum2["InsecureRandomness"] = "INSECURE_RANDOMNESS";
150
+ IssueType_Enum2["InsecureTmpFile"] = "INSECURE_TMP_FILE";
149
151
  IssueType_Enum2["InsecureUuidVersion"] = "INSECURE_UUID_VERSION";
150
152
  IssueType_Enum2["InsufficientLogging"] = "INSUFFICIENT_LOGGING";
151
153
  IssueType_Enum2["JqueryDeprecatedSymbols"] = "JQUERY_DEPRECATED_SYMBOLS";
@@ -158,10 +160,13 @@ var IssueType_Enum = /* @__PURE__ */ ((IssueType_Enum2) => {
158
160
  IssueType_Enum2["MissingEqualsOrHashcode"] = "MISSING_EQUALS_OR_HASHCODE";
159
161
  IssueType_Enum2["MissingHstsHeader"] = "MISSING_HSTS_HEADER";
160
162
  IssueType_Enum2["MissingSslMinversion"] = "MISSING_SSL_MINVERSION";
163
+ IssueType_Enum2["ModifiedDefaultParam"] = "MODIFIED_DEFAULT_PARAM";
161
164
  IssueType_Enum2["NonFinalPublicStaticField"] = "NON_FINAL_PUBLIC_STATIC_FIELD";
162
165
  IssueType_Enum2["NonReadonlyField"] = "NON_READONLY_FIELD";
163
166
  IssueType_Enum2["NoEquivalenceMethod"] = "NO_EQUIVALENCE_METHOD";
164
167
  IssueType_Enum2["NoLimitsOrThrottling"] = "NO_LIMITS_OR_THROTTLING";
168
+ IssueType_Enum2["NoReturnInFinally"] = "NO_RETURN_IN_FINALLY";
169
+ IssueType_Enum2["NoVar"] = "NO_VAR";
165
170
  IssueType_Enum2["NullDereference"] = "NULL_DEREFERENCE";
166
171
  IssueType_Enum2["OpenRedirect"] = "OPEN_REDIRECT";
167
172
  IssueType_Enum2["OverlyBroadCatch"] = "OVERLY_BROAD_CATCH";
@@ -177,6 +182,7 @@ var IssueType_Enum = /* @__PURE__ */ ((IssueType_Enum2) => {
177
182
  IssueType_Enum2["SqlInjection"] = "SQL_Injection";
178
183
  IssueType_Enum2["Ssrf"] = "SSRF";
179
184
  IssueType_Enum2["StringFormatMisuse"] = "STRING_FORMAT_MISUSE";
185
+ IssueType_Enum2["SystemExitShouldReraise"] = "SYSTEM_EXIT_SHOULD_RERAISE";
180
186
  IssueType_Enum2["SystemInformationLeak"] = "SYSTEM_INFORMATION_LEAK";
181
187
  IssueType_Enum2["SystemInformationLeakExternal"] = "SYSTEM_INFORMATION_LEAK_EXTERNAL";
182
188
  IssueType_Enum2["TrustBoundaryViolation"] = "TRUST_BOUNDARY_VIOLATION";
@@ -184,6 +190,7 @@ var IssueType_Enum = /* @__PURE__ */ ((IssueType_Enum2) => {
184
190
  IssueType_Enum2["UncheckedLoopCondition"] = "UNCHECKED_LOOP_CONDITION";
185
191
  IssueType_Enum2["UnsafeDeserialization"] = "UNSAFE_DESERIALIZATION";
186
192
  IssueType_Enum2["UnsafeTargetBlank"] = "UNSAFE_TARGET_BLANK";
193
+ IssueType_Enum2["UnsafeWebThread"] = "UNSAFE_WEB_THREAD";
187
194
  IssueType_Enum2["UnvalidatedPublicMethodArgument"] = "UNVALIDATED_PUBLIC_METHOD_ARGUMENT";
188
195
  IssueType_Enum2["UselessRegexpCharEscape"] = "USELESS_REGEXP_CHAR_ESCAPE";
189
196
  IssueType_Enum2["UseOfHardCodedCryptographicKey"] = "USE_OF_HARD_CODED_CRYPTOGRAPHIC_KEY";
@@ -458,10 +465,24 @@ var GetVulByNodesMetadataDocument = `
458
465
  vulnerabilityReportIssueTags {
459
466
  tag: vulnerability_report_issue_tag_value
460
467
  }
461
- codeNodes(order_by: {index: desc}, where: {_or: $filters}) {
468
+ codeNodes(order_by: {index: desc}, where: {_or: $filters}, limit: 1) {
462
469
  path
463
470
  startLine
464
471
  }
472
+ fpId
473
+ }
474
+ }
475
+ }
476
+ `;
477
+ var GetFalsePositiveDocument = `
478
+ query getFalsePositive($fpId: uuid!) {
479
+ getFalsePositive(fpId: $fpId) {
480
+ ... on FalsePositiveData {
481
+ extraContext {
482
+ key
483
+ value
484
+ }
485
+ fixDescription
465
486
  }
466
487
  }
467
488
  }
@@ -692,6 +713,9 @@ function getSdk(client, withWrapper = defaultWrapper) {
692
713
  getVulByNodesMetadata(variables, requestHeaders) {
693
714
  return withWrapper((wrappedRequestHeaders) => client.request(GetVulByNodesMetadataDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "getVulByNodesMetadata", "query", variables);
694
715
  },
716
+ getFalsePositive(variables, requestHeaders) {
717
+ return withWrapper((wrappedRequestHeaders) => client.request(GetFalsePositiveDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "getFalsePositive", "query", variables);
718
+ },
695
719
  updateScmToken(variables, requestHeaders) {
696
720
  return withWrapper((wrappedRequestHeaders) => client.request(UpdateScmTokenDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "updateScmToken", "mutation", variables);
697
721
  },
@@ -1144,7 +1168,14 @@ var issueTypeMap = {
1144
1168
  ["WEBSOCKET_MISSING_ORIGIN_CHECK" /* WebsocketMissingOriginCheck */]: "Missing Websocket Origin Check",
1145
1169
  ["DUPLICATED_STRINGS" /* DuplicatedStrings */]: "String Literals Should not Be Duplicated",
1146
1170
  ["INSECURE_UUID_VERSION" /* InsecureUuidVersion */]: "Insecure UUID Version",
1147
- ["GH_ACTIONS_SHELL_INJECTION" /* GhActionsShellInjection */]: "GitHub Actions Shell Injection"
1171
+ ["GH_ACTIONS_SHELL_INJECTION" /* GhActionsShellInjection */]: "GitHub Actions Shell Injection",
1172
+ ["MODIFIED_DEFAULT_PARAM" /* ModifiedDefaultParam */]: "Modified Default Param",
1173
+ ["UNSAFE_WEB_THREAD" /* UnsafeWebThread */]: "Unsafe Web Thread",
1174
+ ["NO_VAR" /* NoVar */]: 'Prefer "let" or "const"',
1175
+ ["INSECURE_TMP_FILE" /* InsecureTmpFile */]: "Insecure Temporary File",
1176
+ ["SYSTEM_EXIT_SHOULD_RERAISE" /* SystemExitShouldReraise */]: "SystemExit Should Reraise",
1177
+ ["NO_RETURN_IN_FINALLY" /* NoReturnInFinally */]: "No Return in Finally Block",
1178
+ ["AVOID_IDENTITY_COMPARISON_CACHED_TYPES" /* AvoidIdentityComparisonCachedTypes */]: "Avoid Identity Comparison of Cached Types"
1148
1179
  };
1149
1180
  var issueTypeZ = z5.nativeEnum(IssueType_Enum);
1150
1181
  var getIssueTypeFriendlyString = (issueType) => {
@@ -1177,6 +1208,22 @@ var issueDescription = {
1177
1208
  ["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**.",
1178
1209
  ["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."
1179
1210
  };
1211
+ function replaceKeysWithValues(fixDescription, extraContext) {
1212
+ let result = fixDescription;
1213
+ extraContext.forEach(({ key, value }) => {
1214
+ result = result.replace(`\${${key}}`, value);
1215
+ });
1216
+ return result;
1217
+ }
1218
+ function getParsedFalsePositiveMessage(data) {
1219
+ const { fixDescription, extraContext } = data;
1220
+ const containsTemplate = extraContext.some(
1221
+ (context) => fixDescription.includes(`\${${context.key}}`)
1222
+ );
1223
+ const description = containsTemplate ? replaceKeysWithValues(fixDescription, extraContext) : fixDescription;
1224
+ const contextString = containsTemplate ? null : `\`\`\`${extraContext.map(({ value }) => value).join(" ")} \`\`\``;
1225
+ return { description, contextString };
1226
+ }
1180
1227
 
1181
1228
  // src/features/analysis/scm/shared/src/validations.ts
1182
1229
  var IssueTypeSettingZ = z6.object({
@@ -1258,7 +1305,9 @@ var ReportQueryResultZ = z7.object({
1258
1305
  }),
1259
1306
  fixesDoneCount: z7.number(),
1260
1307
  fixesInprogressCount: z7.number(),
1261
- fixesReadyCount: z7.number(),
1308
+ fixesReadyCount: z7.object({
1309
+ aggregate: z7.object({ count: z7.number() })
1310
+ }),
1262
1311
  issueTypes: z7.record(z7.string(), z7.number()).nullable(),
1263
1312
  issueLanguages: z7.record(z7.string(), z7.number()).nullable(),
1264
1313
  fixesCountByEffort: z7.record(z7.string(), z7.number()).nullable(),
@@ -1786,7 +1835,7 @@ var CliError = class extends Error {
1786
1835
  // src/features/analysis/index.ts
1787
1836
  import chalk4 from "chalk";
1788
1837
  import Configstore from "configstore";
1789
- import Debug17 from "debug";
1838
+ import Debug18 from "debug";
1790
1839
  import extract from "extract-zip";
1791
1840
  import { createSpinner as createSpinner4 } from "nanospinner";
1792
1841
  import fetch4 from "node-fetch";
@@ -1797,9 +1846,6 @@ import { z as z29 } from "zod";
1797
1846
  // src/features/analysis/add_fix_comments_for_pr/add_fix_comments_for_pr.ts
1798
1847
  import Debug8 from "debug";
1799
1848
 
1800
- // src/features/analysis/scm/github/GithubSCMLib.ts
1801
- import { z as z24 } from "zod";
1802
-
1803
1849
  // src/features/analysis/scm/errors.ts
1804
1850
  var InvalidRepoUrlError = class extends Error {
1805
1851
  constructor(m) {
@@ -1828,26 +1874,26 @@ var RepoNoTokenAccessError = class extends Error {
1828
1874
  }
1829
1875
  };
1830
1876
 
1831
- // src/features/analysis/scm/scmSubmit/index.ts
1832
- import { simpleGit } from "simple-git";
1833
- var isValidBranchName = async (branchName) => {
1834
- const git = simpleGit();
1835
- try {
1836
- const res = await git.raw(["check-ref-format", "--branch", branchName]);
1837
- if (res) {
1838
- return true;
1839
- }
1840
- return false;
1841
- } catch (e) {
1842
- return false;
1843
- }
1844
- };
1877
+ // src/features/analysis/scm/ado/constants.ts
1878
+ var DEFUALT_ADO_ORIGIN = scmCloudUrl.Ado;
1845
1879
 
1846
- // src/features/analysis/scm/types.ts
1847
- import { z as z14 } from "zod";
1880
+ // src/features/analysis/scm/ado/utils.ts
1881
+ import querystring from "node:querystring";
1882
+ import * as api from "azure-devops-node-api";
1883
+ import Debug2 from "debug";
1884
+ import { z as z18 } from "zod";
1848
1885
 
1849
- // src/features/analysis/scm/shared/src/commitDescriptionMarkup.ts
1886
+ // src/features/analysis/scm/env.ts
1850
1887
  import { z as z9 } from "zod";
1888
+ var EnvVariablesZod = z9.object({
1889
+ GITLAB_API_TOKEN: z9.string().optional(),
1890
+ GITHUB_API_TOKEN: z9.string().optional(),
1891
+ GIT_PROXY_HOST: z9.string()
1892
+ });
1893
+ var { GITLAB_API_TOKEN, GITHUB_API_TOKEN, GIT_PROXY_HOST } = EnvVariablesZod.parse(process.env);
1894
+
1895
+ // src/features/analysis/scm/shared/src/commitDescriptionMarkup.ts
1896
+ import { z as z10 } from "zod";
1851
1897
 
1852
1898
  // src/features/analysis/scm/shared/src/fixDetailsData.ts
1853
1899
  var fixDetailsData = {
@@ -2091,7 +2137,14 @@ var fixDetailsData = {
2091
2137
  ["WEBSOCKET_MISSING_ORIGIN_CHECK" /* WebsocketMissingOriginCheck */]: void 0,
2092
2138
  ["DUPLICATED_STRINGS" /* DuplicatedStrings */]: void 0,
2093
2139
  ["INSECURE_UUID_VERSION" /* InsecureUuidVersion */]: void 0,
2094
- ["GH_ACTIONS_SHELL_INJECTION" /* GhActionsShellInjection */]: void 0
2140
+ ["GH_ACTIONS_SHELL_INJECTION" /* GhActionsShellInjection */]: void 0,
2141
+ ["MODIFIED_DEFAULT_PARAM" /* ModifiedDefaultParam */]: void 0,
2142
+ ["UNSAFE_WEB_THREAD" /* UnsafeWebThread */]: void 0,
2143
+ ["NO_VAR" /* NoVar */]: void 0,
2144
+ ["INSECURE_TMP_FILE" /* InsecureTmpFile */]: void 0,
2145
+ ["SYSTEM_EXIT_SHOULD_RERAISE" /* SystemExitShouldReraise */]: void 0,
2146
+ ["NO_RETURN_IN_FINALLY" /* NoReturnInFinally */]: void 0,
2147
+ ["AVOID_IDENTITY_COMPARISON_CACHED_TYPES" /* AvoidIdentityComparisonCachedTypes */]: void 0
2095
2148
  };
2096
2149
 
2097
2150
  // src/features/analysis/scm/shared/src/commitDescriptionMarkup.ts
@@ -2122,7 +2175,7 @@ var getCommitDescription = ({
2122
2175
  )}**.
2123
2176
 
2124
2177
  `;
2125
- const parseIssueTypeRes = z9.nativeEnum(IssueType_Enum).safeParse(issueType);
2178
+ const parseIssueTypeRes = z10.nativeEnum(IssueType_Enum).safeParse(issueType);
2126
2179
  if (issueType && parseIssueTypeRes.success) {
2127
2180
  if (irrelevantIssueWithTags?.[0]?.tag) {
2128
2181
  description += `
@@ -2159,22 +2212,24 @@ ${guidances.map(({ guidance }) => `## Additional actions required
2159
2212
  var getCommitIssueDescription = ({
2160
2213
  vendor,
2161
2214
  issueType,
2162
- irrelevantIssueWithTags
2215
+ irrelevantIssueWithTags,
2216
+ fpDescription
2163
2217
  }) => {
2164
2218
  const issueTypeString = getIssueTypeFriendlyString(issueType);
2165
2219
  let description = `The following issues reported by ${capitalizeFirstLetter(vendor)} on this PR were found to be irrelevant to your project:
2166
2220
  `;
2167
- const parseIssueTypeRes = z9.nativeEnum(IssueType_Enum).safeParse(issueType);
2221
+ const parseIssueTypeRes = z10.nativeEnum(IssueType_Enum).safeParse(issueType);
2168
2222
  if (issueType && parseIssueTypeRes.success) {
2169
2223
  if (irrelevantIssueWithTags?.[0]?.tag) {
2170
- description += `
2224
+ description = `
2171
2225
  > [!tip]
2226
+ > The following issues reported by ${capitalizeFirstLetter(vendor)} on this PR were found to be irrelevant to your project:
2172
2227
  > ${issueTypeString} - ${lowercaseFirstLetter(getTagTooltip(irrelevantIssueWithTags[0].tag))}.
2173
2228
  > Mobb recommends to ignore this issue, however fix is available if you think differently.
2174
2229
 
2175
2230
 
2176
2231
  ## Justification
2177
- ${issueDescription[irrelevantIssueWithTags[0].tag]}
2232
+ ${fpDescription ?? issueDescription[irrelevantIssueWithTags[0].tag]}
2178
2233
  `;
2179
2234
  }
2180
2235
  const staticData = fixDetailsData[parseIssueTypeRes.data];
@@ -2188,10 +2243,10 @@ ${staticData.issueDescription}
2188
2243
  };
2189
2244
 
2190
2245
  // src/features/analysis/scm/shared/src/guidances.ts
2191
- import { z as z12 } from "zod";
2246
+ import { z as z13 } from "zod";
2192
2247
 
2193
2248
  // src/features/analysis/scm/shared/src/storedFixData/index.ts
2194
- import { z as z10 } from "zod";
2249
+ import { z as z11 } from "zod";
2195
2250
 
2196
2251
  // src/features/analysis/scm/shared/src/storedFixData/passwordInComment.ts
2197
2252
  var passwordInComment = {
@@ -2367,8 +2422,8 @@ var vulnerabilities8 = {
2367
2422
  var xml_default = vulnerabilities8;
2368
2423
 
2369
2424
  // src/features/analysis/scm/shared/src/storedFixData/index.ts
2370
- var StoredFixDataItemZ = z10.object({
2371
- guidance: z10.function().returns(z10.string())
2425
+ var StoredFixDataItemZ = z11.object({
2426
+ guidance: z11.function().returns(z11.string())
2372
2427
  });
2373
2428
  var languages = {
2374
2429
  ["Java" /* Java */]: java_default,
@@ -2382,7 +2437,7 @@ var languages = {
2382
2437
  };
2383
2438
 
2384
2439
  // src/features/analysis/scm/shared/src/storedQuestionData/index.ts
2385
- import { z as z11 } from "zod";
2440
+ import { z as z12 } from "zod";
2386
2441
 
2387
2442
  // src/features/analysis/scm/shared/src/storedQuestionData/csharp/httpOnlyCookie.ts
2388
2443
  var httpOnlyCookie = {
@@ -3581,10 +3636,10 @@ var vulnerabilities14 = {
3581
3636
  var xml_default2 = vulnerabilities14;
3582
3637
 
3583
3638
  // src/features/analysis/scm/shared/src/storedQuestionData/index.ts
3584
- var StoredQuestionDataItemZ = z11.object({
3585
- content: z11.function().args(z11.any()).returns(z11.string()),
3586
- description: z11.function().args(z11.any()).returns(z11.string()),
3587
- guidance: z11.function().args(z11.any()).returns(z11.string())
3639
+ var StoredQuestionDataItemZ = z12.object({
3640
+ content: z12.function().args(z12.any()).returns(z12.string()),
3641
+ description: z12.function().args(z12.any()).returns(z12.string()),
3642
+ guidance: z12.function().args(z12.any()).returns(z12.string())
3588
3643
  });
3589
3644
  var languages2 = {
3590
3645
  ["Java" /* Java */]: java_default2,
@@ -3679,9 +3734,9 @@ function getFixGuidances({
3679
3734
  const fixGuidance = storeFixResult.success ? [storeFixResult.data.guidance({ questions, ...extraContext })] : [];
3680
3735
  return libGuidances.concat(fixGuidance).filter((guidance) => !!guidance);
3681
3736
  }
3682
- var IssueTypeAndLanguageZ = z12.object({
3683
- issueType: z12.nativeEnum(IssueType_Enum),
3684
- issueLanguage: z12.nativeEnum(IssueLanguage_Enum)
3737
+ var IssueTypeAndLanguageZ = z13.object({
3738
+ issueType: z13.nativeEnum(IssueType_Enum),
3739
+ issueLanguage: z13.nativeEnum(IssueLanguage_Enum)
3685
3740
  });
3686
3741
  function getGuidances(args) {
3687
3742
  const safeIssueTypeAndLanguage = IssueTypeAndLanguageZ.safeParse({
@@ -3719,7 +3774,7 @@ function getGuidances(args) {
3719
3774
  }
3720
3775
 
3721
3776
  // src/features/analysis/scm/shared/src/urlParser/urlParser.ts
3722
- import { z as z13 } from "zod";
3777
+ import { z as z14 } from "zod";
3723
3778
  var ADO_PREFIX_PATH = "tfs";
3724
3779
  var NAME_REGEX = /[a-z0-9\-_.+]+/i;
3725
3780
  function detectAdoUrl(args) {
@@ -3736,7 +3791,7 @@ function detectAdoUrl(args) {
3736
3791
  scmType: "Ado" /* Ado */,
3737
3792
  organization,
3738
3793
  // project has single repo - repoName === projectName
3739
- projectName: z13.string().parse(projectName),
3794
+ projectName: z14.string().parse(projectName),
3740
3795
  repoName: projectName,
3741
3796
  prefixPath
3742
3797
  };
@@ -3747,7 +3802,7 @@ function detectAdoUrl(args) {
3747
3802
  return {
3748
3803
  scmType: "Ado" /* Ado */,
3749
3804
  organization,
3750
- projectName: z13.string().parse(projectName),
3805
+ projectName: z14.string().parse(projectName),
3751
3806
  repoName,
3752
3807
  prefixPath
3753
3808
  };
@@ -3761,7 +3816,7 @@ function detectAdoUrl(args) {
3761
3816
  scmType: "Ado" /* Ado */,
3762
3817
  organization,
3763
3818
  // project has only one repo - repoName === projectName
3764
- projectName: z13.string().parse(repoName),
3819
+ projectName: z14.string().parse(repoName),
3765
3820
  repoName,
3766
3821
  prefixPath
3767
3822
  };
@@ -3771,7 +3826,7 @@ function detectAdoUrl(args) {
3771
3826
  return {
3772
3827
  scmType: "Ado" /* Ado */,
3773
3828
  organization,
3774
- projectName: z13.string().parse(projectName),
3829
+ projectName: z14.string().parse(projectName),
3775
3830
  repoName,
3776
3831
  prefixPath
3777
3832
  };
@@ -3897,7 +3952,11 @@ function getIssueUrl({
3897
3952
  return `${appBaseUrl}/organization/${organizationId}/project/${projectId}/report/${analysisId}/issue/${issueId}`;
3898
3953
  }
3899
3954
 
3955
+ // src/features/analysis/scm/utils/index.ts
3956
+ import { z as z16 } from "zod";
3957
+
3900
3958
  // src/features/analysis/scm/types.ts
3959
+ import { z as z15 } from "zod";
3901
3960
  var ReferenceType = /* @__PURE__ */ ((ReferenceType2) => {
3902
3961
  ReferenceType2["BRANCH"] = "BRANCH";
3903
3962
  ReferenceType2["COMMIT"] = "COMMIT";
@@ -3929,14 +3988,13 @@ var scmTypeToScmLibScmType = {
3929
3988
  ["Ado" /* Ado */]: "ADO" /* ADO */,
3930
3989
  ["Bitbucket" /* Bitbucket */]: "BITBUCKET" /* BITBUCKET */
3931
3990
  };
3932
- var GetRefererenceResultZ = z14.object({
3933
- date: z14.date().optional(),
3934
- sha: z14.string(),
3935
- type: z14.nativeEnum(ReferenceType)
3991
+ var GetRefererenceResultZ = z15.object({
3992
+ date: z15.date().optional(),
3993
+ sha: z15.string(),
3994
+ type: z15.nativeEnum(ReferenceType)
3936
3995
  });
3937
3996
 
3938
3997
  // src/features/analysis/scm/utils/index.ts
3939
- import { z as z15 } from "zod";
3940
3998
  function getFixUrlWithRedirect(params) {
3941
3999
  const {
3942
4000
  fixId,
@@ -4047,7 +4105,7 @@ function shouldValidateUrl(repoUrl) {
4047
4105
  return repoUrl && isUrlHasPath(repoUrl);
4048
4106
  }
4049
4107
  function isBrokerUrl(url) {
4050
- return z15.string().uuid().safeParse(new URL(url).host).success;
4108
+ return z16.string().uuid().safeParse(new URL(url).host).success;
4051
4109
  }
4052
4110
  function buildAuthorizedRepoUrl(args) {
4053
4111
  const { url, username, password } = args;
@@ -4083,7 +4141,7 @@ function getCloudScmLibTypeFromUrl(url) {
4083
4141
  return void 0;
4084
4142
  }
4085
4143
  function getScmLibTypeFromScmType(scmType) {
4086
- const parsedScmType = z15.nativeEnum(ScmType).parse(scmType);
4144
+ const parsedScmType = z16.nativeEnum(ScmType).parse(scmType);
4087
4145
  return scmTypeToScmLibScmType[parsedScmType];
4088
4146
  }
4089
4147
  function getScmConfig({
@@ -4149,162 +4207,6 @@ function getScmConfig({
4149
4207
  };
4150
4208
  }
4151
4209
 
4152
- // src/features/analysis/scm/scm.ts
4153
- var SCMLib = class {
4154
- constructor(url, accessToken, scmOrg) {
4155
- __publicField(this, "url");
4156
- __publicField(this, "accessToken");
4157
- __publicField(this, "scmOrg");
4158
- this.accessToken = accessToken;
4159
- this.url = url;
4160
- this.scmOrg = scmOrg;
4161
- }
4162
- async getUrlWithCredentials() {
4163
- if (!this.url) {
4164
- console.error("no url for getUrlWithCredentials()");
4165
- throw new Error("no url");
4166
- }
4167
- const trimmedUrl = this.url.trim().replace(/\/$/, "");
4168
- const accessToken = this.getAccessToken();
4169
- if (!accessToken) {
4170
- return trimmedUrl;
4171
- }
4172
- if (this.scmLibType === "ADO" /* ADO */) {
4173
- const { host, protocol, pathname } = new URL(trimmedUrl);
4174
- return `${protocol}//${accessToken}@${host}${pathname}`;
4175
- }
4176
- const finalUrl = this.scmLibType === "GITLAB" /* GITLAB */ ? `${trimmedUrl}.git` : trimmedUrl;
4177
- const username = await this._getUsernameForAuthUrl();
4178
- return buildAuthorizedRepoUrl({
4179
- url: finalUrl,
4180
- username,
4181
- password: accessToken
4182
- });
4183
- }
4184
- getAccessToken() {
4185
- return this.accessToken || "";
4186
- }
4187
- getUrl() {
4188
- return this.url;
4189
- }
4190
- getName() {
4191
- if (!this.url) {
4192
- return "";
4193
- }
4194
- return this.url.split("/").at(-1) || "";
4195
- }
4196
- _validateAccessToken() {
4197
- if (!this.accessToken) {
4198
- console.error("no access token");
4199
- throw new Error("no access token");
4200
- }
4201
- }
4202
- static async getIsValidBranchName(branchName) {
4203
- return isValidBranchName(branchName);
4204
- }
4205
- _validateAccessTokenAndUrl() {
4206
- this._validateAccessToken();
4207
- this._validateUrl();
4208
- }
4209
- _validateUrl() {
4210
- if (!this.url) {
4211
- console.error("no url");
4212
- throw new InvalidRepoUrlError("no url");
4213
- }
4214
- }
4215
- };
4216
-
4217
- // src/features/analysis/scm/github/github.ts
4218
- import { RequestError } from "@octokit/request-error";
4219
-
4220
- // src/features/analysis/scm/constants.ts
4221
- var MOBB_ICON_IMG = "https://app.mobb.ai/gh-action/Logo_Rounded_Icon.svg";
4222
- var MAX_BRANCHES_FETCH = 1e3;
4223
-
4224
- // src/features/analysis/scm/github/consts.ts
4225
- var POST_COMMENT_PATH = "POST /repos/{owner}/{repo}/pulls/{pull_number}/comments";
4226
- var DELETE_COMMENT_PATH = "DELETE /repos/{owner}/{repo}/pulls/comments/{comment_id}";
4227
- var UPDATE_COMMENT_PATH = "PATCH /repos/{owner}/{repo}/pulls/comments/{comment_id}";
4228
- var GET_PR_COMMENTS_PATH = "GET /repos/{owner}/{repo}/pulls/{pull_number}/comments";
4229
- var GET_PR_COMMENT_PATH = "GET /repos/{owner}/{repo}/pulls/comments/{comment_id}";
4230
- var REPLY_TO_CODE_REVIEW_COMMENT_PATH = "POST /repos/{owner}/{repo}/pulls/{pull_number}/comments/{comment_id}/replies";
4231
- var GET_PR = "GET /repos/{owner}/{repo}/pulls/{pull_number}";
4232
- var POST_GENERAL_PR_COMMENT = "POST /repos/{owner}/{repo}/issues/{issue_number}/comments";
4233
- var GET_GENERAL_PR_COMMENTS = "GET /repos/{owner}/{repo}/issues/{issue_number}/comments";
4234
- var DELETE_GENERAL_PR_COMMENT = "DELETE /repos/{owner}/{repo}/issues/comments/{comment_id}";
4235
- var CREATE_OR_UPDATE_A_REPOSITORY_SECRET = "PUT /repos/{owner}/{repo}/actions/secrets/{secret_name}";
4236
- var GET_A_REPOSITORY_PUBLIC_KEY = "GET /repos/{owner}/{repo}/actions/secrets/public-key";
4237
- var GET_USER = "GET /user";
4238
- var GET_USER_REPOS = "GET /user/repos";
4239
- var GET_REPO_BRANCHES = "GET /repos/{owner}/{repo}/branches";
4240
- var GET_BLAME_DOCUMENT = `
4241
- query GetBlame(
4242
- $owner: String!
4243
- $repo: String!
4244
- $ref: String!
4245
- $path: String!
4246
- ) {
4247
- repository(name: $repo, owner: $owner) {
4248
- # branch name
4249
- object(expression: $ref) {
4250
- # cast Target to a Commit
4251
- ... on Commit {
4252
- # full repo-relative path to blame file
4253
- blame(path: $path) {
4254
- ranges {
4255
- commit {
4256
- author {
4257
- user {
4258
- name
4259
- login
4260
- }
4261
- }
4262
- authoredDate
4263
- }
4264
- startingLine
4265
- endingLine
4266
- age
4267
- }
4268
- }
4269
- }
4270
-
4271
- }
4272
- }
4273
- }
4274
- `;
4275
-
4276
- // src/features/analysis/scm/github/utils/encrypt_secret.ts
4277
- import sodium from "libsodium-wrappers";
4278
- async function encryptSecret(secret, key) {
4279
- await sodium.ready;
4280
- const binkey = sodium.from_base64(key, sodium.base64_variants.ORIGINAL);
4281
- const binsec = sodium.from_string(secret);
4282
- const encBytes = sodium.crypto_box_seal(binsec, binkey);
4283
- return sodium.to_base64(encBytes, sodium.base64_variants.ORIGINAL);
4284
- }
4285
-
4286
- // src/features/analysis/scm/github/utils/utils.ts
4287
- import { Octokit } from "octokit";
4288
- import { fetch as fetch2, ProxyAgent as ProxyAgent2 } from "undici";
4289
-
4290
- // src/features/analysis/scm/ado/constants.ts
4291
- var DEFUALT_ADO_ORIGIN = scmCloudUrl.Ado;
4292
-
4293
- // src/features/analysis/scm/ado/utils.ts
4294
- import querystring from "node:querystring";
4295
- import * as api from "azure-devops-node-api";
4296
- import Debug2 from "debug";
4297
- import { z as z18 } from "zod";
4298
-
4299
- // src/features/analysis/scm/env.ts
4300
- import { z as z16 } from "zod";
4301
- var EnvVariablesZod = z16.object({
4302
- GITLAB_API_TOKEN: z16.string().optional(),
4303
- GITHUB_API_TOKEN: z16.string().optional(),
4304
- GIT_PROXY_HOST: z16.string()
4305
- });
4306
- var { GITLAB_API_TOKEN, GITHUB_API_TOKEN, GIT_PROXY_HOST } = EnvVariablesZod.parse(process.env);
4307
-
4308
4210
  // src/features/analysis/scm/ado/validation.ts
4309
4211
  import { z as z17 } from "zod";
4310
4212
  var ValidPullRequestStatusZ = z17.union([
@@ -4915,36 +4817,118 @@ async function getAdoRepoList({
4915
4817
 
4916
4818
  // src/features/analysis/scm/ado/AdoSCMLib.ts
4917
4819
  import { setTimeout as setTimeout2 } from "node:timers/promises";
4918
- async function initAdoSdk(params) {
4919
- const { url, accessToken, scmOrg } = params;
4920
- const adoClientParams = await getAdoClientParams({
4921
- tokenOrg: scmOrg,
4922
- accessToken,
4923
- url
4924
- });
4925
- return getAdoSdk(adoClientParams);
4926
- }
4927
- var AdoSCMLib = class extends SCMLib {
4928
- constructor(url, accessToken, scmOrg) {
4929
- super(url, accessToken, scmOrg);
4930
- __publicField(this, "_adoSdkPromise");
4931
- this._adoSdkPromise = initAdoSdk({ accessToken, url, scmOrg });
4932
- }
4933
- async getAdoSdk() {
4934
- if (!this._adoSdkPromise) {
4935
- console.error("ado sdk was not initialized");
4936
- throw new InvalidAccessTokenError("ado sdk was not initialized");
4820
+
4821
+ // src/features/analysis/scm/scmSubmit/index.ts
4822
+ import { simpleGit } from "simple-git";
4823
+ var isValidBranchName = async (branchName) => {
4824
+ const git = simpleGit();
4825
+ try {
4826
+ const res = await git.raw(["check-ref-format", "--branch", branchName]);
4827
+ if (res) {
4828
+ return true;
4937
4829
  }
4938
- return this._adoSdkPromise;
4830
+ return false;
4831
+ } catch (e) {
4832
+ return false;
4939
4833
  }
4940
- async createSubmitRequest(params) {
4941
- this._validateAccessTokenAndUrl();
4942
- for (let i = 0; i < 5; i++) {
4943
- try {
4944
- const { targetBranchName, sourceBranchName, title, body } = params;
4945
- const adoSdk = await this.getAdoSdk();
4946
- const pullRequestId = await adoSdk.createAdoPullRequest({
4947
- title,
4834
+ };
4835
+
4836
+ // src/features/analysis/scm/scm.ts
4837
+ var SCMLib = class {
4838
+ constructor(url, accessToken, scmOrg) {
4839
+ __publicField(this, "url");
4840
+ __publicField(this, "accessToken");
4841
+ __publicField(this, "scmOrg");
4842
+ this.accessToken = accessToken;
4843
+ this.url = url;
4844
+ this.scmOrg = scmOrg;
4845
+ }
4846
+ async getUrlWithCredentials() {
4847
+ if (!this.url) {
4848
+ console.error("no url for getUrlWithCredentials()");
4849
+ throw new Error("no url");
4850
+ }
4851
+ const trimmedUrl = this.url.trim().replace(/\/$/, "");
4852
+ const accessToken = this.getAccessToken();
4853
+ if (!accessToken) {
4854
+ return trimmedUrl;
4855
+ }
4856
+ if (this.scmLibType === "ADO" /* ADO */) {
4857
+ const { host, protocol, pathname } = new URL(trimmedUrl);
4858
+ return `${protocol}//${accessToken}@${host}${pathname}`;
4859
+ }
4860
+ const finalUrl = this.scmLibType === "GITLAB" /* GITLAB */ ? `${trimmedUrl}.git` : trimmedUrl;
4861
+ const username = await this._getUsernameForAuthUrl();
4862
+ return buildAuthorizedRepoUrl({
4863
+ url: finalUrl,
4864
+ username,
4865
+ password: accessToken
4866
+ });
4867
+ }
4868
+ getAccessToken() {
4869
+ return this.accessToken || "";
4870
+ }
4871
+ getUrl() {
4872
+ return this.url;
4873
+ }
4874
+ getName() {
4875
+ if (!this.url) {
4876
+ return "";
4877
+ }
4878
+ return this.url.split("/").at(-1) || "";
4879
+ }
4880
+ _validateAccessToken() {
4881
+ if (!this.accessToken) {
4882
+ console.error("no access token");
4883
+ throw new Error("no access token");
4884
+ }
4885
+ }
4886
+ static async getIsValidBranchName(branchName) {
4887
+ return isValidBranchName(branchName);
4888
+ }
4889
+ _validateAccessTokenAndUrl() {
4890
+ this._validateAccessToken();
4891
+ this._validateUrl();
4892
+ }
4893
+ _validateUrl() {
4894
+ if (!this.url) {
4895
+ console.error("no url");
4896
+ throw new InvalidRepoUrlError("no url");
4897
+ }
4898
+ }
4899
+ };
4900
+
4901
+ // src/features/analysis/scm/ado/AdoSCMLib.ts
4902
+ async function initAdoSdk(params) {
4903
+ const { url, accessToken, scmOrg } = params;
4904
+ const adoClientParams = await getAdoClientParams({
4905
+ tokenOrg: scmOrg,
4906
+ accessToken,
4907
+ url
4908
+ });
4909
+ return getAdoSdk(adoClientParams);
4910
+ }
4911
+ var AdoSCMLib = class extends SCMLib {
4912
+ constructor(url, accessToken, scmOrg) {
4913
+ super(url, accessToken, scmOrg);
4914
+ __publicField(this, "_adoSdkPromise");
4915
+ this._adoSdkPromise = initAdoSdk({ accessToken, url, scmOrg });
4916
+ }
4917
+ async getAdoSdk() {
4918
+ if (!this._adoSdkPromise) {
4919
+ console.error("ado sdk was not initialized");
4920
+ throw new InvalidAccessTokenError("ado sdk was not initialized");
4921
+ }
4922
+ return this._adoSdkPromise;
4923
+ }
4924
+ async createSubmitRequest(params) {
4925
+ this._validateAccessTokenAndUrl();
4926
+ for (let i = 0; i < 5; i++) {
4927
+ try {
4928
+ const { targetBranchName, sourceBranchName, title, body } = params;
4929
+ const adoSdk = await this.getAdoSdk();
4930
+ const pullRequestId = await adoSdk.createAdoPullRequest({
4931
+ title,
4948
4932
  body,
4949
4933
  targetBranchName,
4950
4934
  sourceBranchName,
@@ -5659,787 +5643,175 @@ var BitbucketSCMLib = class extends SCMLib {
5659
5643
  }
5660
5644
  };
5661
5645
 
5662
- // src/features/analysis/scm/gitlab/gitlab.ts
5663
- import querystring3 from "node:querystring";
5664
- import {
5665
- createRequesterFn
5666
- } from "@gitbeaker/requester-utils";
5667
- import {
5668
- AccessLevel,
5669
- Gitlab
5670
- } from "@gitbeaker/rest";
5671
- import Debug4 from "debug";
5672
- import {
5673
- fetch as undiciFetch,
5674
- ProxyAgent
5675
- } from "undici";
5646
+ // src/features/analysis/scm/constants.ts
5647
+ var MOBB_ICON_IMG = "https://app.mobb.ai/gh-action/Logo_Rounded_Icon.svg";
5648
+ var MAX_BRANCHES_FETCH = 1e3;
5676
5649
 
5677
- // src/features/analysis/scm/gitlab/types.ts
5650
+ // src/features/analysis/scm/github/GithubSCMLib.ts
5678
5651
  import { z as z22 } from "zod";
5679
- var GitlabAuthResultZ = z22.object({
5680
- access_token: z22.string(),
5681
- token_type: z22.string(),
5682
- refresh_token: z22.string()
5683
- });
5684
5652
 
5685
- // src/features/analysis/scm/gitlab/gitlab.ts
5686
- var debug4 = Debug4("scm:gitlab");
5687
- function removeTrailingSlash2(str) {
5688
- return str.trim().replace(/\/+$/, "");
5653
+ // src/features/analysis/scm/github/github.ts
5654
+ import { RequestError } from "@octokit/request-error";
5655
+
5656
+ // src/features/analysis/scm/github/consts.ts
5657
+ var POST_COMMENT_PATH = "POST /repos/{owner}/{repo}/pulls/{pull_number}/comments";
5658
+ var DELETE_COMMENT_PATH = "DELETE /repos/{owner}/{repo}/pulls/comments/{comment_id}";
5659
+ var UPDATE_COMMENT_PATH = "PATCH /repos/{owner}/{repo}/pulls/comments/{comment_id}";
5660
+ var GET_PR_COMMENTS_PATH = "GET /repos/{owner}/{repo}/pulls/{pull_number}/comments";
5661
+ var GET_PR_COMMENT_PATH = "GET /repos/{owner}/{repo}/pulls/comments/{comment_id}";
5662
+ var REPLY_TO_CODE_REVIEW_COMMENT_PATH = "POST /repos/{owner}/{repo}/pulls/{pull_number}/comments/{comment_id}/replies";
5663
+ var GET_PR = "GET /repos/{owner}/{repo}/pulls/{pull_number}";
5664
+ var POST_GENERAL_PR_COMMENT = "POST /repos/{owner}/{repo}/issues/{issue_number}/comments";
5665
+ var GET_GENERAL_PR_COMMENTS = "GET /repos/{owner}/{repo}/issues/{issue_number}/comments";
5666
+ var DELETE_GENERAL_PR_COMMENT = "DELETE /repos/{owner}/{repo}/issues/comments/{comment_id}";
5667
+ var CREATE_OR_UPDATE_A_REPOSITORY_SECRET = "PUT /repos/{owner}/{repo}/actions/secrets/{secret_name}";
5668
+ var GET_A_REPOSITORY_PUBLIC_KEY = "GET /repos/{owner}/{repo}/actions/secrets/public-key";
5669
+ var GET_USER = "GET /user";
5670
+ var GET_USER_REPOS = "GET /user/repos";
5671
+ var GET_REPO_BRANCHES = "GET /repos/{owner}/{repo}/branches";
5672
+ var GET_BLAME_DOCUMENT = `
5673
+ query GetBlame(
5674
+ $owner: String!
5675
+ $repo: String!
5676
+ $ref: String!
5677
+ $path: String!
5678
+ ) {
5679
+ repository(name: $repo, owner: $owner) {
5680
+ # branch name
5681
+ object(expression: $ref) {
5682
+ # cast Target to a Commit
5683
+ ... on Commit {
5684
+ # full repo-relative path to blame file
5685
+ blame(path: $path) {
5686
+ ranges {
5687
+ commit {
5688
+ author {
5689
+ user {
5690
+ name
5691
+ login
5692
+ }
5693
+ }
5694
+ authoredDate
5695
+ }
5696
+ startingLine
5697
+ endingLine
5698
+ age
5699
+ }
5700
+ }
5701
+ }
5702
+
5703
+ }
5704
+ }
5705
+ }
5706
+ `;
5707
+
5708
+ // src/features/analysis/scm/github/utils/encrypt_secret.ts
5709
+ import sodium from "libsodium-wrappers";
5710
+ async function encryptSecret(secret, key) {
5711
+ await sodium.ready;
5712
+ const binkey = sodium.from_base64(key, sodium.base64_variants.ORIGINAL);
5713
+ const binsec = sodium.from_string(secret);
5714
+ const encBytes = sodium.crypto_box_seal(binsec, binkey);
5715
+ return sodium.to_base64(encBytes, sodium.base64_variants.ORIGINAL);
5689
5716
  }
5690
- function getRandomGitlabCloudAnonToken() {
5691
- if (!GITLAB_API_TOKEN || typeof GITLAB_API_TOKEN !== "string") {
5692
- return void 0;
5717
+
5718
+ // src/features/analysis/scm/github/utils/utils.ts
5719
+ import { Octokit } from "octokit";
5720
+ import { fetch as fetch2, ProxyAgent } from "undici";
5721
+ function parseGithubOwnerAndRepo(gitHubUrl) {
5722
+ gitHubUrl = normalizeUrl(gitHubUrl);
5723
+ const parsingResult = parseScmURL(gitHubUrl, "GitHub" /* GitHub */);
5724
+ if (!parsingResult) {
5725
+ throw new InvalidUrlPatternError(`invalid github repo Url ${gitHubUrl}`);
5693
5726
  }
5694
- const tokens = GITLAB_API_TOKEN.split(",");
5695
- return tokens[Math.floor(Math.random() * tokens.length)];
5696
- }
5697
- function getGitBeaker(options) {
5698
- const token = options?.gitlabAuthToken ?? getRandomGitlabCloudAnonToken() ?? "";
5699
- const url = options.url;
5700
- const host = url ? new URL(url).origin : "https://gitlab.com";
5701
- if (token?.startsWith("glpat-") || token === "") {
5702
- return new Gitlab({
5703
- token,
5704
- host,
5705
- requesterFn: createRequesterFn(
5706
- (_, reqo) => Promise.resolve(reqo),
5707
- brokerRequestHandler
5708
- )
5709
- });
5727
+ const { organization, repoName } = parsingResult;
5728
+ if (!organization || !repoName) {
5729
+ throw new InvalidUrlPatternError(`invalid github repo Url ${gitHubUrl}`);
5710
5730
  }
5711
- return new Gitlab({
5712
- oauthToken: token,
5713
- host,
5714
- requesterFn: createRequesterFn(
5715
- (_, reqo) => Promise.resolve(reqo),
5716
- brokerRequestHandler
5717
- )
5718
- });
5731
+ return { owner: organization, repo: repoName };
5719
5732
  }
5720
- async function gitlabValidateParams({
5721
- url,
5722
- accessToken
5723
- }) {
5724
- try {
5725
- const api2 = getGitBeaker({ url, gitlabAuthToken: accessToken });
5726
- if (accessToken) {
5727
- await api2.Users.showCurrentUser();
5728
- }
5729
- if (url && shouldValidateUrl(url)) {
5730
- const { projectPath } = parseGitlabOwnerAndRepo(url);
5731
- await api2.Projects.show(projectPath);
5732
- }
5733
- } catch (e) {
5734
- const error = e;
5735
- const code = error.code || error.status || error.statusCode || error.response?.status || error.response?.statusCode || error.response?.code;
5736
- const description = error.description || `${e}`;
5737
- if (code === 401 || code === 403 || description.includes("401") || description.includes("403")) {
5738
- throw new InvalidAccessTokenError(`invalid gitlab access token`);
5739
- }
5740
- if (code === 404 || description.includes("404") || description.includes("Not Found")) {
5741
- throw new InvalidRepoUrlError(`invalid gitlab repo URL: ${url}`);
5742
- }
5743
- console.log("gitlabValidateParams error", e);
5744
- throw new InvalidRepoUrlError(
5745
- `cannot access gitlab repo URL: ${url} with the provided access token`
5746
- );
5733
+ function isGithubOnPrem(url) {
5734
+ if (!url) {
5735
+ return false;
5747
5736
  }
5737
+ return !url.includes(scmCloudUrl.GitHub);
5748
5738
  }
5749
- async function getGitlabUsername(url, accessToken) {
5750
- const api2 = getGitBeaker({ url, gitlabAuthToken: accessToken });
5751
- const res = await api2.Users.showCurrentUser();
5752
- return res.username;
5753
- }
5754
- async function getGitlabIsUserCollaborator({
5755
- accessToken,
5756
- repoUrl
5757
- }) {
5758
- try {
5759
- const { projectPath } = parseGitlabOwnerAndRepo(repoUrl);
5760
- const api2 = getGitBeaker({ url: repoUrl, gitlabAuthToken: accessToken });
5761
- const proj = await api2.Projects.show(projectPath);
5762
- const groupAccess = proj.permissions?.group_access?.access_level || 0;
5763
- const projectAccess = proj.permissions?.project_access?.access_level || 0;
5764
- const accessLevelWithWriteAccess = [
5765
- AccessLevel.DEVELOPER,
5766
- AccessLevel.MAINTAINER,
5767
- AccessLevel.OWNER,
5768
- AccessLevel.ADMIN
5769
- ];
5770
- return accessLevelWithWriteAccess.includes(groupAccess) || accessLevelWithWriteAccess.includes(projectAccess);
5771
- } catch (e) {
5772
- return false;
5773
- }
5774
- }
5775
- var gitlabMergeRequestStatus = {
5776
- merged: "merged",
5777
- opened: "opened",
5778
- closed: "closed"
5779
- };
5780
- async function getGitlabMergeRequestStatus({
5781
- accessToken,
5782
- repoUrl,
5783
- mrNumber
5784
- }) {
5785
- const { projectPath } = parseGitlabOwnerAndRepo(repoUrl);
5786
- const api2 = getGitBeaker({ url: repoUrl, gitlabAuthToken: accessToken });
5787
- const res = await api2.MergeRequests.show(projectPath, mrNumber);
5788
- switch (res.state) {
5789
- case gitlabMergeRequestStatus.merged:
5790
- case gitlabMergeRequestStatus.opened:
5791
- case gitlabMergeRequestStatus.closed:
5792
- return res.state;
5793
- default:
5794
- throw new Error(`unknown merge request state ${res.state}`);
5739
+ function getFetch(url) {
5740
+ if (url && isBrokerUrl(url)) {
5741
+ const dispatcher = new ProxyAgent({
5742
+ uri: GIT_PROXY_HOST,
5743
+ requestTls: {
5744
+ rejectUnauthorized: false
5745
+ }
5746
+ });
5747
+ return (input, init) => {
5748
+ return fetch2(input, {
5749
+ ...init,
5750
+ dispatcher
5751
+ });
5752
+ };
5795
5753
  }
5754
+ return fetch2;
5796
5755
  }
5797
- async function createMarkdownCommentOnPullRequest({
5798
- markdownComment,
5799
- accessToken,
5800
- repoUrl,
5801
- mrNumber
5802
- }) {
5803
- const { projectPath } = parseGitlabOwnerAndRepo(repoUrl);
5804
- const api2 = getGitBeaker({ url: repoUrl, gitlabAuthToken: accessToken });
5805
- return api2.MergeRequestNotes.create(projectPath, mrNumber, markdownComment);
5806
- }
5807
- async function getGitlabIsRemoteBranch({
5808
- accessToken,
5809
- repoUrl,
5810
- branch
5811
- }) {
5812
- const { projectPath } = parseGitlabOwnerAndRepo(repoUrl);
5813
- const api2 = getGitBeaker({ url: repoUrl, gitlabAuthToken: accessToken });
5814
- try {
5815
- const res = await api2.Branches.show(projectPath, branch);
5816
- return res.name === branch;
5817
- } catch (e) {
5818
- return false;
5756
+ function getRandomGithubCloudAnonToken() {
5757
+ if (!GITHUB_API_TOKEN || typeof GITHUB_API_TOKEN !== "string") {
5758
+ return void 0;
5819
5759
  }
5760
+ const tokens = GITHUB_API_TOKEN.split(",");
5761
+ return tokens[Math.floor(Math.random() * tokens.length)];
5820
5762
  }
5821
- async function getGitlabRepoList(url, accessToken) {
5822
- const api2 = getGitBeaker({ url, gitlabAuthToken: accessToken });
5823
- const res = await api2.Projects.all({
5824
- membership: true,
5825
- //TODO: a bug in the sorting mechanism of this api call
5826
- //disallows us to sort by updated_at in descending order
5827
- //so we have to sort by updated_at in ascending order.
5828
- //We can wait for the bug to be fixed or call the api
5829
- //directly with fetch()
5830
- sort: "asc",
5831
- orderBy: "updated_at",
5832
- perPage: 100
5763
+ function getOctoKit(options) {
5764
+ const token = !options?.auth && !isGithubOnPrem(options?.url) ? getRandomGithubCloudAnonToken() : options?.auth;
5765
+ const baseUrl = options?.url && isGithubOnPrem(options.url) ? `${new URL(options.url).origin}/api/v3` : void 0;
5766
+ return new Octokit({
5767
+ ...options,
5768
+ auth: token,
5769
+ baseUrl,
5770
+ //GITHUB_API_TOKEN is only defined in the backend and not when running Bugsy as CLI. We want to enable these debug logs in the backend
5771
+ //to debug the performance of these API calls.
5772
+ log: GITHUB_API_TOKEN ? console : void 0,
5773
+ request: {
5774
+ fetch: getFetch(baseUrl)
5775
+ },
5776
+ retry: {
5777
+ enabled: false
5778
+ },
5779
+ throttle: {
5780
+ enabled: false
5781
+ }
5833
5782
  });
5834
- return Promise.all(
5835
- res.map(async (project) => {
5836
- const proj = await api2.Projects.show(project.id);
5837
- const owner = proj.namespace.name;
5838
- const repoLanguages = await api2.Projects.showLanguages(project.id);
5839
- return {
5840
- repoName: project.path,
5841
- repoUrl: project.web_url,
5842
- repoOwner: owner,
5843
- repoLanguages: Object.keys(repoLanguages),
5844
- repoIsPublic: project.visibility === "public",
5845
- repoUpdatedAt: project.last_activity_at
5846
- };
5847
- })
5848
- );
5849
5783
  }
5850
- async function getGitlabBranchList({
5851
- accessToken,
5852
- repoUrl
5853
- }) {
5854
- const { projectPath } = parseGitlabOwnerAndRepo(repoUrl);
5855
- const api2 = getGitBeaker({ url: repoUrl, gitlabAuthToken: accessToken });
5784
+ function isGithubActionActionToken(token) {
5785
+ return token.startsWith("ghs_");
5786
+ }
5787
+ async function githubValidateParams(url, accessToken) {
5856
5788
  try {
5857
- const res = await api2.Branches.all(projectPath, {
5858
- //keyset API pagination is not supported by GL for the branch list (at least not the on-prem version)
5859
- //so for now we stick with the default pagination and just return the first page and limit the results to 1000 entries.
5860
- //This is a temporary solution until we implement list branches with name search.
5861
- perPage: MAX_BRANCHES_FETCH,
5862
- page: 1
5863
- });
5864
- res.sort((a, b) => {
5865
- if (!a.commit?.committed_date || !b.commit?.committed_date) {
5866
- return 0;
5867
- }
5868
- return new Date(b.commit?.committed_date).getTime() - new Date(a.commit?.committed_date).getTime();
5869
- });
5870
- return res.map((branch) => branch.name).slice(0, MAX_BRANCHES_FETCH);
5789
+ const oktoKit = getOctoKit({ auth: accessToken, url });
5790
+ if (accessToken && !isGithubActionActionToken(accessToken)) {
5791
+ await oktoKit.rest.users.getAuthenticated();
5792
+ }
5793
+ if (url && shouldValidateUrl(url)) {
5794
+ const { owner, repo } = parseGithubOwnerAndRepo(url);
5795
+ await oktoKit.request(GET_REPO_BRANCHES, {
5796
+ owner,
5797
+ repo,
5798
+ per_page: 1
5799
+ });
5800
+ }
5871
5801
  } catch (e) {
5872
- return [];
5873
- }
5874
- }
5875
- async function createMergeRequest(options) {
5876
- const { projectPath } = parseGitlabOwnerAndRepo(options.repoUrl);
5877
- const api2 = getGitBeaker({
5878
- url: options.repoUrl,
5879
- gitlabAuthToken: options.accessToken
5880
- });
5881
- const res = await api2.MergeRequests.create(
5882
- projectPath,
5883
- options.sourceBranchName,
5884
- options.targetBranchName,
5885
- options.title,
5886
- {
5887
- description: options.body
5802
+ console.log("could not init github scm", e);
5803
+ const error = e;
5804
+ const code = error.status || error.statusCode || error.response?.status || error.response?.statusCode || error.response?.code;
5805
+ if (code === 401 || code === 403) {
5806
+ throw new InvalidAccessTokenError(`invalid github access token`);
5888
5807
  }
5889
- );
5890
- return res.iid;
5891
- }
5892
- async function getGitlabMergeRequest({
5893
- url,
5894
- prNumber,
5895
- accessToken
5896
- }) {
5897
- const { projectPath } = parseGitlabOwnerAndRepo(url);
5898
- const api2 = getGitBeaker({
5899
- url,
5900
- gitlabAuthToken: accessToken
5901
- });
5902
- return await api2.MergeRequests.show(projectPath, prNumber);
5903
- }
5904
- async function getGitlabCommitUrl({
5905
- url,
5906
- commitSha,
5907
- accessToken
5908
- }) {
5909
- const { projectPath } = parseGitlabOwnerAndRepo(url);
5910
- const api2 = getGitBeaker({
5911
- url,
5912
- gitlabAuthToken: accessToken
5913
- });
5914
- return await api2.Commits.show(projectPath, commitSha);
5915
- }
5916
- async function getGitlabRepoDefaultBranch(repoUrl, options) {
5917
- const api2 = getGitBeaker({
5918
- url: repoUrl,
5919
- gitlabAuthToken: options?.gitlabAuthToken
5920
- });
5921
- const { projectPath } = parseGitlabOwnerAndRepo(repoUrl);
5922
- const project = await api2.Projects.show(projectPath);
5923
- if (!project.default_branch) {
5924
- throw new Error("no default branch");
5925
- }
5926
- return project.default_branch;
5927
- }
5928
- async function getGitlabReferenceData({ ref, gitlabUrl }, options) {
5929
- const { projectPath } = parseGitlabOwnerAndRepo(gitlabUrl);
5930
- const api2 = getGitBeaker({
5931
- url: gitlabUrl,
5932
- gitlabAuthToken: options?.gitlabAuthToken
5933
- });
5934
- const results = await Promise.allSettled([
5935
- (async () => {
5936
- const res = await api2.Branches.show(projectPath, ref);
5937
- return {
5938
- sha: res.commit.id,
5939
- type: "BRANCH" /* BRANCH */,
5940
- date: res.commit.committed_date ? new Date(res.commit.committed_date) : void 0
5941
- };
5942
- })(),
5943
- (async () => {
5944
- const res = await api2.Commits.show(projectPath, ref);
5945
- return {
5946
- sha: res.id,
5947
- type: "COMMIT" /* COMMIT */,
5948
- date: res.committed_date ? new Date(res.committed_date) : void 0
5949
- };
5950
- })(),
5951
- (async () => {
5952
- const res = await api2.Tags.show(projectPath, ref);
5953
- return {
5954
- sha: res.commit.id,
5955
- type: "TAG" /* TAG */,
5956
- date: res.commit.committed_date ? new Date(res.commit.committed_date) : void 0
5957
- };
5958
- })()
5959
- ]);
5960
- const [branchRes, commitRes, tagRes] = results;
5961
- if (tagRes.status === "fulfilled") {
5962
- return tagRes.value;
5963
- }
5964
- if (branchRes.status === "fulfilled") {
5965
- return branchRes.value;
5966
- }
5967
- if (commitRes.status === "fulfilled") {
5968
- return commitRes.value;
5969
- }
5970
- throw new RefNotFoundError(`ref: ${ref} does not exist`);
5971
- }
5972
- function parseGitlabOwnerAndRepo(gitlabUrl) {
5973
- gitlabUrl = removeTrailingSlash2(gitlabUrl);
5974
- const parsingResult = parseScmURL(gitlabUrl, "GitLab" /* GitLab */);
5975
- if (!parsingResult || !parsingResult.repoName) {
5976
- throw new InvalidUrlPatternError(`invalid gitlab repo Url ${gitlabUrl}`);
5977
- }
5978
- const { organization, repoName, projectPath } = parsingResult;
5979
- return { owner: organization, repo: repoName, projectPath };
5980
- }
5981
- async function getGitlabBlameRanges({ ref, gitlabUrl, path: path8 }, options) {
5982
- const { projectPath } = parseGitlabOwnerAndRepo(gitlabUrl);
5983
- const api2 = getGitBeaker({
5984
- url: gitlabUrl,
5985
- gitlabAuthToken: options?.gitlabAuthToken
5986
- });
5987
- const resp = await api2.RepositoryFiles.allFileBlames(projectPath, path8, ref);
5988
- let lineNumber = 1;
5989
- return resp.filter((range) => range.lines).map((range) => {
5990
- const oldLineNumber = lineNumber;
5991
- if (!range.lines) {
5992
- throw new Error("range.lines should not be undefined");
5993
- }
5994
- lineNumber += range.lines.length;
5995
- return {
5996
- startingLine: oldLineNumber,
5997
- endingLine: lineNumber - 1,
5998
- login: range.commit.author_email,
5999
- email: range.commit.author_email,
6000
- name: range.commit.author_name
6001
- };
6002
- });
6003
- }
6004
- async function processBody(response) {
6005
- const headers = response.headers;
6006
- const type2 = headers.get("content-type")?.split(";")[0]?.trim();
6007
- if (type2 === "application/json") {
6008
- return await response.json();
6009
- }
6010
- return await response.text();
6011
- }
6012
- async function brokerRequestHandler(endpoint, options) {
6013
- const { prefixUrl, searchParams } = options || {};
6014
- let baseUrl;
6015
- if (prefixUrl) baseUrl = prefixUrl.endsWith("/") ? prefixUrl : `${prefixUrl}/`;
6016
- const url = new URL(endpoint, baseUrl);
6017
- url.search = searchParams || "";
6018
- const dispatcher = url && isBrokerUrl(url.href) ? new ProxyAgent({
6019
- uri: GIT_PROXY_HOST,
6020
- requestTls: {
6021
- rejectUnauthorized: false
6022
- }
6023
- }) : void 0;
6024
- const response = await undiciFetch(url, {
6025
- headers: options?.headers,
6026
- method: options?.method,
6027
- body: options?.body ? String(options?.body) : void 0,
6028
- dispatcher
6029
- }).catch((e) => {
6030
- if (e.name === "TimeoutError" || e.name === "AbortError") {
6031
- throw new Error("Query timeout was reached");
6032
- }
6033
- throw e;
6034
- });
6035
- if (response.ok)
6036
- return {
6037
- body: await processBody(response),
6038
- headers: Object.fromEntries(response.headers.entries()),
6039
- status: response.status
6040
- };
6041
- throw new Error(`gitbeaker: ${response.statusText}`);
6042
- }
6043
-
6044
- // src/features/analysis/scm/gitlab/GitlabSCMLib.ts
6045
- var GitlabSCMLib = class extends SCMLib {
6046
- constructor(url, accessToken, scmOrg) {
6047
- super(url, accessToken, scmOrg);
6048
- }
6049
- async createSubmitRequest(params) {
6050
- this._validateAccessTokenAndUrl();
6051
- const { targetBranchName, sourceBranchName, title, body } = params;
6052
- return String(
6053
- await createMergeRequest({
6054
- title,
6055
- body,
6056
- targetBranchName,
6057
- sourceBranchName,
6058
- repoUrl: this.url,
6059
- accessToken: this.accessToken
6060
- })
6061
- );
6062
- }
6063
- async validateParams() {
6064
- return gitlabValidateParams({
6065
- url: this.url,
6066
- accessToken: this.accessToken
6067
- });
6068
- }
6069
- async getRepoList(_scmOrg) {
6070
- if (!this.accessToken) {
6071
- console.error("no access token");
6072
- throw new Error("no access token");
6073
- }
6074
- return getGitlabRepoList(this.url, this.accessToken);
6075
- }
6076
- async getBranchList() {
6077
- this._validateAccessTokenAndUrl();
6078
- return getGitlabBranchList({
6079
- accessToken: this.accessToken,
6080
- repoUrl: this.url
6081
- });
6082
- }
6083
- get scmLibType() {
6084
- return "GITLAB" /* GITLAB */;
6085
- }
6086
- getAuthHeaders() {
6087
- if (!this.accessToken) {
6088
- return {};
6089
- }
6090
- if (this.accessToken.startsWith("glpat-")) {
6091
- return {
6092
- "Private-Token": this.accessToken
6093
- };
6094
- } else {
6095
- return { authorization: `Bearer ${this.accessToken}` };
6096
- }
6097
- }
6098
- getDownloadUrl(sha) {
6099
- const urlObj = new URL(this.url || "");
6100
- const ProjectId = encodeURIComponent(
6101
- urlObj.pathname.replace(/^\//, "").replace(/\/$/, "")
6102
- );
6103
- return Promise.resolve(
6104
- //We are moving away from this form as it doesn't work when using a non-human token (group/project token)
6105
- //Where as the API zip endpoint works with any token
6106
- //`${this.url}/-/archive/${sha}/${repoName}-${sha}.zip`
6107
- `${urlObj.origin}/api/v4/projects/${ProjectId}/repository/archive.zip?sha=${sha}`
6108
- );
6109
- }
6110
- async _getUsernameForAuthUrl() {
6111
- if (this?.accessToken?.startsWith("glpat-")) {
6112
- return this.getUsername();
6113
- } else {
6114
- return "oauth2";
6115
- }
6116
- }
6117
- async getIsRemoteBranch(branch) {
6118
- this._validateAccessTokenAndUrl();
6119
- return getGitlabIsRemoteBranch({
6120
- accessToken: this.accessToken,
6121
- repoUrl: this.url,
6122
- branch
6123
- });
6124
- }
6125
- async getUserHasAccessToRepo() {
6126
- this._validateAccessTokenAndUrl();
6127
- return getGitlabIsUserCollaborator({
6128
- accessToken: this.accessToken,
6129
- repoUrl: this.url
6130
- });
6131
- }
6132
- async getUsername() {
6133
- this._validateAccessTokenAndUrl();
6134
- return getGitlabUsername(this.url, this.accessToken);
6135
- }
6136
- async getSubmitRequestStatus(scmSubmitRequestId) {
6137
- this._validateAccessTokenAndUrl();
6138
- const state = await getGitlabMergeRequestStatus({
6139
- accessToken: this.accessToken,
6140
- repoUrl: this.url,
6141
- mrNumber: Number(scmSubmitRequestId)
6142
- });
6143
- switch (state) {
6144
- case gitlabMergeRequestStatus.merged:
6145
- return "merged";
6146
- case gitlabMergeRequestStatus.opened:
6147
- return "open";
6148
- case gitlabMergeRequestStatus.closed:
6149
- return "closed";
6150
- default:
6151
- throw new Error(`unknown state ${state}`);
6152
- }
6153
- }
6154
- async addCommentToSubmitRequest(submitRequestId, comment) {
6155
- this._validateAccessTokenAndUrl();
6156
- await createMarkdownCommentOnPullRequest({
6157
- accessToken: this.accessToken,
6158
- repoUrl: this.url,
6159
- mrNumber: Number(submitRequestId),
6160
- markdownComment: comment
6161
- });
6162
- }
6163
- async getRepoBlameRanges(ref, path8) {
6164
- this._validateUrl();
6165
- return await getGitlabBlameRanges(
6166
- { ref, path: path8, gitlabUrl: this.url },
6167
- {
6168
- url: this.url,
6169
- gitlabAuthToken: this.accessToken
6170
- }
6171
- );
6172
- }
6173
- async getReferenceData(ref) {
6174
- this._validateUrl();
6175
- return await getGitlabReferenceData(
6176
- { ref, gitlabUrl: this.url },
6177
- {
6178
- url: this.url,
6179
- gitlabAuthToken: this.accessToken
6180
- }
6181
- );
6182
- }
6183
- async getRepoDefaultBranch() {
6184
- this._validateUrl();
6185
- return await getGitlabRepoDefaultBranch(this.url, {
6186
- url: this.url,
6187
- gitlabAuthToken: this.accessToken
6188
- });
6189
- }
6190
- async getSubmitRequestUrl(submitRequestUrl) {
6191
- this._validateAccessTokenAndUrl();
6192
- const res = await getGitlabMergeRequest({
6193
- url: this.url,
6194
- prNumber: submitRequestUrl,
6195
- accessToken: this.accessToken
6196
- });
6197
- return res.web_url;
6198
- }
6199
- async getSubmitRequestId(submitRequestUrl) {
6200
- const match = submitRequestUrl.match(/\/merge_requests\/(\d+)/);
6201
- return match?.[1] || "";
6202
- }
6203
- async getCommitUrl(commitId) {
6204
- this._validateAccessTokenAndUrl();
6205
- const res = await getGitlabCommitUrl({
6206
- url: this.url,
6207
- commitSha: commitId,
6208
- accessToken: this.accessToken
6209
- });
6210
- return res.web_url;
6211
- }
6212
- };
6213
-
6214
- // src/features/analysis/scm/scmFactory.ts
6215
- import { z as z23 } from "zod";
6216
-
6217
- // src/features/analysis/scm/StubSCMLib.ts
6218
- var StubSCMLib = class extends SCMLib {
6219
- constructor(url, accessToken, scmOrg) {
6220
- super(url, accessToken, scmOrg);
6221
- }
6222
- async getUrlWithCredentials() {
6223
- console.warn("getUrlWithCredentials() returning empty string");
6224
- return "";
6225
- }
6226
- async createSubmitRequest(_params) {
6227
- console.warn("createSubmitRequest() returning empty string");
6228
- return "";
6229
- }
6230
- get scmLibType() {
6231
- console.warn("scmLibType returning GITHUB as default");
6232
- return "GITHUB" /* GITHUB */;
6233
- }
6234
- getAuthHeaders() {
6235
- console.warn("getAuthHeaders() returning empty object");
6236
- return {};
6237
- }
6238
- async getDownloadUrl(_sha) {
6239
- console.warn("getDownloadUrl() returning empty string");
6240
- return "";
6241
- }
6242
- async getIsRemoteBranch(_branch) {
6243
- console.warn("getIsRemoteBranch() returning false");
6244
- return false;
6245
- }
6246
- async validateParams() {
6247
- console.warn("validateParams() no-op");
6248
- }
6249
- async getRepoList(_scmOrg) {
6250
- console.warn("getRepoList() returning empty array");
6251
- return [];
6252
- }
6253
- async getBranchList() {
6254
- console.warn("getBranchList() returning empty array");
6255
- return [];
6256
- }
6257
- async getUsername() {
6258
- console.warn("getUsername() returning empty string");
6259
- return "";
6260
- }
6261
- async getSubmitRequestStatus(_scmSubmitRequestId) {
6262
- console.warn("getSubmitRequestStatus() returning ERROR");
6263
- return "error";
6264
- }
6265
- async getUserHasAccessToRepo() {
6266
- console.warn("getUserHasAccessToRepo() returning false");
6267
- return false;
6268
- }
6269
- async getRepoBlameRanges(_ref, _path) {
6270
- console.warn("getRepoBlameRanges() returning empty array");
6271
- return [];
6272
- }
6273
- async getReferenceData(_ref) {
6274
- console.warn("getReferenceData() returning null/empty defaults");
6275
- return {
6276
- type: "BRANCH" /* BRANCH */,
6277
- sha: "",
6278
- date: void 0
6279
- };
6280
- }
6281
- async getRepoDefaultBranch() {
6282
- console.warn("getRepoDefaultBranch() returning empty string");
6283
- return "";
6284
- }
6285
- async getSubmitRequestUrl(_submitRequestIdNumber) {
6286
- console.warn("getSubmitRequestUrl() returning empty string");
6287
- return "";
6288
- }
6289
- async getSubmitRequestId(_submitRequestUrl) {
6290
- console.warn("getSubmitRequestId() returning empty string");
6291
- return "";
6292
- }
6293
- async getCommitUrl(_commitId) {
6294
- console.warn("getCommitUrl() returning empty string");
6295
- return "";
6296
- }
6297
- async _getUsernameForAuthUrl() {
6298
- console.warn("_getUsernameForAuthUrl() returning empty string");
6299
- return "";
6300
- }
6301
- async addCommentToSubmitRequest(_submitRequestId, _comment) {
6302
- console.warn("addCommentToSubmitRequest() no-op");
6303
- }
6304
- };
6305
-
6306
- // src/features/analysis/scm/scmFactory.ts
6307
- async function createScmLib({ url, accessToken, scmType, scmOrg }, { propagateExceptions = false } = {}) {
6308
- const trimmedUrl = url ? url.trim().replace(/\/$/, "").replace(/.git$/i, "") : void 0;
6309
- try {
6310
- switch (scmType) {
6311
- case "GITHUB" /* GITHUB */: {
6312
- const scm = new GithubSCMLib(trimmedUrl, accessToken, scmOrg);
6313
- await scm.validateParams();
6314
- return scm;
6315
- }
6316
- case "GITLAB" /* GITLAB */: {
6317
- const scm = new GitlabSCMLib(trimmedUrl, accessToken, scmOrg);
6318
- await scm.validateParams();
6319
- return scm;
6320
- }
6321
- case "ADO" /* ADO */: {
6322
- const scm = new AdoSCMLib(trimmedUrl, accessToken, scmOrg);
6323
- await scm.getAdoSdk();
6324
- await scm.validateParams();
6325
- return scm;
6326
- }
6327
- case "BITBUCKET" /* BITBUCKET */: {
6328
- const scm = new BitbucketSCMLib(trimmedUrl, accessToken, scmOrg);
6329
- await scm.validateParams();
6330
- return scm;
6331
- }
6332
- }
6333
- } catch (e) {
6334
- if (e instanceof InvalidRepoUrlError && url) {
6335
- throw new RepoNoTokenAccessError(
6336
- "no access to repo",
6337
- scmLibScmTypeToScmType[z23.nativeEnum(ScmLibScmType).parse(scmType)]
6338
- );
6339
- }
6340
- console.error(`error validating scm: ${scmType} `, e);
6341
- if (propagateExceptions) {
6342
- throw e;
6343
- }
6344
- }
6345
- return new StubSCMLib(trimmedUrl, void 0, void 0);
6346
- }
6347
-
6348
- // src/features/analysis/scm/github/utils/utils.ts
6349
- function parseGithubOwnerAndRepo(gitHubUrl) {
6350
- gitHubUrl = normalizeUrl(gitHubUrl);
6351
- const parsingResult = parseScmURL(gitHubUrl, "GitHub" /* GitHub */);
6352
- if (!parsingResult) {
6353
- throw new InvalidUrlPatternError(`invalid github repo Url ${gitHubUrl}`);
6354
- }
6355
- const { organization, repoName } = parsingResult;
6356
- if (!organization || !repoName) {
6357
- throw new InvalidUrlPatternError(`invalid github repo Url ${gitHubUrl}`);
6358
- }
6359
- return { owner: organization, repo: repoName };
6360
- }
6361
- function isGithubOnPrem(url) {
6362
- if (!url) {
6363
- return false;
6364
- }
6365
- return !url.includes(scmCloudUrl.GitHub);
6366
- }
6367
- function getFetch(url) {
6368
- if (url && isBrokerUrl(url)) {
6369
- const dispatcher = new ProxyAgent2({
6370
- uri: GIT_PROXY_HOST,
6371
- requestTls: {
6372
- rejectUnauthorized: false
6373
- }
6374
- });
6375
- return (input, init) => {
6376
- return fetch2(input, {
6377
- ...init,
6378
- dispatcher
6379
- });
6380
- };
6381
- }
6382
- return fetch2;
6383
- }
6384
- function getRandomGithubCloudAnonToken() {
6385
- if (!GITHUB_API_TOKEN || typeof GITHUB_API_TOKEN !== "string") {
6386
- return void 0;
6387
- }
6388
- const tokens = GITHUB_API_TOKEN.split(",");
6389
- return tokens[Math.floor(Math.random() * tokens.length)];
6390
- }
6391
- function getOctoKit(options) {
6392
- const token = !options?.auth && !isGithubOnPrem(options?.url) ? getRandomGithubCloudAnonToken() : options?.auth;
6393
- const baseUrl = options?.url && isGithubOnPrem(options.url) ? `${new URL(options.url).origin}/api/v3` : void 0;
6394
- return new Octokit({
6395
- ...options,
6396
- auth: token,
6397
- baseUrl,
6398
- //GITHUB_API_TOKEN is only defined in the backend and not when running Bugsy as CLI. We want to enable these debug logs in the backend
6399
- //to debug the performance of these API calls.
6400
- log: GITHUB_API_TOKEN ? console : void 0,
6401
- request: {
6402
- fetch: getFetch(baseUrl)
6403
- },
6404
- retry: {
6405
- enabled: false
6406
- },
6407
- throttle: {
6408
- enabled: false
6409
- }
6410
- });
6411
- }
6412
- function isGithubActionActionToken(token) {
6413
- return token.startsWith("ghs_");
6414
- }
6415
- async function githubValidateParams(url, accessToken) {
6416
- try {
6417
- const oktoKit = getOctoKit({ auth: accessToken, url });
6418
- if (accessToken && !isGithubActionActionToken(accessToken)) {
6419
- await oktoKit.rest.users.getAuthenticated();
6420
- }
6421
- if (url && shouldValidateUrl(url)) {
6422
- const { owner, repo } = parseGithubOwnerAndRepo(url);
6423
- await oktoKit.request(GET_REPO_BRANCHES, {
6424
- owner,
6425
- repo,
6426
- per_page: 1
6427
- });
6428
- }
6429
- } catch (e) {
6430
- console.log("could not init github scm", e);
6431
- const error = e;
6432
- const code = error.status || error.statusCode || error.response?.status || error.response?.statusCode || error.response?.code;
6433
- if (code === 401 || code === 403) {
6434
- throw new InvalidAccessTokenError(`invalid github access token`);
6435
- }
6436
- if (code === 404) {
6437
- throw new InvalidRepoUrlError(`invalid github repo Url ${url}`);
6438
- }
6439
- console.log("githubValidateParams error", e);
6440
- throw new InvalidRepoUrlError(
6441
- `cannot access GH repo URL: ${url} with the provided access token`
6442
- );
5808
+ if (code === 404) {
5809
+ throw new InvalidRepoUrlError(`invalid github repo Url ${url}`);
5810
+ }
5811
+ console.log("githubValidateParams error", e);
5812
+ throw new InvalidRepoUrlError(
5813
+ `cannot access GH repo URL: ${url} with the provided access token`
5814
+ );
6443
5815
  }
6444
5816
  }
6445
5817
 
@@ -6610,457 +5982,1143 @@ function getGithubSdk(params = {}) {
6610
5982
  throw e;
6611
5983
  }
6612
5984
  },
6613
- async getBranch({
6614
- branch,
6615
- owner,
6616
- repo
6617
- }) {
6618
- return octokit.rest.repos.getBranch({
6619
- branch,
5985
+ async getBranch({
5986
+ branch,
5987
+ owner,
5988
+ repo
5989
+ }) {
5990
+ return octokit.rest.repos.getBranch({
5991
+ branch,
5992
+ owner,
5993
+ repo
5994
+ });
5995
+ },
5996
+ async getCommit({
5997
+ commitSha,
5998
+ owner,
5999
+ repo
6000
+ }) {
6001
+ return octokit.rest.git.getCommit({
6002
+ repo,
6003
+ owner,
6004
+ commit_sha: commitSha
6005
+ });
6006
+ },
6007
+ async getTagDate({
6008
+ tag,
6009
+ owner,
6010
+ repo
6011
+ }) {
6012
+ const refResponse = await octokit.rest.git.getRef({
6013
+ ref: `tags/${tag}`,
6014
+ owner,
6015
+ repo
6016
+ });
6017
+ const tagSha = refResponse.data.object.sha;
6018
+ if (refResponse.data.object.type === "commit") {
6019
+ const res2 = await octokit.rest.git.getCommit({
6020
+ commit_sha: tagSha,
6021
+ owner,
6022
+ repo
6023
+ });
6024
+ return {
6025
+ date: res2.data.committer.date,
6026
+ sha: res2.data.sha
6027
+ };
6028
+ }
6029
+ const res = await octokit.rest.git.getTag({
6030
+ tag_sha: tagSha,
6031
+ owner,
6032
+ repo
6033
+ });
6034
+ return {
6035
+ date: res.data.tagger.date,
6036
+ sha: res.data.sha
6037
+ };
6038
+ },
6039
+ async getGithubBlameRanges(params2) {
6040
+ const { ref, gitHubUrl, path: path8 } = params2;
6041
+ const { owner, repo } = parseGithubOwnerAndRepo(gitHubUrl);
6042
+ const res = await octokit.graphql(
6043
+ GET_BLAME_DOCUMENT,
6044
+ {
6045
+ owner,
6046
+ repo,
6047
+ path: path8,
6048
+ ref
6049
+ }
6050
+ );
6051
+ if (!res?.repository?.object?.blame?.ranges) {
6052
+ return [];
6053
+ }
6054
+ return res.repository.object.blame.ranges.map((range) => ({
6055
+ startingLine: range.startingLine,
6056
+ endingLine: range.endingLine,
6057
+ email: range.commit.author.user?.email || "",
6058
+ name: range.commit.author.user?.name || "",
6059
+ login: range.commit.author.user?.login || ""
6060
+ }));
6061
+ },
6062
+ // todo: refactor the name for this function
6063
+ async createPr(params2) {
6064
+ const { sourceRepoUrl, filesPaths, userRepoUrl, title, body } = params2;
6065
+ const { owner: sourceOwner, repo: sourceRepo } = parseGithubOwnerAndRepo(sourceRepoUrl);
6066
+ const { owner, repo } = parseGithubOwnerAndRepo(userRepoUrl);
6067
+ const [sourceFilePath, secondFilePath] = filesPaths;
6068
+ const sourceFileContentResponse = await octokit.rest.repos.getContent({
6069
+ owner: sourceOwner,
6070
+ repo: sourceRepo,
6071
+ path: "/" + sourceFilePath
6072
+ });
6073
+ const { data: repository } = await octokit.rest.repos.get({ owner, repo });
6074
+ const defaultBranch = repository.default_branch;
6075
+ const newBranchName = `mobb/workflow-${Date.now()}`;
6076
+ await octokit.rest.git.createRef({
6077
+ owner,
6078
+ repo,
6079
+ ref: `refs/heads/${newBranchName}`,
6080
+ sha: await octokit.rest.git.getRef({ owner, repo, ref: `heads/${defaultBranch}` }).then((response) => response.data.object.sha)
6081
+ });
6082
+ const decodedContent = Buffer.from(
6083
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
6084
+ // @ts-ignore
6085
+ sourceFileContentResponse.data.content,
6086
+ "base64"
6087
+ ).toString("utf-8");
6088
+ const tree = [
6089
+ {
6090
+ path: sourceFilePath,
6091
+ mode: "100644",
6092
+ type: "blob",
6093
+ content: decodedContent
6094
+ }
6095
+ ];
6096
+ if (secondFilePath) {
6097
+ const secondFileContentResponse = await octokit.rest.repos.getContent({
6098
+ owner: sourceOwner,
6099
+ repo: sourceRepo,
6100
+ path: "/" + secondFilePath
6101
+ });
6102
+ const secondDecodedContent = Buffer.from(
6103
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
6104
+ // @ts-ignore
6105
+ secondFileContentResponse.data.content,
6106
+ "base64"
6107
+ ).toString("utf-8");
6108
+ tree.push({
6109
+ path: secondFilePath,
6110
+ mode: "100644",
6111
+ type: "blob",
6112
+ content: secondDecodedContent
6113
+ });
6114
+ }
6115
+ const createTreeResponse = await octokit.rest.git.createTree({
6116
+ owner,
6117
+ repo,
6118
+ base_tree: await octokit.rest.git.getRef({ owner, repo, ref: `heads/${defaultBranch}` }).then((response) => response.data.object.sha),
6119
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
6120
+ // @ts-ignore
6121
+ tree
6122
+ });
6123
+ const createCommitResponse = await octokit.rest.git.createCommit({
6124
+ owner,
6125
+ repo,
6126
+ message: "Add new yaml file",
6127
+ tree: createTreeResponse.data.sha,
6128
+ parents: [
6129
+ await octokit.rest.git.getRef({ owner, repo, ref: `heads/${defaultBranch}` }).then((response) => response.data.object.sha)
6130
+ ]
6131
+ });
6132
+ await octokit.rest.git.updateRef({
6133
+ owner,
6134
+ repo,
6135
+ ref: `heads/${newBranchName}`,
6136
+ sha: createCommitResponse.data.sha
6137
+ });
6138
+ const createPRResponse = await octokit.rest.pulls.create({
6139
+ owner,
6140
+ repo,
6141
+ title,
6142
+ head: newBranchName,
6143
+ head_repo: sourceRepo,
6144
+ body,
6145
+ base: defaultBranch
6146
+ });
6147
+ return {
6148
+ pull_request_url: createPRResponse.data.html_url
6149
+ };
6150
+ },
6151
+ async getGithubBranchList(repoUrl) {
6152
+ const { owner, repo } = parseGithubOwnerAndRepo(repoUrl);
6153
+ return octokit.rest.repos.listBranches({
6154
+ owner,
6155
+ repo,
6156
+ per_page: MAX_BRANCHES_FETCH,
6157
+ page: 1
6158
+ });
6159
+ },
6160
+ async createPullRequest(options) {
6161
+ const { owner, repo } = parseGithubOwnerAndRepo(options.repoUrl);
6162
+ return octokit.rest.pulls.create({
6620
6163
  owner,
6621
- repo
6164
+ repo,
6165
+ title: options.title,
6166
+ body: options.body,
6167
+ head: options.sourceBranchName,
6168
+ base: options.targetBranchName,
6169
+ draft: false,
6170
+ maintainer_can_modify: true
6622
6171
  });
6623
6172
  },
6624
- async getCommit({
6625
- commitSha,
6173
+ async forkRepo(options) {
6174
+ const { owner, repo } = parseGithubOwnerAndRepo(options.repoUrl);
6175
+ const createForkRes = await octokit.rest.repos.createFork({
6176
+ owner,
6177
+ repo,
6178
+ default_branch_only: false
6179
+ });
6180
+ return { url: createForkRes.data.html_url };
6181
+ },
6182
+ async getUserInfo() {
6183
+ return octokit.request(GET_USER);
6184
+ }
6185
+ };
6186
+ }
6187
+
6188
+ // src/features/analysis/scm/github/GithubSCMLib.ts
6189
+ var GithubSCMLib = class extends SCMLib {
6190
+ // we don't always need a url, what's important is that we have an access token
6191
+ constructor(url, accessToken, scmOrg) {
6192
+ super(url, accessToken, scmOrg);
6193
+ __publicField(this, "githubSdk");
6194
+ this.githubSdk = getGithubSdk({
6195
+ auth: accessToken,
6196
+ url
6197
+ });
6198
+ }
6199
+ async createSubmitRequest(params) {
6200
+ this._validateAccessTokenAndUrl();
6201
+ const { targetBranchName, sourceBranchName, title, body } = params;
6202
+ const pullRequestResult = await this.githubSdk.createPullRequest({
6203
+ title,
6204
+ body,
6205
+ targetBranchName,
6206
+ sourceBranchName,
6207
+ repoUrl: this.url
6208
+ });
6209
+ return String(pullRequestResult.data.number);
6210
+ }
6211
+ async forkRepo(repoUrl) {
6212
+ this._validateAccessToken();
6213
+ return this.githubSdk.forkRepo({
6214
+ repoUrl
6215
+ });
6216
+ }
6217
+ async createOrUpdateRepositorySecret(params) {
6218
+ this._validateAccessTokenAndUrl();
6219
+ const { owner, repo } = parseGithubOwnerAndRepo(this.url);
6220
+ const { data: repositoryPublicKeyResponse } = await this.githubSdk.getRepositoryPublicKey({ owner, repo });
6221
+ const { key_id, key } = repositoryPublicKeyResponse;
6222
+ const encryptedValue = await encryptSecret(params.value, key);
6223
+ return this.githubSdk.createOrUpdateRepositorySecret({
6224
+ encrypted_value: encryptedValue,
6225
+ secret_name: params.name,
6226
+ key_id,
6227
+ owner,
6228
+ repo
6229
+ });
6230
+ }
6231
+ async createPullRequestWithNewFile(sourceRepoUrl, filesPaths, userRepoUrl, title, body) {
6232
+ const { pull_request_url } = await this.githubSdk.createPr({
6233
+ sourceRepoUrl,
6234
+ filesPaths,
6235
+ userRepoUrl,
6236
+ title,
6237
+ body
6238
+ });
6239
+ return { pull_request_url };
6240
+ }
6241
+ async validateParams() {
6242
+ return githubValidateParams(this.url, this.accessToken);
6243
+ }
6244
+ async postPrComment(params) {
6245
+ this._validateAccessTokenAndUrl();
6246
+ const { owner, repo } = parseGithubOwnerAndRepo(this.url);
6247
+ return this.githubSdk.postPrComment({
6248
+ ...params,
6249
+ owner,
6250
+ repo
6251
+ });
6252
+ }
6253
+ async updatePrComment(params) {
6254
+ this._validateAccessTokenAndUrl();
6255
+ const { owner, repo } = parseGithubOwnerAndRepo(this.url);
6256
+ return this.githubSdk.updatePrComment({
6257
+ ...params,
6258
+ owner,
6259
+ repo
6260
+ });
6261
+ }
6262
+ async deleteComment(params) {
6263
+ this._validateAccessTokenAndUrl();
6264
+ const { owner, repo } = parseGithubOwnerAndRepo(this.url);
6265
+ return this.githubSdk.deleteComment({
6266
+ ...params,
6267
+ owner,
6268
+ repo
6269
+ });
6270
+ }
6271
+ async getPrComments(params) {
6272
+ this._validateAccessTokenAndUrl();
6273
+ const { owner, repo } = parseGithubOwnerAndRepo(this.url);
6274
+ return this.githubSdk.getPrComments({
6275
+ per_page: 100,
6276
+ ...params,
6277
+ owner,
6278
+ repo
6279
+ });
6280
+ }
6281
+ async getPrDiff(params) {
6282
+ this._validateAccessTokenAndUrl();
6283
+ const { owner, repo } = parseGithubOwnerAndRepo(this.url);
6284
+ const prRes = await this.githubSdk.getPrDiff({
6285
+ ...params,
6286
+ owner,
6287
+ repo
6288
+ });
6289
+ return z22.string().parse(prRes.data);
6290
+ }
6291
+ async getRepoList(_scmOrg) {
6292
+ this._validateAccessToken();
6293
+ return this.githubSdk.getGithubRepoList();
6294
+ }
6295
+ async getBranchList() {
6296
+ this._validateAccessTokenAndUrl();
6297
+ const branches = await this.githubSdk.getGithubBranchList(this.url);
6298
+ return branches.data.map((branch) => branch.name);
6299
+ }
6300
+ get scmLibType() {
6301
+ return "GITHUB" /* GITHUB */;
6302
+ }
6303
+ getAuthHeaders() {
6304
+ if (this.accessToken) {
6305
+ return { authorization: `Bearer ${this.accessToken}` };
6306
+ }
6307
+ return {};
6308
+ }
6309
+ getDownloadUrl(sha) {
6310
+ this._validateUrl();
6311
+ const res = parseScmURL(this.url, "GitHub" /* GitHub */);
6312
+ if (!res) {
6313
+ throw new InvalidRepoUrlError("invalid repo url");
6314
+ }
6315
+ const { protocol, hostname, organization, repoName } = res;
6316
+ const downloadUrl = isGithubOnPrem(this.url) ? `${protocol}//${hostname}/api/v3/repos/${organization}/${repoName}/zipball/${sha}` : `https://api.${hostname}/repos/${organization}/${repoName}/zipball/${sha}`;
6317
+ return Promise.resolve(downloadUrl);
6318
+ }
6319
+ async _getUsernameForAuthUrl() {
6320
+ return this.getUsername();
6321
+ }
6322
+ async getIsRemoteBranch(branch) {
6323
+ this._validateUrl();
6324
+ return this.githubSdk.getGithubIsRemoteBranch({ branch, repoUrl: this.url });
6325
+ }
6326
+ async getUserHasAccessToRepo() {
6327
+ this._validateAccessTokenAndUrl();
6328
+ const username = await this.getUsername();
6329
+ return this.githubSdk.getGithubIsUserCollaborator({
6330
+ repoUrl: this.url,
6331
+ username
6332
+ });
6333
+ }
6334
+ async getUsername() {
6335
+ this._validateAccessToken();
6336
+ return this.githubSdk.getGithubUsername();
6337
+ }
6338
+ async getSubmitRequestStatus(scmSubmitRequestId) {
6339
+ this._validateAccessTokenAndUrl();
6340
+ return this.githubSdk.getGithubPullRequestStatus({
6341
+ repoUrl: this.url,
6342
+ prNumber: Number(scmSubmitRequestId)
6343
+ });
6344
+ }
6345
+ async addCommentToSubmitRequest(submitRequestId, comment) {
6346
+ this._validateAccessTokenAndUrl();
6347
+ await this.githubSdk.createMarkdownCommentOnPullRequest({
6348
+ repoUrl: this.url,
6349
+ prNumber: Number(submitRequestId),
6350
+ markdownComment: comment
6351
+ });
6352
+ }
6353
+ async getRepoBlameRanges(ref, path8) {
6354
+ this._validateUrl();
6355
+ return await this.githubSdk.getGithubBlameRanges({
6356
+ ref,
6357
+ path: path8,
6358
+ gitHubUrl: this.url
6359
+ });
6360
+ }
6361
+ async getReferenceData(ref) {
6362
+ this._validateUrl();
6363
+ return this.githubSdk.getGithubReferenceData({ ref, gitHubUrl: this.url });
6364
+ }
6365
+ async getPrComment(commentId) {
6366
+ this._validateUrl();
6367
+ const { owner, repo } = parseGithubOwnerAndRepo(this.url);
6368
+ return await this.githubSdk.getPrComment({
6369
+ repo,
6370
+ owner,
6371
+ comment_id: commentId
6372
+ });
6373
+ }
6374
+ async getRepoDefaultBranch() {
6375
+ this._validateUrl();
6376
+ return await this.githubSdk.getGithubRepoDefaultBranch(this.url);
6377
+ }
6378
+ async getSubmitRequestUrl(submitRequestUrl) {
6379
+ this._validateAccessTokenAndUrl();
6380
+ const { owner, repo } = parseGithubOwnerAndRepo(this.url);
6381
+ const getPrRes = await this.githubSdk.getPr({
6382
+ owner,
6383
+ repo,
6384
+ pull_number: submitRequestUrl
6385
+ });
6386
+ return getPrRes.data.html_url;
6387
+ }
6388
+ async getSubmitRequestId(submitRequestUrl) {
6389
+ const match = submitRequestUrl.match(/\/pull\/(\d+)/);
6390
+ return match?.[1] || "";
6391
+ }
6392
+ async getCommitUrl(commitId) {
6393
+ this._validateAccessTokenAndUrl();
6394
+ const { owner, repo } = parseGithubOwnerAndRepo(this.url);
6395
+ const getCommitRes = await this.githubSdk.getCommit({
6396
+ owner,
6397
+ repo,
6398
+ commitSha: commitId
6399
+ });
6400
+ return getCommitRes.data.html_url;
6401
+ }
6402
+ async postGeneralPrComment(params) {
6403
+ const { prNumber, body } = params;
6404
+ this._validateAccessTokenAndUrl();
6405
+ const { owner, repo } = parseGithubOwnerAndRepo(this.url);
6406
+ return await this.githubSdk.postGeneralPrComment({
6407
+ issue_number: prNumber,
6626
6408
  owner,
6627
- repo
6628
- }) {
6629
- return octokit.rest.git.getCommit({
6630
- repo,
6631
- owner,
6632
- commit_sha: commitSha
6633
- });
6634
- },
6635
- async getTagDate({
6636
- tag,
6409
+ repo,
6410
+ body
6411
+ });
6412
+ }
6413
+ async getGeneralPrComments(params) {
6414
+ const { prNumber } = params;
6415
+ this._validateAccessTokenAndUrl();
6416
+ const { owner, repo } = parseGithubOwnerAndRepo(this.url);
6417
+ return await this.githubSdk.getGeneralPrComments({
6418
+ issue_number: prNumber,
6637
6419
  owner,
6638
6420
  repo
6639
- }) {
6640
- const refResponse = await octokit.rest.git.getRef({
6641
- ref: `tags/${tag}`,
6642
- owner,
6643
- repo
6644
- });
6645
- const tagSha = refResponse.data.object.sha;
6646
- if (refResponse.data.object.type === "commit") {
6647
- const res2 = await octokit.rest.git.getCommit({
6648
- commit_sha: tagSha,
6649
- owner,
6650
- repo
6651
- });
6652
- return {
6653
- date: res2.data.committer.date,
6654
- sha: res2.data.sha
6655
- };
6421
+ });
6422
+ }
6423
+ async deleteGeneralPrComment({
6424
+ commentId
6425
+ }) {
6426
+ this._validateAccessTokenAndUrl();
6427
+ const { owner, repo } = parseGithubOwnerAndRepo(this.url);
6428
+ return this.githubSdk.deleteGeneralPrComment({
6429
+ owner,
6430
+ repo,
6431
+ comment_id: commentId
6432
+ });
6433
+ }
6434
+ };
6435
+
6436
+ // src/features/analysis/scm/gitlab/gitlab.ts
6437
+ import querystring3 from "node:querystring";
6438
+ import {
6439
+ createRequesterFn
6440
+ } from "@gitbeaker/requester-utils";
6441
+ import {
6442
+ AccessLevel,
6443
+ Gitlab
6444
+ } from "@gitbeaker/rest";
6445
+ import Debug4 from "debug";
6446
+ import {
6447
+ fetch as undiciFetch,
6448
+ ProxyAgent as ProxyAgent2
6449
+ } from "undici";
6450
+
6451
+ // src/features/analysis/scm/gitlab/types.ts
6452
+ import { z as z23 } from "zod";
6453
+ var GitlabAuthResultZ = z23.object({
6454
+ access_token: z23.string(),
6455
+ token_type: z23.string(),
6456
+ refresh_token: z23.string()
6457
+ });
6458
+
6459
+ // src/features/analysis/scm/gitlab/gitlab.ts
6460
+ var debug4 = Debug4("scm:gitlab");
6461
+ function removeTrailingSlash2(str) {
6462
+ return str.trim().replace(/\/+$/, "");
6463
+ }
6464
+ function getRandomGitlabCloudAnonToken() {
6465
+ if (!GITLAB_API_TOKEN || typeof GITLAB_API_TOKEN !== "string") {
6466
+ return void 0;
6467
+ }
6468
+ const tokens = GITLAB_API_TOKEN.split(",");
6469
+ return tokens[Math.floor(Math.random() * tokens.length)];
6470
+ }
6471
+ function getGitBeaker(options) {
6472
+ const token = options?.gitlabAuthToken ?? getRandomGitlabCloudAnonToken() ?? "";
6473
+ const url = options.url;
6474
+ const host = url ? new URL(url).origin : "https://gitlab.com";
6475
+ if (token?.startsWith("glpat-") || token === "") {
6476
+ return new Gitlab({
6477
+ token,
6478
+ host,
6479
+ requesterFn: createRequesterFn(
6480
+ (_, reqo) => Promise.resolve(reqo),
6481
+ brokerRequestHandler
6482
+ )
6483
+ });
6484
+ }
6485
+ return new Gitlab({
6486
+ oauthToken: token,
6487
+ host,
6488
+ requesterFn: createRequesterFn(
6489
+ (_, reqo) => Promise.resolve(reqo),
6490
+ brokerRequestHandler
6491
+ )
6492
+ });
6493
+ }
6494
+ async function gitlabValidateParams({
6495
+ url,
6496
+ accessToken
6497
+ }) {
6498
+ try {
6499
+ const api2 = getGitBeaker({ url, gitlabAuthToken: accessToken });
6500
+ if (accessToken) {
6501
+ await api2.Users.showCurrentUser();
6502
+ }
6503
+ if (url && shouldValidateUrl(url)) {
6504
+ const { projectPath } = parseGitlabOwnerAndRepo(url);
6505
+ await api2.Projects.show(projectPath);
6506
+ }
6507
+ } catch (e) {
6508
+ const error = e;
6509
+ const code = error.code || error.status || error.statusCode || error.response?.status || error.response?.statusCode || error.response?.code;
6510
+ const description = error.description || `${e}`;
6511
+ if (code === 401 || code === 403 || description.includes("401") || description.includes("403")) {
6512
+ throw new InvalidAccessTokenError(`invalid gitlab access token`);
6513
+ }
6514
+ if (code === 404 || description.includes("404") || description.includes("Not Found")) {
6515
+ throw new InvalidRepoUrlError(`invalid gitlab repo URL: ${url}`);
6516
+ }
6517
+ console.log("gitlabValidateParams error", e);
6518
+ throw new InvalidRepoUrlError(
6519
+ `cannot access gitlab repo URL: ${url} with the provided access token`
6520
+ );
6521
+ }
6522
+ }
6523
+ async function getGitlabUsername(url, accessToken) {
6524
+ const api2 = getGitBeaker({ url, gitlabAuthToken: accessToken });
6525
+ const res = await api2.Users.showCurrentUser();
6526
+ return res.username;
6527
+ }
6528
+ async function getGitlabIsUserCollaborator({
6529
+ accessToken,
6530
+ repoUrl
6531
+ }) {
6532
+ try {
6533
+ const { projectPath } = parseGitlabOwnerAndRepo(repoUrl);
6534
+ const api2 = getGitBeaker({ url: repoUrl, gitlabAuthToken: accessToken });
6535
+ const proj = await api2.Projects.show(projectPath);
6536
+ const groupAccess = proj.permissions?.group_access?.access_level || 0;
6537
+ const projectAccess = proj.permissions?.project_access?.access_level || 0;
6538
+ const accessLevelWithWriteAccess = [
6539
+ AccessLevel.DEVELOPER,
6540
+ AccessLevel.MAINTAINER,
6541
+ AccessLevel.OWNER,
6542
+ AccessLevel.ADMIN
6543
+ ];
6544
+ return accessLevelWithWriteAccess.includes(groupAccess) || accessLevelWithWriteAccess.includes(projectAccess);
6545
+ } catch (e) {
6546
+ return false;
6547
+ }
6548
+ }
6549
+ var gitlabMergeRequestStatus = {
6550
+ merged: "merged",
6551
+ opened: "opened",
6552
+ closed: "closed"
6553
+ };
6554
+ async function getGitlabMergeRequestStatus({
6555
+ accessToken,
6556
+ repoUrl,
6557
+ mrNumber
6558
+ }) {
6559
+ const { projectPath } = parseGitlabOwnerAndRepo(repoUrl);
6560
+ const api2 = getGitBeaker({ url: repoUrl, gitlabAuthToken: accessToken });
6561
+ const res = await api2.MergeRequests.show(projectPath, mrNumber);
6562
+ switch (res.state) {
6563
+ case gitlabMergeRequestStatus.merged:
6564
+ case gitlabMergeRequestStatus.opened:
6565
+ case gitlabMergeRequestStatus.closed:
6566
+ return res.state;
6567
+ default:
6568
+ throw new Error(`unknown merge request state ${res.state}`);
6569
+ }
6570
+ }
6571
+ async function createMarkdownCommentOnPullRequest({
6572
+ markdownComment,
6573
+ accessToken,
6574
+ repoUrl,
6575
+ mrNumber
6576
+ }) {
6577
+ const { projectPath } = parseGitlabOwnerAndRepo(repoUrl);
6578
+ const api2 = getGitBeaker({ url: repoUrl, gitlabAuthToken: accessToken });
6579
+ return api2.MergeRequestNotes.create(projectPath, mrNumber, markdownComment);
6580
+ }
6581
+ async function getGitlabIsRemoteBranch({
6582
+ accessToken,
6583
+ repoUrl,
6584
+ branch
6585
+ }) {
6586
+ const { projectPath } = parseGitlabOwnerAndRepo(repoUrl);
6587
+ const api2 = getGitBeaker({ url: repoUrl, gitlabAuthToken: accessToken });
6588
+ try {
6589
+ const res = await api2.Branches.show(projectPath, branch);
6590
+ return res.name === branch;
6591
+ } catch (e) {
6592
+ return false;
6593
+ }
6594
+ }
6595
+ async function getGitlabRepoList(url, accessToken) {
6596
+ const api2 = getGitBeaker({ url, gitlabAuthToken: accessToken });
6597
+ const res = await api2.Projects.all({
6598
+ membership: true,
6599
+ //TODO: a bug in the sorting mechanism of this api call
6600
+ //disallows us to sort by updated_at in descending order
6601
+ //so we have to sort by updated_at in ascending order.
6602
+ //We can wait for the bug to be fixed or call the api
6603
+ //directly with fetch()
6604
+ sort: "asc",
6605
+ orderBy: "updated_at",
6606
+ perPage: 100
6607
+ });
6608
+ return Promise.all(
6609
+ res.map(async (project) => {
6610
+ const proj = await api2.Projects.show(project.id);
6611
+ const owner = proj.namespace.name;
6612
+ const repoLanguages = await api2.Projects.showLanguages(project.id);
6613
+ return {
6614
+ repoName: project.path,
6615
+ repoUrl: project.web_url,
6616
+ repoOwner: owner,
6617
+ repoLanguages: Object.keys(repoLanguages),
6618
+ repoIsPublic: project.visibility === "public",
6619
+ repoUpdatedAt: project.last_activity_at
6620
+ };
6621
+ })
6622
+ );
6623
+ }
6624
+ async function getGitlabBranchList({
6625
+ accessToken,
6626
+ repoUrl
6627
+ }) {
6628
+ const { projectPath } = parseGitlabOwnerAndRepo(repoUrl);
6629
+ const api2 = getGitBeaker({ url: repoUrl, gitlabAuthToken: accessToken });
6630
+ try {
6631
+ const res = await api2.Branches.all(projectPath, {
6632
+ //keyset API pagination is not supported by GL for the branch list (at least not the on-prem version)
6633
+ //so for now we stick with the default pagination and just return the first page and limit the results to 1000 entries.
6634
+ //This is a temporary solution until we implement list branches with name search.
6635
+ perPage: MAX_BRANCHES_FETCH,
6636
+ page: 1
6637
+ });
6638
+ res.sort((a, b) => {
6639
+ if (!a.commit?.committed_date || !b.commit?.committed_date) {
6640
+ return 0;
6656
6641
  }
6657
- const res = await octokit.rest.git.getTag({
6658
- tag_sha: tagSha,
6659
- owner,
6660
- repo
6661
- });
6642
+ return new Date(b.commit?.committed_date).getTime() - new Date(a.commit?.committed_date).getTime();
6643
+ });
6644
+ return res.map((branch) => branch.name).slice(0, MAX_BRANCHES_FETCH);
6645
+ } catch (e) {
6646
+ return [];
6647
+ }
6648
+ }
6649
+ async function createMergeRequest(options) {
6650
+ const { projectPath } = parseGitlabOwnerAndRepo(options.repoUrl);
6651
+ const api2 = getGitBeaker({
6652
+ url: options.repoUrl,
6653
+ gitlabAuthToken: options.accessToken
6654
+ });
6655
+ const res = await api2.MergeRequests.create(
6656
+ projectPath,
6657
+ options.sourceBranchName,
6658
+ options.targetBranchName,
6659
+ options.title,
6660
+ {
6661
+ description: options.body
6662
+ }
6663
+ );
6664
+ return res.iid;
6665
+ }
6666
+ async function getGitlabMergeRequest({
6667
+ url,
6668
+ prNumber,
6669
+ accessToken
6670
+ }) {
6671
+ const { projectPath } = parseGitlabOwnerAndRepo(url);
6672
+ const api2 = getGitBeaker({
6673
+ url,
6674
+ gitlabAuthToken: accessToken
6675
+ });
6676
+ return await api2.MergeRequests.show(projectPath, prNumber);
6677
+ }
6678
+ async function getGitlabCommitUrl({
6679
+ url,
6680
+ commitSha,
6681
+ accessToken
6682
+ }) {
6683
+ const { projectPath } = parseGitlabOwnerAndRepo(url);
6684
+ const api2 = getGitBeaker({
6685
+ url,
6686
+ gitlabAuthToken: accessToken
6687
+ });
6688
+ return await api2.Commits.show(projectPath, commitSha);
6689
+ }
6690
+ async function getGitlabRepoDefaultBranch(repoUrl, options) {
6691
+ const api2 = getGitBeaker({
6692
+ url: repoUrl,
6693
+ gitlabAuthToken: options?.gitlabAuthToken
6694
+ });
6695
+ const { projectPath } = parseGitlabOwnerAndRepo(repoUrl);
6696
+ const project = await api2.Projects.show(projectPath);
6697
+ if (!project.default_branch) {
6698
+ throw new Error("no default branch");
6699
+ }
6700
+ return project.default_branch;
6701
+ }
6702
+ async function getGitlabReferenceData({ ref, gitlabUrl }, options) {
6703
+ const { projectPath } = parseGitlabOwnerAndRepo(gitlabUrl);
6704
+ const api2 = getGitBeaker({
6705
+ url: gitlabUrl,
6706
+ gitlabAuthToken: options?.gitlabAuthToken
6707
+ });
6708
+ const results = await Promise.allSettled([
6709
+ (async () => {
6710
+ const res = await api2.Branches.show(projectPath, ref);
6662
6711
  return {
6663
- date: res.data.tagger.date,
6664
- sha: res.data.sha
6712
+ sha: res.commit.id,
6713
+ type: "BRANCH" /* BRANCH */,
6714
+ date: res.commit.committed_date ? new Date(res.commit.committed_date) : void 0
6665
6715
  };
6666
- },
6667
- async getGithubBlameRanges(params2) {
6668
- const { ref, gitHubUrl, path: path8 } = params2;
6669
- const { owner, repo } = parseGithubOwnerAndRepo(gitHubUrl);
6670
- const res = await octokit.graphql(
6671
- GET_BLAME_DOCUMENT,
6672
- {
6673
- owner,
6674
- repo,
6675
- path: path8,
6676
- ref
6677
- }
6678
- );
6679
- if (!res?.repository?.object?.blame?.ranges) {
6680
- return [];
6681
- }
6682
- return res.repository.object.blame.ranges.map((range) => ({
6683
- startingLine: range.startingLine,
6684
- endingLine: range.endingLine,
6685
- email: range.commit.author.user?.email || "",
6686
- name: range.commit.author.user?.name || "",
6687
- login: range.commit.author.user?.login || ""
6688
- }));
6689
- },
6690
- // todo: refactor the name for this function
6691
- async createPr(params2) {
6692
- const { sourceRepoUrl, filesPaths, userRepoUrl, title, body } = params2;
6693
- const { owner: sourceOwner, repo: sourceRepo } = parseGithubOwnerAndRepo(sourceRepoUrl);
6694
- const { owner, repo } = parseGithubOwnerAndRepo(userRepoUrl);
6695
- const [sourceFilePath, secondFilePath] = filesPaths;
6696
- const sourceFileContentResponse = await octokit.rest.repos.getContent({
6697
- owner: sourceOwner,
6698
- repo: sourceRepo,
6699
- path: "/" + sourceFilePath
6700
- });
6701
- const { data: repository } = await octokit.rest.repos.get({ owner, repo });
6702
- const defaultBranch = repository.default_branch;
6703
- const newBranchName = `mobb/workflow-${Date.now()}`;
6704
- await octokit.rest.git.createRef({
6705
- owner,
6706
- repo,
6707
- ref: `refs/heads/${newBranchName}`,
6708
- sha: await octokit.rest.git.getRef({ owner, repo, ref: `heads/${defaultBranch}` }).then((response) => response.data.object.sha)
6709
- });
6710
- const decodedContent = Buffer.from(
6711
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
6712
- // @ts-ignore
6713
- sourceFileContentResponse.data.content,
6714
- "base64"
6715
- ).toString("utf-8");
6716
- const tree = [
6717
- {
6718
- path: sourceFilePath,
6719
- mode: "100644",
6720
- type: "blob",
6721
- content: decodedContent
6722
- }
6723
- ];
6724
- if (secondFilePath) {
6725
- const secondFileContentResponse = await octokit.rest.repos.getContent({
6726
- owner: sourceOwner,
6727
- repo: sourceRepo,
6728
- path: "/" + secondFilePath
6729
- });
6730
- const secondDecodedContent = Buffer.from(
6731
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
6732
- // @ts-ignore
6733
- secondFileContentResponse.data.content,
6734
- "base64"
6735
- ).toString("utf-8");
6736
- tree.push({
6737
- path: secondFilePath,
6738
- mode: "100644",
6739
- type: "blob",
6740
- content: secondDecodedContent
6741
- });
6742
- }
6743
- const createTreeResponse = await octokit.rest.git.createTree({
6744
- owner,
6745
- repo,
6746
- base_tree: await octokit.rest.git.getRef({ owner, repo, ref: `heads/${defaultBranch}` }).then((response) => response.data.object.sha),
6747
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
6748
- // @ts-ignore
6749
- tree
6750
- });
6751
- const createCommitResponse = await octokit.rest.git.createCommit({
6752
- owner,
6753
- repo,
6754
- message: "Add new yaml file",
6755
- tree: createTreeResponse.data.sha,
6756
- parents: [
6757
- await octokit.rest.git.getRef({ owner, repo, ref: `heads/${defaultBranch}` }).then((response) => response.data.object.sha)
6758
- ]
6759
- });
6760
- await octokit.rest.git.updateRef({
6761
- owner,
6762
- repo,
6763
- ref: `heads/${newBranchName}`,
6764
- sha: createCommitResponse.data.sha
6765
- });
6766
- const createPRResponse = await octokit.rest.pulls.create({
6767
- owner,
6768
- repo,
6769
- title,
6770
- head: newBranchName,
6771
- head_repo: sourceRepo,
6772
- body,
6773
- base: defaultBranch
6774
- });
6716
+ })(),
6717
+ (async () => {
6718
+ const res = await api2.Commits.show(projectPath, ref);
6775
6719
  return {
6776
- pull_request_url: createPRResponse.data.html_url
6720
+ sha: res.id,
6721
+ type: "COMMIT" /* COMMIT */,
6722
+ date: res.committed_date ? new Date(res.committed_date) : void 0
6777
6723
  };
6778
- },
6779
- async getGithubBranchList(repoUrl) {
6780
- const { owner, repo } = parseGithubOwnerAndRepo(repoUrl);
6781
- return octokit.rest.repos.listBranches({
6782
- owner,
6783
- repo,
6784
- per_page: MAX_BRANCHES_FETCH,
6785
- page: 1
6786
- });
6787
- },
6788
- async createPullRequest(options) {
6789
- const { owner, repo } = parseGithubOwnerAndRepo(options.repoUrl);
6790
- return octokit.rest.pulls.create({
6791
- owner,
6792
- repo,
6793
- title: options.title,
6794
- body: options.body,
6795
- head: options.sourceBranchName,
6796
- base: options.targetBranchName,
6797
- draft: false,
6798
- maintainer_can_modify: true
6799
- });
6800
- },
6801
- async forkRepo(options) {
6802
- const { owner, repo } = parseGithubOwnerAndRepo(options.repoUrl);
6803
- const createForkRes = await octokit.rest.repos.createFork({
6804
- owner,
6805
- repo,
6806
- default_branch_only: false
6807
- });
6808
- return { url: createForkRes.data.html_url };
6809
- },
6810
- async getUserInfo() {
6811
- return octokit.request(GET_USER);
6724
+ })(),
6725
+ (async () => {
6726
+ const res = await api2.Tags.show(projectPath, ref);
6727
+ return {
6728
+ sha: res.commit.id,
6729
+ type: "TAG" /* TAG */,
6730
+ date: res.commit.committed_date ? new Date(res.commit.committed_date) : void 0
6731
+ };
6732
+ })()
6733
+ ]);
6734
+ const [branchRes, commitRes, tagRes] = results;
6735
+ if (tagRes.status === "fulfilled") {
6736
+ return tagRes.value;
6737
+ }
6738
+ if (branchRes.status === "fulfilled") {
6739
+ return branchRes.value;
6740
+ }
6741
+ if (commitRes.status === "fulfilled") {
6742
+ return commitRes.value;
6743
+ }
6744
+ throw new RefNotFoundError(`ref: ${ref} does not exist`);
6745
+ }
6746
+ function parseGitlabOwnerAndRepo(gitlabUrl) {
6747
+ gitlabUrl = removeTrailingSlash2(gitlabUrl);
6748
+ const parsingResult = parseScmURL(gitlabUrl, "GitLab" /* GitLab */);
6749
+ if (!parsingResult || !parsingResult.repoName) {
6750
+ throw new InvalidUrlPatternError(`invalid gitlab repo Url ${gitlabUrl}`);
6751
+ }
6752
+ const { organization, repoName, projectPath } = parsingResult;
6753
+ return { owner: organization, repo: repoName, projectPath };
6754
+ }
6755
+ async function getGitlabBlameRanges({ ref, gitlabUrl, path: path8 }, options) {
6756
+ const { projectPath } = parseGitlabOwnerAndRepo(gitlabUrl);
6757
+ const api2 = getGitBeaker({
6758
+ url: gitlabUrl,
6759
+ gitlabAuthToken: options?.gitlabAuthToken
6760
+ });
6761
+ const resp = await api2.RepositoryFiles.allFileBlames(projectPath, path8, ref);
6762
+ let lineNumber = 1;
6763
+ return resp.filter((range) => range.lines).map((range) => {
6764
+ const oldLineNumber = lineNumber;
6765
+ if (!range.lines) {
6766
+ throw new Error("range.lines should not be undefined");
6812
6767
  }
6813
- };
6768
+ lineNumber += range.lines.length;
6769
+ return {
6770
+ startingLine: oldLineNumber,
6771
+ endingLine: lineNumber - 1,
6772
+ login: range.commit.author_email,
6773
+ email: range.commit.author_email,
6774
+ name: range.commit.author_name
6775
+ };
6776
+ });
6777
+ }
6778
+ async function processBody(response) {
6779
+ const headers = response.headers;
6780
+ const type2 = headers.get("content-type")?.split(";")[0]?.trim();
6781
+ if (type2 === "application/json") {
6782
+ return await response.json();
6783
+ }
6784
+ return await response.text();
6785
+ }
6786
+ async function brokerRequestHandler(endpoint, options) {
6787
+ const { prefixUrl, searchParams } = options || {};
6788
+ let baseUrl;
6789
+ if (prefixUrl) baseUrl = prefixUrl.endsWith("/") ? prefixUrl : `${prefixUrl}/`;
6790
+ const url = new URL(endpoint, baseUrl);
6791
+ url.search = searchParams || "";
6792
+ const dispatcher = url && isBrokerUrl(url.href) ? new ProxyAgent2({
6793
+ uri: GIT_PROXY_HOST,
6794
+ requestTls: {
6795
+ rejectUnauthorized: false
6796
+ }
6797
+ }) : void 0;
6798
+ const response = await undiciFetch(url, {
6799
+ headers: options?.headers,
6800
+ method: options?.method,
6801
+ body: options?.body ? String(options?.body) : void 0,
6802
+ dispatcher
6803
+ }).catch((e) => {
6804
+ if (e.name === "TimeoutError" || e.name === "AbortError") {
6805
+ throw new Error("Query timeout was reached");
6806
+ }
6807
+ throw e;
6808
+ });
6809
+ if (response.ok)
6810
+ return {
6811
+ body: await processBody(response),
6812
+ headers: Object.fromEntries(response.headers.entries()),
6813
+ status: response.status
6814
+ };
6815
+ throw new Error(`gitbeaker: ${response.statusText}`);
6814
6816
  }
6815
6817
 
6816
- // src/features/analysis/scm/github/GithubSCMLib.ts
6817
- var GithubSCMLib = class extends SCMLib {
6818
- // we don't always need a url, what's important is that we have an access token
6818
+ // src/features/analysis/scm/gitlab/GitlabSCMLib.ts
6819
+ var GitlabSCMLib = class extends SCMLib {
6819
6820
  constructor(url, accessToken, scmOrg) {
6820
6821
  super(url, accessToken, scmOrg);
6821
- __publicField(this, "githubSdk");
6822
- this.githubSdk = getGithubSdk({
6823
- auth: accessToken,
6824
- url
6825
- });
6826
6822
  }
6827
6823
  async createSubmitRequest(params) {
6828
6824
  this._validateAccessTokenAndUrl();
6829
6825
  const { targetBranchName, sourceBranchName, title, body } = params;
6830
- const pullRequestResult = await this.githubSdk.createPullRequest({
6831
- title,
6832
- body,
6833
- targetBranchName,
6834
- sourceBranchName,
6835
- repoUrl: this.url
6836
- });
6837
- return String(pullRequestResult.data.number);
6838
- }
6839
- async forkRepo(repoUrl) {
6840
- this._validateAccessToken();
6841
- return this.githubSdk.forkRepo({
6842
- repoUrl
6843
- });
6844
- }
6845
- async createOrUpdateRepositorySecret(params) {
6846
- this._validateAccessTokenAndUrl();
6847
- const { owner, repo } = parseGithubOwnerAndRepo(this.url);
6848
- const { data: repositoryPublicKeyResponse } = await this.githubSdk.getRepositoryPublicKey({ owner, repo });
6849
- const { key_id, key } = repositoryPublicKeyResponse;
6850
- const encryptedValue = await encryptSecret(params.value, key);
6851
- return this.githubSdk.createOrUpdateRepositorySecret({
6852
- encrypted_value: encryptedValue,
6853
- secret_name: params.name,
6854
- key_id,
6855
- owner,
6856
- repo
6857
- });
6858
- }
6859
- async createPullRequestWithNewFile(sourceRepoUrl, filesPaths, userRepoUrl, title, body) {
6860
- const { pull_request_url } = await this.githubSdk.createPr({
6861
- sourceRepoUrl,
6862
- filesPaths,
6863
- userRepoUrl,
6864
- title,
6865
- body
6866
- });
6867
- return { pull_request_url };
6826
+ return String(
6827
+ await createMergeRequest({
6828
+ title,
6829
+ body,
6830
+ targetBranchName,
6831
+ sourceBranchName,
6832
+ repoUrl: this.url,
6833
+ accessToken: this.accessToken
6834
+ })
6835
+ );
6868
6836
  }
6869
6837
  async validateParams() {
6870
- return githubValidateParams(this.url, this.accessToken);
6871
- }
6872
- async postPrComment(params) {
6873
- this._validateAccessTokenAndUrl();
6874
- const { owner, repo } = parseGithubOwnerAndRepo(this.url);
6875
- return this.githubSdk.postPrComment({
6876
- ...params,
6877
- owner,
6878
- repo
6879
- });
6880
- }
6881
- async updatePrComment(params) {
6882
- this._validateAccessTokenAndUrl();
6883
- const { owner, repo } = parseGithubOwnerAndRepo(this.url);
6884
- return this.githubSdk.updatePrComment({
6885
- ...params,
6886
- owner,
6887
- repo
6888
- });
6889
- }
6890
- async deleteComment(params) {
6891
- this._validateAccessTokenAndUrl();
6892
- const { owner, repo } = parseGithubOwnerAndRepo(this.url);
6893
- return this.githubSdk.deleteComment({
6894
- ...params,
6895
- owner,
6896
- repo
6897
- });
6898
- }
6899
- async getPrComments(params) {
6900
- this._validateAccessTokenAndUrl();
6901
- const { owner, repo } = parseGithubOwnerAndRepo(this.url);
6902
- return this.githubSdk.getPrComments({
6903
- per_page: 100,
6904
- ...params,
6905
- owner,
6906
- repo
6907
- });
6908
- }
6909
- async getPrDiff(params) {
6910
- this._validateAccessTokenAndUrl();
6911
- const { owner, repo } = parseGithubOwnerAndRepo(this.url);
6912
- const prRes = await this.githubSdk.getPrDiff({
6913
- ...params,
6914
- owner,
6915
- repo
6838
+ return gitlabValidateParams({
6839
+ url: this.url,
6840
+ accessToken: this.accessToken
6916
6841
  });
6917
- return z24.string().parse(prRes.data);
6918
6842
  }
6919
6843
  async getRepoList(_scmOrg) {
6920
- this._validateAccessToken();
6921
- return this.githubSdk.getGithubRepoList();
6844
+ if (!this.accessToken) {
6845
+ console.error("no access token");
6846
+ throw new Error("no access token");
6847
+ }
6848
+ return getGitlabRepoList(this.url, this.accessToken);
6922
6849
  }
6923
6850
  async getBranchList() {
6924
6851
  this._validateAccessTokenAndUrl();
6925
- const branches = await this.githubSdk.getGithubBranchList(this.url);
6926
- return branches.data.map((branch) => branch.name);
6852
+ return getGitlabBranchList({
6853
+ accessToken: this.accessToken,
6854
+ repoUrl: this.url
6855
+ });
6927
6856
  }
6928
6857
  get scmLibType() {
6929
- return "GITHUB" /* GITHUB */;
6858
+ return "GITLAB" /* GITLAB */;
6930
6859
  }
6931
6860
  getAuthHeaders() {
6932
- if (this.accessToken) {
6861
+ if (!this.accessToken) {
6862
+ return {};
6863
+ }
6864
+ if (this.accessToken.startsWith("glpat-")) {
6865
+ return {
6866
+ "Private-Token": this.accessToken
6867
+ };
6868
+ } else {
6933
6869
  return { authorization: `Bearer ${this.accessToken}` };
6934
6870
  }
6935
- return {};
6936
6871
  }
6937
6872
  getDownloadUrl(sha) {
6938
- this._validateUrl();
6939
- const res = parseScmURL(this.url, "GitHub" /* GitHub */);
6940
- if (!res) {
6941
- throw new InvalidRepoUrlError("invalid repo url");
6942
- }
6943
- const { protocol, hostname, organization, repoName } = res;
6944
- const downloadUrl = isGithubOnPrem(this.url) ? `${protocol}//${hostname}/api/v3/repos/${organization}/${repoName}/zipball/${sha}` : `https://api.${hostname}/repos/${organization}/${repoName}/zipball/${sha}`;
6945
- return Promise.resolve(downloadUrl);
6873
+ const urlObj = new URL(this.url || "");
6874
+ const ProjectId = encodeURIComponent(
6875
+ urlObj.pathname.replace(/^\//, "").replace(/\/$/, "")
6876
+ );
6877
+ return Promise.resolve(
6878
+ //We are moving away from this form as it doesn't work when using a non-human token (group/project token)
6879
+ //Where as the API zip endpoint works with any token
6880
+ //`${this.url}/-/archive/${sha}/${repoName}-${sha}.zip`
6881
+ `${urlObj.origin}/api/v4/projects/${ProjectId}/repository/archive.zip?sha=${sha}`
6882
+ );
6946
6883
  }
6947
6884
  async _getUsernameForAuthUrl() {
6948
- return this.getUsername();
6885
+ if (this?.accessToken?.startsWith("glpat-")) {
6886
+ return this.getUsername();
6887
+ } else {
6888
+ return "oauth2";
6889
+ }
6949
6890
  }
6950
6891
  async getIsRemoteBranch(branch) {
6951
- this._validateUrl();
6952
- return this.githubSdk.getGithubIsRemoteBranch({ branch, repoUrl: this.url });
6892
+ this._validateAccessTokenAndUrl();
6893
+ return getGitlabIsRemoteBranch({
6894
+ accessToken: this.accessToken,
6895
+ repoUrl: this.url,
6896
+ branch
6897
+ });
6953
6898
  }
6954
6899
  async getUserHasAccessToRepo() {
6955
6900
  this._validateAccessTokenAndUrl();
6956
- const username = await this.getUsername();
6957
- return this.githubSdk.getGithubIsUserCollaborator({
6958
- repoUrl: this.url,
6959
- username
6901
+ return getGitlabIsUserCollaborator({
6902
+ accessToken: this.accessToken,
6903
+ repoUrl: this.url
6960
6904
  });
6961
6905
  }
6962
6906
  async getUsername() {
6963
- this._validateAccessToken();
6964
- return this.githubSdk.getGithubUsername();
6907
+ this._validateAccessTokenAndUrl();
6908
+ return getGitlabUsername(this.url, this.accessToken);
6965
6909
  }
6966
6910
  async getSubmitRequestStatus(scmSubmitRequestId) {
6967
6911
  this._validateAccessTokenAndUrl();
6968
- return this.githubSdk.getGithubPullRequestStatus({
6912
+ const state = await getGitlabMergeRequestStatus({
6913
+ accessToken: this.accessToken,
6969
6914
  repoUrl: this.url,
6970
- prNumber: Number(scmSubmitRequestId)
6915
+ mrNumber: Number(scmSubmitRequestId)
6971
6916
  });
6917
+ switch (state) {
6918
+ case gitlabMergeRequestStatus.merged:
6919
+ return "merged";
6920
+ case gitlabMergeRequestStatus.opened:
6921
+ return "open";
6922
+ case gitlabMergeRequestStatus.closed:
6923
+ return "closed";
6924
+ default:
6925
+ throw new Error(`unknown state ${state}`);
6926
+ }
6972
6927
  }
6973
6928
  async addCommentToSubmitRequest(submitRequestId, comment) {
6974
6929
  this._validateAccessTokenAndUrl();
6975
- await this.githubSdk.createMarkdownCommentOnPullRequest({
6930
+ await createMarkdownCommentOnPullRequest({
6931
+ accessToken: this.accessToken,
6976
6932
  repoUrl: this.url,
6977
- prNumber: Number(submitRequestId),
6933
+ mrNumber: Number(submitRequestId),
6978
6934
  markdownComment: comment
6979
6935
  });
6980
6936
  }
6981
6937
  async getRepoBlameRanges(ref, path8) {
6982
6938
  this._validateUrl();
6983
- return await this.githubSdk.getGithubBlameRanges({
6984
- ref,
6985
- path: path8,
6986
- gitHubUrl: this.url
6987
- });
6939
+ return await getGitlabBlameRanges(
6940
+ { ref, path: path8, gitlabUrl: this.url },
6941
+ {
6942
+ url: this.url,
6943
+ gitlabAuthToken: this.accessToken
6944
+ }
6945
+ );
6988
6946
  }
6989
6947
  async getReferenceData(ref) {
6990
6948
  this._validateUrl();
6991
- return this.githubSdk.getGithubReferenceData({ ref, gitHubUrl: this.url });
6992
- }
6993
- async getPrComment(commentId) {
6994
- this._validateUrl();
6995
- const { owner, repo } = parseGithubOwnerAndRepo(this.url);
6996
- return await this.githubSdk.getPrComment({
6997
- repo,
6998
- owner,
6999
- comment_id: commentId
7000
- });
6949
+ return await getGitlabReferenceData(
6950
+ { ref, gitlabUrl: this.url },
6951
+ {
6952
+ url: this.url,
6953
+ gitlabAuthToken: this.accessToken
6954
+ }
6955
+ );
7001
6956
  }
7002
6957
  async getRepoDefaultBranch() {
7003
6958
  this._validateUrl();
7004
- return await this.githubSdk.getGithubRepoDefaultBranch(this.url);
6959
+ return await getGitlabRepoDefaultBranch(this.url, {
6960
+ url: this.url,
6961
+ gitlabAuthToken: this.accessToken
6962
+ });
7005
6963
  }
7006
6964
  async getSubmitRequestUrl(submitRequestUrl) {
7007
6965
  this._validateAccessTokenAndUrl();
7008
- const { owner, repo } = parseGithubOwnerAndRepo(this.url);
7009
- const getPrRes = await this.githubSdk.getPr({
7010
- owner,
7011
- repo,
7012
- pull_number: submitRequestUrl
6966
+ const res = await getGitlabMergeRequest({
6967
+ url: this.url,
6968
+ prNumber: submitRequestUrl,
6969
+ accessToken: this.accessToken
7013
6970
  });
7014
- return getPrRes.data.html_url;
6971
+ return res.web_url;
7015
6972
  }
7016
6973
  async getSubmitRequestId(submitRequestUrl) {
7017
- const match = submitRequestUrl.match(/\/pull\/(\d+)/);
6974
+ const match = submitRequestUrl.match(/\/merge_requests\/(\d+)/);
7018
6975
  return match?.[1] || "";
7019
6976
  }
7020
6977
  async getCommitUrl(commitId) {
7021
6978
  this._validateAccessTokenAndUrl();
7022
- const { owner, repo } = parseGithubOwnerAndRepo(this.url);
7023
- const getCommitRes = await this.githubSdk.getCommit({
7024
- owner,
7025
- repo,
7026
- commitSha: commitId
6979
+ const res = await getGitlabCommitUrl({
6980
+ url: this.url,
6981
+ commitSha: commitId,
6982
+ accessToken: this.accessToken
7027
6983
  });
7028
- return getCommitRes.data.html_url;
6984
+ return res.web_url;
7029
6985
  }
7030
- async postGeneralPrComment(params) {
7031
- const { prNumber, body } = params;
7032
- this._validateAccessTokenAndUrl();
7033
- const { owner, repo } = parseGithubOwnerAndRepo(this.url);
7034
- return await this.githubSdk.postGeneralPrComment({
7035
- issue_number: prNumber,
7036
- owner,
7037
- repo,
7038
- body
7039
- });
6986
+ };
6987
+
6988
+ // src/features/analysis/scm/scmFactory.ts
6989
+ import { z as z24 } from "zod";
6990
+
6991
+ // src/features/analysis/scm/StubSCMLib.ts
6992
+ var StubSCMLib = class extends SCMLib {
6993
+ constructor(url, accessToken, scmOrg) {
6994
+ super(url, accessToken, scmOrg);
7040
6995
  }
7041
- async getGeneralPrComments(params) {
7042
- const { prNumber } = params;
7043
- this._validateAccessTokenAndUrl();
7044
- const { owner, repo } = parseGithubOwnerAndRepo(this.url);
7045
- return await this.githubSdk.getGeneralPrComments({
7046
- issue_number: prNumber,
7047
- owner,
7048
- repo
7049
- });
6996
+ async getUrlWithCredentials() {
6997
+ console.warn("getUrlWithCredentials() returning empty string");
6998
+ return "";
7050
6999
  }
7051
- async deleteGeneralPrComment({
7052
- commentId
7053
- }) {
7054
- this._validateAccessTokenAndUrl();
7055
- const { owner, repo } = parseGithubOwnerAndRepo(this.url);
7056
- return this.githubSdk.deleteGeneralPrComment({
7057
- owner,
7058
- repo,
7059
- comment_id: commentId
7060
- });
7000
+ async createSubmitRequest(_params) {
7001
+ console.warn("createSubmitRequest() returning empty string");
7002
+ return "";
7003
+ }
7004
+ get scmLibType() {
7005
+ console.warn("scmLibType returning GITHUB as default");
7006
+ return "GITHUB" /* GITHUB */;
7007
+ }
7008
+ getAuthHeaders() {
7009
+ console.warn("getAuthHeaders() returning empty object");
7010
+ return {};
7011
+ }
7012
+ async getDownloadUrl(_sha) {
7013
+ console.warn("getDownloadUrl() returning empty string");
7014
+ return "";
7015
+ }
7016
+ async getIsRemoteBranch(_branch) {
7017
+ console.warn("getIsRemoteBranch() returning false");
7018
+ return false;
7019
+ }
7020
+ async validateParams() {
7021
+ console.warn("validateParams() no-op");
7022
+ }
7023
+ async getRepoList(_scmOrg) {
7024
+ console.warn("getRepoList() returning empty array");
7025
+ return [];
7026
+ }
7027
+ async getBranchList() {
7028
+ console.warn("getBranchList() returning empty array");
7029
+ return [];
7030
+ }
7031
+ async getUsername() {
7032
+ console.warn("getUsername() returning empty string");
7033
+ return "";
7034
+ }
7035
+ async getSubmitRequestStatus(_scmSubmitRequestId) {
7036
+ console.warn("getSubmitRequestStatus() returning ERROR");
7037
+ return "error";
7038
+ }
7039
+ async getUserHasAccessToRepo() {
7040
+ console.warn("getUserHasAccessToRepo() returning false");
7041
+ return false;
7042
+ }
7043
+ async getRepoBlameRanges(_ref, _path) {
7044
+ console.warn("getRepoBlameRanges() returning empty array");
7045
+ return [];
7046
+ }
7047
+ async getReferenceData(_ref) {
7048
+ console.warn("getReferenceData() returning null/empty defaults");
7049
+ return {
7050
+ type: "BRANCH" /* BRANCH */,
7051
+ sha: "",
7052
+ date: void 0
7053
+ };
7054
+ }
7055
+ async getRepoDefaultBranch() {
7056
+ console.warn("getRepoDefaultBranch() returning empty string");
7057
+ return "";
7058
+ }
7059
+ async getSubmitRequestUrl(_submitRequestIdNumber) {
7060
+ console.warn("getSubmitRequestUrl() returning empty string");
7061
+ return "";
7062
+ }
7063
+ async getSubmitRequestId(_submitRequestUrl) {
7064
+ console.warn("getSubmitRequestId() returning empty string");
7065
+ return "";
7066
+ }
7067
+ async getCommitUrl(_commitId) {
7068
+ console.warn("getCommitUrl() returning empty string");
7069
+ return "";
7070
+ }
7071
+ async _getUsernameForAuthUrl() {
7072
+ console.warn("_getUsernameForAuthUrl() returning empty string");
7073
+ return "";
7074
+ }
7075
+ async addCommentToSubmitRequest(_submitRequestId, _comment) {
7076
+ console.warn("addCommentToSubmitRequest() no-op");
7061
7077
  }
7062
7078
  };
7063
7079
 
7080
+ // src/features/analysis/scm/scmFactory.ts
7081
+ async function createScmLib({ url, accessToken, scmType, scmOrg }, { propagateExceptions = false } = {}) {
7082
+ const trimmedUrl = url ? url.trim().replace(/\/$/, "").replace(/.git$/i, "") : void 0;
7083
+ try {
7084
+ switch (scmType) {
7085
+ case "GITHUB" /* GITHUB */: {
7086
+ const scm = new GithubSCMLib(trimmedUrl, accessToken, scmOrg);
7087
+ await scm.validateParams();
7088
+ return scm;
7089
+ }
7090
+ case "GITLAB" /* GITLAB */: {
7091
+ const scm = new GitlabSCMLib(trimmedUrl, accessToken, scmOrg);
7092
+ await scm.validateParams();
7093
+ return scm;
7094
+ }
7095
+ case "ADO" /* ADO */: {
7096
+ const scm = new AdoSCMLib(trimmedUrl, accessToken, scmOrg);
7097
+ await scm.getAdoSdk();
7098
+ await scm.validateParams();
7099
+ return scm;
7100
+ }
7101
+ case "BITBUCKET" /* BITBUCKET */: {
7102
+ const scm = new BitbucketSCMLib(trimmedUrl, accessToken, scmOrg);
7103
+ await scm.validateParams();
7104
+ return scm;
7105
+ }
7106
+ }
7107
+ } catch (e) {
7108
+ if (e instanceof InvalidRepoUrlError && url) {
7109
+ throw new RepoNoTokenAccessError(
7110
+ "no access to repo",
7111
+ scmLibScmTypeToScmType[z24.nativeEnum(ScmLibScmType).parse(scmType)]
7112
+ );
7113
+ }
7114
+ console.error(`error validating scm: ${scmType} `, e);
7115
+ if (propagateExceptions) {
7116
+ throw e;
7117
+ }
7118
+ }
7119
+ return new StubSCMLib(trimmedUrl, void 0, void 0);
7120
+ }
7121
+
7064
7122
  // src/features/analysis/add_fix_comments_for_pr/utils/utils.ts
7065
7123
  import Debug7 from "debug";
7066
7124
  import parseDiff from "parse-diff";
@@ -7235,7 +7293,8 @@ function buildIssueCommentBody({
7235
7293
  projectId,
7236
7294
  analysisId,
7237
7295
  organizationId,
7238
- irrelevantIssueWithTags
7296
+ irrelevantIssueWithTags,
7297
+ fpDescription
7239
7298
  }) {
7240
7299
  const issueUrl = getIssueUrlWithRedirect({
7241
7300
  appBaseUrl: WEB_APP_URL,
@@ -7250,9 +7309,10 @@ function buildIssueCommentBody({
7250
7309
  const subTitle = getCommitIssueDescription({
7251
7310
  issueType,
7252
7311
  vendor: scannerToVulnerability_Report_Vendor_Enum[scanner],
7253
- irrelevantIssueWithTags
7312
+ irrelevantIssueWithTags,
7313
+ fpDescription
7254
7314
  });
7255
- const issuePageLink = `[Learn more and fine tune the issue](${issueUrl})`;
7315
+ const issuePageLink = `[Learn more about this issue](${issueUrl})`;
7256
7316
  return `${title}
7257
7317
  ${subTitle}
7258
7318
  ${issuePageLink}`;
@@ -7323,7 +7383,8 @@ async function postIssueComment(params) {
7323
7383
  scm,
7324
7384
  commitSha,
7325
7385
  pullRequest,
7326
- scanner
7386
+ scanner,
7387
+ fpDescription
7327
7388
  } = params;
7328
7389
  const {
7329
7390
  path: path8,
@@ -7354,7 +7415,8 @@ Refresh the page in order to see the changes.`,
7354
7415
  scanner,
7355
7416
  projectId,
7356
7417
  analysisId,
7357
- organizationId
7418
+ organizationId,
7419
+ fpDescription
7358
7420
  });
7359
7421
  return await scm.updatePrComment({
7360
7422
  body: commentBody,
@@ -7567,33 +7629,49 @@ async function addFixCommentsForPr({
7567
7629
  });
7568
7630
  }
7569
7631
  ),
7570
- ...irrelevantVulnerabilityReportIssues.map((vulnerabilityReportIssue) => {
7571
- return vulnerabilityReportIssue.codeNodes.map(
7572
- (vulnerabilityReportIssueCodeNode) => {
7573
- return postIssueComment({
7574
- vulnerabilityReportIssueCodeNode: {
7575
- path: vulnerabilityReportIssueCodeNode.path,
7576
- startLine: vulnerabilityReportIssueCodeNode.startLine,
7577
- vulnerabilityReportIssue: {
7578
- fixId: "",
7579
- safeIssueType: vulnerabilityReportIssue.safeIssueType,
7580
- vulnerabilityReportIssueTags: vulnerabilityReportIssue.vulnerabilityReportIssueTags,
7581
- category: vulnerabilityReportIssue.category
7582
- },
7583
- vulnerabilityReportIssueId: vulnerabilityReportIssue.id
7584
- },
7585
- projectId,
7586
- analysisId,
7587
- organizationId,
7588
- fixesById,
7589
- scm,
7590
- pullRequest,
7591
- scanner,
7592
- commitSha
7632
+ ...irrelevantVulnerabilityReportIssues.map(
7633
+ async (vulnerabilityReportIssue) => {
7634
+ let fpDescription = null;
7635
+ if (vulnerabilityReportIssue.fpId) {
7636
+ const fpRes = await gqlClient.getFalsePositive({
7637
+ fpId: vulnerabilityReportIssue.fpId
7593
7638
  });
7639
+ const parsedFpRes = await FalsePositivePartsZ.parseAsync(
7640
+ fpRes?.getFalsePositive
7641
+ );
7642
+ const { description, contextString } = getParsedFalsePositiveMessage(parsedFpRes);
7643
+ fpDescription = contextString ? `${description}
7644
+
7645
+ ${contextString}` : description;
7594
7646
  }
7595
- );
7596
- }),
7647
+ return vulnerabilityReportIssue.codeNodes.map(
7648
+ (vulnerabilityReportIssueCodeNode) => {
7649
+ return postIssueComment({
7650
+ vulnerabilityReportIssueCodeNode: {
7651
+ path: vulnerabilityReportIssueCodeNode.path,
7652
+ startLine: vulnerabilityReportIssueCodeNode.startLine,
7653
+ vulnerabilityReportIssue: {
7654
+ fixId: "",
7655
+ safeIssueType: vulnerabilityReportIssue.safeIssueType,
7656
+ vulnerabilityReportIssueTags: vulnerabilityReportIssue.vulnerabilityReportIssueTags,
7657
+ category: vulnerabilityReportIssue.category
7658
+ },
7659
+ vulnerabilityReportIssueId: vulnerabilityReportIssue.id
7660
+ },
7661
+ projectId,
7662
+ analysisId,
7663
+ organizationId,
7664
+ fixesById,
7665
+ scm,
7666
+ pullRequest,
7667
+ scanner,
7668
+ commitSha,
7669
+ fpDescription
7670
+ });
7671
+ }
7672
+ );
7673
+ }
7674
+ ),
7597
7675
  postAnalysisInsightComment({
7598
7676
  prVulenrabilities,
7599
7677
  pullRequest,
@@ -7699,20 +7777,24 @@ async function getGitInfo(srcDirPath) {
7699
7777
 
7700
7778
  // src/features/analysis/graphql/gql.ts
7701
7779
  import fetchOrig from "cross-fetch";
7702
- import Debug11 from "debug";
7780
+ import Debug12 from "debug";
7703
7781
  import { GraphQLClient } from "graphql-request";
7704
- import { HttpProxyAgent as HttpProxyAgent2 } from "http-proxy-agent";
7782
+ import { HttpProxyAgent } from "http-proxy-agent";
7705
7783
  import { HttpsProxyAgent as HttpsProxyAgent2 } from "https-proxy-agent";
7706
7784
  import { v4 as uuidv4 } from "uuid";
7707
7785
 
7708
7786
  // src/features/analysis/graphql/subscribe.ts
7787
+ import Debug11 from "debug";
7709
7788
  import { createClient } from "graphql-ws";
7710
- import { HttpProxyAgent } from "http-proxy-agent";
7711
7789
  import { HttpsProxyAgent } from "https-proxy-agent";
7712
7790
  import WebSocket from "ws";
7791
+ var debug11 = Debug11("mobbdev:subscribe");
7713
7792
  var SUBSCRIPTION_TIMEOUT_MS = 30 * 60 * 1e3;
7714
7793
  function createWSClient(options) {
7715
- const proxy = options.url.startsWith("https://") && process.env["HTTPS_PROXY"] ? new HttpsProxyAgent(process.env["HTTPS_PROXY"]) : options.url.startsWith("http://") && process.env["HTTP_PROXY"] ? new HttpProxyAgent(process.env["HTTP_PROXY"]) : null;
7794
+ const proxy = options.url.startsWith("wss://") && process.env["HTTPS_PROXY"] ? new HttpsProxyAgent(process.env["HTTPS_PROXY"]) : options.url.startsWith("ws://") && process.env["HTTP_PROXY"] ? new HttpsProxyAgent(process.env["HTTP_PROXY"]) : null;
7795
+ debug11(
7796
+ `Using proxy: ${proxy ? "yes" : "no"} with url: ${options.url} and with proxy: ${process.env["HTTP_PROXY"]} for the websocket connection`
7797
+ );
7716
7798
  const CustomWebSocket = class extends WebSocket {
7717
7799
  constructor(address, protocols) {
7718
7800
  super(address, protocols, proxy ? { agent: proxy } : void 0);
@@ -7820,6 +7902,7 @@ var VulnerabilityReportIssueNoFixCodeNodeZ = z27.object({
7820
7902
  fixId: z27.string().nullable(),
7821
7903
  category: ValidCategoriesZ,
7822
7904
  safeIssueType: z27.string(),
7905
+ fpId: z27.string().uuid().nullable(),
7823
7906
  codeNodes: z27.array(
7824
7907
  z27.object({
7825
7908
  path: z27.string(),
@@ -7857,7 +7940,7 @@ var GetVulByNodesMetadataZ = z27.object({
7857
7940
  });
7858
7941
 
7859
7942
  // src/features/analysis/graphql/gql.ts
7860
- var debug11 = Debug11("mobbdev:gql");
7943
+ var debug12 = Debug12("mobbdev:gql");
7861
7944
  var API_KEY_HEADER_NAME = "x-mobb-key";
7862
7945
  var REPORT_STATE_CHECK_DELAY = 5 * 1e3;
7863
7946
  function getProxyAgent(url) {
@@ -7867,12 +7950,12 @@ function getProxyAgent(url) {
7867
7950
  const isHttps = parsedUrl.protocol === "https:";
7868
7951
  const proxy = isHttps ? HTTPS_PROXY : isHttp ? HTTP_PROXY : null;
7869
7952
  if (proxy) {
7870
- debug11("Using proxy %s", proxy);
7871
- debug11("Proxy agent %o", proxy);
7872
- return isHttps ? new HttpsProxyAgent2(proxy) : new HttpProxyAgent2(proxy);
7953
+ debug12("Using proxy %s", proxy);
7954
+ debug12("Proxy agent %o", proxy);
7955
+ return isHttps ? new HttpsProxyAgent2(proxy) : new HttpProxyAgent(proxy);
7873
7956
  }
7874
7957
  } catch (err) {
7875
- debug11(`Skipping proxy for ${url}. Reason: ${err.message}`);
7958
+ debug12(`Skipping proxy for ${url}. Reason: ${err.message}`);
7876
7959
  }
7877
7960
  return void 0;
7878
7961
  }
@@ -7887,7 +7970,7 @@ var fetchWithProxy = (url, options = {}) => {
7887
7970
  });
7888
7971
  }
7889
7972
  } catch (err) {
7890
- debug11(`Skipping proxy for ${url}. Reason: ${err.message}`);
7973
+ debug12(`Skipping proxy for ${url}. Reason: ${err.message}`);
7891
7974
  }
7892
7975
  return fetchOrig(url, options);
7893
7976
  };
@@ -7896,7 +7979,7 @@ var GQLClient = class {
7896
7979
  __publicField(this, "_client");
7897
7980
  __publicField(this, "_clientSdk");
7898
7981
  __publicField(this, "_auth");
7899
- debug11(`init with ${args}`);
7982
+ debug12(`init with ${args}`);
7900
7983
  this._auth = args;
7901
7984
  this._client = new GraphQLClient(API_URL, {
7902
7985
  headers: args.type === "apiKey" ? { [API_KEY_HEADER_NAME]: args.apiKey || "" } : {
@@ -7905,7 +7988,7 @@ var GQLClient = class {
7905
7988
  fetch: fetchWithProxy,
7906
7989
  requestMiddleware: (request) => {
7907
7990
  const requestId = uuidv4();
7908
- debug11(
7991
+ debug12(
7909
7992
  `sending API request with id: ${requestId} and with request: ${request.body}`
7910
7993
  );
7911
7994
  return {
@@ -7935,7 +8018,7 @@ var GQLClient = class {
7935
8018
  await this.getUserInfo();
7936
8019
  } catch (e) {
7937
8020
  if (e?.toString().startsWith("FetchError")) {
7938
- debug11("verify connection failed %o", e);
8021
+ debug12("verify connection failed %o", e);
7939
8022
  return false;
7940
8023
  }
7941
8024
  }
@@ -7947,7 +8030,7 @@ var GQLClient = class {
7947
8030
  try {
7948
8031
  info = await this.getUserInfo();
7949
8032
  } catch (e) {
7950
- debug11("verify token failed %o", e);
8033
+ debug12("verify token failed %o", e);
7951
8034
  return false;
7952
8035
  }
7953
8036
  return info?.email || true;
@@ -7991,7 +8074,7 @@ var GQLClient = class {
7991
8074
  try {
7992
8075
  await this._clientSdk.CreateCommunityUser();
7993
8076
  } catch (e) {
7994
- debug11("create community user failed %o", e);
8077
+ debug12("create community user failed %o", e);
7995
8078
  }
7996
8079
  }
7997
8080
  async updateScmToken(args) {
@@ -8183,19 +8266,22 @@ var GQLClient = class {
8183
8266
  async getReferenceData(args) {
8184
8267
  return this._clientSdk.gitReference(args);
8185
8268
  }
8269
+ async getFalsePositive(args) {
8270
+ return this._clientSdk.getFalsePositive(args);
8271
+ }
8186
8272
  };
8187
8273
 
8188
8274
  // src/features/analysis/pack.ts
8189
8275
  import fs2 from "node:fs";
8190
8276
  import path4 from "node:path";
8191
8277
  import AdmZip from "adm-zip";
8192
- import Debug12 from "debug";
8278
+ import Debug13 from "debug";
8193
8279
  import { globby } from "globby";
8194
8280
  import { isBinary } from "istextorbinary";
8195
8281
  import { simpleGit as simpleGit3 } from "simple-git";
8196
8282
  import { parseStringPromise } from "xml2js";
8197
8283
  import { z as z28 } from "zod";
8198
- var debug12 = Debug12("mobbdev:pack");
8284
+ var debug13 = Debug13("mobbdev:pack");
8199
8285
  var MAX_FILE_SIZE = 1024 * 1024 * 5;
8200
8286
  var FPR_SOURCE_CODE_FILE_MAPPING_SCHEMA = z28.object({
8201
8287
  properties: z28.object({
@@ -8218,7 +8304,7 @@ function _get_manifest_files_suffixes() {
8218
8304
  return ["package.json", "pom.xml"];
8219
8305
  }
8220
8306
  async function pack(srcDirPath, vulnFiles) {
8221
- debug12("pack folder %s", srcDirPath);
8307
+ debug13("pack folder %s", srcDirPath);
8222
8308
  let git = void 0;
8223
8309
  try {
8224
8310
  git = simpleGit3({
@@ -8228,13 +8314,13 @@ async function pack(srcDirPath, vulnFiles) {
8228
8314
  });
8229
8315
  await git.status();
8230
8316
  } catch (e) {
8231
- debug12("failed to run git %o", e);
8317
+ debug13("failed to run git %o", e);
8232
8318
  git = void 0;
8233
8319
  if (e instanceof Error) {
8234
8320
  if (e.message.includes(" spawn ")) {
8235
- debug12("git cli not installed");
8321
+ debug13("git cli not installed");
8236
8322
  } else if (e.message.includes("not a git repository")) {
8237
- debug12("folder is not a git repo");
8323
+ debug13("folder is not a git repo");
8238
8324
  } else {
8239
8325
  throw e;
8240
8326
  }
@@ -8249,9 +8335,9 @@ async function pack(srcDirPath, vulnFiles) {
8249
8335
  followSymbolicLinks: false,
8250
8336
  dot: true
8251
8337
  });
8252
- debug12("files found %d", filepaths.length);
8338
+ debug13("files found %d", filepaths.length);
8253
8339
  const zip = new AdmZip();
8254
- debug12("compressing files");
8340
+ debug13("compressing files");
8255
8341
  for (const filepath of filepaths) {
8256
8342
  const absFilepath = path4.join(srcDirPath, filepath.toString());
8257
8343
  vulnFiles = vulnFiles.concat(_get_manifest_files_suffixes());
@@ -8259,25 +8345,25 @@ async function pack(srcDirPath, vulnFiles) {
8259
8345
  absFilepath.toString().replaceAll(path4.win32.sep, path4.posix.sep),
8260
8346
  vulnFiles
8261
8347
  )) {
8262
- debug12("ignoring %s because it is not a vulnerability file", filepath);
8348
+ debug13("ignoring %s because it is not a vulnerability file", filepath);
8263
8349
  continue;
8264
8350
  }
8265
8351
  if (fs2.lstatSync(absFilepath).size > MAX_FILE_SIZE) {
8266
- debug12("ignoring %s because the size is > 5MB", filepath);
8352
+ debug13("ignoring %s because the size is > 5MB", filepath);
8267
8353
  continue;
8268
8354
  }
8269
8355
  const data = git ? await git.showBuffer([`HEAD:./${filepath}`]) : fs2.readFileSync(absFilepath);
8270
8356
  if (isBinary(null, data)) {
8271
- debug12("ignoring %s because is seems to be a binary file", filepath);
8357
+ debug13("ignoring %s because is seems to be a binary file", filepath);
8272
8358
  continue;
8273
8359
  }
8274
8360
  zip.addFile(filepath.toString(), data);
8275
8361
  }
8276
- debug12("get zip file buffer");
8362
+ debug13("get zip file buffer");
8277
8363
  return zip.toBuffer();
8278
8364
  }
8279
8365
  async function repackFpr(fprPath) {
8280
- debug12("repack fpr file %s", fprPath);
8366
+ debug13("repack fpr file %s", fprPath);
8281
8367
  const zipIn = new AdmZip(fprPath);
8282
8368
  const zipOut = new AdmZip();
8283
8369
  const mappingXML = zipIn.readAsText("src-archive/index.xml", "utf-8");
@@ -8292,7 +8378,7 @@ async function repackFpr(fprPath) {
8292
8378
  zipOut.addFile(realPath, buf);
8293
8379
  }
8294
8380
  }
8295
- debug12("get repacked zip file buffer");
8381
+ debug13("get repacked zip file buffer");
8296
8382
  return zipOut.toBuffer();
8297
8383
  }
8298
8384
 
@@ -8369,7 +8455,7 @@ var cxOperatingSystemSupportMessage = `Your operating system does not support ch
8369
8455
 
8370
8456
  // src/utils/child_process.ts
8371
8457
  import cp from "node:child_process";
8372
- import Debug13 from "debug";
8458
+ import Debug14 from "debug";
8373
8459
  import * as process2 from "process";
8374
8460
  import supportsColor from "supports-color";
8375
8461
  var { stdout: stdout2 } = supportsColor;
@@ -8388,16 +8474,16 @@ function createSpwan({ args, processPath, name }, options) {
8388
8474
  return createChildProcess({ childProcess: child, name }, options);
8389
8475
  }
8390
8476
  function createChildProcess({ childProcess, name }, options) {
8391
- const debug19 = Debug13(`mobbdev:${name}`);
8477
+ const debug20 = Debug14(`mobbdev:${name}`);
8392
8478
  const { display } = options;
8393
8479
  return new Promise((resolve, reject) => {
8394
8480
  let out = "";
8395
8481
  const onData = (chunk) => {
8396
- debug19(`chunk received from ${name} std ${chunk}`);
8482
+ debug20(`chunk received from ${name} std ${chunk}`);
8397
8483
  out += chunk;
8398
8484
  };
8399
8485
  if (!childProcess || !childProcess?.stdout || !childProcess?.stderr) {
8400
- debug19(`unable to fork ${name}`);
8486
+ debug20(`unable to fork ${name}`);
8401
8487
  reject(new Error(`unable to fork ${name}`));
8402
8488
  }
8403
8489
  childProcess.stdout?.on("data", onData);
@@ -8407,11 +8493,11 @@ function createChildProcess({ childProcess, name }, options) {
8407
8493
  childProcess.stderr?.pipe(process2.stderr);
8408
8494
  }
8409
8495
  childProcess.on("exit", (code) => {
8410
- debug19(`${name} exit code ${code}`);
8496
+ debug20(`${name} exit code ${code}`);
8411
8497
  resolve({ message: out, code });
8412
8498
  });
8413
8499
  childProcess.on("error", (err) => {
8414
- debug19(`${name} error %o`, err);
8500
+ debug20(`${name} error %o`, err);
8415
8501
  reject(err);
8416
8502
  });
8417
8503
  });
@@ -8419,12 +8505,12 @@ function createChildProcess({ childProcess, name }, options) {
8419
8505
 
8420
8506
  // src/features/analysis/scanners/checkmarx.ts
8421
8507
  import chalk2 from "chalk";
8422
- import Debug14 from "debug";
8508
+ import Debug15 from "debug";
8423
8509
  import { existsSync } from "fs";
8424
8510
  import { createSpinner as createSpinner2 } from "nanospinner";
8425
8511
  import { type } from "os";
8426
8512
  import path5 from "path";
8427
- var debug13 = Debug14("mobbdev:checkmarx");
8513
+ var debug14 = Debug15("mobbdev:checkmarx");
8428
8514
  var require2 = createRequire(import.meta.url);
8429
8515
  var getCheckmarxPath = () => {
8430
8516
  const os2 = type();
@@ -8465,14 +8551,14 @@ function validateCheckmarxInstallation() {
8465
8551
  existsSync(getCheckmarxPath());
8466
8552
  }
8467
8553
  async function forkCheckmarx(args, { display }) {
8468
- debug13("fork checkmarx with args %o %s", args.join(" "), display);
8554
+ debug14("fork checkmarx with args %o %s", args.join(" "), display);
8469
8555
  return createSpwan(
8470
8556
  { args, processPath: getCheckmarxPath(), name: "checkmarx" },
8471
8557
  { display }
8472
8558
  );
8473
8559
  }
8474
8560
  async function getCheckmarxReport({ reportPath, repositoryRoot, branch, projectName }, { skipPrompts = false }) {
8475
- debug13("get checkmarx report start %s %s", reportPath, repositoryRoot);
8561
+ debug14("get checkmarx report start %s %s", reportPath, repositoryRoot);
8476
8562
  const { code: loginCode } = await forkCheckmarx(VALIDATE_COMMAND, {
8477
8563
  display: false
8478
8564
  });
@@ -8540,20 +8626,20 @@ async function validateCheckamxCredentials() {
8540
8626
  // src/features/analysis/scanners/snyk.ts
8541
8627
  import { createRequire as createRequire2 } from "node:module";
8542
8628
  import chalk3 from "chalk";
8543
- import Debug15 from "debug";
8629
+ import Debug16 from "debug";
8544
8630
  import { createSpinner as createSpinner3 } from "nanospinner";
8545
8631
  import open from "open";
8546
- var debug14 = Debug15("mobbdev:snyk");
8632
+ var debug15 = Debug16("mobbdev:snyk");
8547
8633
  var require3 = createRequire2(import.meta.url);
8548
8634
  var SNYK_PATH = require3.resolve("snyk/bin/snyk");
8549
8635
  var SNYK_ARTICLE_URL = "https://docs.snyk.io/scan-using-snyk/snyk-code/configure-snyk-code#enable-snyk-code";
8550
- debug14("snyk executable path %s", SNYK_PATH);
8636
+ debug15("snyk executable path %s", SNYK_PATH);
8551
8637
  async function forkSnyk(args, { display }) {
8552
- debug14("fork snyk with args %o %s", args, display);
8638
+ debug15("fork snyk with args %o %s", args, display);
8553
8639
  return createFork({ args, processPath: SNYK_PATH, name: "snyk" }, { display });
8554
8640
  }
8555
8641
  async function getSnykReport(reportPath, repoRoot, { skipPrompts = false }) {
8556
- debug14("get snyk report start %s %s", reportPath, repoRoot);
8642
+ debug15("get snyk report start %s %s", reportPath, repoRoot);
8557
8643
  const config4 = await forkSnyk(["config"], { display: false });
8558
8644
  const { message: configMessage } = config4;
8559
8645
  if (!configMessage.includes("api: ")) {
@@ -8567,7 +8653,7 @@ async function getSnykReport(reportPath, repoRoot, { skipPrompts = false }) {
8567
8653
  snykLoginSpinner.update({
8568
8654
  text: "\u{1F513} Waiting for Snyk login to complete"
8569
8655
  });
8570
- debug14("no token in the config %s", config4);
8656
+ debug15("no token in the config %s", config4);
8571
8657
  await forkSnyk(["auth"], { display: true });
8572
8658
  snykLoginSpinner.success({ text: "\u{1F513} Login to Snyk Successful" });
8573
8659
  }
@@ -8577,12 +8663,12 @@ async function getSnykReport(reportPath, repoRoot, { skipPrompts = false }) {
8577
8663
  { display: true }
8578
8664
  );
8579
8665
  if (scanOutput.includes("Snyk Code is not supported for org")) {
8580
- debug14("snyk code is not enabled %s", scanOutput);
8666
+ debug15("snyk code is not enabled %s", scanOutput);
8581
8667
  snykSpinner.error({ text: "\u{1F50D} Snyk configuration needed" });
8582
8668
  const answer = await snykArticlePrompt();
8583
- debug14("answer %s", answer);
8669
+ debug15("answer %s", answer);
8584
8670
  if (answer) {
8585
- debug14("opening the browser");
8671
+ debug15("opening the browser");
8586
8672
  await open(SNYK_ARTICLE_URL);
8587
8673
  }
8588
8674
  console.log(
@@ -8597,18 +8683,18 @@ async function getSnykReport(reportPath, repoRoot, { skipPrompts = false }) {
8597
8683
  }
8598
8684
 
8599
8685
  // src/features/analysis/upload-file.ts
8600
- import Debug16 from "debug";
8686
+ import Debug17 from "debug";
8601
8687
  import fetch3, { File, fileFrom, FormData } from "node-fetch";
8602
- var debug15 = Debug16("mobbdev:upload-file");
8688
+ var debug16 = Debug17("mobbdev:upload-file");
8603
8689
  async function uploadFile({
8604
8690
  file,
8605
8691
  url,
8606
8692
  uploadKey,
8607
8693
  uploadFields
8608
8694
  }) {
8609
- debug15("upload file start %s", url);
8610
- debug15("upload fields %o", uploadFields);
8611
- debug15("upload key %s", uploadKey);
8695
+ debug16("upload file start %s", url);
8696
+ debug16("upload fields %o", uploadFields);
8697
+ debug16("upload key %s", uploadKey);
8612
8698
  const form = new FormData();
8613
8699
  Object.entries(uploadFields).forEach(([key, value]) => {
8614
8700
  form.append(key, value);
@@ -8617,10 +8703,10 @@ async function uploadFile({
8617
8703
  form.append("key", uploadKey);
8618
8704
  }
8619
8705
  if (typeof file === "string") {
8620
- debug15("upload file from path %s", file);
8706
+ debug16("upload file from path %s", file);
8621
8707
  form.append("file", await fileFrom(file));
8622
8708
  } else {
8623
- debug15("upload file from buffer");
8709
+ debug16("upload file from buffer");
8624
8710
  form.append("file", new File([file], "file"));
8625
8711
  }
8626
8712
  const agent = getProxyAgent(url);
@@ -8630,10 +8716,10 @@ async function uploadFile({
8630
8716
  agent
8631
8717
  });
8632
8718
  if (!response.ok) {
8633
- debug15("error from S3 %s %s", response.body, response.status);
8719
+ debug16("error from S3 %s %s", response.body, response.status);
8634
8720
  throw new Error(`Failed to upload the file: ${response.status}`);
8635
8721
  }
8636
- debug15("upload file done");
8722
+ debug16("upload file done");
8637
8723
  }
8638
8724
 
8639
8725
  // src/features/analysis/index.ts
@@ -8667,9 +8753,9 @@ async function downloadRepo({
8667
8753
  }) {
8668
8754
  const { createSpinner: createSpinner5 } = Spinner2({ ci });
8669
8755
  const repoSpinner = createSpinner5("\u{1F4BE} Downloading Repo").start();
8670
- debug16("download repo %s %s %s", repoUrl, dirname);
8756
+ debug17("download repo %s %s %s", repoUrl, dirname);
8671
8757
  const zipFilePath = path6.join(dirname, "repo.zip");
8672
- debug16("download URL: %s auth headers: %o", downloadUrl, authHeaders);
8758
+ debug17("download URL: %s auth headers: %o", downloadUrl, authHeaders);
8673
8759
  const response = await fetch4(downloadUrl, {
8674
8760
  method: "GET",
8675
8761
  headers: {
@@ -8677,7 +8763,7 @@ async function downloadRepo({
8677
8763
  }
8678
8764
  });
8679
8765
  if (!response.ok) {
8680
- debug16("SCM zipball request failed %s %s", response.body, response.status);
8766
+ debug17("SCM zipball request failed %s %s", response.body, response.status);
8681
8767
  repoSpinner.error({ text: "\u{1F4BE} Repo download failed" });
8682
8768
  throw new Error(`Can't access ${chalk4.bold(repoUrl)}`);
8683
8769
  }
@@ -8691,7 +8777,7 @@ async function downloadRepo({
8691
8777
  if (!repoRoot) {
8692
8778
  throw new Error("Repo root not found");
8693
8779
  }
8694
- debug16("repo root %s", repoRoot);
8780
+ debug17("repo root %s", repoRoot);
8695
8781
  repoSpinner.success({ text: "\u{1F4BE} Repo downloaded successfully" });
8696
8782
  return path6.join(dirname, repoRoot);
8697
8783
  }
@@ -8700,9 +8786,9 @@ var getReportUrl = ({
8700
8786
  projectId,
8701
8787
  fixReportId
8702
8788
  }) => `${WEB_APP_URL}/organization/${organizationId}/project/${projectId}/report/${fixReportId}`;
8703
- var debug16 = Debug17("mobbdev:index");
8789
+ var debug17 = Debug18("mobbdev:index");
8704
8790
  var config2 = new Configstore(packageJson.name, { apiToken: "" });
8705
- debug16("config %o", config2);
8791
+ debug17("config %o", config2);
8706
8792
  async function runAnalysis(params, options) {
8707
8793
  const tmpObj = tmp.dirSync({
8708
8794
  unsafeCleanup: true
@@ -8846,7 +8932,7 @@ async function _scan(params, { skipPrompts = false } = {}) {
8846
8932
  commitDirectly,
8847
8933
  pullRequest
8848
8934
  } = params;
8849
- debug16("start %s %s", dirname, repo);
8935
+ debug17("start %s %s", dirname, repo);
8850
8936
  const { createSpinner: createSpinner5 } = Spinner2({ ci });
8851
8937
  skipPrompts = skipPrompts || ci;
8852
8938
  let gqlClient = new GQLClient({
@@ -8917,8 +9003,8 @@ async function _scan(params, { skipPrompts = false } = {}) {
8917
9003
  );
8918
9004
  }
8919
9005
  const { sha } = getReferenceDataRes.gitReference;
8920
- debug16("project id %s", projectId);
8921
- debug16("default branch %s", reference);
9006
+ debug17("project id %s", projectId);
9007
+ debug17("default branch %s", reference);
8922
9008
  if (command === "scan") {
8923
9009
  reportPath = await getReport(
8924
9010
  {
@@ -9247,9 +9333,9 @@ async function waitForAnaysisAndReviewPr({
9247
9333
  import chalk5 from "chalk";
9248
9334
  import chalkAnimation from "chalk-animation";
9249
9335
  import Configstore2 from "configstore";
9250
- import Debug18 from "debug";
9336
+ import Debug19 from "debug";
9251
9337
  import open3 from "open";
9252
- var debug17 = Debug18("mobbdev:commands");
9338
+ var debug18 = Debug19("mobbdev:commands");
9253
9339
  async function review(params, { skipPrompts = true } = {}) {
9254
9340
  const {
9255
9341
  repo,
@@ -9438,9 +9524,9 @@ async function handleMobbLogin({
9438
9524
  });
9439
9525
  loginSpinner.spin();
9440
9526
  if (encryptedApiToken) {
9441
- debug17("encrypted API token received %s", encryptedApiToken);
9527
+ debug18("encrypted API token received %s", encryptedApiToken);
9442
9528
  newApiToken = crypto.privateDecrypt(privateKey, Buffer.from(encryptedApiToken, "base64")).toString("utf-8");
9443
- debug17("API token decrypted");
9529
+ debug18("API token decrypted");
9444
9530
  break;
9445
9531
  }
9446
9532
  await sleep(LOGIN_CHECK_DELAY);
@@ -9454,7 +9540,7 @@ async function handleMobbLogin({
9454
9540
  const newGqlClient = new GQLClient({ apiKey: newApiToken, type: "apiKey" });
9455
9541
  const loginSuccess = await newGqlClient.verifyToken();
9456
9542
  if (loginSuccess) {
9457
- debug17("set api token %s", newApiToken);
9543
+ debug18("set api token %s", newApiToken);
9458
9544
  config3.set("apiToken", newApiToken);
9459
9545
  loginSpinner.success({
9460
9546
  text: `\u{1F513} Login to Mobb successful! ${typeof loginSpinner === "string" ? `Logged in as ${loginSuccess}` : ""}`
@@ -9849,13 +9935,13 @@ var parseArgs = async (args) => {
9849
9935
  };
9850
9936
 
9851
9937
  // src/index.ts
9852
- var debug18 = Debug19("mobbdev:index");
9938
+ var debug19 = Debug20("mobbdev:index");
9853
9939
  async function run() {
9854
9940
  return parseArgs(hideBin(process.argv));
9855
9941
  }
9856
9942
  (async () => {
9857
9943
  try {
9858
- debug18("Bugsy CLI v%s running...", packageJson.version);
9944
+ debug19("Bugsy CLI v%s running...", packageJson.version);
9859
9945
  await run();
9860
9946
  process.exit(0);
9861
9947
  } catch (err) {