mobbdev 0.0.67 → 0.0.69
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 +347 -94
- package/package.json +3 -1
package/dist/index.mjs
CHANGED
|
@@ -163,7 +163,7 @@ import fetch3 from "node-fetch";
|
|
|
163
163
|
import open2 from "open";
|
|
164
164
|
import semver from "semver";
|
|
165
165
|
import tmp2 from "tmp";
|
|
166
|
-
import { z as
|
|
166
|
+
import { z as z9 } from "zod";
|
|
167
167
|
|
|
168
168
|
// src/features/analysis/git.ts
|
|
169
169
|
import Debug2 from "debug";
|
|
@@ -274,6 +274,7 @@ var SUBMIT_VULNERABILITY_REPORT = gql`
|
|
|
274
274
|
$reference: String!
|
|
275
275
|
$projectId: String!
|
|
276
276
|
$sha: String
|
|
277
|
+
$experimentalEnabled: Boolean
|
|
277
278
|
$vulnerabilityReportFileName: String
|
|
278
279
|
$pullRequest: Int
|
|
279
280
|
) {
|
|
@@ -282,6 +283,7 @@ var SUBMIT_VULNERABILITY_REPORT = gql`
|
|
|
282
283
|
repoUrl: $repoUrl
|
|
283
284
|
reference: $reference
|
|
284
285
|
sha: $sha
|
|
286
|
+
experimentalEnabled: $experimentalEnabled
|
|
285
287
|
pullRequest: $pullRequest
|
|
286
288
|
projectId: $projectId
|
|
287
289
|
vulnerabilityReportFileName: $vulnerabilityReportFileName
|
|
@@ -762,6 +764,7 @@ var GQLClient = class {
|
|
|
762
764
|
const filters = hunks.map((hunk) => {
|
|
763
765
|
const filter = {
|
|
764
766
|
path: { _eq: hunk.path },
|
|
767
|
+
vulnerabilityReportIssue: { fixId: { _is_null: false } },
|
|
765
768
|
_or: hunk.ranges.map(({ endLine, startLine }) => ({
|
|
766
769
|
startLine: { _gte: startLine, _lte: endLine },
|
|
767
770
|
endLine: { _gte: startLine, _lte: endLine }
|
|
@@ -812,6 +815,7 @@ var GQLClient = class {
|
|
|
812
815
|
reference,
|
|
813
816
|
projectId,
|
|
814
817
|
sha,
|
|
818
|
+
experimentalEnabled,
|
|
815
819
|
vulnerabilityReportFileName,
|
|
816
820
|
pullRequest
|
|
817
821
|
} = params;
|
|
@@ -822,7 +826,8 @@ var GQLClient = class {
|
|
|
822
826
|
vulnerabilityReportFileName,
|
|
823
827
|
projectId,
|
|
824
828
|
pullRequest,
|
|
825
|
-
sha: sha || ""
|
|
829
|
+
sha: sha || "",
|
|
830
|
+
experimentalEnabled
|
|
826
831
|
});
|
|
827
832
|
return CreateUpdateFixReportMutationZ.parse(res);
|
|
828
833
|
}
|
|
@@ -897,15 +902,30 @@ var GQLClient = class {
|
|
|
897
902
|
// src/features/analysis/handle_finished_analysis.ts
|
|
898
903
|
import Debug4 from "debug";
|
|
899
904
|
import parseDiff from "parse-diff";
|
|
900
|
-
import { z as
|
|
905
|
+
import { z as z8 } from "zod";
|
|
906
|
+
|
|
907
|
+
// src/features/analysis/scm/constants.ts
|
|
908
|
+
var MOBB_ICON_IMG = "https://app.mobb.ai/mobb.png";
|
|
909
|
+
var COMMIT_FIX_SVG = `https://app.mobb.ai/gh-action/commit-button.svg`;
|
|
901
910
|
|
|
902
911
|
// src/features/analysis/scm/gitlab.ts
|
|
903
912
|
import querystring from "node:querystring";
|
|
904
913
|
import { Gitlab } from "@gitbeaker/rest";
|
|
905
|
-
import { z as
|
|
914
|
+
import { z as z7 } from "zod";
|
|
906
915
|
|
|
907
916
|
// src/features/analysis/scm/scm.ts
|
|
908
917
|
import { Octokit as Octokit2 } from "@octokit/core";
|
|
918
|
+
import { z as z6 } from "zod";
|
|
919
|
+
|
|
920
|
+
// src/features/analysis/scm/github/encryptSecret.ts
|
|
921
|
+
import sodium from "libsodium-wrappers";
|
|
922
|
+
async function encryptSecret(secret, key) {
|
|
923
|
+
await sodium.ready;
|
|
924
|
+
const binkey = sodium.from_base64(key, sodium.base64_variants.ORIGINAL);
|
|
925
|
+
const binsec = sodium.from_string(secret);
|
|
926
|
+
const encBytes = sodium.crypto_box_seal(binsec, binkey);
|
|
927
|
+
return sodium.to_base64(encBytes, sodium.base64_variants.ORIGINAL);
|
|
928
|
+
}
|
|
909
929
|
|
|
910
930
|
// src/features/analysis/scm/github/github.ts
|
|
911
931
|
import { RequestError } from "@octokit/request-error";
|
|
@@ -1137,6 +1157,16 @@ async function createPullRequest(options) {
|
|
|
1137
1157
|
});
|
|
1138
1158
|
return res.data.number;
|
|
1139
1159
|
}
|
|
1160
|
+
async function forkRepo(options) {
|
|
1161
|
+
const { owner, repo } = parseOwnerAndRepo(options.repoUrl);
|
|
1162
|
+
const oktoKit = getOktoKit({ githubAuthToken: options.accessToken });
|
|
1163
|
+
const res = await oktoKit.rest.repos.createFork({
|
|
1164
|
+
owner,
|
|
1165
|
+
repo,
|
|
1166
|
+
default_branch_only: false
|
|
1167
|
+
});
|
|
1168
|
+
return { url: res.data.html_url ? String(res.data.html_url) : null };
|
|
1169
|
+
}
|
|
1140
1170
|
async function getRepos(oktoKit) {
|
|
1141
1171
|
const res = await oktoKit.request("GET /user/repos?sort=updated", {
|
|
1142
1172
|
headers: {
|
|
@@ -1285,13 +1315,83 @@ async function getGithubBlameRanges({ ref, gitHubUrl, path: path8 }, options) {
|
|
|
1285
1315
|
login: range.commit.author.user.login
|
|
1286
1316
|
}));
|
|
1287
1317
|
}
|
|
1318
|
+
async function createPr({
|
|
1319
|
+
sourceRepoUrl,
|
|
1320
|
+
sourceFilePath,
|
|
1321
|
+
targetFilePath,
|
|
1322
|
+
userRepoUrl,
|
|
1323
|
+
title
|
|
1324
|
+
}, options) {
|
|
1325
|
+
const oktoKit = getOktoKit(options);
|
|
1326
|
+
const { owner: sourceOwner, repo: sourceRepo } = parseOwnerAndRepo(sourceRepoUrl);
|
|
1327
|
+
const { owner, repo } = parseOwnerAndRepo(userRepoUrl);
|
|
1328
|
+
const sourceFileContentResponse = await oktoKit.rest.repos.getContent({
|
|
1329
|
+
owner: sourceOwner,
|
|
1330
|
+
repo: sourceRepo,
|
|
1331
|
+
path: "/" + sourceFilePath
|
|
1332
|
+
});
|
|
1333
|
+
const newBranchName = `mobb/workflow-${Date.now()}`;
|
|
1334
|
+
oktoKit.rest.git.createRef({
|
|
1335
|
+
owner,
|
|
1336
|
+
repo,
|
|
1337
|
+
ref: `refs/heads/${newBranchName}`,
|
|
1338
|
+
sha: await oktoKit.rest.git.getRef({ owner, repo, ref: "heads/main" }).then((response) => response.data.object.sha)
|
|
1339
|
+
});
|
|
1340
|
+
const decodedContent = Buffer.from(
|
|
1341
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
1342
|
+
// @ts-ignore
|
|
1343
|
+
sourceFileContentResponse.data.content,
|
|
1344
|
+
"base64"
|
|
1345
|
+
).toString("utf-8");
|
|
1346
|
+
const createTreeResponse = await oktoKit.rest.git.createTree({
|
|
1347
|
+
owner,
|
|
1348
|
+
repo,
|
|
1349
|
+
base_tree: await oktoKit.rest.git.getRef({ owner, repo, ref: `heads/main` }).then((response) => response.data.object.sha),
|
|
1350
|
+
tree: [
|
|
1351
|
+
{
|
|
1352
|
+
path: targetFilePath,
|
|
1353
|
+
mode: "100644",
|
|
1354
|
+
type: "blob",
|
|
1355
|
+
content: decodedContent
|
|
1356
|
+
}
|
|
1357
|
+
]
|
|
1358
|
+
});
|
|
1359
|
+
const createCommitResponse = await oktoKit.rest.git.createCommit({
|
|
1360
|
+
owner,
|
|
1361
|
+
repo,
|
|
1362
|
+
message: "Add new yaml file",
|
|
1363
|
+
tree: createTreeResponse.data.sha,
|
|
1364
|
+
parents: [
|
|
1365
|
+
await oktoKit.rest.git.getRef({ owner, repo, ref: `heads/main` }).then((response) => response.data.object.sha)
|
|
1366
|
+
]
|
|
1367
|
+
});
|
|
1368
|
+
await oktoKit.rest.git.updateRef({
|
|
1369
|
+
owner,
|
|
1370
|
+
repo,
|
|
1371
|
+
ref: `heads/${newBranchName}`,
|
|
1372
|
+
sha: createCommitResponse.data.sha
|
|
1373
|
+
});
|
|
1374
|
+
const createPRResponse = await oktoKit.rest.pulls.create({
|
|
1375
|
+
owner,
|
|
1376
|
+
repo,
|
|
1377
|
+
title,
|
|
1378
|
+
head: newBranchName,
|
|
1379
|
+
base: "main"
|
|
1380
|
+
});
|
|
1381
|
+
return {
|
|
1382
|
+
pull_request_url: createPRResponse.data.html_url
|
|
1383
|
+
};
|
|
1384
|
+
}
|
|
1288
1385
|
|
|
1289
1386
|
// src/features/analysis/scm/github/consts.ts
|
|
1290
1387
|
var POST_COMMENT_PATH = "POST /repos/{owner}/{repo}/pulls/{pull_number}/comments";
|
|
1291
1388
|
var DELETE_COMMENT_PATH = "DELETE /repos/{owner}/{repo}/pulls/comments/{comment_id}";
|
|
1292
1389
|
var UPDATE_COMMENT_PATH = "PATCH /repos/{owner}/{repo}/pulls/comments/{comment_id}";
|
|
1293
|
-
var GET_PR_COMMENTS_PATH = "GET /repos/{owner}/{repo}/pulls/comments";
|
|
1390
|
+
var GET_PR_COMMENTS_PATH = "GET /repos/{owner}/{repo}/pulls/{pull_number}/comments";
|
|
1391
|
+
var GET_PR_COMMENT_PATH = "GET /repos/{owner}/{repo}/pulls/comments/{comment_id}";
|
|
1294
1392
|
var GET_PR = "GET /repos/{owner}/{repo}/pulls/{pull_number}";
|
|
1393
|
+
var CREATE_OR_UPDATE_A_REPOSITORY_SECRET = "PUT /repos/{owner}/{repo}/actions/secrets/{secret_name}";
|
|
1394
|
+
var GET_A_REPOSITORY_PUBLIC_KEY = "GET /repos/{owner}/{repo}/actions/secrets/public-key";
|
|
1295
1395
|
|
|
1296
1396
|
// src/features/analysis/scm/github/github-v2.ts
|
|
1297
1397
|
function postPrComment(client, params) {
|
|
@@ -1303,32 +1403,32 @@ function updatePrComment(client, params) {
|
|
|
1303
1403
|
function getPrComments(client, params) {
|
|
1304
1404
|
return client.request(GET_PR_COMMENTS_PATH, params);
|
|
1305
1405
|
}
|
|
1406
|
+
function getPrComment(client, params) {
|
|
1407
|
+
return client.request(GET_PR_COMMENT_PATH, params);
|
|
1408
|
+
}
|
|
1306
1409
|
function deleteComment(client, params) {
|
|
1307
1410
|
return client.request(DELETE_COMMENT_PATH, params);
|
|
1308
1411
|
}
|
|
1309
|
-
function
|
|
1310
|
-
return client.request(GET_PR, params);
|
|
1412
|
+
function getPrDiff(client, params) {
|
|
1413
|
+
return client.request(GET_PR, { ...params, mediaType: { format: "diff" } });
|
|
1414
|
+
}
|
|
1415
|
+
function createOrUpdateRepositorySecret(client, params) {
|
|
1416
|
+
return client.request(CREATE_OR_UPDATE_A_REPOSITORY_SECRET, params);
|
|
1417
|
+
}
|
|
1418
|
+
function getARepositoryPublicKey(client, params) {
|
|
1419
|
+
return client.request(GET_A_REPOSITORY_PUBLIC_KEY, params);
|
|
1311
1420
|
}
|
|
1312
1421
|
|
|
1313
|
-
// src/features/analysis/scm/scmSubmit.ts
|
|
1422
|
+
// src/features/analysis/scm/scmSubmit/index.ts
|
|
1314
1423
|
import fs from "node:fs/promises";
|
|
1315
1424
|
import os from "os";
|
|
1316
1425
|
import path3 from "path";
|
|
1317
1426
|
import { simpleGit as simpleGit2 } from "simple-git";
|
|
1318
1427
|
import tmp from "tmp";
|
|
1428
|
+
import { z as z5 } from "zod";
|
|
1429
|
+
|
|
1430
|
+
// src/features/analysis/scm/scmSubmit/types.ts
|
|
1319
1431
|
import { z as z4 } from "zod";
|
|
1320
|
-
var isValidBranchName = async (branchName) => {
|
|
1321
|
-
const git = simpleGit2();
|
|
1322
|
-
try {
|
|
1323
|
-
const res = await git.raw(["check-ref-format", "--branch", branchName]);
|
|
1324
|
-
if (res) {
|
|
1325
|
-
return true;
|
|
1326
|
-
}
|
|
1327
|
-
return false;
|
|
1328
|
-
} catch (e) {
|
|
1329
|
-
return false;
|
|
1330
|
-
}
|
|
1331
|
-
};
|
|
1332
1432
|
var BaseSubmitToScmMessageZ = z4.object({
|
|
1333
1433
|
submitFixRequestId: z4.string().uuid(),
|
|
1334
1434
|
fixes: z4.array(
|
|
@@ -1349,7 +1449,8 @@ var CommitToSameBranchParamsZ = BaseSubmitToScmMessageZ.merge(
|
|
|
1349
1449
|
type: z4.literal(submitToScmMessageType.commitToSameBranch),
|
|
1350
1450
|
branch: z4.string(),
|
|
1351
1451
|
commitMessage: z4.string(),
|
|
1352
|
-
commitDescription: z4.string().nullish()
|
|
1452
|
+
commitDescription: z4.string().nullish(),
|
|
1453
|
+
githubCommentId: z4.number().nullish()
|
|
1353
1454
|
})
|
|
1354
1455
|
);
|
|
1355
1456
|
var SubmitFixesToDifferentBranchParamsZ = z4.object({
|
|
@@ -1366,8 +1467,7 @@ var FixResponseArrayZ = z4.array(
|
|
|
1366
1467
|
fixId: z4.string().uuid()
|
|
1367
1468
|
})
|
|
1368
1469
|
);
|
|
1369
|
-
var
|
|
1370
|
-
type: z4.nativeEnum(submitToScmMessageType),
|
|
1470
|
+
var SubmitFixesBaseResponseMessageZ = z4.object({
|
|
1371
1471
|
submitFixRequestId: z4.string().uuid(),
|
|
1372
1472
|
submitBranches: z4.array(
|
|
1373
1473
|
z4.object({
|
|
@@ -1387,7 +1487,33 @@ var SubmitFixesResponseMessageZ = z4.object({
|
|
|
1387
1487
|
})
|
|
1388
1488
|
}).optional()
|
|
1389
1489
|
});
|
|
1390
|
-
var
|
|
1490
|
+
var SubmitFixesToSameBranchResponseMessageZ = z4.object({
|
|
1491
|
+
type: z4.literal(submitToScmMessageType.commitToSameBranch),
|
|
1492
|
+
githubCommentId: z4.number().nullish()
|
|
1493
|
+
}).merge(SubmitFixesBaseResponseMessageZ);
|
|
1494
|
+
var SubmitFixesToDifferentBranchResponseMessageZ = z4.object({
|
|
1495
|
+
type: z4.literal(submitToScmMessageType.submitFixesForDifferentBranch),
|
|
1496
|
+
githubCommentId: z4.number().optional()
|
|
1497
|
+
}).merge(SubmitFixesBaseResponseMessageZ);
|
|
1498
|
+
var SubmitFixeResponseMessageZ = z4.discriminatedUnion("type", [
|
|
1499
|
+
SubmitFixesToSameBranchResponseMessageZ,
|
|
1500
|
+
SubmitFixesToDifferentBranchResponseMessageZ
|
|
1501
|
+
]);
|
|
1502
|
+
|
|
1503
|
+
// src/features/analysis/scm/scmSubmit/index.ts
|
|
1504
|
+
var isValidBranchName = async (branchName) => {
|
|
1505
|
+
const git = simpleGit2();
|
|
1506
|
+
try {
|
|
1507
|
+
const res = await git.raw(["check-ref-format", "--branch", branchName]);
|
|
1508
|
+
if (res) {
|
|
1509
|
+
return true;
|
|
1510
|
+
}
|
|
1511
|
+
return false;
|
|
1512
|
+
} catch (e) {
|
|
1513
|
+
return false;
|
|
1514
|
+
}
|
|
1515
|
+
};
|
|
1516
|
+
var FixesZ = z5.array(z5.object({ fixId: z5.string(), diff: z5.string() })).nonempty();
|
|
1391
1517
|
|
|
1392
1518
|
// src/features/analysis/scm/scm.ts
|
|
1393
1519
|
function getScmLibTypeFromUrl(url) {
|
|
@@ -1538,6 +1664,23 @@ var GitlabSCMLib = class extends SCMLib {
|
|
|
1538
1664
|
accessToken: this.accessToken
|
|
1539
1665
|
});
|
|
1540
1666
|
}
|
|
1667
|
+
async forkRepo() {
|
|
1668
|
+
if (!this.accessToken) {
|
|
1669
|
+
console.error("no access token");
|
|
1670
|
+
throw new Error("no access token");
|
|
1671
|
+
}
|
|
1672
|
+
throw new Error("not supported yet");
|
|
1673
|
+
}
|
|
1674
|
+
async createOrUpdateRepositorySecret() {
|
|
1675
|
+
if (!this.accessToken) {
|
|
1676
|
+
console.error("no access token");
|
|
1677
|
+
throw new Error("no access token");
|
|
1678
|
+
}
|
|
1679
|
+
throw new Error("not supported yet");
|
|
1680
|
+
}
|
|
1681
|
+
async createPullRequestWithNewFile(_sourceRepoUrl, _sourceFilePath, _targetFilePath, _userRepoUrl, _title) {
|
|
1682
|
+
throw new Error("not implemented");
|
|
1683
|
+
}
|
|
1541
1684
|
async getRepoList() {
|
|
1542
1685
|
if (!this.accessToken) {
|
|
1543
1686
|
console.error("no access token");
|
|
@@ -1659,8 +1802,15 @@ var GitlabSCMLib = class extends SCMLib {
|
|
|
1659
1802
|
gitlabAuthToken: this.accessToken
|
|
1660
1803
|
});
|
|
1661
1804
|
}
|
|
1805
|
+
getPrComment(_commentId) {
|
|
1806
|
+
throw new Error("getPrComment not implemented.");
|
|
1807
|
+
}
|
|
1808
|
+
updatePrComment(_params, _oktokit) {
|
|
1809
|
+
throw new Error("updatePrComment not implemented.");
|
|
1810
|
+
}
|
|
1662
1811
|
};
|
|
1663
1812
|
var GithubSCMLib = class extends SCMLib {
|
|
1813
|
+
// we don't always need a url, what's important is that we have an access token
|
|
1664
1814
|
constructor(url, accessToken) {
|
|
1665
1815
|
super(url, accessToken);
|
|
1666
1816
|
__publicField(this, "oktokit");
|
|
@@ -1682,6 +1832,54 @@ var GithubSCMLib = class extends SCMLib {
|
|
|
1682
1832
|
})
|
|
1683
1833
|
);
|
|
1684
1834
|
}
|
|
1835
|
+
async forkRepo(repoUrl) {
|
|
1836
|
+
if (!this.accessToken) {
|
|
1837
|
+
console.error("no access token");
|
|
1838
|
+
throw new Error("no access token");
|
|
1839
|
+
}
|
|
1840
|
+
return forkRepo({
|
|
1841
|
+
repoUrl,
|
|
1842
|
+
accessToken: this.accessToken
|
|
1843
|
+
});
|
|
1844
|
+
}
|
|
1845
|
+
async createOrUpdateRepositorySecret(params, _oktokit) {
|
|
1846
|
+
if (!_oktokit && !this.accessToken || !this.url) {
|
|
1847
|
+
throw new Error("cannot delete comment without access token or url");
|
|
1848
|
+
}
|
|
1849
|
+
const oktokit = _oktokit || this.oktokit;
|
|
1850
|
+
const { owner, repo } = parseOwnerAndRepo(this.url);
|
|
1851
|
+
const { data: repositoryPublicKeyResponse } = await getARepositoryPublicKey(
|
|
1852
|
+
oktokit,
|
|
1853
|
+
{
|
|
1854
|
+
owner,
|
|
1855
|
+
repo
|
|
1856
|
+
}
|
|
1857
|
+
);
|
|
1858
|
+
const { key_id, key } = repositoryPublicKeyResponse;
|
|
1859
|
+
const encryptedValue = await encryptSecret(params.value, key);
|
|
1860
|
+
return createOrUpdateRepositorySecret(oktokit, {
|
|
1861
|
+
encrypted_value: encryptedValue,
|
|
1862
|
+
secret_name: params.name,
|
|
1863
|
+
key_id,
|
|
1864
|
+
owner,
|
|
1865
|
+
repo
|
|
1866
|
+
});
|
|
1867
|
+
}
|
|
1868
|
+
async createPullRequestWithNewFile(sourceRepoUrl, sourceFilePath, targetFilePath, userRepoUrl, title) {
|
|
1869
|
+
const { pull_request_url } = await createPr(
|
|
1870
|
+
{
|
|
1871
|
+
sourceRepoUrl,
|
|
1872
|
+
sourceFilePath,
|
|
1873
|
+
targetFilePath,
|
|
1874
|
+
userRepoUrl,
|
|
1875
|
+
title
|
|
1876
|
+
},
|
|
1877
|
+
{
|
|
1878
|
+
githubAuthToken: this.accessToken
|
|
1879
|
+
}
|
|
1880
|
+
);
|
|
1881
|
+
return { pull_request_url };
|
|
1882
|
+
}
|
|
1685
1883
|
async validateParams() {
|
|
1686
1884
|
return githubValidateParams(this.url, this.accessToken);
|
|
1687
1885
|
}
|
|
@@ -1739,13 +1937,12 @@ var GithubSCMLib = class extends SCMLib {
|
|
|
1739
1937
|
throw new Error("cannot get Pr Comments without access token or url");
|
|
1740
1938
|
}
|
|
1741
1939
|
const { owner, repo } = parseOwnerAndRepo(this.url);
|
|
1742
|
-
const prRes = await
|
|
1940
|
+
const prRes = await getPrDiff(this.oktokit, {
|
|
1743
1941
|
...params,
|
|
1744
1942
|
owner,
|
|
1745
1943
|
repo
|
|
1746
1944
|
});
|
|
1747
|
-
|
|
1748
|
-
return this.oktokit.request("GET " + diffUrl);
|
|
1945
|
+
return z6.string().parse(prRes.data);
|
|
1749
1946
|
}
|
|
1750
1947
|
async getRepoList() {
|
|
1751
1948
|
if (!this.accessToken) {
|
|
@@ -1843,6 +2040,18 @@ var GithubSCMLib = class extends SCMLib {
|
|
|
1843
2040
|
}
|
|
1844
2041
|
);
|
|
1845
2042
|
}
|
|
2043
|
+
async getPrComment(commentId) {
|
|
2044
|
+
if (!this.url) {
|
|
2045
|
+
console.error("no url");
|
|
2046
|
+
throw new Error("no url");
|
|
2047
|
+
}
|
|
2048
|
+
const { owner, repo } = parseOwnerAndRepo(this.url);
|
|
2049
|
+
return await getPrComment(this.oktokit, {
|
|
2050
|
+
repo,
|
|
2051
|
+
owner,
|
|
2052
|
+
comment_id: commentId
|
|
2053
|
+
});
|
|
2054
|
+
}
|
|
1846
2055
|
async getRepoDefaultBranch() {
|
|
1847
2056
|
if (!this.url) {
|
|
1848
2057
|
console.error("no url");
|
|
@@ -1878,6 +2087,18 @@ var StubSCMLib = class extends SCMLib {
|
|
|
1878
2087
|
console.error("validateParams() not implemented");
|
|
1879
2088
|
throw new Error("validateParams() not implemented");
|
|
1880
2089
|
}
|
|
2090
|
+
async forkRepo() {
|
|
2091
|
+
console.error("forkRepo() not implemented");
|
|
2092
|
+
throw new Error("forkRepo() not implemented");
|
|
2093
|
+
}
|
|
2094
|
+
async createOrUpdateRepositorySecret() {
|
|
2095
|
+
console.error("forkRepo() not implemented");
|
|
2096
|
+
throw new Error("forkRepo() not implemented");
|
|
2097
|
+
}
|
|
2098
|
+
async createPullRequestWithNewFile(_sourceRepoUrl, _sourceFilePath, _targetFilePath, _userRepoUrl, _title) {
|
|
2099
|
+
console.error("createPullRequestWithNewFile() not implemented");
|
|
2100
|
+
throw new Error("createPullRequestWithNewFile() not implemented");
|
|
2101
|
+
}
|
|
1881
2102
|
async getRepoList() {
|
|
1882
2103
|
console.error("getBranchList() not implemented");
|
|
1883
2104
|
throw new Error("getBranchList() not implemented");
|
|
@@ -1910,14 +2131,22 @@ var StubSCMLib = class extends SCMLib {
|
|
|
1910
2131
|
console.error("getRepoDefaultBranch() not implemented");
|
|
1911
2132
|
throw new Error("getRepoDefaultBranch() not implemented");
|
|
1912
2133
|
}
|
|
2134
|
+
async getPrComment(_commentId) {
|
|
2135
|
+
console.error("getPrComment() not implemented");
|
|
2136
|
+
throw new Error("getPrComment() not implemented");
|
|
2137
|
+
}
|
|
2138
|
+
async updatePrComment() {
|
|
2139
|
+
console.error("updatePrComment() not implemented");
|
|
2140
|
+
throw new Error("updatePrComment() not implemented");
|
|
2141
|
+
}
|
|
1913
2142
|
};
|
|
1914
2143
|
|
|
1915
2144
|
// src/features/analysis/scm/gitlab.ts
|
|
1916
2145
|
function removeTrailingSlash2(str) {
|
|
1917
2146
|
return str.trim().replace(/\/+$/, "");
|
|
1918
2147
|
}
|
|
1919
|
-
var EnvVariablesZod2 =
|
|
1920
|
-
GITLAB_API_TOKEN:
|
|
2148
|
+
var EnvVariablesZod2 = z7.object({
|
|
2149
|
+
GITLAB_API_TOKEN: z7.string().optional()
|
|
1921
2150
|
});
|
|
1922
2151
|
var { GITLAB_API_TOKEN } = EnvVariablesZod2.parse(process.env);
|
|
1923
2152
|
function getGitBeaker(options) {
|
|
@@ -2146,38 +2375,13 @@ async function getGitlabBlameRanges({ ref, gitlabUrl, path: path8 }, options) {
|
|
|
2146
2375
|
};
|
|
2147
2376
|
});
|
|
2148
2377
|
}
|
|
2149
|
-
var GitlabAuthResultZ =
|
|
2150
|
-
access_token:
|
|
2151
|
-
token_type:
|
|
2152
|
-
refresh_token:
|
|
2378
|
+
var GitlabAuthResultZ = z7.object({
|
|
2379
|
+
access_token: z7.string(),
|
|
2380
|
+
token_type: z7.string(),
|
|
2381
|
+
refresh_token: z7.string()
|
|
2153
2382
|
});
|
|
2154
2383
|
|
|
2155
|
-
// src/features/analysis/utils/
|
|
2156
|
-
function calculateRanges(integers) {
|
|
2157
|
-
if (integers.length === 0) {
|
|
2158
|
-
return [];
|
|
2159
|
-
}
|
|
2160
|
-
integers.sort((a, b) => a - b);
|
|
2161
|
-
const ranges = integers.reduce(
|
|
2162
|
-
(result, current, index) => {
|
|
2163
|
-
if (index === 0) {
|
|
2164
|
-
return [...result, [current, current]];
|
|
2165
|
-
}
|
|
2166
|
-
const currentRange = result[result.length - 1];
|
|
2167
|
-
const [_start, end] = currentRange;
|
|
2168
|
-
if (current === end + 1) {
|
|
2169
|
-
currentRange[1] = current;
|
|
2170
|
-
} else {
|
|
2171
|
-
result.push([current, current]);
|
|
2172
|
-
}
|
|
2173
|
-
return result;
|
|
2174
|
-
},
|
|
2175
|
-
[]
|
|
2176
|
-
);
|
|
2177
|
-
return ranges;
|
|
2178
|
-
}
|
|
2179
|
-
|
|
2180
|
-
// src/features/analysis/utils/get_issue_type.ts
|
|
2384
|
+
// src/features/analysis/scm/utils/get_issue_type.ts
|
|
2181
2385
|
var getIssueType = (issueType) => {
|
|
2182
2386
|
switch (issueType) {
|
|
2183
2387
|
case "SQL_Injection" /* SqlInjection */:
|
|
@@ -2236,48 +2440,86 @@ var getIssueType = (issueType) => {
|
|
|
2236
2440
|
}
|
|
2237
2441
|
};
|
|
2238
2442
|
|
|
2239
|
-
// src/features/analysis/utils/index.ts
|
|
2240
|
-
function getFixUrlWithRedirect({
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2443
|
+
// src/features/analysis/scm/utils/index.ts
|
|
2444
|
+
function getFixUrlWithRedirect(params) {
|
|
2445
|
+
const {
|
|
2446
|
+
fixId,
|
|
2447
|
+
projectId,
|
|
2448
|
+
organizationId,
|
|
2449
|
+
analysisId,
|
|
2450
|
+
redirectUrl,
|
|
2451
|
+
appBaseUrl,
|
|
2452
|
+
commentId
|
|
2453
|
+
} = params;
|
|
2454
|
+
const searchParams = new URLSearchParams();
|
|
2455
|
+
searchParams.append("commit_redirect_url", redirectUrl);
|
|
2456
|
+
searchParams.append("comment_id", commentId.toString());
|
|
2247
2457
|
return `${getFixUrl({
|
|
2458
|
+
appBaseUrl,
|
|
2248
2459
|
fixId,
|
|
2249
2460
|
projectId,
|
|
2250
2461
|
organizationId,
|
|
2251
2462
|
analysisId
|
|
2252
|
-
})}
|
|
2463
|
+
})}?${searchParams.toString()}`;
|
|
2253
2464
|
}
|
|
2254
2465
|
function getFixUrl({
|
|
2466
|
+
appBaseUrl,
|
|
2255
2467
|
fixId,
|
|
2256
2468
|
projectId,
|
|
2257
2469
|
organizationId,
|
|
2258
2470
|
analysisId
|
|
2259
2471
|
}) {
|
|
2260
|
-
return `${
|
|
2472
|
+
return `${appBaseUrl}/organization/${organizationId}/project/${projectId}/report/${analysisId}/fix/${fixId}`;
|
|
2261
2473
|
}
|
|
2262
|
-
function getCommitUrl({
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2474
|
+
function getCommitUrl(params) {
|
|
2475
|
+
const {
|
|
2476
|
+
fixId,
|
|
2477
|
+
projectId,
|
|
2478
|
+
organizationId,
|
|
2479
|
+
analysisId,
|
|
2480
|
+
redirectUrl,
|
|
2481
|
+
appBaseUrl,
|
|
2482
|
+
commentId
|
|
2483
|
+
} = params;
|
|
2484
|
+
const searchParams = new URLSearchParams();
|
|
2485
|
+
searchParams.append("redirect_url", redirectUrl);
|
|
2486
|
+
searchParams.append("comment_id", commentId.toString());
|
|
2269
2487
|
return `${getFixUrl({
|
|
2488
|
+
appBaseUrl,
|
|
2270
2489
|
fixId,
|
|
2271
2490
|
projectId,
|
|
2272
2491
|
organizationId,
|
|
2273
2492
|
analysisId
|
|
2274
|
-
})}/commit
|
|
2493
|
+
})}/commit?${searchParams.toString()}`;
|
|
2494
|
+
}
|
|
2495
|
+
|
|
2496
|
+
// src/features/analysis/utils/calculate_ranges.ts
|
|
2497
|
+
function calculateRanges(integers) {
|
|
2498
|
+
if (integers.length === 0) {
|
|
2499
|
+
return [];
|
|
2500
|
+
}
|
|
2501
|
+
integers.sort((a, b) => a - b);
|
|
2502
|
+
const ranges = integers.reduce(
|
|
2503
|
+
(result, current, index) => {
|
|
2504
|
+
if (index === 0) {
|
|
2505
|
+
return [...result, [current, current]];
|
|
2506
|
+
}
|
|
2507
|
+
const currentRange = result[result.length - 1];
|
|
2508
|
+
const [_start, end] = currentRange;
|
|
2509
|
+
if (current === end + 1) {
|
|
2510
|
+
currentRange[1] = current;
|
|
2511
|
+
} else {
|
|
2512
|
+
result.push([current, current]);
|
|
2513
|
+
}
|
|
2514
|
+
return result;
|
|
2515
|
+
},
|
|
2516
|
+
[]
|
|
2517
|
+
);
|
|
2518
|
+
return ranges;
|
|
2275
2519
|
}
|
|
2276
2520
|
|
|
2277
2521
|
// src/features/analysis/handle_finished_analysis.ts
|
|
2278
2522
|
var debug4 = Debug4("mobbdev:handle-finished-analysis");
|
|
2279
|
-
var MOBB_ICON_IMG = "";
|
|
2280
|
-
var COMMIT_FIX_SVG = `https://felt-laptop-20190711103614-deployment.s3.us-east-1.amazonaws.com/commit-button.svg`;
|
|
2281
2523
|
var commitFixButton = (commitUrl) => `<a href="${commitUrl}"><img src=${COMMIT_FIX_SVG}></a>`;
|
|
2282
2524
|
function scannerToFriendlyString(scanner) {
|
|
2283
2525
|
switch (scanner) {
|
|
@@ -2301,7 +2543,7 @@ async function getFixesFromDiff(params) {
|
|
|
2301
2543
|
});
|
|
2302
2544
|
const lineAddedRanges = calculateRanges(fileNumbers);
|
|
2303
2545
|
const fileFilter = {
|
|
2304
|
-
path:
|
|
2546
|
+
path: z8.string().parse(file.to),
|
|
2305
2547
|
ranges: lineAddedRanges.map(([startLine, endLine]) => ({
|
|
2306
2548
|
endLine,
|
|
2307
2549
|
startLine
|
|
@@ -2333,16 +2575,19 @@ async function handleFinishedAnalysis({
|
|
|
2333
2575
|
}
|
|
2334
2576
|
} = getAnalysis.analysis;
|
|
2335
2577
|
const { commitSha, pullRequest } = getAnalysis.analysis.repo;
|
|
2336
|
-
const
|
|
2578
|
+
const diff = await scm.getPrDiff({ pull_number: pullRequest });
|
|
2337
2579
|
const { vulnerabilityReportIssueCodeNodes } = await getFixesFromDiff({
|
|
2338
|
-
diff
|
|
2580
|
+
diff,
|
|
2339
2581
|
gqlClient,
|
|
2340
2582
|
vulnerabilityReportId: getAnalysis.analysis.vulnerabilityReportId
|
|
2341
2583
|
});
|
|
2342
|
-
const comments = await scm.getPrComments(
|
|
2584
|
+
const comments = await scm.getPrComments(
|
|
2585
|
+
{ pull_number: pullRequest },
|
|
2586
|
+
githubActionOctokit
|
|
2587
|
+
);
|
|
2343
2588
|
await Promise.all(
|
|
2344
2589
|
comments.data.filter((comment) => {
|
|
2345
|
-
return comment.body.includes(
|
|
2590
|
+
return comment.body.includes(MOBB_ICON_IMG);
|
|
2346
2591
|
}).map((comment) => {
|
|
2347
2592
|
try {
|
|
2348
2593
|
return scm.deleteComment(
|
|
@@ -2374,25 +2619,30 @@ async function handleFinishedAnalysis({
|
|
|
2374
2619
|
},
|
|
2375
2620
|
githubActionOctokit
|
|
2376
2621
|
);
|
|
2622
|
+
const commentId = commentRes.data.id;
|
|
2377
2623
|
const commitUrl = getCommitUrl({
|
|
2624
|
+
appBaseUrl: WEB_APP_URL,
|
|
2378
2625
|
fixId: fix_by_pk.id,
|
|
2379
2626
|
projectId,
|
|
2380
2627
|
analysisId,
|
|
2381
2628
|
organizationId,
|
|
2382
|
-
redirectUrl: commentRes.data.html_url
|
|
2629
|
+
redirectUrl: commentRes.data.html_url,
|
|
2630
|
+
commentId
|
|
2383
2631
|
});
|
|
2384
2632
|
const fixUrl = getFixUrlWithRedirect({
|
|
2633
|
+
appBaseUrl: WEB_APP_URL,
|
|
2385
2634
|
fixId: fix_by_pk.id,
|
|
2386
2635
|
projectId,
|
|
2387
2636
|
analysisId,
|
|
2388
2637
|
organizationId,
|
|
2389
|
-
redirectUrl: commentRes.data.html_url
|
|
2638
|
+
redirectUrl: commentRes.data.html_url,
|
|
2639
|
+
commentId
|
|
2390
2640
|
});
|
|
2391
2641
|
const scanerString = scannerToFriendlyString(scanner);
|
|
2392
2642
|
const issueType = getIssueType(fix_by_pk.issueType);
|
|
2393
|
-
const title = `# ${MOBB_ICON_IMG} ${issueType} fix by Mobb is ready`;
|
|
2643
|
+
const title = `#  ${issueType} fix by Mobb is ready`;
|
|
2394
2644
|
const subTitle = `### Apply the following code change to fix ${issueType} issue detected by ${scanerString}:`;
|
|
2395
|
-
const
|
|
2645
|
+
const diff2 = `\`\`\`diff
|
|
2396
2646
|
${patch}
|
|
2397
2647
|
\`\`\``;
|
|
2398
2648
|
const fixPageLink = `[Learn more and fine tune the fix](${fixUrl})`;
|
|
@@ -2400,12 +2650,12 @@ ${patch}
|
|
|
2400
2650
|
{
|
|
2401
2651
|
body: `${title}
|
|
2402
2652
|
${subTitle}
|
|
2403
|
-
${
|
|
2653
|
+
${diff2}
|
|
2404
2654
|
${commitFixButton(
|
|
2405
2655
|
commitUrl
|
|
2406
2656
|
)}
|
|
2407
2657
|
${fixPageLink}`,
|
|
2408
|
-
comment_id:
|
|
2658
|
+
comment_id: commentId
|
|
2409
2659
|
},
|
|
2410
2660
|
githubActionOctokit
|
|
2411
2661
|
);
|
|
@@ -2892,6 +3142,7 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
2892
3142
|
srcPath,
|
|
2893
3143
|
commitHash,
|
|
2894
3144
|
ref,
|
|
3145
|
+
experimentalEnabled,
|
|
2895
3146
|
scanner,
|
|
2896
3147
|
cxProjectName,
|
|
2897
3148
|
mobbProjectName,
|
|
@@ -2993,7 +3244,7 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
2993
3244
|
gqlClient,
|
|
2994
3245
|
scm,
|
|
2995
3246
|
githubActionOctokit: new Octokit3({ auth: githubActionToken }),
|
|
2996
|
-
scanner:
|
|
3247
|
+
scanner: z9.nativeEnum(SCANNERS).parse(scanner)
|
|
2997
3248
|
})
|
|
2998
3249
|
);
|
|
2999
3250
|
}
|
|
@@ -3005,11 +3256,12 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
3005
3256
|
try {
|
|
3006
3257
|
const sumbitRes = await gqlClient.submitVulnerabilityReport({
|
|
3007
3258
|
fixReportId: reportUploadInfo.fixReportId,
|
|
3008
|
-
repoUrl:
|
|
3259
|
+
repoUrl: z9.string().parse(repo),
|
|
3009
3260
|
reference,
|
|
3010
3261
|
projectId,
|
|
3011
3262
|
vulnerabilityReportFileName: "report.json",
|
|
3012
3263
|
sha,
|
|
3264
|
+
experimentalEnabled,
|
|
3013
3265
|
pullRequest: params.pullRequest
|
|
3014
3266
|
});
|
|
3015
3267
|
if (sumbitRes.submitVulnerabilityReport.__typename !== "VulnerabilityReport") {
|
|
@@ -3255,6 +3507,7 @@ async function review(params, { skipPrompts = true } = {}) {
|
|
|
3255
3507
|
apiKey,
|
|
3256
3508
|
ci: true,
|
|
3257
3509
|
commitHash,
|
|
3510
|
+
experimentalEnabled: false,
|
|
3258
3511
|
mobbProjectName,
|
|
3259
3512
|
pullRequest,
|
|
3260
3513
|
githubToken,
|
|
@@ -3370,7 +3623,7 @@ var commitHashOption = {
|
|
|
3370
3623
|
// src/args/validation.ts
|
|
3371
3624
|
import chalk6 from "chalk";
|
|
3372
3625
|
import path7 from "path";
|
|
3373
|
-
import { z as
|
|
3626
|
+
import { z as z10 } from "zod";
|
|
3374
3627
|
function throwRepoUrlErrorMessage({
|
|
3375
3628
|
error,
|
|
3376
3629
|
repoUrl,
|
|
@@ -3387,7 +3640,7 @@ Example:
|
|
|
3387
3640
|
)}`;
|
|
3388
3641
|
throw new CliError(formattedErrorMessage);
|
|
3389
3642
|
}
|
|
3390
|
-
var UrlZ =
|
|
3643
|
+
var UrlZ = z10.string({
|
|
3391
3644
|
invalid_type_error: "is not a valid GitHub / GitLab URL"
|
|
3392
3645
|
}).refine((data) => !!parseScmURL(data), {
|
|
3393
3646
|
message: "is not a valid GitHub / GitLab URL"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mobbdev",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.69",
|
|
4
4
|
"description": "Automated secure code remediation tool",
|
|
5
5
|
"repository": "https://github.com/mobb-dev/bugsy",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
"@octokit/graphql": "5.0.5",
|
|
28
28
|
"@octokit/plugin-rest-endpoint-methods": "7.0.1",
|
|
29
29
|
"@octokit/request-error": "3.0.3",
|
|
30
|
+
"@types/libsodium-wrappers": "0.7.13",
|
|
30
31
|
"adm-zip": "0.5.10",
|
|
31
32
|
"axios": "1.5.0",
|
|
32
33
|
"chalk": "5.3.0",
|
|
@@ -42,6 +43,7 @@
|
|
|
42
43
|
"inquirer": "9.2.7",
|
|
43
44
|
"isomorphic-ws": "5.0.0",
|
|
44
45
|
"istextorbinary": "6.0.0",
|
|
46
|
+
"libsodium-wrappers": "0.7.13",
|
|
45
47
|
"nanospinner": "1.1.0",
|
|
46
48
|
"node-fetch": "3.3.1",
|
|
47
49
|
"octokit": "2.0.14",
|