mobbdev 0.0.84 → 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 +404 -79
  2. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -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";
@@ -476,6 +475,17 @@ var GET_FIX = gql2`
476
475
  }
477
476
  }
478
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
+ `;
479
489
  var GET_VUL_BY_NODES_METADATA = gql2`
480
490
  query getVulByNodesMetadata(
481
491
  $filters: [vulnerability_report_issue_code_node_bool_exp!]
@@ -486,6 +496,7 @@ var GET_VUL_BY_NODES_METADATA = gql2`
486
496
  where: {
487
497
  _or: $filters
488
498
  vulnerabilityReportIssue: {
499
+ fixId: { _is_null: false }
489
500
  vulnerabilityReportId: { _eq: $vulnerabilityReportId }
490
501
  }
491
502
  }
@@ -498,6 +509,35 @@ var GET_VUL_BY_NODES_METADATA = gql2`
498
509
  fixId
499
510
  }
500
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
+ }
501
541
  }
502
542
  `;
503
543
 
@@ -711,15 +751,17 @@ var GetAnalysisQueryZ = z2.object({
711
751
  })
712
752
  })
713
753
  });
714
- var GetFixQueryZ = z2.object({
715
- fix_by_pk: z2.object({
716
- issueType: z2.string(),
717
- id: z2.string(),
718
- patchAndQuestions: z2.object({
719
- patch: z2.string()
720
- })
754
+ var FixDataZ = z2.object({
755
+ issueType: z2.string(),
756
+ id: z2.string(),
757
+ patchAndQuestions: z2.object({
758
+ patch: z2.string()
721
759
  })
722
760
  });
761
+ var GetFixQueryZ = z2.object({
762
+ fix_by_pk: FixDataZ
763
+ });
764
+ var GetFixesQueryZ = z2.object({ fixes: z2.array(FixDataZ) });
723
765
  var VulnerabilityReportIssueCodeNodeZ = z2.object({
724
766
  vulnerabilityReportIssueId: z2.string(),
725
767
  path: z2.string(),
@@ -729,7 +771,22 @@ var VulnerabilityReportIssueCodeNodeZ = z2.object({
729
771
  })
730
772
  });
731
773
  var GetVulByNodesMetadataZ = z2.object({
732
- 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
+ })
733
790
  });
734
791
 
735
792
  // src/features/analysis/graphql/gql.ts
@@ -844,7 +901,6 @@ var GQLClient = class {
844
901
  const filters = hunks.map((hunk) => {
845
902
  const filter = {
846
903
  path: { _eq: hunk.path },
847
- vulnerabilityReportIssue: { fixId: { _is_null: false } },
848
904
  _or: hunk.ranges.map(({ endLine, startLine }) => ({
849
905
  startLine: { _gte: startLine, _lte: endLine },
850
906
  endLine: { _gte: startLine, _lte: endLine }
@@ -868,10 +924,20 @@ var GQLClient = class {
868
924
  [vulnerabilityReportIssueCodeNode.vulnerabilityReportIssueId]: vulnerabilityReportIssueCodeNode
869
925
  };
870
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;
871
932
  return {
872
933
  vulnerabilityReportIssueCodeNodes: Object.values(
873
934
  uniqueVulByNodesMetadata
874
- )
935
+ ),
936
+ nonFixablePrVuls,
937
+ fixablePrVuls,
938
+ totalScanVulnerabilities,
939
+ vulnerabilitiesOutsidePr,
940
+ totalPrVulnerabilities
875
941
  };
876
942
  }
877
943
  async digestVulnerabilityReport({
@@ -977,9 +1043,19 @@ var GQLClient = class {
977
1043
  );
978
1044
  return GetFixQueryZ.parse(res);
979
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
+ }
980
1055
  };
981
1056
 
982
1057
  // src/features/analysis/handle_finished_analysis.ts
1058
+ import { Octokit as Octokit3 } from "@octokit/core";
983
1059
  import Debug4 from "debug";
984
1060
  import parseDiff from "parse-diff";
985
1061
  import { z as z9 } from "zod";
@@ -1527,6 +1603,9 @@ var UPDATE_COMMENT_PATH = "PATCH /repos/{owner}/{repo}/pulls/comments/{comment_i
1527
1603
  var GET_PR_COMMENTS_PATH = "GET /repos/{owner}/{repo}/pulls/{pull_number}/comments";
1528
1604
  var GET_PR_COMMENT_PATH = "GET /repos/{owner}/{repo}/pulls/comments/{comment_id}";
1529
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}";
1530
1609
  var CREATE_OR_UPDATE_A_REPOSITORY_SECRET = "PUT /repos/{owner}/{repo}/actions/secrets/{secret_name}";
1531
1610
  var GET_A_REPOSITORY_PUBLIC_KEY = "GET /repos/{owner}/{repo}/actions/secrets/public-key";
1532
1611
 
@@ -1558,6 +1637,15 @@ function createOrUpdateRepositorySecret(client, params) {
1558
1637
  function getARepositoryPublicKey(client, params) {
1559
1638
  return client.request(GET_A_REPOSITORY_PUBLIC_KEY, params);
1560
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
+ }
1561
1649
 
1562
1650
  // src/features/analysis/scm/gitlab.ts
1563
1651
  import querystring from "node:querystring";
@@ -2285,6 +2373,15 @@ var AdoSCMLib = class extends SCMLib {
2285
2373
  getPr() {
2286
2374
  throw new Error("Method not implemented.");
2287
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
+ }
2288
2385
  };
2289
2386
  var GitlabSCMLib = class extends SCMLib {
2290
2387
  async createSubmitRequest(targetBranchName, sourceBranchName, title, body) {
@@ -2459,6 +2556,15 @@ var GitlabSCMLib = class extends SCMLib {
2459
2556
  getPr() {
2460
2557
  throw new Error("Method not implemented.");
2461
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
+ }
2462
2568
  };
2463
2569
  var GithubSCMLib = class extends SCMLib {
2464
2570
  // we don't always need a url, what's important is that we have an access token
@@ -2727,6 +2833,48 @@ var GithubSCMLib = class extends SCMLib {
2727
2833
  pull_number: prNumber
2728
2834
  });
2729
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
+ }
2730
2878
  };
2731
2879
  var StubSCMLib = class extends SCMLib {
2732
2880
  async createSubmitRequest(_targetBranchName, _sourceBranchName, _title, _body) {
@@ -2813,6 +2961,15 @@ var StubSCMLib = class extends SCMLib {
2813
2961
  console.error("getPr() not implemented");
2814
2962
  throw new Error("getPr() not implemented");
2815
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
+ }
2816
2973
  };
2817
2974
 
2818
2975
  // src/features/analysis/scm/ado.ts
@@ -3264,7 +3421,7 @@ var AdoAuthResultZ = z8.object({
3264
3421
  });
3265
3422
 
3266
3423
  // src/features/analysis/scm/constants.ts
3267
- 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";
3268
3425
  var COMMIT_FIX_SVG = `https://app.mobb.ai/gh-action/commit-button.svg`;
3269
3426
 
3270
3427
  // src/features/analysis/scm/utils/get_issue_type.ts
@@ -3379,6 +3536,13 @@ function getCommitUrl(params) {
3379
3536
  })}/commit?${searchParams.toString()}`;
3380
3537
  }
3381
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
+
3382
3546
  // src/features/analysis/utils/calculate_ranges.ts
3383
3547
  function calculateRanges(integers) {
3384
3548
  if (integers.length === 0) {
@@ -3406,7 +3570,10 @@ function calculateRanges(integers) {
3406
3570
 
3407
3571
  // src/features/analysis/handle_finished_analysis.ts
3408
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.`;
3409
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`;
3410
3577
  function scannerToFriendlyString(scanner) {
3411
3578
  switch (scanner) {
3412
3579
  case "checkmarx":
@@ -3419,7 +3586,7 @@ function scannerToFriendlyString(scanner) {
3419
3586
  return "Snyk";
3420
3587
  }
3421
3588
  }
3422
- async function getFixesFromDiff(params) {
3589
+ async function getRelevantVulenrabilitiesFromDiff(params) {
3423
3590
  const { gqlClient, diff, vulnerabilityReportId } = params;
3424
3591
  const parsedDiff = parseDiff(diff);
3425
3592
  const fileHunks = parsedDiff.map((file) => {
@@ -3442,13 +3609,45 @@ async function getFixesFromDiff(params) {
3442
3609
  vulnerabilityReportId
3443
3610
  });
3444
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
+ }
3445
3643
  async function handleFinishedAnalysis({
3446
3644
  analysisId,
3447
3645
  scm: _scm,
3448
3646
  gqlClient,
3449
- githubActionOctokit,
3647
+ githubActionToken,
3450
3648
  scanner
3451
3649
  }) {
3650
+ const githubActionOctokit = new Octokit3({ auth: githubActionToken });
3452
3651
  if (_scm instanceof GithubSCMLib === false) {
3453
3652
  return;
3454
3653
  }
@@ -3462,17 +3661,59 @@ async function handleFinishedAnalysis({
3462
3661
  } = getAnalysis.analysis;
3463
3662
  const { commitSha, pullRequest } = getAnalysis.analysis.repo;
3464
3663
  const diff = await scm.getPrDiff({ pull_number: pullRequest });
3465
- const { vulnerabilityReportIssueCodeNodes } = await getFixesFromDiff({
3664
+ const prVulenrabilities = await getRelevantVulenrabilitiesFromDiff({
3466
3665
  diff,
3467
3666
  gqlClient,
3468
3667
  vulnerabilityReportId: getAnalysis.analysis.vulnerabilityReportId
3469
3668
  });
3470
- const comments = await scm.getPrComments(
3471
- { pull_number: pullRequest },
3472
- githubActionOctokit
3669
+ const { vulnerabilityReportIssueCodeNodes } = prVulenrabilities;
3670
+ const fixesId = vulnerabilityReportIssueCodeNodes.map(
3671
+ ({ vulnerabilityReportIssue: { fixId } }) => fixId
3473
3672
  );
3474
- await Promise.all(
3475
- 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) => {
3476
3717
  return comment.body.includes(MOBB_ICON_IMG);
3477
3718
  }).map((comment) => {
3478
3719
  try {
@@ -3484,70 +3725,154 @@ async function handleFinishedAnalysis({
3484
3725
  debug4("delete comment failed %s", e);
3485
3726
  return Promise.resolve();
3486
3727
  }
3487
- })
3488
- );
3489
- return Promise.all(
3490
- vulnerabilityReportIssueCodeNodes.map(
3491
- async (vulnerabilityReportIssueCodeNodes2) => {
3492
- const { path: path9, startLine, vulnerabilityReportIssue } = vulnerabilityReportIssueCodeNodes2;
3493
- const { fixId } = vulnerabilityReportIssue;
3494
- const { fix_by_pk } = await gqlClient.getFix(fixId);
3495
- const {
3496
- patchAndQuestions: { patch }
3497
- } = fix_by_pk;
3498
- const commentRes = await scm.postPrComment(
3499
- {
3500
- body: "empty",
3501
- pull_number: pullRequest,
3502
- commit_id: commitSha,
3503
- path: path9,
3504
- line: startLine
3505
- },
3506
- githubActionOctokit
3507
- );
3508
- const commentId = commentRes.data.id;
3509
- const commitUrl = getCommitUrl({
3510
- appBaseUrl: WEB_APP_URL,
3511
- fixId: fix_by_pk.id,
3512
- projectId,
3513
- analysisId,
3514
- organizationId,
3515
- redirectUrl: commentRes.data.html_url,
3516
- commentId
3517
- });
3518
- const fixUrl = getFixUrlWithRedirect({
3519
- appBaseUrl: WEB_APP_URL,
3520
- fixId: fix_by_pk.id,
3521
- projectId,
3522
- analysisId,
3523
- organizationId,
3524
- redirectUrl: commentRes.data.html_url,
3525
- commentId
3526
- });
3527
- const scanerString = scannerToFriendlyString(scanner);
3528
- const issueType = getIssueType(fix_by_pk.issueType);
3529
- const title = `# ![image](${MOBB_ICON_IMG}) ${issueType} fix is ready`;
3530
- const subTitle = `### Apply the following code change to fix ${issueType} issue detected by ${scanerString}:`;
3531
- 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
3532
3781
  ${patch}
3533
3782
  \`\`\``;
3534
- const fixPageLink = `[Learn more and fine tune the fix](${fixUrl})`;
3535
- await scm.updatePrComment(
3536
- {
3537
- body: `${title}
3783
+ const fixPageLink = `[Learn more and fine tune the fix](${fixUrl})`;
3784
+ await scm.updatePrComment(
3785
+ {
3786
+ body: `${title}
3538
3787
  ${subTitle}
3539
3788
  ${diff2}
3540
3789
  ${commitFixButton(
3541
- commitUrl
3542
- )}
3790
+ commitUrl
3791
+ )}
3543
3792
  ${fixPageLink}`,
3544
- comment_id: commentId
3545
- },
3546
- githubActionOctokit
3547
- );
3548
- }
3549
- )
3550
- );
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
+ ]);
3551
3876
  }
3552
3877
 
3553
3878
  // src/features/analysis/pack.ts
@@ -4162,7 +4487,7 @@ async function _scan(params, { skipPrompts = false } = {}) {
4162
4487
  analysisId,
4163
4488
  gqlClient,
4164
4489
  scm,
4165
- githubActionOctokit: new Octokit3({ auth: githubActionToken }),
4490
+ githubActionToken: z10.string().parse(githubActionToken),
4166
4491
  scanner: z10.nativeEnum(SCANNERS).parse(scanner)
4167
4492
  })
4168
4493
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mobbdev",
3
- "version": "0.0.84",
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",