mobbdev 0.0.83 → 0.0.85

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 +599 -162
  2. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -94,8 +94,8 @@ var errorMessages = {
94
94
  missingCxProjectName: `project name ${chalk.bold(
95
95
  "(--cx-project-name)"
96
96
  )} is needed if you're using checkmarx`,
97
- missingScmType: `SCM type ${chalk.bold(
98
- "(--scm-type)"
97
+ missingUrl: `url ${chalk.bold(
98
+ "(--url)"
99
99
  )} is needed if you're adding an SCM token`,
100
100
  invalidScmType: `SCM type ${chalk.bold(
101
101
  "(--scm-type)"
@@ -173,7 +173,6 @@ var CliError = class extends Error {
173
173
  };
174
174
 
175
175
  // src/features/analysis/index.ts
176
- import { Octokit as Octokit3 } from "@octokit/core";
177
176
  import chalk4 from "chalk";
178
177
  import Configstore from "configstore";
179
178
  import Debug10 from "debug";
@@ -237,23 +236,33 @@ import { v4 as uuidv4 } from "uuid";
237
236
  import { gql } from "graphql-request";
238
237
  var UPDATE_SCM_TOKEN = gql`
239
238
  mutation updateScmToken(
240
- $type: ScmType!
239
+ $scmType: String!
240
+ $url: String!
241
241
  $token: String!
242
242
  $org: String
243
243
  $username: String
244
244
  $refreshToken: String
245
245
  ) {
246
246
  updateScmToken(
247
- type: $type
247
+ scmType: $scmType
248
+ url: $url
248
249
  token: $token
249
250
  org: $org
250
251
  username: $username
251
252
  refreshToken: $refreshToken
252
253
  ) {
253
- id
254
- adoAccessToken
255
- gitlabAccessToken
256
- gitHubAccessToken
254
+ __typename
255
+ ... on ScmAccessTokenUpdateSuccess {
256
+ token
257
+ }
258
+ ... on InvalidScmTypeError {
259
+ status
260
+ error
261
+ }
262
+ ... on BadScmCredentials {
263
+ status
264
+ error
265
+ }
257
266
  }
258
267
  }
259
268
  `;
@@ -368,10 +377,20 @@ var ME = gql2`
368
377
  me {
369
378
  id
370
379
  email
371
- githubToken
372
- gitlabToken
373
- adoToken
374
- adoOrg
380
+ scmConfigs {
381
+ id
382
+ isBroker
383
+ orgId
384
+ refreshToken
385
+ scmType
386
+ scmUrl
387
+ scmUsername
388
+ token
389
+ tokenLastUpdate
390
+ userId
391
+ scmOrg
392
+ isTokenAvailable
393
+ }
375
394
  }
376
395
  }
377
396
  `;
@@ -456,6 +475,17 @@ var GET_FIX = gql2`
456
475
  }
457
476
  }
458
477
  `;
478
+ var GET_FIXES = gql2`
479
+ query getFixes($filters: fix_bool_exp!) {
480
+ fixes: fix(where: $filters) {
481
+ issueType
482
+ id
483
+ patchAndQuestions {
484
+ patch
485
+ }
486
+ }
487
+ }
488
+ `;
459
489
  var GET_VUL_BY_NODES_METADATA = gql2`
460
490
  query getVulByNodesMetadata(
461
491
  $filters: [vulnerability_report_issue_code_node_bool_exp!]
@@ -466,6 +496,7 @@ var GET_VUL_BY_NODES_METADATA = gql2`
466
496
  where: {
467
497
  _or: $filters
468
498
  vulnerabilityReportIssue: {
499
+ fixId: { _is_null: false }
469
500
  vulnerabilityReportId: { _eq: $vulnerabilityReportId }
470
501
  }
471
502
  }
@@ -478,6 +509,35 @@ var GET_VUL_BY_NODES_METADATA = gql2`
478
509
  fixId
479
510
  }
480
511
  }
512
+ fixablePrVuls: vulnerability_report_issue_aggregate(
513
+ where: {
514
+ fixId: { _is_null: false }
515
+ vulnerabilityReportId: { _eq: $vulnerabilityReportId }
516
+ codeNodes: { _or: $filters }
517
+ }
518
+ ) {
519
+ aggregate {
520
+ count
521
+ }
522
+ }
523
+ nonFixablePrVuls: vulnerability_report_issue_aggregate(
524
+ where: {
525
+ fixId: { _is_null: true }
526
+ vulnerabilityReportId: { _eq: $vulnerabilityReportId }
527
+ codeNodes: { _or: $filters }
528
+ }
529
+ ) {
530
+ aggregate {
531
+ count
532
+ }
533
+ }
534
+ totalScanVulnerabilities: vulnerability_report_issue_aggregate(
535
+ where: { vulnerabilityReportId: { _eq: $vulnerabilityReportId } }
536
+ ) {
537
+ aggregate {
538
+ count
539
+ }
540
+ }
481
541
  }
