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.
- package/dist/index.mjs +404 -79
- 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
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
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://
|
|
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 = ``;
|
|
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
|
|
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
|
-
|
|
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
|
|
3664
|
+
const prVulenrabilities = await getRelevantVulenrabilitiesFromDiff({
|
|
3466
3665
|
diff,
|
|
3467
3666
|
gqlClient,
|
|
3468
3667
|
vulnerabilityReportId: getAnalysis.analysis.vulnerabilityReportId
|
|
3469
3668
|
});
|
|
3470
|
-
const
|
|
3471
|
-
|
|
3472
|
-
|
|
3669
|
+
const { vulnerabilityReportIssueCodeNodes } = prVulenrabilities;
|
|
3670
|
+
const fixesId = vulnerabilityReportIssueCodeNodes.map(
|
|
3671
|
+
({ vulnerabilityReportIssue: { fixId } }) => fixId
|
|
3473
3672
|
);
|
|
3474
|
-
await
|
|
3475
|
-
|
|
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
|
-
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
|
|
3520
|
-
|
|
3521
|
-
|
|
3522
|
-
|
|
3523
|
-
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3529
|
-
|
|
3530
|
-
|
|
3531
|
-
|
|
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
|
-
|
|
3535
|
-
|
|
3536
|
-
|
|
3537
|
-
|
|
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
|
-
|
|
3542
|
-
|
|
3790
|
+
commitUrl
|
|
3791
|
+
)}
|
|
3543
3792
|
${fixPageLink}`,
|
|
3544
|
-
|
|
3545
|
-
|
|
3546
|
-
|
|
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
|
-
|
|
4490
|
+
githubActionToken: z10.string().parse(githubActionToken),
|
|
4166
4491
|
scanner: z10.nativeEnum(SCANNERS).parse(scanner)
|
|
4167
4492
|
})
|
|
4168
4493
|
);
|