mobbdev 1.0.45 → 1.0.47
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 +228 -68
- package/package.json +3 -1
package/dist/index.mjs
CHANGED
|
@@ -614,8 +614,12 @@ var GitReferenceDocument = `
|
|
|
614
614
|
}
|
|
615
615
|
`;
|
|
616
616
|
var AutoPrAnalysisDocument = `
|
|
617
|
-
mutation autoPrAnalysis($analysisId: String!, $commitDirectly: Boolean) {
|
|
618
|
-
autoPrAnalysis(
|
|
617
|
+
mutation autoPrAnalysis($analysisId: String!, $commitDirectly: Boolean, $prId: Int) {
|
|
618
|
+
autoPrAnalysis(
|
|
619
|
+
analysisId: $analysisId
|
|
620
|
+
sameBranchCommit: $commitDirectly
|
|
621
|
+
prId: $prId
|
|
622
|
+
) {
|
|
619
623
|
__typename
|
|
620
624
|
... on AutoPrSuccess {
|
|
621
625
|
status
|
|
@@ -1569,6 +1573,7 @@ var VUL_REPORT_DIGEST_TIMEOUT_MS = 1e3 * 60 * 30;
|
|
|
1569
1573
|
|
|
1570
1574
|
// src/features/analysis/index.ts
|
|
1571
1575
|
import fs4 from "node:fs";
|
|
1576
|
+
import fsPromises from "node:fs/promises";
|
|
1572
1577
|
import path7 from "node:path";
|
|
1573
1578
|
import { env as env2 } from "node:process";
|
|
1574
1579
|
import { pipeline } from "node:stream/promises";
|
|
@@ -1684,7 +1689,7 @@ import { createSpinner as createSpinner4 } from "nanospinner";
|
|
|
1684
1689
|
import fetch4 from "node-fetch";
|
|
1685
1690
|
import open2 from "open";
|
|
1686
1691
|
import tmp2 from "tmp";
|
|
1687
|
-
import { z as
|
|
1692
|
+
import { z as z31 } from "zod";
|
|
1688
1693
|
|
|
1689
1694
|
// src/features/analysis/add_fix_comments_for_pr/add_fix_comments_for_pr.ts
|
|
1690
1695
|
import Debug8 from "debug";
|
|
@@ -4302,6 +4307,26 @@ async function getAdoSdk(params) {
|
|
|
4302
4307
|
}
|
|
4303
4308
|
return parsedPullRequestStatus.data;
|
|
4304
4309
|
},
|
|
4310
|
+
async addCommentToAdoPullRequest({
|
|
4311
|
+
repoUrl,
|
|
4312
|
+
prNumber,
|
|
4313
|
+
markdownComment
|
|
4314
|
+
}) {
|
|
4315
|
+
const { repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
|
|
4316
|
+
const git = await api2.getGitApi();
|
|
4317
|
+
const comment = {
|
|
4318
|
+
comments: [
|
|
4319
|
+
{
|
|
4320
|
+
parentCommentId: 0,
|
|
4321
|
+
// Root comment
|
|
4322
|
+
content: markdownComment,
|
|
4323
|
+
commentType: 1
|
|
4324
|
+
// Default type
|
|
4325
|
+
}
|
|
4326
|
+
]
|
|
4327
|
+
};
|
|
4328
|
+
await git.createThread(comment, repo, prNumber, projectName);
|
|
4329
|
+
},
|
|
4305
4330
|
async getAdoIsRemoteBranch({
|
|
4306
4331
|
repoUrl,
|
|
4307
4332
|
branch
|
|
@@ -4617,7 +4642,8 @@ var CommitToSameBranchParamsZ = BaseSubmitToScmMessageZ.merge(
|
|
|
4617
4642
|
branch: z19.string(),
|
|
4618
4643
|
commitMessages: z19.array(z19.string()),
|
|
4619
4644
|
commitDescriptions: z19.array(z19.string().nullish()),
|
|
4620
|
-
githubCommentId: z19.number().nullish()
|
|
4645
|
+
githubCommentId: z19.number().nullish(),
|
|
4646
|
+
prId: z19.number().nullish()
|
|
4621
4647
|
})
|
|
4622
4648
|
);
|
|
4623
4649
|
var SubmitFixesToDifferentBranchParamsZ = z19.object({
|
|
@@ -4676,7 +4702,8 @@ var GitCommitZ = z19.object({
|
|
|
4676
4702
|
var SubmitFixesToSameBranchResponseMessageZ = z19.object({
|
|
4677
4703
|
type: z19.literal(submitToScmMessageType.commitToSameBranch),
|
|
4678
4704
|
githubCommentId: z19.number().nullish(),
|
|
4679
|
-
commits: z19.array(GitCommitZ)
|
|
4705
|
+
commits: z19.array(GitCommitZ),
|
|
4706
|
+
prId: z19.number().nullish()
|
|
4680
4707
|
}).merge(SubmitFixesBaseResponseMessageZ);
|
|
4681
4708
|
var SubmitFixesToDifferentBranchResponseMessageZ = z19.object({
|
|
4682
4709
|
type: z19.literal(submitToScmMessageType.submitFixesForDifferentBranch),
|
|
@@ -4931,16 +4958,16 @@ var AdoSCMLib = class extends SCMLib {
|
|
|
4931
4958
|
repoUrl: this.url
|
|
4932
4959
|
});
|
|
4933
4960
|
}
|
|
4934
|
-
async
|
|
4961
|
+
async getSubmitRequestUrl(submitRequestIdNumber) {
|
|
4935
4962
|
this._validateUrl();
|
|
4936
4963
|
const adoSdk = await this.getAdoSdk();
|
|
4937
4964
|
return adoSdk.getAdoPrUrl({
|
|
4938
4965
|
url: this.url,
|
|
4939
|
-
prNumber
|
|
4966
|
+
prNumber: submitRequestIdNumber
|
|
4940
4967
|
});
|
|
4941
4968
|
}
|
|
4942
|
-
async
|
|
4943
|
-
const match =
|
|
4969
|
+
async getSubmitRequestId(submitRequestUrl) {
|
|
4970
|
+
const match = submitRequestUrl.match(/\/pullrequest\/(\d+)/);
|
|
4944
4971
|
return match?.[1] || "";
|
|
4945
4972
|
}
|
|
4946
4973
|
async getCommitUrl(commitId) {
|
|
@@ -4951,6 +4978,15 @@ var AdoSCMLib = class extends SCMLib {
|
|
|
4951
4978
|
commitId
|
|
4952
4979
|
});
|
|
4953
4980
|
}
|
|
4981
|
+
async addCommentToSubmitRequest(scmSubmitRequestId, comment) {
|
|
4982
|
+
this._validateAccessTokenAndUrl();
|
|
4983
|
+
const adoSdk = await this.getAdoSdk();
|
|
4984
|
+
await adoSdk.addCommentToAdoPullRequest({
|
|
4985
|
+
repoUrl: this.url,
|
|
4986
|
+
prNumber: Number(scmSubmitRequestId),
|
|
4987
|
+
markdownComment: comment
|
|
4988
|
+
});
|
|
4989
|
+
}
|
|
4954
4990
|
};
|
|
4955
4991
|
|
|
4956
4992
|
// src/features/analysis/scm/bitbucket/bitbucket.ts
|
|
@@ -4992,7 +5028,7 @@ function parseBitbucketOrganizationAndRepo(bitbucketUrl) {
|
|
|
4992
5028
|
const validatedBitbucketResult = BitbucketParseResultZ.parse(parsingResult);
|
|
4993
5029
|
return {
|
|
4994
5030
|
workspace: validatedBitbucketResult.organization,
|
|
4995
|
-
|
|
5031
|
+
repo_slug: validatedBitbucketResult.repoName
|
|
4996
5032
|
};
|
|
4997
5033
|
}
|
|
4998
5034
|
function getBitbucketIntance(params) {
|
|
@@ -5032,11 +5068,11 @@ function getBitbucketSdk(params) {
|
|
|
5032
5068
|
}));
|
|
5033
5069
|
},
|
|
5034
5070
|
async getBranchList(params2) {
|
|
5035
|
-
const { workspace,
|
|
5071
|
+
const { workspace, repo_slug } = parseBitbucketOrganizationAndRepo(
|
|
5036
5072
|
params2.repoUrl
|
|
5037
5073
|
);
|
|
5038
5074
|
const res = await bitbucketClient.refs.listBranches({
|
|
5039
|
-
repo_slug
|
|
5075
|
+
repo_slug,
|
|
5040
5076
|
workspace,
|
|
5041
5077
|
pagelen: 100,
|
|
5042
5078
|
//It seems to not work with very large numbers like 1000 (MAX_BRANCHES_FETCH) and returns a bad request response
|
|
@@ -5049,8 +5085,8 @@ function getBitbucketSdk(params) {
|
|
|
5049
5085
|
},
|
|
5050
5086
|
async getIsUserCollaborator(params2) {
|
|
5051
5087
|
const { repoUrl } = params2;
|
|
5052
|
-
const {
|
|
5053
|
-
const fullRepoName = `${workspace}/${
|
|
5088
|
+
const { repo_slug, workspace } = parseBitbucketOrganizationAndRepo(repoUrl);
|
|
5089
|
+
const fullRepoName = `${workspace}/${repo_slug}`;
|
|
5054
5090
|
const res = await bitbucketClient.user.listPermissionsForRepos({
|
|
5055
5091
|
q: `repository.full_name~"${fullRepoName}"`
|
|
5056
5092
|
});
|
|
@@ -5059,11 +5095,11 @@ function getBitbucketSdk(params) {
|
|
|
5059
5095
|
) ?? false;
|
|
5060
5096
|
},
|
|
5061
5097
|
async createPullRequest(params2) {
|
|
5062
|
-
const {
|
|
5098
|
+
const { repo_slug, workspace } = parseBitbucketOrganizationAndRepo(
|
|
5063
5099
|
params2.repoUrl
|
|
5064
5100
|
);
|
|
5065
5101
|
const res = await bitbucketClient.pullrequests.create({
|
|
5066
|
-
repo_slug
|
|
5102
|
+
repo_slug,
|
|
5067
5103
|
workspace,
|
|
5068
5104
|
_body: {
|
|
5069
5105
|
type: "pullrequest",
|
|
@@ -5086,43 +5122,43 @@ function getBitbucketSdk(params) {
|
|
|
5086
5122
|
return res.data;
|
|
5087
5123
|
},
|
|
5088
5124
|
async getDownloadlink(params2) {
|
|
5089
|
-
const {
|
|
5125
|
+
const { repo_slug, workspace } = parseBitbucketOrganizationAndRepo(
|
|
5090
5126
|
params2.repoUrl
|
|
5091
5127
|
);
|
|
5092
5128
|
const res = await bitbucketClient.downloads.list({
|
|
5093
|
-
repo_slug
|
|
5129
|
+
repo_slug,
|
|
5094
5130
|
workspace
|
|
5095
5131
|
});
|
|
5096
5132
|
return res.data;
|
|
5097
5133
|
},
|
|
5098
5134
|
async getBranch(params2) {
|
|
5099
|
-
const {
|
|
5135
|
+
const { repo_slug, workspace } = parseBitbucketOrganizationAndRepo(
|
|
5100
5136
|
params2.repoUrl
|
|
5101
5137
|
);
|
|
5102
5138
|
const res = await bitbucketClient.refs.getBranch({
|
|
5103
5139
|
name: params2.branchName,
|
|
5104
|
-
repo_slug
|
|
5140
|
+
repo_slug,
|
|
5105
5141
|
workspace
|
|
5106
5142
|
});
|
|
5107
5143
|
return res.data;
|
|
5108
5144
|
},
|
|
5109
5145
|
async getRepo(params2) {
|
|
5110
|
-
const {
|
|
5146
|
+
const { repo_slug, workspace } = parseBitbucketOrganizationAndRepo(
|
|
5111
5147
|
params2.repoUrl
|
|
5112
5148
|
);
|
|
5113
5149
|
const res = await bitbucketClient.repositories.get({
|
|
5114
|
-
repo_slug
|
|
5150
|
+
repo_slug,
|
|
5115
5151
|
workspace
|
|
5116
5152
|
});
|
|
5117
5153
|
return res.data;
|
|
5118
5154
|
},
|
|
5119
5155
|
async getCommit(params2) {
|
|
5120
|
-
const {
|
|
5156
|
+
const { repo_slug, workspace } = parseBitbucketOrganizationAndRepo(
|
|
5121
5157
|
params2.repoUrl
|
|
5122
5158
|
);
|
|
5123
5159
|
const res = await bitbucketClient.commits.get({
|
|
5124
5160
|
commit: params2.commitSha,
|
|
5125
|
-
repo_slug
|
|
5161
|
+
repo_slug,
|
|
5126
5162
|
workspace
|
|
5127
5163
|
});
|
|
5128
5164
|
return res.data;
|
|
@@ -5151,9 +5187,9 @@ function getBitbucketSdk(params) {
|
|
|
5151
5187
|
},
|
|
5152
5188
|
async getTagRef(params2) {
|
|
5153
5189
|
const { tagName, repoUrl } = params2;
|
|
5154
|
-
const {
|
|
5190
|
+
const { repo_slug, workspace } = parseBitbucketOrganizationAndRepo(repoUrl);
|
|
5155
5191
|
const tagRes = await bitbucketClient.refs.getTag({
|
|
5156
|
-
repo_slug
|
|
5192
|
+
repo_slug,
|
|
5157
5193
|
workspace,
|
|
5158
5194
|
name: tagName
|
|
5159
5195
|
});
|
|
@@ -5186,12 +5222,31 @@ function getBitbucketSdk(params) {
|
|
|
5186
5222
|
return `${parsedRepoUrl}/get/${sha}.zip`;
|
|
5187
5223
|
},
|
|
5188
5224
|
async getPullRequest(params2) {
|
|
5189
|
-
const {
|
|
5225
|
+
const { repo_slug, workspace } = parseBitbucketOrganizationAndRepo(
|
|
5190
5226
|
params2.url
|
|
5191
5227
|
);
|
|
5192
5228
|
const res = await bitbucketClient.pullrequests.get({
|
|
5193
5229
|
pull_request_id: params2.prNumber,
|
|
5194
|
-
repo_slug
|
|
5230
|
+
repo_slug,
|
|
5231
|
+
workspace
|
|
5232
|
+
});
|
|
5233
|
+
return res.data;
|
|
5234
|
+
},
|
|
5235
|
+
async addCommentToPullRequest({
|
|
5236
|
+
url,
|
|
5237
|
+
prNumber,
|
|
5238
|
+
markdownComment
|
|
5239
|
+
}) {
|
|
5240
|
+
const { repo_slug, workspace } = parseBitbucketOrganizationAndRepo(url);
|
|
5241
|
+
const res = await bitbucketClient.pullrequests.createComment({
|
|
5242
|
+
//@ts-expect-error tyep requires _body.type, but it its uses api fails
|
|
5243
|
+
_body: {
|
|
5244
|
+
content: {
|
|
5245
|
+
raw: markdownComment
|
|
5246
|
+
}
|
|
5247
|
+
},
|
|
5248
|
+
pull_request_id: prNumber,
|
|
5249
|
+
repo_slug,
|
|
5195
5250
|
workspace
|
|
5196
5251
|
});
|
|
5197
5252
|
return res.data;
|
|
@@ -5461,24 +5516,32 @@ var BitbucketSCMLib = class extends SCMLib {
|
|
|
5461
5516
|
const repoRes = await this.bitbucketSdk.getRepo({ repoUrl: this.url });
|
|
5462
5517
|
return z23.string().parse(repoRes.mainbranch?.name);
|
|
5463
5518
|
}
|
|
5464
|
-
|
|
5519
|
+
getSubmitRequestUrl(submitRequestId) {
|
|
5465
5520
|
this._validateUrl();
|
|
5466
|
-
const {
|
|
5521
|
+
const { repo_slug, workspace } = parseBitbucketOrganizationAndRepo(this.url);
|
|
5467
5522
|
return Promise.resolve(
|
|
5468
|
-
`https://bitbucket.org/${workspace}/${
|
|
5523
|
+
`https://bitbucket.org/${workspace}/${repo_slug}/pull-requests/${submitRequestId}`
|
|
5469
5524
|
);
|
|
5470
5525
|
}
|
|
5471
|
-
async
|
|
5472
|
-
const match =
|
|
5526
|
+
async getSubmitRequestId(submitRequestUrl) {
|
|
5527
|
+
const match = submitRequestUrl.match(/\/pull-requests\/(\d+)/);
|
|
5473
5528
|
return match?.[1] || "";
|
|
5474
5529
|
}
|
|
5475
5530
|
getCommitUrl(commitId) {
|
|
5476
5531
|
this._validateUrl();
|
|
5477
|
-
const {
|
|
5532
|
+
const { repo_slug, workspace } = parseBitbucketOrganizationAndRepo(this.url);
|
|
5478
5533
|
return Promise.resolve(
|
|
5479
|
-
`https://bitbucket.org/${workspace}/${
|
|
5534
|
+
`https://bitbucket.org/${workspace}/${repo_slug}/commits/${commitId}`
|
|
5480
5535
|
);
|
|
5481
5536
|
}
|
|
5537
|
+
async addCommentToSubmitRequest(submitRequestId, comment) {
|
|
5538
|
+
this._validateUrl();
|
|
5539
|
+
await this.bitbucketSdk.addCommentToPullRequest({
|
|
5540
|
+
prNumber: Number(submitRequestId),
|
|
5541
|
+
url: this.url,
|
|
5542
|
+
markdownComment: comment
|
|
5543
|
+
});
|
|
5544
|
+
}
|
|
5482
5545
|
};
|
|
5483
5546
|
|
|
5484
5547
|
// src/features/analysis/scm/github/GithubSCMLib.ts
|
|
@@ -5639,6 +5702,14 @@ var GithubSCMLib = class extends SCMLib {
|
|
|
5639
5702
|
prNumber: Number(scmSubmitRequestId)
|
|
5640
5703
|
});
|
|
5641
5704
|
}
|
|
5705
|
+
async addCommentToSubmitRequest(submitRequestId, comment) {
|
|
5706
|
+
this._validateAccessTokenAndUrl();
|
|
5707
|
+
await this.githubSdk.createMarkdownCommentOnPullRequest({
|
|
5708
|
+
repoUrl: this.url,
|
|
5709
|
+
prNumber: Number(submitRequestId),
|
|
5710
|
+
markdownComment: comment
|
|
5711
|
+
});
|
|
5712
|
+
}
|
|
5642
5713
|
async getRepoBlameRanges(ref, path9) {
|
|
5643
5714
|
this._validateUrl();
|
|
5644
5715
|
return await this.githubSdk.getGithubBlameRanges({
|
|
@@ -5664,18 +5735,18 @@ var GithubSCMLib = class extends SCMLib {
|
|
|
5664
5735
|
this._validateUrl();
|
|
5665
5736
|
return await this.githubSdk.getGithubRepoDefaultBranch(this.url);
|
|
5666
5737
|
}
|
|
5667
|
-
async
|
|
5738
|
+
async getSubmitRequestUrl(submitRequestUrl) {
|
|
5668
5739
|
this._validateAccessTokenAndUrl();
|
|
5669
5740
|
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
5670
5741
|
const getPrRes = await this.githubSdk.getPr({
|
|
5671
5742
|
owner,
|
|
5672
5743
|
repo,
|
|
5673
|
-
pull_number:
|
|
5744
|
+
pull_number: submitRequestUrl
|
|
5674
5745
|
});
|
|
5675
5746
|
return getPrRes.data.html_url;
|
|
5676
5747
|
}
|
|
5677
|
-
async
|
|
5678
|
-
const match =
|
|
5748
|
+
async getSubmitRequestId(submitRequestUrl) {
|
|
5749
|
+
const match = submitRequestUrl.match(/\/pull\/(\d+)/);
|
|
5679
5750
|
return match?.[1] || "";
|
|
5680
5751
|
}
|
|
5681
5752
|
async getCommitUrl(commitId) {
|
|
@@ -5852,6 +5923,16 @@ async function getGitlabMergeRequestStatus({
|
|
|
5852
5923
|
throw new Error(`unknown merge request state ${res.state}`);
|
|
5853
5924
|
}
|
|
5854
5925
|
}
|
|
5926
|
+
async function createMarkdownCommentOnPullRequest({
|
|
5927
|
+
markdownComment,
|
|
5928
|
+
accessToken,
|
|
5929
|
+
repoUrl,
|
|
5930
|
+
mrNumber
|
|
5931
|
+
}) {
|
|
5932
|
+
const { projectPath } = parseGitlabOwnerAndRepo(repoUrl);
|
|
5933
|
+
const api2 = getGitBeaker({ url: repoUrl, gitlabAuthToken: accessToken });
|
|
5934
|
+
return api2.MergeRequestNotes.create(projectPath, mrNumber, markdownComment);
|
|
5935
|
+
}
|
|
5855
5936
|
async function getGitlabIsRemoteBranch({
|
|
5856
5937
|
accessToken,
|
|
5857
5938
|
repoUrl,
|
|
@@ -6202,6 +6283,15 @@ var GitlabSCMLib = class extends SCMLib {
|
|
|
6202
6283
|
throw new Error(`unknown state ${state}`);
|
|
6203
6284
|
}
|
|
6204
6285
|
}
|
|
6286
|
+
async addCommentToSubmitRequest(submitRequestId, comment) {
|
|
6287
|
+
this._validateAccessTokenAndUrl();
|
|
6288
|
+
await createMarkdownCommentOnPullRequest({
|
|
6289
|
+
accessToken: this.accessToken,
|
|
6290
|
+
repoUrl: this.url,
|
|
6291
|
+
mrNumber: Number(submitRequestId),
|
|
6292
|
+
markdownComment: comment
|
|
6293
|
+
});
|
|
6294
|
+
}
|
|
6205
6295
|
async getRepoBlameRanges(ref, path9) {
|
|
6206
6296
|
this._validateUrl();
|
|
6207
6297
|
return await getGitlabBlameRanges(
|
|
@@ -6229,17 +6319,17 @@ var GitlabSCMLib = class extends SCMLib {
|
|
|
6229
6319
|
gitlabAuthToken: this.accessToken
|
|
6230
6320
|
});
|
|
6231
6321
|
}
|
|
6232
|
-
async
|
|
6322
|
+
async getSubmitRequestUrl(submitRequestUrl) {
|
|
6233
6323
|
this._validateAccessTokenAndUrl();
|
|
6234
6324
|
const res = await getGitlabMergeRequest({
|
|
6235
6325
|
url: this.url,
|
|
6236
|
-
prNumber,
|
|
6326
|
+
prNumber: submitRequestUrl,
|
|
6237
6327
|
accessToken: this.accessToken
|
|
6238
6328
|
});
|
|
6239
6329
|
return res.web_url;
|
|
6240
6330
|
}
|
|
6241
|
-
async
|
|
6242
|
-
const match =
|
|
6331
|
+
async getSubmitRequestId(submitRequestUrl) {
|
|
6332
|
+
const match = submitRequestUrl.match(/\/merge_requests\/(\d+)/);
|
|
6243
6333
|
return match?.[1] || "";
|
|
6244
6334
|
}
|
|
6245
6335
|
async getCommitUrl(commitId) {
|
|
@@ -6324,12 +6414,12 @@ var StubSCMLib = class extends SCMLib {
|
|
|
6324
6414
|
console.warn("getRepoDefaultBranch() returning empty string");
|
|
6325
6415
|
return "";
|
|
6326
6416
|
}
|
|
6327
|
-
async
|
|
6328
|
-
console.warn("
|
|
6417
|
+
async getSubmitRequestUrl(_submitRequestIdNumber) {
|
|
6418
|
+
console.warn("getSubmitRequestUrl() returning empty string");
|
|
6329
6419
|
return "";
|
|
6330
6420
|
}
|
|
6331
|
-
async
|
|
6332
|
-
console.warn("
|
|
6421
|
+
async getSubmitRequestId(_submitRequestUrl) {
|
|
6422
|
+
console.warn("getSubmitRequestId() returning empty string");
|
|
6333
6423
|
return "";
|
|
6334
6424
|
}
|
|
6335
6425
|
async getCommitUrl(_commitId) {
|
|
@@ -6340,6 +6430,9 @@ var StubSCMLib = class extends SCMLib {
|
|
|
6340
6430
|
console.warn("_getUsernameForAuthUrl() returning empty string");
|
|
6341
6431
|
return "";
|
|
6342
6432
|
}
|
|
6433
|
+
async addCommentToSubmitRequest(_submitRequestId, _comment) {
|
|
6434
|
+
console.warn("addCommentToSubmitRequest() no-op");
|
|
6435
|
+
}
|
|
6343
6436
|
};
|
|
6344
6437
|
|
|
6345
6438
|
// src/features/analysis/scm/scmFactory.ts
|
|
@@ -6565,6 +6658,16 @@ function getGithubSdk(params = {}) {
|
|
|
6565
6658
|
}
|
|
6566
6659
|
return res.data.state;
|
|
6567
6660
|
},
|
|
6661
|
+
async createMarkdownCommentOnPullRequest(params2) {
|
|
6662
|
+
const { repoUrl, prNumber, markdownComment } = params2;
|
|
6663
|
+
const { owner, repo } = parseGithubOwnerAndRepo(repoUrl);
|
|
6664
|
+
return octokit.rest.issues.createComment({
|
|
6665
|
+
owner,
|
|
6666
|
+
repo,
|
|
6667
|
+
issue_number: prNumber,
|
|
6668
|
+
body: markdownComment
|
|
6669
|
+
});
|
|
6670
|
+
},
|
|
6568
6671
|
async getGithubIsRemoteBranch(params2) {
|
|
6569
6672
|
const { repoUrl, branch } = params2;
|
|
6570
6673
|
const { owner, repo } = parseGithubOwnerAndRepo(repoUrl);
|
|
@@ -7301,7 +7404,7 @@ async function addFixCommentsForPr({
|
|
|
7301
7404
|
import Debug9 from "debug";
|
|
7302
7405
|
var debug9 = Debug9("mobbdev:handleAutoPr");
|
|
7303
7406
|
async function handleAutoPr(params) {
|
|
7304
|
-
const { gqlClient, analysisId, commitDirectly, createSpinner: createSpinner5 } = params;
|
|
7407
|
+
const { gqlClient, analysisId, commitDirectly, prId, createSpinner: createSpinner5 } = params;
|
|
7305
7408
|
const createAutoPrSpinner = createSpinner5(
|
|
7306
7409
|
"\u{1F504} Waiting for the analysis to finish before initiating automatic pull request creation"
|
|
7307
7410
|
).start();
|
|
@@ -7312,7 +7415,8 @@ async function handleAutoPr(params) {
|
|
|
7312
7415
|
callback: async (analysisId2) => {
|
|
7313
7416
|
const autoPrAnalysisRes = await gqlClient.autoPrAnalysis(
|
|
7314
7417
|
analysisId2,
|
|
7315
|
-
commitDirectly
|
|
7418
|
+
commitDirectly,
|
|
7419
|
+
prId
|
|
7316
7420
|
);
|
|
7317
7421
|
debug9("auto pr analysis res %o", autoPrAnalysisRes);
|
|
7318
7422
|
if (autoPrAnalysisRes.autoPrAnalysis?.__typename === "AutoPrError") {
|
|
@@ -7770,10 +7874,11 @@ var GQLClient = class {
|
|
|
7770
7874
|
}
|
|
7771
7875
|
return res.analysis;
|
|
7772
7876
|
}
|
|
7773
|
-
async autoPrAnalysis(analysisId, commitDirectly) {
|
|
7877
|
+
async autoPrAnalysis(analysisId, commitDirectly, prId) {
|
|
7774
7878
|
return this._clientSdk.autoPrAnalysis({
|
|
7775
7879
|
analysisId,
|
|
7776
|
-
commitDirectly
|
|
7880
|
+
commitDirectly,
|
|
7881
|
+
prId
|
|
7777
7882
|
});
|
|
7778
7883
|
}
|
|
7779
7884
|
async getFixes(fixIds) {
|
|
@@ -7798,15 +7903,29 @@ import Debug12 from "debug";
|
|
|
7798
7903
|
import { globby } from "globby";
|
|
7799
7904
|
import { isBinary } from "istextorbinary";
|
|
7800
7905
|
import { simpleGit as simpleGit3 } from "simple-git";
|
|
7906
|
+
import { parseStringPromise } from "xml2js";
|
|
7907
|
+
import { z as z30 } from "zod";
|
|
7801
7908
|
var debug12 = Debug12("mobbdev:pack");
|
|
7802
7909
|
var MAX_FILE_SIZE = 1024 * 1024 * 5;
|
|
7910
|
+
var FPR_SOURCE_CODE_FILE_MAPPING_SCHEMA = z30.object({
|
|
7911
|
+
properties: z30.object({
|
|
7912
|
+
entry: z30.array(
|
|
7913
|
+
z30.object({
|
|
7914
|
+
_: z30.string(),
|
|
7915
|
+
$: z30.object({
|
|
7916
|
+
key: z30.string()
|
|
7917
|
+
})
|
|
7918
|
+
})
|
|
7919
|
+
)
|
|
7920
|
+
})
|
|
7921
|
+
});
|
|
7803
7922
|
function endsWithAny(str, suffixes) {
|
|
7804
7923
|
return suffixes.some(function(suffix) {
|
|
7805
7924
|
return str.endsWith(suffix);
|
|
7806
7925
|
});
|
|
7807
7926
|
}
|
|
7808
7927
|
function _get_manifest_files_suffixes() {
|
|
7809
|
-
return ["package.json"];
|
|
7928
|
+
return ["package.json", "pom.xml"];
|
|
7810
7929
|
}
|
|
7811
7930
|
async function pack(srcDirPath, vulnFiles) {
|
|
7812
7931
|
debug12("pack folder %s", srcDirPath);
|
|
@@ -7867,6 +7986,25 @@ async function pack(srcDirPath, vulnFiles) {
|
|
|
7867
7986
|
debug12("get zip file buffer");
|
|
7868
7987
|
return zip.toBuffer();
|
|
7869
7988
|
}
|
|
7989
|
+
async function repackFpr(fprPath) {
|
|
7990
|
+
debug12("repack fpr file %s", fprPath);
|
|
7991
|
+
const zipIn = new AdmZip(fprPath);
|
|
7992
|
+
const zipOut = new AdmZip();
|
|
7993
|
+
const mappingXML = zipIn.readAsText("src-archive/index.xml", "utf-8");
|
|
7994
|
+
const filesMapping = FPR_SOURCE_CODE_FILE_MAPPING_SCHEMA.parse(
|
|
7995
|
+
await parseStringPromise(mappingXML)
|
|
7996
|
+
);
|
|
7997
|
+
for (const fileMapping of filesMapping.properties.entry) {
|
|
7998
|
+
const zipPath = fileMapping._;
|
|
7999
|
+
const realPath = fileMapping.$.key;
|
|
8000
|
+
const buf = zipIn.readFile(zipPath);
|
|
8001
|
+
if (buf) {
|
|
8002
|
+
zipOut.addFile(realPath, buf);
|
|
8003
|
+
}
|
|
8004
|
+
}
|
|
8005
|
+
debug12("get repacked zip file buffer");
|
|
8006
|
+
return zipOut.toBuffer();
|
|
8007
|
+
}
|
|
7870
8008
|
|
|
7871
8009
|
// src/features/analysis/prompts.ts
|
|
7872
8010
|
import inquirer from "inquirer";
|
|
@@ -8411,7 +8549,8 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
8411
8549
|
command,
|
|
8412
8550
|
organizationId: userOrganizationId,
|
|
8413
8551
|
autoPr,
|
|
8414
|
-
commitDirectly
|
|
8552
|
+
commitDirectly,
|
|
8553
|
+
pullRequest
|
|
8415
8554
|
} = params;
|
|
8416
8555
|
debug16("start %s %s", dirname, repo);
|
|
8417
8556
|
const { createSpinner: createSpinner5 } = Spinner2({ ci });
|
|
@@ -8529,7 +8668,7 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
8529
8668
|
spinner: mobbSpinner,
|
|
8530
8669
|
submitVulnerabilityReportVariables: {
|
|
8531
8670
|
fixReportId: reportUploadInfo.fixReportId,
|
|
8532
|
-
repoUrl:
|
|
8671
|
+
repoUrl: z31.string().parse(repo),
|
|
8533
8672
|
reference,
|
|
8534
8673
|
projectId,
|
|
8535
8674
|
vulnerabilityReportFileName: "report.json",
|
|
@@ -8551,6 +8690,7 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
8551
8690
|
gqlClient,
|
|
8552
8691
|
analysisId: reportUploadInfo.fixReportId,
|
|
8553
8692
|
commitDirectly,
|
|
8693
|
+
prId: pullRequest,
|
|
8554
8694
|
createSpinner: createSpinner5
|
|
8555
8695
|
});
|
|
8556
8696
|
}
|
|
@@ -8642,9 +8782,16 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
8642
8782
|
projectId,
|
|
8643
8783
|
command
|
|
8644
8784
|
});
|
|
8645
|
-
const
|
|
8785
|
+
const srcFileStatus = await fsPromises.lstat(srcPath);
|
|
8646
8786
|
const zippingSpinner = createSpinner5("\u{1F4E6} Zipping repo").start();
|
|
8647
|
-
|
|
8787
|
+
let zipBuffer;
|
|
8788
|
+
let gitInfo = { success: false };
|
|
8789
|
+
if (srcFileStatus.isFile() && path7.extname(srcPath).toLowerCase() === ".fpr") {
|
|
8790
|
+
zipBuffer = await repackFpr(srcPath);
|
|
8791
|
+
} else {
|
|
8792
|
+
gitInfo = await getGitInfo(srcPath);
|
|
8793
|
+
zipBuffer = await pack(srcPath, vulnFiles);
|
|
8794
|
+
}
|
|
8648
8795
|
zippingSpinner.success({ text: "\u{1F4E6} Zipping repo successful!" });
|
|
8649
8796
|
const uploadRepoSpinner = createSpinner5("\u{1F4C1} Uploading Repo").start();
|
|
8650
8797
|
try {
|
|
@@ -8675,9 +8822,9 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
8675
8822
|
}
|
|
8676
8823
|
});
|
|
8677
8824
|
if (command === "review") {
|
|
8678
|
-
const params2 =
|
|
8679
|
-
repo:
|
|
8680
|
-
githubActionToken:
|
|
8825
|
+
const params2 = z31.object({
|
|
8826
|
+
repo: z31.string().url(),
|
|
8827
|
+
githubActionToken: z31.string()
|
|
8681
8828
|
}).parse({ repo, githubActionToken });
|
|
8682
8829
|
const scm = await createScmLib(
|
|
8683
8830
|
{
|
|
@@ -8699,7 +8846,7 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
8699
8846
|
analysisId,
|
|
8700
8847
|
gqlClient,
|
|
8701
8848
|
scm,
|
|
8702
|
-
scanner:
|
|
8849
|
+
scanner: z31.nativeEnum(SCANNERS).parse(scanner)
|
|
8703
8850
|
});
|
|
8704
8851
|
},
|
|
8705
8852
|
callbackStates: ["Finished" /* Finished */]
|
|
@@ -8717,6 +8864,7 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
8717
8864
|
gqlClient,
|
|
8718
8865
|
analysisId: reportUploadInfo.fixReportId,
|
|
8719
8866
|
commitDirectly,
|
|
8867
|
+
prId: pullRequest,
|
|
8720
8868
|
createSpinner: createSpinner5
|
|
8721
8869
|
});
|
|
8722
8870
|
}
|
|
@@ -8823,7 +8971,8 @@ async function analyze({
|
|
|
8823
8971
|
mobbProjectName,
|
|
8824
8972
|
organizationId,
|
|
8825
8973
|
autoPr,
|
|
8826
|
-
commitDirectly
|
|
8974
|
+
commitDirectly,
|
|
8975
|
+
pullRequest
|
|
8827
8976
|
}, { skipPrompts = false } = {}) {
|
|
8828
8977
|
!ci && await showWelcomeMessage(skipPrompts);
|
|
8829
8978
|
await runAnalysis(
|
|
@@ -8839,7 +8988,8 @@ async function analyze({
|
|
|
8839
8988
|
organizationId,
|
|
8840
8989
|
command: "analyze",
|
|
8841
8990
|
autoPr,
|
|
8842
|
-
commitDirectly
|
|
8991
|
+
commitDirectly,
|
|
8992
|
+
pullRequest
|
|
8843
8993
|
},
|
|
8844
8994
|
{ skipPrompts }
|
|
8845
8995
|
);
|
|
@@ -9082,7 +9232,7 @@ var scmTokenOption = {
|
|
|
9082
9232
|
// src/args/validation.ts
|
|
9083
9233
|
import chalk7 from "chalk";
|
|
9084
9234
|
import path8 from "path";
|
|
9085
|
-
import { z as
|
|
9235
|
+
import { z as z32 } from "zod";
|
|
9086
9236
|
function throwRepoUrlErrorMessage({
|
|
9087
9237
|
error,
|
|
9088
9238
|
repoUrl,
|
|
@@ -9099,11 +9249,11 @@ Example:
|
|
|
9099
9249
|
)}`;
|
|
9100
9250
|
throw new CliError(formattedErrorMessage);
|
|
9101
9251
|
}
|
|
9102
|
-
var UrlZ =
|
|
9252
|
+
var UrlZ = z32.string({
|
|
9103
9253
|
invalid_type_error: `is not a valid ${Object.values(ScmType).join("/ ")} URL`
|
|
9104
9254
|
});
|
|
9105
9255
|
function validateOrganizationId(organizationId) {
|
|
9106
|
-
const orgIdValidation =
|
|
9256
|
+
const orgIdValidation = z32.string().uuid().nullish().safeParse(organizationId);
|
|
9107
9257
|
if (!orgIdValidation.success) {
|
|
9108
9258
|
throw new CliError(`organizationId: ${organizationId} is not a valid UUID`);
|
|
9109
9259
|
}
|
|
@@ -9150,14 +9300,19 @@ function analyzeBuilder(yargs2) {
|
|
|
9150
9300
|
}).option("repo", repoOption).option("p", {
|
|
9151
9301
|
alias: "src-path",
|
|
9152
9302
|
describe: chalk8.bold(
|
|
9153
|
-
"Path to the repository folder with the source code"
|
|
9303
|
+
"Path to the repository folder with the source code; alternatively, you can specify the Fortify FPR file to extract source code out of it"
|
|
9154
9304
|
),
|
|
9155
9305
|
type: "string"
|
|
9156
9306
|
}).option("ref", refOption).option("ch", {
|
|
9157
9307
|
alias: "commit-hash",
|
|
9158
9308
|
describe: chalk8.bold("Hash of the commit"),
|
|
9159
9309
|
type: "string"
|
|
9160
|
-
}).option("mobb-project-name", mobbProjectNameOption).option("y", yesOption).option("ci", ciOption).option("org", organizationIdOptions).option("api-key", apiKeyOption).option("commit-hash", commitHashOption).option("auto-pr", autoPrOption).option("commit-directly", commitDirectlyOption).
|
|
9310
|
+
}).option("mobb-project-name", mobbProjectNameOption).option("y", yesOption).option("ci", ciOption).option("org", organizationIdOptions).option("api-key", apiKeyOption).option("commit-hash", commitHashOption).option("auto-pr", autoPrOption).option("commit-directly", commitDirectlyOption).option("pull-request", {
|
|
9311
|
+
alias: ["pr", "pr-number", "pr-id"],
|
|
9312
|
+
describe: chalk8.bold("Number of the pull request"),
|
|
9313
|
+
type: "number",
|
|
9314
|
+
demandOption: false
|
|
9315
|
+
}).example(
|
|
9161
9316
|
"npx mobbdev@latest analyze -r https://github.com/WebGoat/WebGoat -f <your_vulnerability_report_path>",
|
|
9162
9317
|
"analyze an existing repository"
|
|
9163
9318
|
).help();
|
|
@@ -9182,6 +9337,11 @@ Can't access ${chalk8.bold(argv.f)}`);
|
|
|
9182
9337
|
"--commit-directly flag requires --auto-pr to be provided as well"
|
|
9183
9338
|
);
|
|
9184
9339
|
}
|
|
9340
|
+
if (argv.pullRequest && !argv["commit-directly"]) {
|
|
9341
|
+
throw new CliError(
|
|
9342
|
+
"--pull-request flag requires --commit-directly to be provided as well"
|
|
9343
|
+
);
|
|
9344
|
+
}
|
|
9185
9345
|
validateReportFileFormat(argv.f);
|
|
9186
9346
|
}
|
|
9187
9347
|
async function analyzeHandler(args) {
|
|
@@ -9210,7 +9370,7 @@ function reviewBuilder(yargs2) {
|
|
|
9210
9370
|
type: "string",
|
|
9211
9371
|
demandOption: true
|
|
9212
9372
|
}).option("pull-request", {
|
|
9213
|
-
alias: "pr",
|
|
9373
|
+
alias: ["pr", "pr-number", "pr-id"],
|
|
9214
9374
|
describe: chalk9.bold("Number of the pull request"),
|
|
9215
9375
|
type: "number",
|
|
9216
9376
|
demandOption: true
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mobbdev",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.47",
|
|
4
4
|
"description": "Automated secure code remediation tool",
|
|
5
5
|
"repository": "git+https://github.com/mobb-dev/bugsy.git",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -70,6 +70,7 @@
|
|
|
70
70
|
"undici": "6.21.1",
|
|
71
71
|
"uuid": "11.1.0",
|
|
72
72
|
"ws": "8.18.0",
|
|
73
|
+
"xml2js": "0.6.2",
|
|
73
74
|
"yargs": "17.7.2",
|
|
74
75
|
"zod": "3.24.2"
|
|
75
76
|
},
|
|
@@ -89,6 +90,7 @@
|
|
|
89
90
|
"@types/tmp": "0.2.6",
|
|
90
91
|
"@types/uuid": "10.0.0",
|
|
91
92
|
"@types/ws": "8.5.14",
|
|
93
|
+
"@types/xml2js": "0.4.14",
|
|
92
94
|
"@types/yargs": "17.0.33",
|
|
93
95
|
"@typescript-eslint/eslint-plugin": "7.17.0",
|
|
94
96
|
"@typescript-eslint/parser": "7.17.0",
|