482
542
  `;
483
543
 
@@ -565,10 +625,7 @@ function subscribe(query, variables, callback, wsClientOptions) {
565
625
  import { z as z2 } from "zod";
566
626
  var UpdateScmTokenZ = z2.object({
567
627
  updateScmToken: z2.object({
568
- id: z2.string(),
569
- gitHubAccessToken: z2.string().nullable(),
570
- gitlabAccessToken: z2.string().nullable(),
571
- adoAccessToken: z2.string().nullable()
628
+ token: z2.string()
572
629
  })
573
630
  });
574
631
  var UploadFieldsZ = z2.object({
@@ -694,15 +751,17 @@ var GetAnalysisQueryZ = z2.object({
694
751
  })
695
752
  })
696
753
  });
697
- var GetFixQueryZ = z2.object({
698
- fix_by_pk: z2.object({
699
- issueType: z2.string(),
700
- id: z2.string(),
701
- patchAndQuestions: z2.object({
702
- patch: z2.string()
703
- })
754
+ var FixDataZ = z2.object({
755
+ issueType: z2.string(),
756
+ id: z2.string(),
757
+ patchAndQuestions: z2.object({
758
+ patch: z2.string()
704
759
  })
705
760
  });
761
+ var GetFixQueryZ = z2.object({
762
+ fix_by_pk: FixDataZ
763
+ });
764
+ var GetFixesQueryZ = z2.object({ fixes: z2.array(FixDataZ) });
706
765
  var VulnerabilityReportIssueCodeNodeZ = z2.object({
707
766
  vulnerabilityReportIssueId: z2.string(),
708
767
  path: z2.string(),
@@ -712,7 +771,22 @@ var VulnerabilityReportIssueCodeNodeZ = z2.object({
712
771
  })
713
772
  });
714
773
  var GetVulByNodesMetadataZ = z2.object({
715
- vulnerabilityReportIssueCodeNodes: z2.array(VulnerabilityReportIssueCodeNodeZ)
774
+ vulnerabilityReportIssueCodeNodes: z2.array(VulnerabilityReportIssueCodeNodeZ),
775
+ nonFixablePrVuls: z2.object({
776
+ aggregate: z2.object({
777
+ count: z2.number()
778
+ })
779
+ }),
780
+ fixablePrVuls: z2.object({
781
+ aggregate: z2.object({
782
+ count: z2.number()
783
+ })
784
+ }),
785
+ totalScanVulnerabilities: z2.object({
786
+ aggregate: z2.object({
787
+ count: z2.number()
788
+ })
789
+ })
716
790
  });
717
791
 
718
792
  // src/features/analysis/graphql/gql.ts
@@ -803,9 +877,10 @@ var GQLClient = class {
803
877
  }
804
878
  }
805
879
  async updateScmToken(args) {
806
- const { type: type2, token, org, username, refreshToken } = args;
880
+ const { scmType, url, token, org, username, refreshToken } = args;
807
881
  const updateScmTokenResult = await this._client.request(UPDATE_SCM_TOKEN, {
808
- type: type2,
882
+ scmType,
883
+ url,
809
884
  token,
810
885
  org,
811
886
  username,
@@ -826,7 +901,6 @@ var GQLClient = class {
826
901
  const filters = hunks.map((hunk) => {
827
902
  const filter = {
828
903
  path: { _eq: hunk.path },
829
- vulnerabilityReportIssue: { fixId: { _is_null: false } },
830
904
  _or: hunk.ranges.map(({ endLine, startLine }) => ({
831
905
  startLine: { _gte: startLine, _lte: endLine },
832
906
  endLine: { _gte: startLine, _lte: endLine }
@@ -850,10 +924,20 @@ var GQLClient = class {
850
924
  [vulnerabilityReportIssueCodeNode.vulnerabilityReportIssueId]: vulnerabilityReportIssueCodeNode
851
925
  };
852
926
  }, {});
927
+ const nonFixablePrVuls = parsedGetVulByNodesMetadataRes.nonFixablePrVuls.aggregate.count;
928
+ const fixablePrVuls = parsedGetVulByNodesMetadataRes.fixablePrVuls.aggregate.count;
929
+ const totalScanVulnerabilities = parsedGetVulByNodesMetadataRes.totalScanVulnerabilities.aggregate.count;
930
+ const vulnerabilitiesOutsidePr = totalScanVulnerabilities - nonFixablePrVuls - fixablePrVuls;
931
+ const totalPrVulnerabilities = nonFixablePrVuls + fixablePrVuls;
853
932
  return {
854
933
  vulnerabilityReportIssueCodeNodes: Object.values(
855
934
  uniqueVulByNodesMetadata
856
- )
935
+ ),
936
+ nonFixablePrVuls,
937
+ fixablePrVuls,
938
+ totalScanVulnerabilities,
939
+ vulnerabilitiesOutsidePr,
940
+ totalPrVulnerabilities
857
941
  };
858
942
  }
859
943
  async digestVulnerabilityReport({
@@ -959,9 +1043,19 @@ var GQLClient = class {
959
1043
  );
960
1044
  return GetFixQueryZ.parse(res);
961
1045
  }
1046
+ async getFixes(fixIds) {
1047
+ const res = await this._client.request(
1048
+ GET_FIXES,
1049
+ {
1050
+ filters: { id: { _in: fixIds } }
1051
+ }
1052
+ );
1053
+ return GetFixesQueryZ.parse(res);
1054
+ }
962
1055
  };
963
1056
 
964
1057
  // src/features/analysis/handle_finished_analysis.ts
1058
+ import { Octokit as Octokit3 } from "@octokit/core";
965
1059
  import Debug4 from "debug";
966
1060
  import parseDiff from "parse-diff";
967
1061
  import { z as z9 } from "zod";
@@ -1402,9 +1496,9 @@ async function getGithubBlameRanges({ ref, gitHubUrl, path: path9 }, options) {
1402
1496
  return res.repository.object.blame.ranges.map((range) => ({
1403
1497
  startingLine: range.startingLine,
1404
1498
  endingLine: range.endingLine,
1405
- email: range.commit.author.user.email,
1406
- name: range.commit.author.user.name,
1407
- login: range.commit.author.user.login
1499
+ email: range.commit.author.user?.email || "",
1500
+ name: range.commit.author.user?.name || "",
1501
+ login: range.commit.author.user?.login || ""
1408
1502
  }));
1409
1503
  }
1410
1504
  async function createPr({
@@ -1509,6 +1603,9 @@ var UPDATE_COMMENT_PATH = "PATCH /repos/{owner}/{repo}/pulls/comments/{comment_i
1509
1603
  var GET_PR_COMMENTS_PATH = "GET /repos/{owner}/{repo}/pulls/{pull_number}/comments";
1510
1604
  var GET_PR_COMMENT_PATH = "GET /repos/{owner}/{repo}/pulls/comments/{comment_id}";
1511
1605
  var GET_PR = "GET /repos/{owner}/{repo}/pulls/{pull_number}";
1606
+ var POST_GENERAL_PR_COMMENT = "POST /repos/{owner}/{repo}/issues/{issue_number}/comments";
1607
+ var GET_GENERAL_PR_COMMENTS = "GET /repos/{owner}/{repo}/issues/{issue_number}/comments";
1608
+ var DELETE_GENERAL_PR_COMMENT = "DELETE /repos/{owner}/{repo}/issues/comments/{comment_id}";
1512
1609
  var CREATE_OR_UPDATE_A_REPOSITORY_SECRET = "PUT /repos/{owner}/{repo}/actions/secrets/{secret_name}";
1513
1610
  var GET_A_REPOSITORY_PUBLIC_KEY = "GET /repos/{owner}/{repo}/actions/secrets/public-key";
1514
1611
 
@@ -1540,6 +1637,15 @@ function createOrUpdateRepositorySecret(client, params) {
1540
1637
  function getARepositoryPublicKey(client, params) {
1541
1638
  return client.request(GET_A_REPOSITORY_PUBLIC_KEY, params);
1542
1639
  }
1640
+ function postGeneralPrComment(client, params) {
1641
+ return client.request(POST_GENERAL_PR_COMMENT, params);
1642
+ }
1643
+ function getGeneralPrComments(client, params) {
1644
+ return client.request(GET_GENERAL_PR_COMMENTS, params);
1645
+ }
1646
+ function deleteGeneralPrComment(client, params) {
1647
+ return client.request(DELETE_GENERAL_PR_COMMENT, params);
1648
+ }
1543
1649
 
1544
1650
  // src/features/analysis/scm/gitlab.ts
1545
1651
  import querystring from "node:querystring";
@@ -1881,7 +1987,7 @@ var isValidBranchName = async (branchName) => {
1881
1987
  var FixesZ = z6.array(z6.object({ fixId: z6.string(), diff: z6.string() })).nonempty();
1882
1988
 
1883
1989
  // src/features/analysis/scm/scm.ts
1884
- function getScmLibTypeFromUrl(url) {
1990
+ function getCloudScmLibTypeFromUrl(url) {
1885
1991
  if (!url) {
1886
1992
  return void 0;
1887
1993
  }
@@ -1898,19 +2004,92 @@ function getScmLibTypeFromUrl(url) {
1898
2004
  }
1899
2005
  return void 0;
1900
2006
  }
2007
+ function getScmTypeFromScmLibType(scmLibType) {
2008
+ if (scmLibType === "GITLAB" /* GITLAB */) {
2009
+ return "GitLab" /* GitLab */;
2010
+ }
2011
+ if (scmLibType === "GITHUB" /* GITHUB */) {
2012
+ return "GitHub" /* GitHub */;
2013
+ }
2014
+ if (scmLibType === "ADO" /* ADO */) {
2015
+ return "Ado" /* Ado */;
2016
+ }
2017
+ throw new Error(`unknown scm lib type: ${scmLibType}`);
2018
+ }
2019
+ function getScmLibTypeFromScmType(scmType) {
2020
+ if (scmType === "GitLab" /* GitLab */) {
2021
+ return "GITLAB" /* GITLAB */;
2022
+ }
2023
+ if (scmType === "GitHub" /* GitHub */) {
2024
+ return "GITHUB" /* GITHUB */;
2025
+ }
2026
+ if (scmType === "Ado" /* Ado */) {
2027
+ return "ADO" /* ADO */;
2028
+ }
2029
+ throw new Error(`unknown scm type: ${scmType}`);
2030
+ }
2031
+ function getScmConfig({
2032
+ url,
2033
+ scmConfigs,
2034
+ includeOrgTokens = true
2035
+ }) {
2036
+ const filteredScmConfigs = scmConfigs.filter((scm) => {
2037
+ const urlObject = new URL(url);
2038
+ const configUrl = new URL(scm.scmUrl);
2039
+ return (
2040
+ //if we the user does an ADO oauth flow then the token is saved for dev.azure.com but
2041
+ //sometimes the user uses the url dev.azure.com and sometimes the url visualstudio.com
2042
+ //so we need to check both
2043
+ (urlObject.hostname === configUrl.hostname || urlObject.hostname.endsWith(".visualstudio.com") && configUrl.hostname === "dev.azure.com") && urlObject.protocol === configUrl.protocol && urlObject.port === configUrl.port
2044
+ );
2045
+ });
2046
+ const scmOrgConfig = filteredScmConfigs.find((scm) => scm.orgId && scm.token);
2047
+ if (scmOrgConfig && includeOrgTokens) {
2048
+ return {
2049
+ id: scmOrgConfig.id,
2050
+ accessToken: scmOrgConfig.token || void 0,
2051
+ scmLibType: getScmLibTypeFromScmType(scmOrgConfig.scmType),
2052
+ scmOrg: scmOrgConfig.scmOrg || void 0
2053
+ };
2054
+ }
2055
+ const scmUserConfig = filteredScmConfigs.find(
2056
+ (scm) => scm.userId && scm.token
2057
+ );
2058
+ if (scmUserConfig) {
2059
+ return {
2060
+ id: scmUserConfig.id,
2061
+ accessToken: scmUserConfig.token || void 0,
2062
+ scmLibType: getScmLibTypeFromScmType(scmUserConfig.scmType),
2063
+ scmOrg: scmUserConfig.scmOrg || void 0
2064
+ };
2065
+ }
2066
+ const type2 = getCloudScmLibTypeFromUrl(url);
2067
+ if (type2) {
2068
+ return {
2069
+ id: void 0,
2070
+ accessToken: void 0,
2071
+ scmLibType: type2,
2072
+ scmOrg: void 0
2073
+ };
2074
+ }
2075
+ return {
2076
+ id: void 0,
2077
+ accessToken: void 0,
2078
+ scmLibType: void 0,
2079
+ scmOrg: void 0
2080
+ };
2081
+ }
1901
2082
  async function scmCanReachRepo({
1902
2083
  repoUrl,
1903
- githubToken,
1904
- gitlabToken,
1905
- adoToken,
2084
+ scmType,
2085
+ accessToken,
1906
2086
  scmOrg
1907
2087
  }) {
1908
2088
  try {
1909
- const scmLibType = getScmLibTypeFromUrl(repoUrl);
1910
2089
  await SCMLib.init({
1911
2090
  url: repoUrl,
1912
- accessToken: scmLibType === "GITHUB" /* GITHUB */ ? githubToken : scmLibType === "GITLAB" /* GITLAB */ ? gitlabToken : scmLibType === "ADO" /* ADO */ ? adoToken : "",
1913
- scmType: scmLibType,
2091
+ accessToken,
2092
+ scmType: getScmLibTypeFromScmType(scmType),
1914
2093
  scmOrg
1915
2094
  });
1916
2095
  return true;
@@ -1961,7 +2140,7 @@ var SCMLib = class {
1961
2140
  if (!this.accessToken) {
1962
2141
  return trimmedUrl;
1963
2142
  }
1964
- const scmLibType = getScmLibTypeFromUrl(trimmedUrl);
2143
+ const scmLibType = this.getScmLibType();
1965
2144
  if (scmLibType === "ADO" /* ADO */) {
1966
2145
  return `https://${this.accessToken}@${trimmedUrl.toLowerCase().replace("https://", "")}`;
1967
2146
  }
@@ -2088,6 +2267,9 @@ var AdoSCMLib = class extends SCMLib {
2088
2267
  repoUrl: this.url
2089
2268
  });
2090
2269
  }
2270
+ getScmLibType() {
2271
+ return "ADO" /* ADO */;
2272
+ }
2091
2273
  getAuthHeaders() {
2092
2274
  if (this.accessToken) {
2093
2275
  if (getAdoTokenType(this.accessToken) === "OAUTH" /* OAUTH */) {
@@ -2191,6 +2373,15 @@ var AdoSCMLib = class extends SCMLib {
2191
2373
  getPr() {
2192
2374
  throw new Error("Method not implemented.");
2193
2375
  }
2376
+ postGeneralPrComment() {
2377
+ throw new Error("Method not implemented.");
2378
+ }
2379
+ getGeneralPrComments() {
2380
+ throw new Error("Method not implemented.");
2381
+ }
2382
+ deleteGeneralPrComment() {
2383
+ throw new Error("Method not implemented.");
2384
+ }
2194
2385
  };
2195
2386
  var GitlabSCMLib = class extends SCMLib {
2196
2387
  async createSubmitRequest(targetBranchName, sourceBranchName, title, body) {
@@ -2249,6 +2440,9 @@ var GitlabSCMLib = class extends SCMLib {
2249
2440
  repoUrl: this.url
2250
2441
  });
2251
2442
  }
2443
+ getScmLibType() {
2444
+ return "GITLAB" /* GITLAB */;
2445
+ }
2252
2446
  getAuthHeaders() {
2253
2447
  if (this?.accessToken?.startsWith("glpat-")) {
2254
2448
  return {
@@ -2362,6 +2556,15 @@ var GitlabSCMLib = class extends SCMLib {
2362
2556
  getPr() {
2363
2557
  throw new Error("Method not implemented.");
2364
2558
  }
2559
+ postGeneralPrComment() {
2560
+ throw new Error("Method not implemented.");
2561
+ }
2562
+ getGeneralPrComments() {
2563
+ throw new Error("Method not implemented.");
2564
+ }
2565
+ deleteGeneralPrComment() {
2566
+ throw new Error("Method not implemented.");
2567
+ }
2365
2568
  };
2366
2569
  var GithubSCMLib = class extends SCMLib {
2367
2570
  // we don't always need a url, what's important is that we have an access token
@@ -2512,6 +2715,9 @@ var GithubSCMLib = class extends SCMLib {
2512
2715
  }
2513
2716
  return getGithubBranchList(this.accessToken, this.url);
2514
2717
  }
2718
+ getScmLibType() {
2719
+ return "GITHUB" /* GITHUB */;
2720
+ }
2515
2721
  getAuthHeaders() {
2516
2722
  if (this.accessToken) {
2517
2723
  return { authorization: `Bearer ${this.accessToken}` };
@@ -2627,12 +2833,58 @@ var GithubSCMLib = class extends SCMLib {
2627
2833
  pull_number: prNumber
2628
2834
  });
2629
2835
  }
2836
+ async postGeneralPrComment(params, auth) {
2837
+ const { prNumber, body } = params;
2838
+ if (!this.url) {
2839
+ console.error("no url");
2840
+ throw new Error("no url");
2841
+ }
2842
+ const oktoKit = auth ? new Octokit2({ auth: auth.authToken }) : this.oktokit;
2843
+ const { owner, repo } = parseGithubOwnerAndRepo(this.url);
2844
+ return await postGeneralPrComment(oktoKit, {
2845
+ issue_number: prNumber,
2846
+ owner,
2847
+ repo,
2848
+ body
2849
+ });
2850
+ }
2851
+ async getGeneralPrComments(params, auth) {
2852
+ const { prNumber } = params;
2853
+ if (!this.url) {
2854
+ console.error("no url");
2855
+ throw new Error("no url");
2856
+ }
2857
+ const oktoKit = auth ? new Octokit2({ auth: auth.authToken }) : this.oktokit;
2858
+ const { owner, repo } = parseGithubOwnerAndRepo(this.url);
2859
+ return await getGeneralPrComments(oktoKit, {
2860
+ issue_number: prNumber,
2861
+ owner,
2862
+ repo
2863
+ });
2864
+ }
2865
+ async deleteGeneralPrComment({ commentId }, auth) {
2866
+ if (!this.url) {
2867
+ console.error("no url");
2868
+ throw new Error("no url");
2869
+ }
2870
+ const oktoKit = auth ? new Octokit2({ auth: auth.authToken }) : this.oktokit;
2871
+ const { owner, repo } = parseGithubOwnerAndRepo(this.url);
2872
+ return deleteGeneralPrComment(oktoKit, {
2873
+ owner,
2874
+ repo,
2875
+ comment_id: commentId
2876
+ });
2877
+ }
2630
2878
  };
2631
2879
  var StubSCMLib = class extends SCMLib {
2632
2880
  async createSubmitRequest(_targetBranchName, _sourceBranchName, _title, _body) {
2633
2881
  console.error("createSubmitRequest() not implemented");
2634
2882
  throw new Error("createSubmitRequest() not implemented");
2635
2883
  }
2884
+ getScmLibType() {
2885
+ console.error("getScmLibType() not implemented");
2886
+ throw new Error("getScmLibType() not implemented");
2887
+ }
2636
2888
  getAuthHeaders() {
2637
2889
  console.error("getAuthHeaders() not implemented");
2638
2890
  throw new Error("getAuthHeaders() not implemented");
@@ -2709,6 +2961,15 @@ var StubSCMLib = class extends SCMLib {
2709
2961
  console.error("getPr() not implemented");
2710
2962
  throw new Error("getPr() not implemented");
2711
2963
  }
2964
+ postGeneralPrComment() {
2965
+ throw new Error("Method not implemented.");
2966
+ }
2967
+ getGeneralPrComments() {
2968
+ throw new Error("Method not implemented.");
2969
+ }
2970
+ deleteGeneralPrComment() {
2971
+ throw new Error("Method not implemented.");
2972
+ }
2712
2973
  };
2713
2974
 
2714
2975
  // src/features/analysis/scm/ado.ts
@@ -3160,7 +3421,7 @@ var AdoAuthResultZ = z8.object({
3160
3421
  });
3161
3422
 
3162
3423
  // src/features/analysis/scm/constants.ts
3163
- var MOBB_ICON_IMG = "https://svgshare.com/i/12DK.svg";
3424
+ var MOBB_ICON_IMG = "https://app.mobb.ai/gh-action/Logo_Rounded_Icon.svg";
3164
3425
  var COMMIT_FIX_SVG = `https://app.mobb.ai/gh-action/commit-button.svg`;
3165
3426
 
3166
3427
  // src/features/analysis/scm/utils/get_issue_type.ts
@@ -3275,6 +3536,13 @@ function getCommitUrl(params) {
3275
3536
  })}/commit?${searchParams.toString()}`;
3276
3537
  }
3277
3538
 
3539
+ // src/features/analysis/utils/by_key.ts
3540
+ function keyBy(array, keyBy2) {
3541
+ return array.reduce((acc, item) => {
3542
+ return { ...acc, [item[keyBy2]]: item };
3543
+ }, {});
3544
+ }
3545
+
3278
3546
  // src/features/analysis/utils/calculate_ranges.ts
3279
3547
  function calculateRanges(integers) {
3280
3548
  if (integers.length === 0) {
@@ -3302,7 +3570,10 @@ function calculateRanges(integers) {
3302
3570
 
3303
3571
  // src/features/analysis/handle_finished_analysis.ts
3304
3572
  var debug4 = Debug4("mobbdev:handle-finished-analysis");
3573
+ var contactUsMarkdown = `For specific requests [contact us](https://mobb.ai/contact) and we'll do the most to answer your need quickly.`;
3305
3574
  var commitFixButton = (commitUrl) => `<a href="${commitUrl}"><img src=${COMMIT_FIX_SVG}></a>`;
3575
+ var MobbIconMarkdown = `![image](${MOBB_ICON_IMG})`;
3576
+ var noVulnerabilitiesFoundTitle = `# ${MobbIconMarkdown} No security issues were found \u2705`;
3306
3577
  function scannerToFriendlyString(scanner) {
3307
3578
  switch (scanner) {
3308
3579
  case "checkmarx":
@@ -3315,7 +3586,7 @@ function scannerToFriendlyString(scanner) {
3315
3586
  return "Snyk";
3316
3587
  }
3317
3588
  }
3318
- async function getFixesFromDiff(params) {
3589
+ async function getRelevantVulenrabilitiesFromDiff(params) {
3319
3590
  const { gqlClient, diff, vulnerabilityReportId } = params;
3320
3591
  const parsedDiff = parseDiff(diff);
3321
3592
  const fileHunks = parsedDiff.map((file) => {
@@ -3338,13 +3609,45 @@ async function getFixesFromDiff(params) {
3338
3609
  vulnerabilityReportId
3339
3610
  });
3340
3611
  }
3612
+ async function getFixesData(params) {
3613
+ const { gqlClient, fixesId } = params;
3614
+ const { fixes } = await gqlClient.getFixes(fixesId);
3615
+ return keyBy(fixes, "id");
3616
+ }
3617
+ function buildAnalysisSummaryComment(params) {
3618
+ const { prVulenrabilities: fixesFromDiff, fixesById } = params;
3619
+ const { vulnerabilityReportIssueCodeNodes, fixablePrVuls } = fixesFromDiff;
3620
+ const title = `# ${MobbIconMarkdown} ${fixablePrVuls} ${fixablePrVuls === 1 ? "fix is" : "fixes are"} ready to be committed`;
3621
+ const summary = Object.entries(
3622
+ // count every issue type
3623
+ vulnerabilityReportIssueCodeNodes.reduce(
3624
+ (result, vulnerabilityReportIssueCodeNode) => {
3625
+ const { vulnerabilityReportIssue } = vulnerabilityReportIssueCodeNode;
3626
+ const fix = fixesById[vulnerabilityReportIssue.fixId];
3627
+ if (!fix) {
3628
+ throw new Error(`fix ${vulnerabilityReportIssue.fixId} not found`);
3629
+ }
3630
+ const issueType = getIssueType(fix.issueType);
3631
+ const vulnerabilityReportIssueCount = (result[issueType] || 0) + 1;
3632
+ return {
3633
+ ...result,
3634
+ [issueType]: vulnerabilityReportIssueCount
3635
+ };
3636
+ },
3637
+ {}
3638
+ )
3639
+ ).map(([issueType, issueTypeCount]) => `**${issueType}** - ${issueTypeCount}`);
3640
+ return `${title}
3641
+ ${summary.join("\n")}`;
3642
+ }
3341
3643
  async function handleFinishedAnalysis({
3342
3644
  analysisId,
3343
3645
  scm: _scm,
3344
3646
  gqlClient,
3345
- githubActionOctokit,
3647
+ githubActionToken,
3346
3648
  scanner
3347
3649
  }) {
3650
+ const githubActionOctokit = new Octokit3({ auth: githubActionToken });
3348
3651
  if (_scm instanceof GithubSCMLib === false) {
3349
3652
  return;
3350
3653
  }
@@ -3358,17 +3661,59 @@ async function handleFinishedAnalysis({
3358
3661
  } = getAnalysis.analysis;
3359
3662
  const { commitSha, pullRequest } = getAnalysis.analysis.repo;
3360
3663
  const diff = await scm.getPrDiff({ pull_number: pullRequest });
3361
- const { vulnerabilityReportIssueCodeNodes } = await getFixesFromDiff({
3664
+ const prVulenrabilities = await getRelevantVulenrabilitiesFromDiff({
3362
3665
  diff,
3363
3666
  gqlClient,
3364
3667
  vulnerabilityReportId: getAnalysis.analysis.vulnerabilityReportId
3365
3668
  });
3366
- const comments = await scm.getPrComments(
3367
- { pull_number: pullRequest },
3368
- githubActionOctokit
3669
+ const { vulnerabilityReportIssueCodeNodes } = prVulenrabilities;
3670
+ const fixesId = vulnerabilityReportIssueCodeNodes.map(
3671
+ ({ vulnerabilityReportIssue: { fixId } }) => fixId
3369
3672
  );
3370
- await Promise.all(
3371
- comments.data.filter((comment) => {
3673
+ const fixesById = await getFixesData({ fixesId, gqlClient });
3674
+ const [comments, generalPrComments] = await Promise.all([
3675
+ scm.getPrComments({ pull_number: pullRequest }, githubActionOctokit),
3676
+ scm.getGeneralPrComments(
3677
+ { prNumber: pullRequest },
3678
+ { authToken: githubActionToken }
3679
+ )
3680
+ ]);
3681
+ async function postAnalysisSummary() {
3682
+ if (Object.values(fixesById).length === 0) {
3683
+ return;
3684
+ }
3685
+ const analysisSummaryComment = buildAnalysisSummaryComment({
3686
+ fixesById,
3687
+ prVulenrabilities
3688
+ });
3689
+ await scm.postGeneralPrComment(
3690
+ {
3691
+ body: analysisSummaryComment,
3692
+ prNumber: pullRequest
3693
+ },
3694
+ { authToken: githubActionToken }
3695
+ );
3696
+ }
3697
+ function deleteAllPreviousGeneralPrComments() {
3698
+ return generalPrComments.data.filter((comment) => {
3699
+ if (!comment.body) {
3700
+ return false;
3701
+ }
3702
+ return comment.body.includes(MOBB_ICON_IMG);
3703
+ }).map((comment) => {
3704
+ try {
3705
+ return scm.deleteGeneralPrComment(
3706
+ { commentId: comment.id },
3707
+ { authToken: githubActionToken }
3708
+ );
3709
+ } catch (e) {
3710
+ debug4("delete comment failed %s", e);
3711
+ return Promise.resolve();
3712
+ }
3713
+ });
3714
+ }
3715
+ function deleteAllPreviousComments() {
3716
+ return comments.data.filter((comment) => {
3372
3717
  return comment.body.includes(MOBB_ICON_IMG);
3373
3718
  }).map((comment) => {
3374
3719
  try {
@@ -3380,70 +3725,154 @@ async function handleFinishedAnalysis({
3380
3725
  debug4("delete comment failed %s", e);
3381
3726
  return Promise.resolve();
3382
3727
  }
3383
- })
3384
- );
3385
- return Promise.all(
3386
- vulnerabilityReportIssueCodeNodes.map(
3387
- async (vulnerabilityReportIssueCodeNodes2) => {
3388
- const { path: path9, startLine, vulnerabilityReportIssue } = vulnerabilityReportIssueCodeNodes2;
3389
- const { fixId } = vulnerabilityReportIssue;
3390
- const { fix_by_pk } = await gqlClient.getFix(fixId);
3391
- const {
3392
- patchAndQuestions: { patch }
3393
- } = fix_by_pk;
3394
- const commentRes = await scm.postPrComment(
3395
- {
3396
- body: "empty",
3397
- pull_number: pullRequest,
3398
- commit_id: commitSha,
3399
- path: path9,
3400
- line: startLine
3401
- },
3402
- githubActionOctokit
3403
- );
3404
- const commentId = commentRes.data.id;
3405
- const commitUrl = getCommitUrl({
3406
- appBaseUrl: WEB_APP_URL,
3407
- fixId: fix_by_pk.id,
3408
- projectId,
3409
- analysisId,
3410
- organizationId,
3411
- redirectUrl: commentRes.data.html_url,
3412
- commentId
3413
- });
3414
- const fixUrl = getFixUrlWithRedirect({
3415
- appBaseUrl: WEB_APP_URL,
3416
- fixId: fix_by_pk.id,
3417
- projectId,
3418
- analysisId,
3419
- organizationId,
3420
- redirectUrl: commentRes.data.html_url,
3421
- commentId
3422
- });
3423
- const scanerString = scannerToFriendlyString(scanner);
3424
- const issueType = getIssueType(fix_by_pk.issueType);
3425
- const title = `# ![image](${MOBB_ICON_IMG}) ${issueType} fix is ready`;
3426
- const subTitle = `### Apply the following code change to fix ${issueType} issue detected by ${scanerString}:`;
3427
- const diff2 = `\`\`\`diff
3728
+ });
3729
+ }
3730
+ await Promise.all([
3731
+ ...deleteAllPreviousComments(),
3732
+ ...deleteAllPreviousGeneralPrComments()
3733
+ ]);
3734
+ async function postFixComment(vulnerabilityReportIssueCodeNode) {
3735
+ const {
3736
+ path: path9,
3737
+ startLine,
3738
+ vulnerabilityReportIssue: { fixId }
3739
+ } = vulnerabilityReportIssueCodeNode;
3740
+ const fix = fixesById[fixId];
3741
+ if (!fix) {
3742
+ throw new Error(`fix ${fixId} not found`);
3743
+ }
3744
+ const {
3745
+ patchAndQuestions: { patch }
3746
+ } = fix;
3747
+ const commentRes = await scm.postPrComment(
3748
+ {
3749
+ body: "empty",
3750
+ pull_number: pullRequest,
3751
+ commit_id: commitSha,
3752
+ path: path9,
3753
+ line: startLine
3754
+ },
3755
+ githubActionOctokit
3756
+ );
3757
+ const commentId = commentRes.data.id;
3758
+ const commitUrl = getCommitUrl({
3759
+ appBaseUrl: WEB_APP_URL,
3760
+ fixId,
3761
+ projectId,
3762
+ analysisId,
3763
+ organizationId,
3764
+ redirectUrl: commentRes.data.html_url,
3765
+ commentId
3766
+ });
3767
+ const fixUrl = getFixUrlWithRedirect({
3768
+ appBaseUrl: WEB_APP_URL,
3769
+ fixId,
3770
+ projectId,
3771
+ analysisId,
3772
+ organizationId,
3773
+ redirectUrl: commentRes.data.html_url,
3774
+ commentId
3775
+ });
3776
+ const scanerString = scannerToFriendlyString(scanner);
3777
+ const issueType = getIssueType(fix.issueType);
3778
+ const title = `# ${MobbIconMarkdown} ${issueType} fix is ready`;
3779
+ const subTitle = `### Apply the following code change to fix ${issueType} issue detected by **${scanerString}**:`;
3780
+ const diff2 = `\`\`\`diff
3428
3781
  ${patch}
3429
3782
  \`\`\``;
3430
- const fixPageLink = `[Learn more and fine tune the fix](${fixUrl})`;
3431
- await scm.updatePrComment(
3432
- {
3433
- body: `${title}
3783
+ const fixPageLink = `[Learn more and fine tune the fix](${fixUrl})`;
3784
+ await scm.updatePrComment(
3785
+ {
3786
+ body: `${title}
3434
3787
  ${subTitle}
3435
3788
  ${diff2}
3436
3789
  ${commitFixButton(
3437
- commitUrl
3438
- )}
3790
+ commitUrl
3791
+ )}
3439
3792
  ${fixPageLink}`,
3440
- comment_id: commentId
3441
- },
3442
- githubActionOctokit
3443
- );
3444
- }
3445
- )
3446
- );
3793
+ comment_id: commentId
3794
+ },
3795
+ githubActionOctokit
3796
+ );
3797
+ }
3798
+ async function postAnalysisInsightComment() {
3799
+ const scanerString = scannerToFriendlyString(scanner);
3800
+ const {
3801
+ totalPrVulnerabilities,
3802
+ vulnerabilitiesOutsidePr,
3803
+ fixablePrVuls,
3804
+ nonFixablePrVuls
3805
+ } = prVulenrabilities;
3806
+ debug4({
3807
+ fixablePrVuls,
3808
+ nonFixablePrVuls,
3809
+ vulnerabilitiesOutsidePr,
3810
+ totalPrVulnerabilities
3811
+ });
3812
+ if (totalPrVulnerabilities === 0 && vulnerabilitiesOutsidePr === 0) {
3813
+ const body = `Awesome! No vulnerabilities were found by **${scanerString}**`;
3814
+ const noVulsFoundComment = `${noVulnerabilitiesFoundTitle}
3815
+ ${body}`;
3816
+ await scm.postGeneralPrComment(
3817
+ {
3818
+ body: noVulsFoundComment,
3819
+ prNumber: pullRequest
3820
+ },
3821
+ { authToken: githubActionToken }
3822
+ );
3823
+ return;
3824
+ }
3825
+ if (totalPrVulnerabilities === 0 && vulnerabilitiesOutsidePr > 0) {
3826
+ const body = `Awesome! No vulnerabilities were found by **${scanerString}** in the changes made as part of this PR.`;
3827
+ const body2 = `Please notice there are issues in this repo that are unrelated to this PR.`;
3828
+ const noVulsFoundComment = `${noVulnerabilitiesFoundTitle}
3829
+ ${body}
3830
+ ${body2}`;
3831
+ await scm.postGeneralPrComment(
3832
+ {
3833
+ body: noVulsFoundComment,
3834
+ prNumber: pullRequest
3835
+ },
3836
+ { authToken: githubActionToken }
3837
+ );
3838
+ return;
3839
+ }
3840
+ if (fixablePrVuls === 0 && nonFixablePrVuls > 0) {
3841
+ const title = `# ${MobbIconMarkdown} We couldn't fix the issues detected by **${scanerString}**`;
3842
+ const body = `Mobb Fixer gets better and better every day, but unfortunately your current issues aren't supported yet.`;
3843
+ const noFixableVulsComment = `${title}
3844
+ ${body}
3845
+ ${contactUsMarkdown}`;
3846
+ await scm.postGeneralPrComment(
3847
+ {
3848
+ body: noFixableVulsComment,
3849
+ prNumber: pullRequest
3850
+ },
3851
+ { authToken: githubActionToken }
3852
+ );
3853
+ return;
3854
+ }
3855
+ if (fixablePrVuls < nonFixablePrVuls && fixablePrVuls > 0) {
3856
+ const title = `# ${MobbIconMarkdown} We couldn't fix some of the issues detected by **${scanerString}**`;
3857
+ const body = "Mobb Fixer gets better and better every day, but unfortunately your current issues aren't supported yet.";
3858
+ const fixableVulsComment = `${title}
3859
+ ${body}
3860
+ ${contactUsMarkdown}`;
3861
+ await scm.postGeneralPrComment(
3862
+ {
3863
+ body: fixableVulsComment,
3864
+ prNumber: pullRequest
3865
+ },
3866
+ { authToken: githubActionToken }
3867
+ );
3868
+ return;
3869
+ }
3870
+ }
3871
+ await Promise.all([
3872
+ ...prVulenrabilities.vulnerabilityReportIssueCodeNodes.map(postFixComment),
3873
+ postAnalysisInsightComment(),
3874
+ postAnalysisSummary()
3875
+ ]);
3447
3876
  }
3448
3877
 
3449
3878
  // src/features/analysis/pack.ts
@@ -3913,11 +4342,8 @@ async function runAnalysis(params, options) {
3913
4342
  tmpObj.removeCallback();
3914
4343
  }
3915
4344
  }
3916
- function _getTokenAndUrlForScmType({
3917
- scmLibType,
3918
- githubToken,
3919
- gitlabToken,
3920
- adoToken
4345
+ function _getUrlForScmType({
4346
+ scmLibType
3921
4347
  }) {
3922
4348
  const githubAuthUrl = `${WEB_APP_URL}/github-auth`;
3923
4349
  const gitlabAuthUrl = `${WEB_APP_URL}/gitlab-auth`;
@@ -3925,22 +4351,18 @@ function _getTokenAndUrlForScmType({
3925
4351
  switch (scmLibType) {
3926
4352
  case "GITHUB" /* GITHUB */:
3927
4353
  return {
3928
- token: githubToken,
3929
4354
  authUrl: githubAuthUrl
3930
4355
  };
3931
4356
  case "GITLAB" /* GITLAB */:
3932
4357
  return {
3933
- token: gitlabToken,
3934
4358
  authUrl: gitlabAuthUrl
3935
4359
  };
3936
4360
  case "ADO" /* ADO */:
3937
4361
  return {
3938
- token: adoToken,
3939
4362
  authUrl: adoAuthUrl
3940
4363
  };
3941
4364
  default:
3942
4365
  return {
3943
- token: void 0,
3944
4366
  authUrl: void 0
3945
4367
  };
3946
4368
  }
@@ -3983,35 +4405,34 @@ async function _scan(params, { skipPrompts = false } = {}) {
3983
4405
  throw new Error("repo is required in case srcPath is not provided");
3984
4406
  }
3985
4407
  const userInfo = await gqlClient.getUserInfo();
3986
- const { githubToken, gitlabToken, adoToken, adoOrg } = userInfo;
4408
+ const tokenInfo = getScmConfig({
4409
+ url: repo,
4410
+ scmConfigs: userInfo.scmConfigs,
4411
+ includeOrgTokens: false
4412
+ });
3987
4413
  const isRepoAvailable = await scmCanReachRepo({
3988
4414
  repoUrl: repo,
3989
- githubToken,
3990
- gitlabToken,
3991
- adoToken,
3992
- scmOrg: adoOrg
4415
+ accessToken: tokenInfo.accessToken,
4416
+ scmOrg: tokenInfo.scmOrg,
4417
+ scmType: getScmTypeFromScmLibType(tokenInfo.scmLibType)
3993
4418
  });
3994
- const scmLibType = getScmLibTypeFromUrl(repo);
3995
- const { authUrl: scmAuthUrl, token } = _getTokenAndUrlForScmType({
3996
- scmLibType,
3997
- githubToken,
3998
- gitlabToken,
3999
- adoToken
4419
+ const cloudScmLibType = getCloudScmLibTypeFromUrl(repo);
4420
+ const { authUrl: scmAuthUrl } = _getUrlForScmType({
4421
+ scmLibType: cloudScmLibType
4000
4422
  });
4001
- let myToken = token;
4423
+ let myToken = tokenInfo.accessToken;
4002
4424
  if (!isRepoAvailable) {
4003
- if (ci || !scmLibType || !scmAuthUrl) {
4425
+ if (ci || !cloudScmLibType || !scmAuthUrl) {
4004
4426
  const errorMessage = scmAuthUrl ? `Cannot access repo ${repo}` : `Cannot access repo ${repo} with the provided token, please visit ${scmAuthUrl} to refresh your source control management system token`;
4005
4427
  throw new Error(errorMessage);
4006
4428
  }
4007
- if (scmLibType && scmAuthUrl) {
4008
- myToken = await handleScmIntegration(token, scmLibType, scmAuthUrl) || "";
4429
+ if (cloudScmLibType && scmAuthUrl) {
4430
+ myToken = await handleScmIntegration(tokenInfo.accessToken, scmAuthUrl, repo) || "";
4009
4431
  const isRepoAvailable2 = await scmCanReachRepo({
4010
4432
  repoUrl: repo,
4011
- githubToken: myToken,
4012
- gitlabToken: myToken,
4013
- adoToken: myToken,
4014
- scmOrg: adoOrg
4433
+ accessToken: myToken,
4434
+ scmOrg: tokenInfo.scmOrg,
4435
+ scmType: getScmTypeFromScmLibType(tokenInfo.scmLibType)
4015
4436
  });
4016
4437
  if (!isRepoAvailable2) {
4017
4438
  throw new Error(
@@ -4022,9 +4443,9 @@ async function _scan(params, { skipPrompts = false } = {}) {
4022
4443
  }
4023
4444
  const scm = await SCMLib.init({
4024
4445
  url: repo,
4025
- accessToken: token,
4026
- scmType: scmLibType,
4027
- scmOrg: adoOrg
4446
+ accessToken: myToken,
4447
+ scmOrg: tokenInfo.scmOrg,
4448
+ scmType: tokenInfo.scmLibType
4028
4449
  });
4029
4450
  const reference = ref ?? await scm.getRepoDefaultBranch();
4030
4451
  const { sha } = await scm.getReferenceData(reference);
@@ -4066,7 +4487,7 @@ async function _scan(params, { skipPrompts = false } = {}) {
4066
4487
  analysisId,
4067
4488
  gqlClient,
4068
4489
  scm,
4069
- githubActionOctokit: new Octokit3({ auth: githubActionToken }),
4490
+ githubActionToken: z10.string().parse(githubActionToken),
4070
4491
  scanner: z10.nativeEnum(SCANNERS).parse(scanner)
4071
4492
  })
4072
4493
  );
@@ -4196,8 +4617,9 @@ async function _scan(params, { skipPrompts = false } = {}) {
4196
4617
  throw new CliError2();
4197
4618
  }
4198
4619
  }
4199
- async function handleScmIntegration(oldToken, scmLibType2, scmAuthUrl2) {
4200
- const scmName = scmLibType2 === "GITHUB" /* GITHUB */ ? "Github" : scmLibType2 === "GITLAB" /* GITLAB */ ? "Gitlab" : scmLibType2 === "ADO" /* ADO */ ? "Azure DevOps" : "";
4620
+ async function handleScmIntegration(oldToken, scmAuthUrl2, repoUrl) {
4621
+ const scmLibType = getCloudScmLibTypeFromUrl(repoUrl);
4622
+ const scmName = scmLibType === "GITHUB" /* GITHUB */ ? "Github" : scmLibType === "GITLAB" /* GITLAB */ ? "Gitlab" : scmLibType === "ADO" /* ADO */ ? "Azure DevOps" : "";
4201
4623
  const addScmIntegration = skipPrompts ? true : await scmIntegrationPrompt(scmName);
4202
4624
  const scmSpinner = createSpinner4(
4203
4625
  `\u{1F517} Waiting for ${scmName} integration...`
@@ -4211,14 +4633,15 @@ async function _scan(params, { skipPrompts = false } = {}) {
4211
4633
  );
4212
4634
  await open2(scmAuthUrl2);
4213
4635
  for (let i = 0; i < LOGIN_MAX_WAIT / LOGIN_CHECK_DELAY; i++) {
4214
- const { githubToken: githubToken2, gitlabToken: gitlabToken2 } = await gqlClient.getUserInfo();
4215
- if (scmLibType2 === "GITHUB" /* GITHUB */ && githubToken2 !== oldToken) {
4216
- scmSpinner.success({ text: "\u{1F517} Github integration successful!" });
4217
- return githubToken2;
4218
- }
4219
- if (scmLibType2 === "GITLAB" /* GITLAB */ && gitlabToken2 !== oldToken) {
4220
- scmSpinner.success({ text: "\u{1F517} Gitlab integration successful!" });
4221
- return gitlabToken2;
4636
+ const userInfo2 = await gqlClient.getUserInfo();
4637
+ const tokenInfo2 = getScmConfig({
4638
+ url: repoUrl,
4639
+ scmConfigs: userInfo2.scmConfigs,
4640
+ includeOrgTokens: false
4641
+ });
4642
+ if (tokenInfo2.accessToken && tokenInfo2.accessToken !== oldToken) {
4643
+ scmSpinner.success({ text: `\u{1F517} ${scmName} integration successful!` });
4644
+ return tokenInfo2.accessToken;
4222
4645
  }
4223
4646
  scmSpinner.spin();
4224
4647
  await sleep(LOGIN_CHECK_DELAY);
@@ -4373,12 +4796,16 @@ var packageJson2 = JSON.parse(
4373
4796
  );
4374
4797
  var config3 = new Configstore2(packageJson2.name, { apiToken: "" });
4375
4798
  async function addScmToken(addScmTokenOptions) {
4376
- const { apiKey, token, organization, scm, username, refreshToken } = addScmTokenOptions;
4799
+ const { apiKey, token, organization, scmType, url, username, refreshToken } = addScmTokenOptions;
4377
4800
  const gqlClient = new GQLClient({
4378
4801
  apiKey: apiKey || config3.get("apiToken")
4379
4802
  });
4803
+ if (!scmType) {
4804
+ throw new CliError(errorMessages.invalidScmType);
4805
+ }
4380
4806
  await gqlClient.updateScmToken({
4381
- type: scm,
4807
+ scmType,
4808
+ url,
4382
4809
  token,
4383
4810
  org: organization,
4384
4811
  username,
@@ -4462,9 +4889,16 @@ var commitHashOption = {
4462
4889
  type: "string"
4463
4890
  };
4464
4891
  var scmTypeOption = {
4892
+ demandOption: true,
4465
4893
  describe: chalk5.bold("SCM type (GitHub, GitLab, Ado)"),
4466
4894
  type: "string"
4467
4895
  };
4896
+ var urlOption = {
4897
+ describe: chalk5.bold(
4898
+ "URL of the repository (used in GitHub, GitLab, Azure DevOps)"
4899
+ ),
4900
+ type: "string"
4901
+ };
4468
4902
  var scmOrgOption = {
4469
4903
  describe: chalk5.bold("Organization name in SCM (used in Azure DevOps)"),
4470
4904
  type: "string"
@@ -4651,29 +5085,32 @@ async function scanHandler(args) {
4651
5085
 
4652
5086
  // src/args/commands/token.ts
4653
5087
  function addScmTokenBuilder(args) {
4654
- return args.option("scm", scmTypeOption).option("token", scmTokenOption).option("organization", scmOrgOption).option("username", scmUsernameOption).option("refresh-token", scmRefreshTokenOption).option("api-key", apiKeyOption).example(
4655
- "$0 add-scm-token --scm ado --token abcdef0123456 --organization myOrg",
5088
+ return args.option("scm-type", scmTypeOption).option("url", urlOption).option("token", scmTokenOption).option("organization", scmOrgOption).option("username", scmUsernameOption).option("refresh-token", scmRefreshTokenOption).option("api-key", apiKeyOption).example(
5089
+ "$0 add-scm-token --scm-type Ado --url https://dev.azure.com/adoorg/test/_git/repo --token abcdef0123456 --organization myOrg",
4656
5090
  "Add your SCM (Github, Gitlab, Azure DevOps) token to Mobb to enable automated fixes."
4657
- ).help().demandOption(["scm", "token"]);
5091
+ ).help().demandOption(["url", "token"]);
4658
5092
  }
4659
5093
  function validateAddScmTokenOptions(argv) {
4660
- if (!argv.scm) {
4661
- throw new CliError(errorMessages.missingScmType);
4662
- }
4663
- if (!Object.values(ScmTypes).includes(argv.scm)) {
4664
- throw new CliError(errorMessages.invalidScmType);
5094
+ if (!argv.url) {
5095
+ throw new CliError(errorMessages.missingUrl);
4665
5096
  }
4666
5097
  if (!argv.token) {
4667
5098
  throw new CliError(errorMessages.missingToken);
4668
5099
  }
4669
- if (argv.scm === ScmTypes.AzureDevOps && !argv.organization) {
5100
+ if ("GitHub" /* GitHub */ !== argv.scmType && "Ado" /* Ado */ !== argv.scmType && "GitLab" /* GitLab */ !== argv.scmType) {
4670
5101
  throw new CliError(
4671
- "\nError: --organization flag is required for Azure DevOps"
5102
+ "\nError: --scm-type must reference a valid SCM type (GitHub, GitLab, Ado)"
4672
5103
  );
4673
5104
  }
4674
- if (argv.scm === ScmTypes.Github && !argv.username) {
5105
+ const urlObj = new URL(argv.url);
5106
+ if (urlObj.hostname === "github.com" && !argv.username) {
4675
5107
  throw new CliError("\nError: --username flag is required for GitHub");
4676
5108
  }
5109
+ if ((urlObj.hostname === "dev.azure.com" || urlObj.hostname.endsWith(".visualstudio.com")) && !argv.organization) {
5110
+ throw new CliError(
5111
+ "\nError: --organization flag is required for Azure DevOps"
5112
+ );
5113
+ }
4677
5114
  }
4678
5115
  async function addScmTokenHandler(args) {
4679
5116
  validateAddScmTokenOptions(args);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mobbdev",
3
- "version": "0.0.83",
3
+ "version": "0.0.85",
4
4
  "description": "Automated secure code remediation tool",
5
5
  "repository": "https://github.com/mobb-dev/bugsy",
6
6
  "main": "dist/index.js",