mobbdev 0.0.145 → 0.0.152
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 +1642 -1512
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -32,661 +32,174 @@ import fs4 from "node:fs";
|
|
|
32
32
|
import path7 from "node:path";
|
|
33
33
|
|
|
34
34
|
// src/constants.ts
|
|
35
|
-
import
|
|
35
|
+
import path2 from "node:path";
|
|
36
36
|
import { fileURLToPath } from "node:url";
|
|
37
37
|
import chalk from "chalk";
|
|
38
38
|
import Debug from "debug";
|
|
39
39
|
import * as dotenv from "dotenv";
|
|
40
|
-
import { z } from "zod";
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
};
|
|
49
|
-
var SCANNERS = {
|
|
50
|
-
Checkmarx: "checkmarx",
|
|
51
|
-
Codeql: "codeql",
|
|
52
|
-
Fortify: "fortify",
|
|
53
|
-
Snyk: "snyk",
|
|
54
|
-
Sonarqube: "sonarqube"
|
|
55
|
-
};
|
|
56
|
-
var SupportedScannersZ = z.enum([SCANNERS.Checkmarx, SCANNERS.Snyk]);
|
|
57
|
-
var envVariablesSchema = z.object({
|
|
58
|
-
WEB_APP_URL: z.string(),
|
|
59
|
-
API_URL: z.string(),
|
|
60
|
-
HASURA_ACCESS_KEY: z.string(),
|
|
61
|
-
LOCAL_GRAPHQL_ENDPOINT: z.string()
|
|
62
|
-
}).required();
|
|
63
|
-
var envVariables = envVariablesSchema.parse(process.env);
|
|
64
|
-
debug("config %o", envVariables);
|
|
65
|
-
var mobbAscii = `
|
|
66
|
-
..
|
|
67
|
-
..........
|
|
68
|
-
.................
|
|
69
|
-
...........................
|
|
70
|
-
..............................
|
|
71
|
-
................................
|
|
72
|
-
..................................
|
|
73
|
-
....................................
|
|
74
|
-
.....................................
|
|
75
|
-
.............................................
|
|
76
|
-
.................................................
|
|
77
|
-
............................... .................
|
|
78
|
-
.................................. ............
|
|
79
|
-
.................. ............. ..........
|
|
80
|
-
......... ........ ......... ......
|
|
81
|
-
............... ....
|
|
82
|
-
.... ..
|
|
83
|
-
|
|
84
|
-
. ...
|
|
85
|
-
..............
|
|
86
|
-
......................
|
|
87
|
-
...........................
|
|
88
|
-
................................
|
|
89
|
-
......................................
|
|
90
|
-
...............................
|
|
91
|
-
.................
|
|
92
|
-
`;
|
|
93
|
-
var PROJECT_DEFAULT_NAME = "My first project";
|
|
94
|
-
var WEB_APP_URL = envVariables.WEB_APP_URL;
|
|
95
|
-
var API_URL = envVariables.API_URL;
|
|
96
|
-
var HASURA_ACCESS_KEY = envVariables.HASURA_ACCESS_KEY;
|
|
97
|
-
var LOCAL_GRAPHQL_ENDPOINT = envVariables.LOCAL_GRAPHQL_ENDPOINT;
|
|
98
|
-
var errorMessages = {
|
|
99
|
-
missingCxProjectName: `project name ${chalk.bold(
|
|
100
|
-
"(--cx-project-name)"
|
|
101
|
-
)} is needed if you're using checkmarx`,
|
|
102
|
-
missingUrl: `url ${chalk.bold(
|
|
103
|
-
"(--url)"
|
|
104
|
-
)} is needed if you're adding an SCM token`,
|
|
105
|
-
invalidScmType: `SCM type ${chalk.bold(
|
|
106
|
-
"(--scm-type)"
|
|
107
|
-
)} is invalid, please use one of: ${Object.values(ScmTypes).join(", ")}`,
|
|
108
|
-
missingToken: `SCM token ${chalk.bold(
|
|
109
|
-
"(--token)"
|
|
110
|
-
)} is needed if you're adding an SCM token`
|
|
111
|
-
};
|
|
112
|
-
var progressMassages = {
|
|
113
|
-
processingVulnerabilityReportSuccess: "\u2699\uFE0F Vulnerability report proccessed successfully",
|
|
114
|
-
processingVulnerabilityReport: "\u2699\uFE0F Proccessing vulnerability report",
|
|
115
|
-
processingVulnerabilityReportFailed: "\u2699\uFE0F Error Proccessing vulnerability report"
|
|
40
|
+
import { z as z10 } from "zod";
|
|
41
|
+
|
|
42
|
+
// src/features/analysis/scm/shared/src/types.ts
|
|
43
|
+
var scmCloudUrl = {
|
|
44
|
+
GitLab: "https://gitlab.com",
|
|
45
|
+
GitHub: "https://github.com",
|
|
46
|
+
Ado: "https://dev.azure.com",
|
|
47
|
+
Bitbucket: "https://bitbucket.org"
|
|
116
48
|
};
|
|
117
|
-
var
|
|
49
|
+
var ScmType = /* @__PURE__ */ ((ScmType2) => {
|
|
50
|
+
ScmType2["GitHub"] = "GitHub";
|
|
51
|
+
ScmType2["GitLab"] = "GitLab";
|
|
52
|
+
ScmType2["Ado"] = "Ado";
|
|
53
|
+
ScmType2["Bitbucket"] = "Bitbucket";
|
|
54
|
+
return ScmType2;
|
|
55
|
+
})(ScmType || {});
|
|
118
56
|
|
|
119
|
-
// src/features/analysis/
|
|
120
|
-
|
|
121
|
-
import fs3 from "node:fs";
|
|
122
|
-
import os from "node:os";
|
|
123
|
-
import path6 from "node:path";
|
|
124
|
-
import { pipeline } from "node:stream/promises";
|
|
57
|
+
// src/features/analysis/scm/ado/constants.ts
|
|
58
|
+
var DEFUALT_ADO_ORIGIN = scmCloudUrl.Ado;
|
|
125
59
|
|
|
126
|
-
// src/
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
60
|
+
// src/features/analysis/scm/ado/utils.ts
|
|
61
|
+
import querystring3 from "node:querystring";
|
|
62
|
+
import * as api from "azure-devops-node-api";
|
|
63
|
+
import { z as z9 } from "zod";
|
|
64
|
+
|
|
65
|
+
// src/features/analysis/scm/env.ts
|
|
66
|
+
import { z } from "zod";
|
|
67
|
+
var EnvVariablesZod = z.object({
|
|
68
|
+
GITLAB_API_TOKEN: z.string().optional(),
|
|
69
|
+
BROKERED_HOSTS: z.string().toLowerCase().transform(
|
|
70
|
+
(x) => x.split(",").map((url) => url.trim(), []).filter(Boolean)
|
|
71
|
+
).default(""),
|
|
72
|
+
GITHUB_API_TOKEN: z.string().optional(),
|
|
73
|
+
GIT_PROXY_HOST: z.string().default("http://tinyproxy:8888")
|
|
74
|
+
});
|
|
75
|
+
var { GITLAB_API_TOKEN, BROKERED_HOSTS, GITHUB_API_TOKEN, GIT_PROXY_HOST } = EnvVariablesZod.parse(process.env);
|
|
76
|
+
|
|
77
|
+
// src/features/analysis/scm/scm.ts
|
|
78
|
+
import { z as z7 } from "zod";
|
|
79
|
+
|
|
80
|
+
// src/features/analysis/scm/bitbucket/bitbucket.ts
|
|
81
|
+
import querystring from "node:querystring";
|
|
82
|
+
import bitbucketPkg from "bitbucket";
|
|
83
|
+
import * as bitbucketPkgNode from "bitbucket";
|
|
84
|
+
import { z as z3 } from "zod";
|
|
85
|
+
|
|
86
|
+
// src/features/analysis/scm/shared/src/urlParser/urlParser.ts
|
|
87
|
+
import { z as z2 } from "zod";
|
|
88
|
+
function detectAdoUrl(args) {
|
|
89
|
+
const { pathname, hostname, scmType } = args;
|
|
90
|
+
const hostnameParts = hostname.split(".");
|
|
91
|
+
const adoCloudHostname = new URL(scmCloudUrl.Ado).hostname;
|
|
92
|
+
const prefixPath = pathname.at(0)?.toLowerCase() === ADO_PREFIX_PATH ? ADO_PREFIX_PATH : "";
|
|
93
|
+
const normilizedPath = prefixPath ? pathname.slice(1) : pathname;
|
|
94
|
+
if (hostnameParts.length === 3 && hostnameParts[1] === "visualstudio" && hostnameParts[2] === "com") {
|
|
95
|
+
if (normilizedPath.length === 2 && normilizedPath[0] === "_git") {
|
|
96
|
+
const [_git, projectName] = normilizedPath;
|
|
97
|
+
const [organization] = hostnameParts;
|
|
98
|
+
return {
|
|
99
|
+
scmType: "Ado" /* Ado */,
|
|
100
|
+
organization,
|
|
101
|
+
// project has single repo - repoName === projectName
|
|
102
|
+
projectName: z2.string().parse(projectName),
|
|
103
|
+
repoName: projectName,
|
|
104
|
+
prefixPath
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
if (normilizedPath.length === 3 && normilizedPath[1] === "_git") {
|
|
108
|
+
const [projectName, _git, repoName] = normilizedPath;
|
|
109
|
+
const [organization] = hostnameParts;
|
|
110
|
+
return {
|
|
111
|
+
scmType: "Ado" /* Ado */,
|
|
112
|
+
organization,
|
|
113
|
+
projectName: z2.string().parse(projectName),
|
|
114
|
+
repoName,
|
|
115
|
+
prefixPath
|
|
116
|
+
};
|
|
144
117
|
}
|
|
145
118
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
119
|
+
if (hostname === adoCloudHostname || scmType === "Ado" /* Ado */) {
|
|
120
|
+
if (normilizedPath[normilizedPath.length - 2] === "_git") {
|
|
121
|
+
if (normilizedPath.length === 3) {
|
|
122
|
+
const [organization, _git, repoName] = normilizedPath;
|
|
123
|
+
return {
|
|
124
|
+
scmType: "Ado" /* Ado */,
|
|
125
|
+
organization,
|
|
126
|
+
// project has only one repo - repoName === projectName
|
|
127
|
+
projectName: z2.string().parse(repoName),
|
|
128
|
+
repoName,
|
|
129
|
+
prefixPath
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
if (normilizedPath.length === 4) {
|
|
133
|
+
const [organization, projectName, _git, repoName] = normilizedPath;
|
|
134
|
+
return {
|
|
135
|
+
scmType: "Ado" /* Ado */,
|
|
136
|
+
organization,
|
|
137
|
+
projectName: z2.string().parse(projectName),
|
|
138
|
+
repoName,
|
|
139
|
+
prefixPath
|
|
140
|
+
};
|
|
160
141
|
}
|
|
161
142
|
}
|
|
162
143
|
}
|
|
144
|
+
return null;
|
|
163
145
|
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
state
|
|
146
|
+
function detectGithubUrl(args) {
|
|
147
|
+
const { pathname, hostname, scmType } = args;
|
|
148
|
+
const githubHostname = new URL(scmCloudUrl.GitHub).hostname;
|
|
149
|
+
if (hostname === githubHostname || scmType === "GitHub" /* GitHub */) {
|
|
150
|
+
if (pathname.length === 2) {
|
|
151
|
+
return {
|
|
152
|
+
scmType: "GitHub" /* GitHub */,
|
|
153
|
+
organization: pathname[0],
|
|
154
|
+
repoName: pathname[1]
|
|
155
|
+
};
|
|
156
|
+
}
|
|
176
157
|
}
|
|
158
|
+
return null;
|
|
177
159
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
160
|
+
function detectGitlabUrl(args) {
|
|
161
|
+
const { pathname, hostname, scmType } = args;
|
|
162
|
+
const gitlabHostname = new URL(scmCloudUrl.GitLab).hostname;
|
|
163
|
+
if (hostname === gitlabHostname || scmType === "GitLab" /* GitLab */) {
|
|
164
|
+
if (pathname.length >= 2) {
|
|
165
|
+
return {
|
|
166
|
+
scmType: "GitLab" /* GitLab */,
|
|
167
|
+
organization: pathname[0],
|
|
168
|
+
repoName: pathname[pathname.length - 1]
|
|
169
|
+
};
|
|
170
|
+
}
|
|
185
171
|
}
|
|
172
|
+
return null;
|
|
186
173
|
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
174
|
+
function detectBitbucketUrl(args) {
|
|
175
|
+
const { pathname, hostname, scmType } = args;
|
|
176
|
+
const bitbucketHostname = new URL(scmCloudUrl.Bitbucket).hostname;
|
|
177
|
+
if (hostname === bitbucketHostname || scmType === "Bitbucket" /* Bitbucket */) {
|
|
178
|
+
if (pathname.length === 2) {
|
|
179
|
+
return {
|
|
180
|
+
scmType: "Bitbucket" /* Bitbucket */,
|
|
181
|
+
organization: pathname[0],
|
|
182
|
+
repoName: pathname[1]
|
|
183
|
+
};
|
|
184
|
+
}
|
|
193
185
|
}
|
|
186
|
+
return null;
|
|
194
187
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
vulnerabilityReport {
|
|
207
|
-
projectId
|
|
208
|
-
project {
|
|
209
|
-
organizationId
|
|
210
|
-
}
|
|
211
|
-
file {
|
|
212
|
-
signedFile {
|
|
213
|
-
url
|
|
214
|
-
}
|
|
215
|
-
}
|
|
188
|
+
var getRepoUrlFunctionMap = {
|
|
189
|
+
["GitLab" /* GitLab */]: detectGitlabUrl,
|
|
190
|
+
["GitHub" /* GitHub */]: detectGithubUrl,
|
|
191
|
+
["Ado" /* Ado */]: detectAdoUrl,
|
|
192
|
+
["Bitbucket" /* Bitbucket */]: detectBitbucketUrl
|
|
193
|
+
};
|
|
194
|
+
function getRepoInfo(args) {
|
|
195
|
+
for (const detectUrl of Object.values(getRepoUrlFunctionMap)) {
|
|
196
|
+
const detectUrlRes = detectUrl(args);
|
|
197
|
+
if (detectUrlRes) {
|
|
198
|
+
return detectUrlRes;
|
|
216
199
|
}
|
|
217
200
|
}
|
|
201
|
+
return null;
|
|
218
202
|
}
|
|
219
|
-
`;
|
|
220
|
-
var GetFixesDocument = `
|
|
221
|
-
query getFixes($filters: fix_bool_exp!) {
|
|
222
|
-
fixes: fix(where: $filters) {
|
|
223
|
-
issueType
|
|
224
|
-
id
|
|
225
|
-
patchAndQuestions {
|
|
226
|
-
__typename
|
|
227
|
-
... on FixData {
|
|
228
|
-
patch
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
`;
|
|
234
|
-
var GetVulByNodesMetadataDocument = `
|
|
235
|
-
query getVulByNodesMetadata($filters: [vulnerability_report_issue_code_node_bool_exp!], $vulnerabilityReportId: uuid!) {
|
|
236
|
-
vulnerabilityReportIssueCodeNodes: vulnerability_report_issue_code_node(
|
|
237
|
-
order_by: {index: desc}
|
|
238
|
-
where: {_or: $filters, vulnerabilityReportIssue: {fixId: {_is_null: false}, vulnerabilityReportId: {_eq: $vulnerabilityReportId}}}
|
|
239
|
-
) {
|
|
240
|
-
vulnerabilityReportIssueId
|
|
241
|
-
path
|
|
242
|
-
startLine
|
|
243
|
-
vulnerabilityReportIssue {
|
|
244
|
-
issueType
|
|
245
|
-
fixId
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
fixablePrVuls: vulnerability_report_issue_aggregate(
|
|
249
|
-
where: {fixId: {_is_null: false}, vulnerabilityReportId: {_eq: $vulnerabilityReportId}, codeNodes: {_or: $filters}}
|
|
250
|
-
) {
|
|
251
|
-
aggregate {
|
|
252
|
-
count
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
nonFixablePrVuls: vulnerability_report_issue_aggregate(
|
|
256
|
-
where: {fixId: {_is_null: true}, vulnerabilityReportId: {_eq: $vulnerabilityReportId}, codeNodes: {_or: $filters}}
|
|
257
|
-
) {
|
|
258
|
-
aggregate {
|
|
259
|
-
count
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
totalScanVulnerabilities: vulnerability_report_issue_aggregate(
|
|
263
|
-
where: {vulnerabilityReportId: {_eq: $vulnerabilityReportId}}
|
|
264
|
-
) {
|
|
265
|
-
aggregate {
|
|
266
|
-
count
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
`;
|
|
271
|
-
var UpdateScmTokenDocument = `
|
|
272
|
-
mutation updateScmToken($scmType: String!, $url: String!, $token: String!, $org: String, $refreshToken: String) {
|
|
273
|
-
updateScmToken(
|
|
274
|
-
scmType: $scmType
|
|
275
|
-
url: $url
|
|
276
|
-
token: $token
|
|
277
|
-
org: $org
|
|
278
|
-
refreshToken: $refreshToken
|
|
279
|
-
) {
|
|
280
|
-
__typename
|
|
281
|
-
... on ScmAccessTokenUpdateSuccess {
|
|
282
|
-
token
|
|
283
|
-
}
|
|
284
|
-
... on InvalidScmTypeError {
|
|
285
|
-
status
|
|
286
|
-
error
|
|
287
|
-
}
|
|
288
|
-
... on BadScmCredentials {
|
|
289
|
-
status
|
|
290
|
-
error
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
`;
|
|
295
|
-
var UploadS3BucketInfoDocument = `
|
|
296
|
-
mutation uploadS3BucketInfo($fileName: String!) {
|
|
297
|
-
uploadS3BucketInfo(fileName: $fileName) {
|
|
298
|
-
status
|
|
299
|
-
error
|
|
300
|
-
reportUploadInfo: uploadInfo {
|
|
301
|
-
url
|
|
302
|
-
fixReportId
|
|
303
|
-
uploadFieldsJSON
|
|
304
|
-
uploadKey
|
|
305
|
-
}
|
|
306
|
-
repoUploadInfo {
|
|
307
|
-
url
|
|
308
|
-
fixReportId
|
|
309
|
-
uploadFieldsJSON
|
|
310
|
-
uploadKey
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
`;
|
|
315
|
-
var DigestVulnerabilityReportDocument = `
|
|
316
|
-
mutation DigestVulnerabilityReport($vulnerabilityReportFileName: String!, $fixReportId: String!, $projectId: String!, $scanSource: String!) {
|
|
317
|
-
digestVulnerabilityReport(
|
|
318
|
-
fixReportId: $fixReportId
|
|
319
|
-
vulnerabilityReportFileName: $vulnerabilityReportFileName
|
|
320
|
-
projectId: $projectId
|
|
321
|
-
scanSource: $scanSource
|
|
322
|
-
) {
|
|
323
|
-
__typename
|
|
324
|
-
... on VulnerabilityReport {
|
|
325
|
-
vulnerabilityReportId
|
|
326
|
-
fixReportId
|
|
327
|
-
}
|
|
328
|
-
... on RabbitSendError {
|
|
329
|
-
status
|
|
330
|
-
error
|
|
331
|
-
}
|
|
332
|
-
... on ReportValidationError {
|
|
333
|
-
status
|
|
334
|
-
error
|
|
335
|
-
}
|
|
336
|
-
... on ReferenceNotFoundError {
|
|
337
|
-
status
|
|
338
|
-
error
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
`;
|
|
343
|
-
var SubmitVulnerabilityReportDocument = `
|
|
344
|
-
mutation SubmitVulnerabilityReport($fixReportId: String!, $repoUrl: String!, $reference: String!, $projectId: String!, $scanSource: String!, $sha: String, $experimentalEnabled: Boolean, $vulnerabilityReportFileName: String, $pullRequest: Int) {
|
|
345
|
-
submitVulnerabilityReport(
|
|
346
|
-
fixReportId: $fixReportId
|
|
347
|
-
repoUrl: $repoUrl
|
|
348
|
-
reference: $reference
|
|
349
|
-
sha: $sha
|
|
350
|
-
experimentalEnabled: $experimentalEnabled
|
|
351
|
-
pullRequest: $pullRequest
|
|
352
|
-
projectId: $projectId
|
|
353
|
-
vulnerabilityReportFileName: $vulnerabilityReportFileName
|
|
354
|
-
scanSource: $scanSource
|
|
355
|
-
) {
|
|
356
|
-
__typename
|
|
357
|
-
... on VulnerabilityReport {
|
|
358
|
-
vulnerabilityReportId
|
|
359
|
-
fixReportId
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
`;
|
|
364
|
-
var CreateCommunityUserDocument = `
|
|
365
|
-
mutation CreateCommunityUser {
|
|
366
|
-
initOrganizationAndProject {
|
|
367
|
-
__typename
|
|
368
|
-
... on InitOrganizationAndProjectGoodResponse {
|
|
369
|
-
projectId
|
|
370
|
-
userId
|
|
371
|
-
organizationId
|
|
372
|
-
}
|
|
373
|
-
... on UserAlreadyInProjectError {
|
|
374
|
-
error
|
|
375
|
-
status
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
`;
|
|
380
|
-
var CreateCliLoginDocument = `
|
|
381
|
-
mutation CreateCliLogin($publicKey: String!) {
|
|
382
|
-
insert_cli_login_one(object: {publicKey: $publicKey}) {
|
|
383
|
-
id
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
`;
|
|
387
|
-
var PerformCliLoginDocument = `
|
|
388
|
-
mutation performCliLogin($loginId: String!) {
|
|
389
|
-
performCliLogin(loginId: $loginId) {
|
|
390
|
-
status
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
`;
|
|
394
|
-
var CreateProjectDocument = `
|
|
395
|
-
mutation CreateProject($organizationId: String!, $projectName: String!) {
|
|
396
|
-
createProject(organizationId: $organizationId, projectName: $projectName) {
|
|
397
|
-
projectId
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
`;
|
|
401
|
-
var defaultWrapper = (action, _operationName, _operationType, _variables) => action();
|
|
402
|
-
function getSdk(client, withWrapper = defaultWrapper) {
|
|
403
|
-
return {
|
|
404
|
-
Me(variables, requestHeaders) {
|
|
405
|
-
return withWrapper((wrappedRequestHeaders) => client.request(MeDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "Me", "query", variables);
|
|
406
|
-
},
|
|
407
|
-
getOrgAndProjectId(variables, requestHeaders) {
|
|
408
|
-
return withWrapper((wrappedRequestHeaders) => client.request(GetOrgAndProjectIdDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "getOrgAndProjectId", "query", variables);
|
|
409
|
-
},
|
|
410
|
-
GetEncryptedApiToken(variables, requestHeaders) {
|
|
411
|
-
return withWrapper((wrappedRequestHeaders) => client.request(GetEncryptedApiTokenDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "GetEncryptedApiToken", "query", variables);
|
|
412
|
-
},
|
|
413
|
-
FixReportState(variables, requestHeaders) {
|
|
414
|
-
return withWrapper((wrappedRequestHeaders) => client.request(FixReportStateDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "FixReportState", "query", variables);
|
|
415
|
-
},
|
|
416
|
-
GetVulnerabilityReportPaths(variables, requestHeaders) {
|
|
417
|
-
return withWrapper((wrappedRequestHeaders) => client.request(GetVulnerabilityReportPathsDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "GetVulnerabilityReportPaths", "query", variables);
|
|
418
|
-
},
|
|
419
|
-
getAnalysis(variables, requestHeaders) {
|
|
420
|
-
return withWrapper((wrappedRequestHeaders) => client.request(GetAnalysisDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "getAnalysis", "subscription", variables);
|
|
421
|
-
},
|
|
422
|
-
getAnalsyis(variables, requestHeaders) {
|
|
423
|
-
return withWrapper((wrappedRequestHeaders) => client.request(GetAnalsyisDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "getAnalsyis", "query", variables);
|
|
424
|
-
},
|
|
425
|
-
getFixes(variables, requestHeaders) {
|
|
426
|
-
return withWrapper((wrappedRequestHeaders) => client.request(GetFixesDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "getFixes", "query", variables);
|
|
427
|
-
},
|
|
428
|
-
getVulByNodesMetadata(variables, requestHeaders) {
|
|
429
|
-
return withWrapper((wrappedRequestHeaders) => client.request(GetVulByNodesMetadataDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "getVulByNodesMetadata", "query", variables);
|
|
430
|
-
},
|
|
431
|
-
updateScmToken(variables, requestHeaders) {
|
|
432
|
-
return withWrapper((wrappedRequestHeaders) => client.request(UpdateScmTokenDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "updateScmToken", "mutation", variables);
|
|
433
|
-
},
|
|
434
|
-
uploadS3BucketInfo(variables, requestHeaders) {
|
|
435
|
-
return withWrapper((wrappedRequestHeaders) => client.request(UploadS3BucketInfoDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "uploadS3BucketInfo", "mutation", variables);
|
|
436
|
-
},
|
|
437
|
-
DigestVulnerabilityReport(variables, requestHeaders) {
|
|
438
|
-
return withWrapper((wrappedRequestHeaders) => client.request(DigestVulnerabilityReportDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "DigestVulnerabilityReport", "mutation", variables);
|
|
439
|
-
},
|
|
440
|
-
SubmitVulnerabilityReport(variables, requestHeaders) {
|
|
441
|
-
return withWrapper((wrappedRequestHeaders) => client.request(SubmitVulnerabilityReportDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "SubmitVulnerabilityReport", "mutation", variables);
|
|
442
|
-
},
|
|
443
|
-
CreateCommunityUser(variables, requestHeaders) {
|
|
444
|
-
return withWrapper((wrappedRequestHeaders) => client.request(CreateCommunityUserDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "CreateCommunityUser", "mutation", variables);
|
|
445
|
-
},
|
|
446
|
-
CreateCliLogin(variables, requestHeaders) {
|
|
447
|
-
return withWrapper((wrappedRequestHeaders) => client.request(CreateCliLoginDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "CreateCliLogin", "mutation", variables);
|
|
448
|
-
},
|
|
449
|
-
performCliLogin(variables, requestHeaders) {
|
|
450
|
-
return withWrapper((wrappedRequestHeaders) => client.request(PerformCliLoginDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "performCliLogin", "mutation", variables);
|
|
451
|
-
},
|
|
452
|
-
CreateProject(variables, requestHeaders) {
|
|
453
|
-
return withWrapper((wrappedRequestHeaders) => client.request(CreateProjectDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "CreateProject", "mutation", variables);
|
|
454
|
-
}
|
|
455
|
-
};
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
// src/utils/index.ts
|
|
459
|
-
var utils_exports = {};
|
|
460
|
-
__export(utils_exports, {
|
|
461
|
-
CliError: () => CliError,
|
|
462
|
-
Spinner: () => Spinner,
|
|
463
|
-
getDirName: () => getDirName,
|
|
464
|
-
getTopLevelDirName: () => getTopLevelDirName,
|
|
465
|
-
keypress: () => keypress,
|
|
466
|
-
sleep: () => sleep
|
|
467
|
-
});
|
|
468
|
-
|
|
469
|
-
// src/utils/dirname.ts
|
|
470
|
-
import path2 from "node:path";
|
|
471
|
-
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
472
|
-
function getDirName() {
|
|
473
|
-
return path2.dirname(fileURLToPath2(import.meta.url));
|
|
474
|
-
}
|
|
475
|
-
function getTopLevelDirName(fullPath) {
|
|
476
|
-
return path2.parse(fullPath).name;
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
// src/utils/keypress.ts
|
|
480
|
-
import readline from "node:readline";
|
|
481
|
-
async function keypress() {
|
|
482
|
-
const rl = readline.createInterface({
|
|
483
|
-
input: process.stdin,
|
|
484
|
-
output: process.stdout
|
|
485
|
-
});
|
|
486
|
-
return new Promise((resolve) => {
|
|
487
|
-
rl.question("", (answer) => {
|
|
488
|
-
rl.close();
|
|
489
|
-
process.stderr.moveCursor(0, -1);
|
|
490
|
-
process.stderr.clearLine(1);
|
|
491
|
-
resolve(answer);
|
|
492
|
-
});
|
|
493
|
-
});
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
// src/utils/spinner.ts
|
|
497
|
-
import {
|
|
498
|
-
createSpinner as _createSpinner
|
|
499
|
-
} from "nanospinner";
|
|
500
|
-
var mockSpinner = {
|
|
501
|
-
success: () => mockSpinner,
|
|
502
|
-
error: () => mockSpinner,
|
|
503
|
-
warn: () => mockSpinner,
|
|
504
|
-
stop: () => mockSpinner,
|
|
505
|
-
start: () => mockSpinner,
|
|
506
|
-
update: () => mockSpinner,
|
|
507
|
-
reset: () => mockSpinner,
|
|
508
|
-
clear: () => mockSpinner,
|
|
509
|
-
spin: () => mockSpinner
|
|
510
|
-
};
|
|
511
|
-
function Spinner({ ci = false } = {}) {
|
|
512
|
-
return {
|
|
513
|
-
createSpinner: (text, options) => ci ? mockSpinner : _createSpinner(text, options)
|
|
514
|
-
};
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
// src/utils/index.ts
|
|
518
|
-
var sleep = (ms = 2e3) => new Promise((r) => setTimeout(r, ms));
|
|
519
|
-
var CliError = class extends Error {
|
|
520
|
-
};
|
|
521
|
-
|
|
522
|
-
// src/features/analysis/index.ts
|
|
523
|
-
import chalk4 from "chalk";
|
|
524
|
-
import Configstore from "configstore";
|
|
525
|
-
import Debug12 from "debug";
|
|
526
|
-
import extract from "extract-zip";
|
|
527
|
-
import fetch4 from "node-fetch";
|
|
528
|
-
import open2 from "open";
|
|
529
|
-
import semver from "semver";
|
|
530
|
-
import tmp2 from "tmp";
|
|
531
|
-
import { z as z12 } from "zod";
|
|
532
|
-
|
|
533
|
-
// src/features/analysis/add_fix_comments_for_pr/add_fix_comments_for_pr.ts
|
|
534
|
-
import Debug4 from "debug";
|
|
535
|
-
|
|
536
|
-
// src/features/analysis/scm/types.ts
|
|
537
|
-
var ReferenceType = /* @__PURE__ */ ((ReferenceType2) => {
|
|
538
|
-
ReferenceType2["BRANCH"] = "BRANCH";
|
|
539
|
-
ReferenceType2["COMMIT"] = "COMMIT";
|
|
540
|
-
ReferenceType2["TAG"] = "TAG";
|
|
541
|
-
return ReferenceType2;
|
|
542
|
-
})(ReferenceType || {});
|
|
543
|
-
var ScmLibScmType = /* @__PURE__ */ ((ScmLibScmType2) => {
|
|
544
|
-
ScmLibScmType2["GITHUB"] = "GITHUB";
|
|
545
|
-
ScmLibScmType2["GITLAB"] = "GITLAB";
|
|
546
|
-
ScmLibScmType2["ADO"] = "ADO";
|
|
547
|
-
ScmLibScmType2["BITBUCKET"] = "BITBUCKET";
|
|
548
|
-
return ScmLibScmType2;
|
|
549
|
-
})(ScmLibScmType || {});
|
|
550
|
-
var scmCloudUrl = {
|
|
551
|
-
GitLab: "https://gitlab.com",
|
|
552
|
-
GitHub: "https://github.com",
|
|
553
|
-
Ado: "https://dev.azure.com",
|
|
554
|
-
Bitbucket: "https://bitbucket.org"
|
|
555
|
-
};
|
|
556
|
-
var ScmType = /* @__PURE__ */ ((ScmType2) => {
|
|
557
|
-
ScmType2["GitHub"] = "GitHub";
|
|
558
|
-
ScmType2["GitLab"] = "GitLab";
|
|
559
|
-
ScmType2["Ado"] = "Ado";
|
|
560
|
-
ScmType2["Bitbucket"] = "Bitbucket";
|
|
561
|
-
return ScmType2;
|
|
562
|
-
})(ScmType || {});
|
|
563
|
-
|
|
564
|
-
// src/features/analysis/scm/ado/constants.ts
|
|
565
|
-
var DEFUALT_ADO_ORIGIN = scmCloudUrl.Ado;
|
|
566
|
-
|
|
567
|
-
// src/features/analysis/scm/ado/utils.ts
|
|
568
|
-
import querystring3 from "node:querystring";
|
|
569
|
-
import * as api from "azure-devops-node-api";
|
|
570
|
-
import { z as z9 } from "zod";
|
|
571
|
-
|
|
572
|
-
// src/features/analysis/scm/env.ts
|
|
573
|
-
import { z as z2 } from "zod";
|
|
574
|
-
var EnvVariablesZod = z2.object({
|
|
575
|
-
GITLAB_API_TOKEN: z2.string().optional(),
|
|
576
|
-
BROKERED_HOSTS: z2.string().toLowerCase().transform(
|
|
577
|
-
(x) => x.split(",").map((url) => url.trim(), []).filter(Boolean)
|
|
578
|
-
).default(""),
|
|
579
|
-
GITHUB_API_TOKEN: z2.string().optional(),
|
|
580
|
-
GIT_PROXY_HOST: z2.string().default("http://tinyproxy:8888")
|
|
581
|
-
});
|
|
582
|
-
var { GITLAB_API_TOKEN, BROKERED_HOSTS, GITHUB_API_TOKEN, GIT_PROXY_HOST } = EnvVariablesZod.parse(process.env);
|
|
583
|
-
|
|
584
|
-
// src/features/analysis/scm/scm.ts
|
|
585
|
-
import { z as z7 } from "zod";
|
|
586
|
-
|
|
587
|
-
// src/features/analysis/scm/bitbucket/bitbucket.ts
|
|
588
|
-
import querystring from "node:querystring";
|
|
589
|
-
import bitbucketPkg from "bitbucket";
|
|
590
|
-
import * as bitbucketPkgNode from "bitbucket";
|
|
591
|
-
import { z as z3 } from "zod";
|
|
592
|
-
|
|
593
|
-
// src/features/analysis/scm/urlParser.ts
|
|
594
|
-
function detectAdoUrl(args) {
|
|
595
|
-
const { pathname, hostname, scmType } = args;
|
|
596
|
-
const hostnameParts = hostname.split(".");
|
|
597
|
-
const adoHostname = new URL(scmCloudUrl.Ado).hostname;
|
|
598
|
-
if (hostnameParts.length === 3 && hostnameParts[1] === "visualstudio" && hostnameParts[2] === "com") {
|
|
599
|
-
if (pathname.length === 2 && pathname[0] === "_git") {
|
|
600
|
-
return {
|
|
601
|
-
organization: hostnameParts[0],
|
|
602
|
-
projectName: pathname[1],
|
|
603
|
-
repoName: pathname[1]
|
|
604
|
-
};
|
|
605
|
-
}
|
|
606
|
-
if (pathname.length === 3 && pathname[1] === "_git") {
|
|
607
|
-
return {
|
|
608
|
-
organization: hostnameParts[0],
|
|
609
|
-
projectName: pathname[0],
|
|
610
|
-
repoName: pathname[2]
|
|
611
|
-
};
|
|
612
|
-
}
|
|
613
|
-
}
|
|
614
|
-
if (hostname === adoHostname || scmType === "Ado" /* Ado */) {
|
|
615
|
-
if (pathname.length === 3 && pathname[1] === "_git") {
|
|
616
|
-
return {
|
|
617
|
-
organization: pathname[0],
|
|
618
|
-
projectName: pathname[2],
|
|
619
|
-
repoName: pathname[2]
|
|
620
|
-
};
|
|
621
|
-
}
|
|
622
|
-
if (pathname.length === 4 && pathname[2] === "_git") {
|
|
623
|
-
return {
|
|
624
|
-
organization: pathname[0],
|
|
625
|
-
projectName: pathname[1],
|
|
626
|
-
repoName: pathname[3]
|
|
627
|
-
};
|
|
628
|
-
}
|
|
629
|
-
}
|
|
630
|
-
return null;
|
|
631
|
-
}
|
|
632
|
-
function detectGithubUrl(args) {
|
|
633
|
-
const { pathname, hostname, scmType } = args;
|
|
634
|
-
const githubHostname = new URL(scmCloudUrl.GitHub).hostname;
|
|
635
|
-
if (hostname === githubHostname || scmType === "GitHub" /* GitHub */) {
|
|
636
|
-
if (pathname.length === 2) {
|
|
637
|
-
return {
|
|
638
|
-
organization: pathname[0],
|
|
639
|
-
projectName: void 0,
|
|
640
|
-
repoName: pathname[1]
|
|
641
|
-
};
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
|
-
return null;
|
|
645
|
-
}
|
|
646
|
-
function detectGitlabUrl(args) {
|
|
647
|
-
const { pathname, hostname, scmType } = args;
|
|
648
|
-
const gitlabHostname = new URL(scmCloudUrl.GitLab).hostname;
|
|
649
|
-
if (hostname === gitlabHostname || scmType === "GitLab" /* GitLab */) {
|
|
650
|
-
if (pathname.length >= 2) {
|
|
651
|
-
return {
|
|
652
|
-
organization: pathname[0],
|
|
653
|
-
projectName: void 0,
|
|
654
|
-
repoName: pathname[pathname.length - 1]
|
|
655
|
-
};
|
|
656
|
-
}
|
|
657
|
-
}
|
|
658
|
-
return null;
|
|
659
|
-
}
|
|
660
|
-
function detectBitbucketUrl(args) {
|
|
661
|
-
const { pathname, hostname, scmType } = args;
|
|
662
|
-
const bitbucketHostname = new URL(scmCloudUrl.Bitbucket).hostname;
|
|
663
|
-
if (hostname === bitbucketHostname || scmType === "Bitbucket" /* Bitbucket */) {
|
|
664
|
-
if (pathname.length === 2) {
|
|
665
|
-
return {
|
|
666
|
-
organization: pathname[0],
|
|
667
|
-
projectName: void 0,
|
|
668
|
-
repoName: pathname[1]
|
|
669
|
-
};
|
|
670
|
-
}
|
|
671
|
-
}
|
|
672
|
-
return null;
|
|
673
|
-
}
|
|
674
|
-
var getRepoUrlFunctionMap = {
|
|
675
|
-
["GitLab" /* GitLab */]: detectGitlabUrl,
|
|
676
|
-
["GitHub" /* GitHub */]: detectGithubUrl,
|
|
677
|
-
["Ado" /* Ado */]: detectAdoUrl,
|
|
678
|
-
["Bitbucket" /* Bitbucket */]: detectBitbucketUrl
|
|
679
|
-
};
|
|
680
|
-
function getRepoInfo(args) {
|
|
681
|
-
for (const detectUrl of Object.values(getRepoUrlFunctionMap)) {
|
|
682
|
-
const detectUrlRes = detectUrl(args);
|
|
683
|
-
if (detectUrlRes) {
|
|
684
|
-
return detectUrlRes;
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
return null;
|
|
688
|
-
}
|
|
689
|
-
var NAME_REGEX = /[a-z0-9\-_.+]+/i;
|
|
690
203
|
var parseScmURL = (scmURL, scmType) => {
|
|
691
204
|
try {
|
|
692
205
|
const url = new URL(scmURL);
|
|
@@ -699,41 +212,55 @@ var parseScmURL = (scmURL, scmType) => {
|
|
|
699
212
|
});
|
|
700
213
|
if (!repo)
|
|
701
214
|
return null;
|
|
702
|
-
const { organization, repoName
|
|
215
|
+
const { organization, repoName } = repo;
|
|
703
216
|
if (!organization || !repoName)
|
|
704
217
|
return null;
|
|
705
218
|
if (!organization.match(NAME_REGEX) || !repoName.match(NAME_REGEX))
|
|
706
|
-
return null;
|
|
707
|
-
|
|
708
|
-
hostname,
|
|
709
|
-
organization,
|
|
710
|
-
projectPath,
|
|
711
|
-
repoName,
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
if (pathParts.length > 4)
|
|
728
|
-
return false;
|
|
729
|
-
if (pathParts.some((part) => !part.match(NAME_REGEX)))
|
|
730
|
-
return false;
|
|
731
|
-
return true;
|
|
219
|
+
return null;
|
|
220
|
+
const res = {
|
|
221
|
+
hostname,
|
|
222
|
+
organization,
|
|
223
|
+
projectPath,
|
|
224
|
+
repoName,
|
|
225
|
+
protocol: url.protocol,
|
|
226
|
+
pathElements: projectPath.split("/")
|
|
227
|
+
};
|
|
228
|
+
if (repo.scmType === "Ado" /* Ado */) {
|
|
229
|
+
return {
|
|
230
|
+
projectName: repo.projectName,
|
|
231
|
+
prefixPath: repo.prefixPath,
|
|
232
|
+
scmType: repo.scmType,
|
|
233
|
+
...res
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
return {
|
|
237
|
+
scmType: repo.scmType,
|
|
238
|
+
...res
|
|
239
|
+
};
|
|
732
240
|
} catch (e) {
|
|
733
241
|
return null;
|
|
734
242
|
}
|
|
735
243
|
};
|
|
736
244
|
|
|
245
|
+
// src/features/analysis/scm/shared/src/index.ts
|
|
246
|
+
var NAME_REGEX = /[a-z0-9\-_.+]+/i;
|
|
247
|
+
var ADO_PREFIX_PATH = "tfs";
|
|
248
|
+
|
|
249
|
+
// src/features/analysis/scm/types.ts
|
|
250
|
+
var ReferenceType = /* @__PURE__ */ ((ReferenceType2) => {
|
|
251
|
+
ReferenceType2["BRANCH"] = "BRANCH";
|
|
252
|
+
ReferenceType2["COMMIT"] = "COMMIT";
|
|
253
|
+
ReferenceType2["TAG"] = "TAG";
|
|
254
|
+
return ReferenceType2;
|
|
255
|
+
})(ReferenceType || {});
|
|
256
|
+
var ScmLibScmType = /* @__PURE__ */ ((ScmLibScmType2) => {
|
|
257
|
+
ScmLibScmType2["GITHUB"] = "GITHUB";
|
|
258
|
+
ScmLibScmType2["GITLAB"] = "GITLAB";
|
|
259
|
+
ScmLibScmType2["ADO"] = "ADO";
|
|
260
|
+
ScmLibScmType2["BITBUCKET"] = "BITBUCKET";
|
|
261
|
+
return ScmLibScmType2;
|
|
262
|
+
})(ScmLibScmType || {});
|
|
263
|
+
|
|
737
264
|
// src/features/analysis/scm/utils/get_issue_type.ts
|
|
738
265
|
var getIssueType = (issueType) => {
|
|
739
266
|
switch (issueType) {
|
|
@@ -942,6 +469,22 @@ var isUrlHasPath = (url) => {
|
|
|
942
469
|
function shouldValidateUrl(repoUrl) {
|
|
943
470
|
return repoUrl && isUrlHasPath(repoUrl);
|
|
944
471
|
}
|
|
472
|
+
var sanityRepoURL = (scmURL) => {
|
|
473
|
+
try {
|
|
474
|
+
const url = new URL(scmURL);
|
|
475
|
+
const projectPath = url.pathname.substring(1).replace(/.git$/i, "");
|
|
476
|
+
const pathParts = projectPath.split("/");
|
|
477
|
+
if (pathParts.length < 2)
|
|
478
|
+
return false;
|
|
479
|
+
if (pathParts.length > 4 && pathParts.at(0) !== ADO_PREFIX_PATH)
|
|
480
|
+
return false;
|
|
481
|
+
if (pathParts.some((part) => !part.match(NAME_REGEX)))
|
|
482
|
+
return false;
|
|
483
|
+
return true;
|
|
484
|
+
} catch (e) {
|
|
485
|
+
return null;
|
|
486
|
+
}
|
|
487
|
+
};
|
|
945
488
|
|
|
946
489
|
// src/features/analysis/scm/bitbucket/bitbucket.ts
|
|
947
490
|
var BITBUCKET_HOSTNAME = "bitbucket.org";
|
|
@@ -2061,7 +1604,7 @@ initGitlabFetchMock();
|
|
|
2061
1604
|
// src/features/analysis/scm/scmSubmit/index.ts
|
|
2062
1605
|
import fs from "node:fs/promises";
|
|
2063
1606
|
import parseDiff from "parse-diff";
|
|
2064
|
-
import
|
|
1607
|
+
import path from "path";
|
|
2065
1608
|
import { simpleGit } from "simple-git";
|
|
2066
1609
|
import tmp from "tmp";
|
|
2067
1610
|
import { z as z6 } from "zod";
|
|
@@ -2193,10 +1736,10 @@ function getCloudScmLibTypeFromUrl(url) {
|
|
|
2193
1736
|
return void 0;
|
|
2194
1737
|
}
|
|
2195
1738
|
var scmCloudHostname = {
|
|
2196
|
-
GitLab: new URL(scmCloudUrl.GitLab).hostname,
|
|
2197
|
-
GitHub: new URL(scmCloudUrl.GitHub).hostname,
|
|
2198
|
-
Ado: new URL(scmCloudUrl.Ado).hostname,
|
|
2199
|
-
Bitbucket: new URL(scmCloudUrl.Bitbucket).hostname
|
|
1739
|
+
["GitLab" /* GitLab */]: new URL(scmCloudUrl.GitLab).hostname,
|
|
1740
|
+
["GitHub" /* GitHub */]: new URL(scmCloudUrl.GitHub).hostname,
|
|
1741
|
+
["Ado" /* Ado */]: new URL(scmCloudUrl.Ado).hostname,
|
|
1742
|
+
["Bitbucket" /* Bitbucket */]: new URL(scmCloudUrl.Bitbucket).hostname
|
|
2200
1743
|
};
|
|
2201
1744
|
var scmLibScmTypeToScmType = {
|
|
2202
1745
|
["GITLAB" /* GITLAB */]: "GitLab" /* GitLab */,
|
|
@@ -2210,10 +1753,6 @@ var scmTypeToScmLibScmType = {
|
|
|
2210
1753
|
["Ado" /* Ado */]: "ADO" /* ADO */,
|
|
2211
1754
|
["Bitbucket" /* Bitbucket */]: "BITBUCKET" /* BITBUCKET */
|
|
2212
1755
|
};
|
|
2213
|
-
function getScmTypeFromScmLibType(scmLibType) {
|
|
2214
|
-
const parsedScmLibType = z7.nativeEnum(ScmLibScmType).parse(scmLibType);
|
|
2215
|
-
return scmLibScmTypeToScmType[parsedScmLibType];
|
|
2216
|
-
}
|
|
2217
1756
|
function getScmLibTypeFromScmType(scmType) {
|
|
2218
1757
|
const parsedScmType = z7.nativeEnum(ScmType).parse(scmType);
|
|
2219
1758
|
return scmTypeToScmLibScmType[parsedScmType];
|
|
@@ -2269,24 +1808,6 @@ function getScmConfig({
|
|
|
2269
1808
|
scmOrg: void 0
|
|
2270
1809
|
};
|
|
2271
1810
|
}
|
|
2272
|
-
async function scmCanReachRepo({
|
|
2273
|
-
repoUrl,
|
|
2274
|
-
scmType,
|
|
2275
|
-
accessToken,
|
|
2276
|
-
scmOrg
|
|
2277
|
-
}) {
|
|
2278
|
-
try {
|
|
2279
|
-
await SCMLib.init({
|
|
2280
|
-
url: repoUrl,
|
|
2281
|
-
accessToken,
|
|
2282
|
-
scmType: getScmLibTypeFromScmType(scmType),
|
|
2283
|
-
scmOrg
|
|
2284
|
-
});
|
|
2285
|
-
return true;
|
|
2286
|
-
} catch (e) {
|
|
2287
|
-
return false;
|
|
2288
|
-
}
|
|
2289
|
-
}
|
|
2290
1811
|
var InvalidRepoUrlError = class extends Error {
|
|
2291
1812
|
constructor(m) {
|
|
2292
1813
|
super(m);
|
|
@@ -2405,12 +1926,7 @@ var SCMLib = class {
|
|
|
2405
1926
|
static async getIsValidBranchName(branchName) {
|
|
2406
1927
|
return isValidBranchName(branchName);
|
|
2407
1928
|
}
|
|
2408
|
-
static async init({
|
|
2409
|
-
url,
|
|
2410
|
-
accessToken,
|
|
2411
|
-
scmType,
|
|
2412
|
-
scmOrg
|
|
2413
|
-
}) {
|
|
1929
|
+
static async init({ url, accessToken, scmType, scmOrg }, { propagateExceptions = false } = {}) {
|
|
2414
1930
|
const trimmedUrl = url ? url.trim().replace(/\/$/, "").replace(/.git$/i, "") : void 0;
|
|
2415
1931
|
try {
|
|
2416
1932
|
switch (scmType) {
|
|
@@ -2443,6 +1959,9 @@ var SCMLib = class {
|
|
|
2443
1959
|
);
|
|
2444
1960
|
}
|
|
2445
1961
|
console.error(`error validating scm: ${scmType} `, e);
|
|
1962
|
+
if (propagateExceptions) {
|
|
1963
|
+
throw e;
|
|
1964
|
+
}
|
|
2446
1965
|
}
|
|
2447
1966
|
return new StubSCMLib(trimmedUrl, void 0, void 0);
|
|
2448
1967
|
}
|
|
@@ -2941,792 +2460,1360 @@ var GithubSCMLib = class extends SCMLib {
|
|
|
2941
2460
|
async postGeneralPrComment(params) {
|
|
2942
2461
|
const { prNumber, body } = params;
|
|
2943
2462
|
this._validateAccessTokenAndUrl();
|
|
2944
|
-
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
2945
|
-
return await this.githubSdk.postGeneralPrComment({
|
|
2946
|
-
issue_number: prNumber,
|
|
2947
|
-
owner,
|
|
2948
|
-
repo,
|
|
2949
|
-
body
|
|
2950
|
-
});
|
|
2463
|
+
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
2464
|
+
return await this.githubSdk.postGeneralPrComment({
|
|
2465
|
+
issue_number: prNumber,
|
|
2466
|
+
owner,
|
|
2467
|
+
repo,
|
|
2468
|
+
body
|
|
2469
|
+
});
|
|
2470
|
+
}
|
|
2471
|
+
async getGeneralPrComments(params) {
|
|
2472
|
+
const { prNumber } = params;
|
|
2473
|
+
this._validateAccessTokenAndUrl();
|
|
2474
|
+
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
2475
|
+
return await this.githubSdk.getGeneralPrComments({
|
|
2476
|
+
issue_number: prNumber,
|
|
2477
|
+
owner,
|
|
2478
|
+
repo
|
|
2479
|
+
});
|
|
2480
|
+
}
|
|
2481
|
+
async deleteGeneralPrComment({
|
|
2482
|
+
commentId
|
|
2483
|
+
}) {
|
|
2484
|
+
this._validateAccessTokenAndUrl();
|
|
2485
|
+
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
2486
|
+
return this.githubSdk.deleteGeneralPrComment({
|
|
2487
|
+
owner,
|
|
2488
|
+
repo,
|
|
2489
|
+
comment_id: commentId
|
|
2490
|
+
});
|
|
2491
|
+
}
|
|
2492
|
+
};
|
|
2493
|
+
var StubSCMLib = class extends SCMLib {
|
|
2494
|
+
async createSubmitRequest(_params) {
|
|
2495
|
+
console.error("createSubmitRequest() not implemented");
|
|
2496
|
+
throw new Error("createSubmitRequest() not implemented");
|
|
2497
|
+
}
|
|
2498
|
+
getScmLibType() {
|
|
2499
|
+
console.error("getScmLibType() not implemented");
|
|
2500
|
+
throw new Error("getScmLibType() not implemented");
|
|
2501
|
+
}
|
|
2502
|
+
getAuthHeaders() {
|
|
2503
|
+
console.error("getAuthHeaders() not implemented");
|
|
2504
|
+
throw new Error("getAuthHeaders() not implemented");
|
|
2505
|
+
}
|
|
2506
|
+
getDownloadUrl(_sha) {
|
|
2507
|
+
console.error("getDownloadUrl() not implemented");
|
|
2508
|
+
throw new Error("getDownloadUrl() not implemented");
|
|
2509
|
+
}
|
|
2510
|
+
async getIsRemoteBranch(_branch) {
|
|
2511
|
+
console.error("getIsRemoteBranch() not implemented");
|
|
2512
|
+
throw new Error("getIsRemoteBranch() not implemented");
|
|
2513
|
+
}
|
|
2514
|
+
async validateParams() {
|
|
2515
|
+
console.error("validateParams() not implemented");
|
|
2516
|
+
throw new Error("validateParams() not implemented");
|
|
2517
|
+
}
|
|
2518
|
+
async getRepoList(_scmOrg) {
|
|
2519
|
+
console.error("getRepoList() not implemented");
|
|
2520
|
+
throw new Error("getRepoList() not implemented");
|
|
2521
|
+
}
|
|
2522
|
+
async getBranchList() {
|
|
2523
|
+
console.error("getBranchList() not implemented");
|
|
2524
|
+
throw new Error("getBranchList() not implemented");
|
|
2525
|
+
}
|
|
2526
|
+
async getUsername() {
|
|
2527
|
+
console.error("getUsername() not implemented");
|
|
2528
|
+
throw new Error("getUsername() not implemented");
|
|
2529
|
+
}
|
|
2530
|
+
async getSubmitRequestStatus(_scmSubmitRequestId) {
|
|
2531
|
+
console.error("getSubmitRequestStatus() not implemented");
|
|
2532
|
+
throw new Error("getSubmitRequestStatus() not implemented");
|
|
2533
|
+
}
|
|
2534
|
+
async getUserHasAccessToRepo() {
|
|
2535
|
+
console.error("getUserHasAccessToRepo() not implemented");
|
|
2536
|
+
throw new Error("getUserHasAccessToRepo() not implemented");
|
|
2537
|
+
}
|
|
2538
|
+
async getRepoBlameRanges(_ref, _path) {
|
|
2539
|
+
console.error("getRepoBlameRanges() not implemented");
|
|
2540
|
+
throw new Error("getRepoBlameRanges() not implemented");
|
|
2541
|
+
}
|
|
2542
|
+
async getReferenceData(_ref) {
|
|
2543
|
+
console.error("getReferenceData() not implemented");
|
|
2544
|
+
throw new Error("getReferenceData() not implemented");
|
|
2545
|
+
}
|
|
2546
|
+
async getRepoDefaultBranch() {
|
|
2547
|
+
console.error("getRepoDefaultBranch() not implemented");
|
|
2548
|
+
throw new Error("getRepoDefaultBranch() not implemented");
|
|
2549
|
+
}
|
|
2550
|
+
async getPrUrl(_prNumber) {
|
|
2551
|
+
console.error("getPr() not implemented");
|
|
2552
|
+
throw new Error("getPr() not implemented");
|
|
2553
|
+
}
|
|
2554
|
+
_getUsernameForAuthUrl() {
|
|
2555
|
+
throw new Error("Method not implemented.");
|
|
2556
|
+
}
|
|
2557
|
+
};
|
|
2558
|
+
function getUserAndPassword(token) {
|
|
2559
|
+
const [username, password] = token.split(":");
|
|
2560
|
+
const safePasswordAndUsername = z7.object({ username: z7.string(), password: z7.string() }).parse({ username, password });
|
|
2561
|
+
return {
|
|
2562
|
+
username: safePasswordAndUsername.username,
|
|
2563
|
+
password: safePasswordAndUsername.password
|
|
2564
|
+
};
|
|
2565
|
+
}
|
|
2566
|
+
function createBitbucketSdk(token) {
|
|
2567
|
+
if (!token) {
|
|
2568
|
+
return getBitbucketSdk({ authType: "public" });
|
|
2569
|
+
}
|
|
2570
|
+
if (token.includes(":")) {
|
|
2571
|
+
const { password, username } = getUserAndPassword(token);
|
|
2572
|
+
return getBitbucketSdk({
|
|
2573
|
+
authType: "basic",
|
|
2574
|
+
username,
|
|
2575
|
+
password
|
|
2576
|
+
});
|
|
2577
|
+
}
|
|
2578
|
+
return getBitbucketSdk({ authType: "token", token });
|
|
2579
|
+
}
|
|
2580
|
+
var BitbucketSCMLib = class extends SCMLib {
|
|
2581
|
+
constructor(url, accessToken, scmOrg) {
|
|
2582
|
+
super(url, accessToken, scmOrg);
|
|
2583
|
+
__publicField(this, "bitbucketSdk");
|
|
2584
|
+
const bitbucketSdk = createBitbucketSdk(accessToken);
|
|
2585
|
+
this.bitbucketSdk = bitbucketSdk;
|
|
2586
|
+
}
|
|
2587
|
+
getAuthData() {
|
|
2588
|
+
const authType = this.bitbucketSdk.getAuthType();
|
|
2589
|
+
switch (authType) {
|
|
2590
|
+
case "basic": {
|
|
2591
|
+
this._validateAccessToken();
|
|
2592
|
+
const { username, password } = getUserAndPassword(this.accessToken);
|
|
2593
|
+
return { username, password, authType };
|
|
2594
|
+
}
|
|
2595
|
+
case "token": {
|
|
2596
|
+
return { authType, token: z7.string().parse(this.accessToken) };
|
|
2597
|
+
}
|
|
2598
|
+
case "public":
|
|
2599
|
+
return { authType };
|
|
2600
|
+
}
|
|
2601
|
+
}
|
|
2602
|
+
async createSubmitRequest(params) {
|
|
2603
|
+
this._validateAccessTokenAndUrl();
|
|
2604
|
+
const pullRequestRes = await this.bitbucketSdk.createPullRequest({
|
|
2605
|
+
...params,
|
|
2606
|
+
repoUrl: this.url
|
|
2607
|
+
});
|
|
2608
|
+
return String(z7.number().parse(pullRequestRes.id));
|
|
2609
|
+
}
|
|
2610
|
+
async validateParams() {
|
|
2611
|
+
return validateBitbucketParams({
|
|
2612
|
+
bitbucketClient: this.bitbucketSdk,
|
|
2613
|
+
url: this.url
|
|
2614
|
+
});
|
|
2615
|
+
}
|
|
2616
|
+
async getRepoList(scmOrg) {
|
|
2617
|
+
this._validateAccessToken();
|
|
2618
|
+
return this.bitbucketSdk.getRepos({
|
|
2619
|
+
workspaceSlug: scmOrg
|
|
2620
|
+
});
|
|
2621
|
+
}
|
|
2622
|
+
async getBranchList() {
|
|
2623
|
+
this._validateAccessTokenAndUrl();
|
|
2624
|
+
return this.bitbucketSdk.getBranchList({
|
|
2625
|
+
repoUrl: this.url
|
|
2626
|
+
});
|
|
2627
|
+
}
|
|
2628
|
+
getScmLibType() {
|
|
2629
|
+
return "BITBUCKET" /* BITBUCKET */;
|
|
2630
|
+
}
|
|
2631
|
+
getAuthHeaders() {
|
|
2632
|
+
const authType = this.bitbucketSdk.getAuthType();
|
|
2633
|
+
switch (authType) {
|
|
2634
|
+
case "public":
|
|
2635
|
+
return {};
|
|
2636
|
+
case "token":
|
|
2637
|
+
return { authorization: `Bearer ${this.accessToken}` };
|
|
2638
|
+
case "basic": {
|
|
2639
|
+
this._validateAccessToken();
|
|
2640
|
+
const { username, password } = getUserAndPassword(this.accessToken);
|
|
2641
|
+
return {
|
|
2642
|
+
authorization: `Basic ${Buffer.from(
|
|
2643
|
+
username + ":" + password
|
|
2644
|
+
).toString("base64")}`
|
|
2645
|
+
};
|
|
2646
|
+
}
|
|
2647
|
+
}
|
|
2648
|
+
}
|
|
2649
|
+
async getDownloadUrl(sha) {
|
|
2650
|
+
this._validateUrl();
|
|
2651
|
+
return this.bitbucketSdk.getDownloadUrl({ url: this.url, sha });
|
|
2652
|
+
}
|
|
2653
|
+
async _getUsernameForAuthUrl() {
|
|
2654
|
+
this._validateAccessTokenAndUrl();
|
|
2655
|
+
const user = await this.bitbucketSdk.getUser();
|
|
2656
|
+
if (!user.username) {
|
|
2657
|
+
throw new Error("no username found");
|
|
2658
|
+
}
|
|
2659
|
+
return user.username;
|
|
2951
2660
|
}
|
|
2952
|
-
async
|
|
2953
|
-
const { prNumber } = params;
|
|
2661
|
+
async getIsRemoteBranch(branch) {
|
|
2954
2662
|
this._validateAccessTokenAndUrl();
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2663
|
+
try {
|
|
2664
|
+
const res = await this.bitbucketSdk.getBranch({
|
|
2665
|
+
branchName: branch,
|
|
2666
|
+
repoUrl: this.url
|
|
2667
|
+
});
|
|
2668
|
+
return res.name === branch;
|
|
2669
|
+
} catch (e) {
|
|
2670
|
+
return false;
|
|
2671
|
+
}
|
|
2961
2672
|
}
|
|
2962
|
-
async
|
|
2963
|
-
commentId
|
|
2964
|
-
}) {
|
|
2673
|
+
async getUserHasAccessToRepo() {
|
|
2965
2674
|
this._validateAccessTokenAndUrl();
|
|
2966
|
-
|
|
2967
|
-
return this.githubSdk.deleteGeneralPrComment({
|
|
2968
|
-
owner,
|
|
2969
|
-
repo,
|
|
2970
|
-
comment_id: commentId
|
|
2971
|
-
});
|
|
2675
|
+
return this.bitbucketSdk.getIsUserCollaborator({ repoUrl: this.url });
|
|
2972
2676
|
}
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
throw new Error("createSubmitRequest() not implemented");
|
|
2677
|
+
async getUsername() {
|
|
2678
|
+
this._validateAccessToken();
|
|
2679
|
+
const res = await this.bitbucketSdk.getUser();
|
|
2680
|
+
return z7.string().parse(res.username);
|
|
2978
2681
|
}
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2682
|
+
async getSubmitRequestStatus(_scmSubmitRequestId) {
|
|
2683
|
+
this._validateAccessTokenAndUrl();
|
|
2684
|
+
const pullRequestRes = await this.bitbucketSdk.getPullRequest({
|
|
2685
|
+
prNumber: Number(_scmSubmitRequestId),
|
|
2686
|
+
url: this.url
|
|
2687
|
+
});
|
|
2688
|
+
switch (pullRequestRes.state) {
|
|
2689
|
+
case "OPEN":
|
|
2690
|
+
return "open";
|
|
2691
|
+
case "MERGED":
|
|
2692
|
+
return "merged";
|
|
2693
|
+
case "DECLINED":
|
|
2694
|
+
return "closed";
|
|
2695
|
+
default:
|
|
2696
|
+
throw new Error(`unknown state ${pullRequestRes.state} `);
|
|
2697
|
+
}
|
|
2982
2698
|
}
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
throw new Error("getAuthHeaders() not implemented");
|
|
2699
|
+
async getRepoBlameRanges(_ref, _path) {
|
|
2700
|
+
return [];
|
|
2986
2701
|
}
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2702
|
+
async getReferenceData(ref) {
|
|
2703
|
+
this._validateUrl();
|
|
2704
|
+
return this.bitbucketSdk.getReferenceData({ url: this.url, ref });
|
|
2990
2705
|
}
|
|
2991
|
-
async
|
|
2992
|
-
|
|
2993
|
-
|
|
2706
|
+
async getRepoDefaultBranch() {
|
|
2707
|
+
this._validateUrl();
|
|
2708
|
+
const repoRes = await this.bitbucketSdk.getRepo({ repoUrl: this.url });
|
|
2709
|
+
return z7.string().parse(repoRes.mainbranch?.name);
|
|
2994
2710
|
}
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2711
|
+
getPrUrl(prNumber) {
|
|
2712
|
+
this._validateUrl();
|
|
2713
|
+
const { repoSlug, workspace } = parseBitbucketOrganizationAndRepo(this.url);
|
|
2714
|
+
return Promise.resolve(
|
|
2715
|
+
`https://bitbucket.org/${workspace}/${repoSlug}/pull-requests/${prNumber}`
|
|
2716
|
+
);
|
|
2998
2717
|
}
|
|
2999
|
-
async
|
|
3000
|
-
|
|
3001
|
-
|
|
2718
|
+
async refreshToken(params) {
|
|
2719
|
+
const getBitbucketTokenResponse = await getBitbucketToken({
|
|
2720
|
+
authType: "refresh_token",
|
|
2721
|
+
...params
|
|
2722
|
+
});
|
|
2723
|
+
return {
|
|
2724
|
+
accessToken: getBitbucketTokenResponse.access_token,
|
|
2725
|
+
refreshToken: getBitbucketTokenResponse.refresh_token
|
|
2726
|
+
};
|
|
3002
2727
|
}
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
2728
|
+
};
|
|
2729
|
+
|
|
2730
|
+
// src/features/analysis/scm/ado/validation.ts
|
|
2731
|
+
import { z as z8 } from "zod";
|
|
2732
|
+
var ValidPullRequestStatusZ = z8.union([
|
|
2733
|
+
z8.literal(1 /* Active */),
|
|
2734
|
+
z8.literal(2 /* Abandoned */),
|
|
2735
|
+
z8.literal(3 /* Completed */)
|
|
2736
|
+
]);
|
|
2737
|
+
var AdoAuthResultZ = z8.object({
|
|
2738
|
+
access_token: z8.string().min(1),
|
|
2739
|
+
token_type: z8.string().min(1),
|
|
2740
|
+
refresh_token: z8.string().min(1)
|
|
2741
|
+
});
|
|
2742
|
+
var profileZ = z8.object({
|
|
2743
|
+
displayName: z8.string(),
|
|
2744
|
+
publicAlias: z8.string().min(1),
|
|
2745
|
+
emailAddress: z8.string(),
|
|
2746
|
+
coreRevision: z8.number(),
|
|
2747
|
+
timeStamp: z8.string(),
|
|
2748
|
+
id: z8.string(),
|
|
2749
|
+
revision: z8.number()
|
|
2750
|
+
});
|
|
2751
|
+
var accountsZ = z8.object({
|
|
2752
|
+
count: z8.number(),
|
|
2753
|
+
value: z8.array(
|
|
2754
|
+
z8.object({
|
|
2755
|
+
accountId: z8.string(),
|
|
2756
|
+
accountUri: z8.string(),
|
|
2757
|
+
accountName: z8.string()
|
|
2758
|
+
})
|
|
2759
|
+
)
|
|
2760
|
+
});
|
|
2761
|
+
|
|
2762
|
+
// src/features/analysis/scm/ado/utils.ts
|
|
2763
|
+
function _getPublicAdoClient({
|
|
2764
|
+
orgName,
|
|
2765
|
+
origin: origin2
|
|
2766
|
+
}) {
|
|
2767
|
+
const orgUrl = `${origin2}/${orgName}`;
|
|
2768
|
+
const authHandler = api.getPersonalAccessTokenHandler("");
|
|
2769
|
+
authHandler.canHandleAuthentication = () => false;
|
|
2770
|
+
authHandler.prepareRequest = (_options) => {
|
|
2771
|
+
return;
|
|
2772
|
+
};
|
|
2773
|
+
const connection = new api.WebApi(orgUrl, authHandler);
|
|
2774
|
+
return connection;
|
|
2775
|
+
}
|
|
2776
|
+
function removeTrailingSlash2(str) {
|
|
2777
|
+
return str.trim().replace(/\/+$/, "");
|
|
2778
|
+
}
|
|
2779
|
+
function parseAdoOwnerAndRepo(adoUrl) {
|
|
2780
|
+
adoUrl = removeTrailingSlash2(adoUrl);
|
|
2781
|
+
const parsingResult = parseScmURL(adoUrl, "Ado" /* Ado */);
|
|
2782
|
+
if (!parsingResult || parsingResult.scmType !== "Ado" /* Ado */) {
|
|
2783
|
+
throw new InvalidUrlPatternError(`
|
|
2784
|
+
: ${adoUrl}`);
|
|
3006
2785
|
}
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
2786
|
+
const {
|
|
2787
|
+
organization,
|
|
2788
|
+
repoName,
|
|
2789
|
+
projectName,
|
|
2790
|
+
projectPath,
|
|
2791
|
+
pathElements,
|
|
2792
|
+
hostname,
|
|
2793
|
+
protocol
|
|
2794
|
+
} = parsingResult;
|
|
2795
|
+
return {
|
|
2796
|
+
owner: decodeURI(organization),
|
|
2797
|
+
repo: decodeURI(repoName),
|
|
2798
|
+
projectName: projectName ? decodeURI(projectName) : void 0,
|
|
2799
|
+
projectPath,
|
|
2800
|
+
pathElements,
|
|
2801
|
+
prefixPath: parsingResult.prefixPath,
|
|
2802
|
+
origin: `${protocol}//${hostname}`
|
|
2803
|
+
};
|
|
2804
|
+
}
|
|
2805
|
+
async function getAdoConnectData({
|
|
2806
|
+
url,
|
|
2807
|
+
tokenOrg,
|
|
2808
|
+
adoTokenInfo
|
|
2809
|
+
}) {
|
|
2810
|
+
if (url) {
|
|
2811
|
+
const urlObject = new URL(url);
|
|
2812
|
+
if (tokenOrg && (urlObject.origin === url || `${urlObject.origin}/tfs` === url)) {
|
|
2813
|
+
return {
|
|
2814
|
+
origin: url,
|
|
2815
|
+
org: tokenOrg
|
|
2816
|
+
};
|
|
2817
|
+
}
|
|
2818
|
+
const { owner, origin: origin2, prefixPath } = parseAdoOwnerAndRepo(url);
|
|
2819
|
+
return {
|
|
2820
|
+
org: owner,
|
|
2821
|
+
origin: prefixPath ? `${origin2}/${prefixPath}` : origin2
|
|
2822
|
+
};
|
|
3010
2823
|
}
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
2824
|
+
if (!tokenOrg) {
|
|
2825
|
+
if (adoTokenInfo.type === "OAUTH" /* OAUTH */) {
|
|
2826
|
+
const [org] = await _getOrgsForOauthToken({
|
|
2827
|
+
oauthToken: adoTokenInfo.accessToken
|
|
2828
|
+
});
|
|
2829
|
+
return {
|
|
2830
|
+
org: z9.string().parse(org),
|
|
2831
|
+
origin: DEFUALT_ADO_ORIGIN
|
|
2832
|
+
};
|
|
2833
|
+
}
|
|
2834
|
+
throw new InvalidRepoUrlError("ADO URL is null");
|
|
3014
2835
|
}
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
2836
|
+
return {
|
|
2837
|
+
org: tokenOrg,
|
|
2838
|
+
origin: DEFUALT_ADO_ORIGIN
|
|
2839
|
+
};
|
|
2840
|
+
}
|
|
2841
|
+
function isAdoOnCloud(url) {
|
|
2842
|
+
const urlObj = new URL(url);
|
|
2843
|
+
return urlObj.origin.toLowerCase() === DEFUALT_ADO_ORIGIN || urlObj.hostname.toLowerCase().endsWith(".visualstudio.com");
|
|
2844
|
+
}
|
|
2845
|
+
async function getAdoApiClient(params) {
|
|
2846
|
+
const { origin: origin2 = DEFUALT_ADO_ORIGIN, orgName } = params;
|
|
2847
|
+
if (params.tokenType === "NONE" /* NONE */ || // note: move to public client if the token is not associated with the PAT org
|
|
2848
|
+
// we're only doing it the ado on the cloud
|
|
2849
|
+
params.tokenType === "PAT" /* PAT */ && params.patTokenOrg !== orgName && isAdoOnCloud(origin2)) {
|
|
2850
|
+
return _getPublicAdoClient({ orgName, origin: origin2 });
|
|
3018
2851
|
}
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
2852
|
+
const orgUrl = `${origin2}/${orgName}`;
|
|
2853
|
+
if (params.tokenType === "OAUTH" /* OAUTH */) {
|
|
2854
|
+
if (isAdoOnCloud(origin2)) {
|
|
2855
|
+
throw new Error(
|
|
2856
|
+
`Oauth token is not supported for ADO on prem - ${origin2} `
|
|
2857
|
+
);
|
|
2858
|
+
}
|
|
2859
|
+
const connection2 = new api.WebApi(
|
|
2860
|
+
orgUrl,
|
|
2861
|
+
api.getBearerHandler(params.accessToken),
|
|
2862
|
+
{}
|
|
2863
|
+
);
|
|
2864
|
+
return connection2;
|
|
3022
2865
|
}
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
2866
|
+
const authHandler = api.getPersonalAccessTokenHandler(params.accessToken);
|
|
2867
|
+
const isBroker = BROKERED_HOSTS.includes(new URL(orgUrl).origin);
|
|
2868
|
+
const connection = new api.WebApi(
|
|
2869
|
+
orgUrl,
|
|
2870
|
+
authHandler,
|
|
2871
|
+
isBroker ? {
|
|
2872
|
+
proxy: {
|
|
2873
|
+
proxyUrl: GIT_PROXY_HOST
|
|
2874
|
+
},
|
|
2875
|
+
ignoreSslError: true
|
|
2876
|
+
} : void 0
|
|
2877
|
+
);
|
|
2878
|
+
return connection;
|
|
2879
|
+
}
|
|
2880
|
+
function getAdoTokenInfo(token) {
|
|
2881
|
+
if (!token) {
|
|
2882
|
+
return { type: "NONE" /* NONE */ };
|
|
3026
2883
|
}
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
throw new Error("getRepoDefaultBranch() not implemented");
|
|
2884
|
+
if (token.includes(".")) {
|
|
2885
|
+
return { type: "OAUTH" /* OAUTH */, accessToken: token };
|
|
3030
2886
|
}
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
2887
|
+
return { type: "PAT" /* PAT */, accessToken: token };
|
|
2888
|
+
}
|
|
2889
|
+
async function getAdoClientParams(params) {
|
|
2890
|
+
const { url, accessToken, tokenOrg } = params;
|
|
2891
|
+
const adoTokenInfo = getAdoTokenInfo(accessToken);
|
|
2892
|
+
const { org, origin: origin2 } = await getAdoConnectData({
|
|
2893
|
+
url,
|
|
2894
|
+
tokenOrg,
|
|
2895
|
+
adoTokenInfo
|
|
2896
|
+
});
|
|
2897
|
+
switch (adoTokenInfo.type) {
|
|
2898
|
+
case "NONE" /* NONE */:
|
|
2899
|
+
return {
|
|
2900
|
+
tokenType: "NONE" /* NONE */,
|
|
2901
|
+
origin: origin2,
|
|
2902
|
+
orgName: org.toLowerCase()
|
|
2903
|
+
};
|
|
2904
|
+
case "OAUTH" /* OAUTH */: {
|
|
2905
|
+
return {
|
|
2906
|
+
tokenType: "OAUTH" /* OAUTH */,
|
|
2907
|
+
accessToken: adoTokenInfo.accessToken,
|
|
2908
|
+
origin: origin2,
|
|
2909
|
+
orgName: org.toLowerCase()
|
|
2910
|
+
};
|
|
2911
|
+
}
|
|
2912
|
+
case "PAT" /* PAT */: {
|
|
2913
|
+
return {
|
|
2914
|
+
tokenType: "PAT" /* PAT */,
|
|
2915
|
+
accessToken: adoTokenInfo.accessToken,
|
|
2916
|
+
patTokenOrg: z9.string().parse(tokenOrg).toLowerCase(),
|
|
2917
|
+
origin: origin2,
|
|
2918
|
+
orgName: org.toLowerCase()
|
|
2919
|
+
};
|
|
2920
|
+
}
|
|
3034
2921
|
}
|
|
3035
|
-
|
|
3036
|
-
|
|
2922
|
+
}
|
|
2923
|
+
async function adoValidateParams({
|
|
2924
|
+
url,
|
|
2925
|
+
accessToken,
|
|
2926
|
+
tokenOrg
|
|
2927
|
+
}) {
|
|
2928
|
+
try {
|
|
2929
|
+
const api2 = await getAdoApiClient(
|
|
2930
|
+
await getAdoClientParams({ url, accessToken, tokenOrg })
|
|
2931
|
+
);
|
|
2932
|
+
await api2.connect();
|
|
2933
|
+
} catch (e) {
|
|
2934
|
+
console.log("adoValidateParams error", e);
|
|
2935
|
+
const error = e;
|
|
2936
|
+
const code = error.code || error.status || error.statusCode || error.response?.status || error.response?.statusCode || error.response?.code;
|
|
2937
|
+
const description = error.description || `${e}`;
|
|
2938
|
+
if (code === 401 || code === 403 || description.includes("401") || description.includes("403")) {
|
|
2939
|
+
throw new InvalidAccessTokenError(`invalid ADO access token`);
|
|
2940
|
+
}
|
|
2941
|
+
if (code === 404 || description.includes("404") || description.includes("Not Found")) {
|
|
2942
|
+
throw new InvalidRepoUrlError(`invalid ADO repo URL ${url}`);
|
|
2943
|
+
}
|
|
2944
|
+
throw e;
|
|
3037
2945
|
}
|
|
3038
|
-
}
|
|
3039
|
-
function
|
|
3040
|
-
|
|
3041
|
-
|
|
2946
|
+
}
|
|
2947
|
+
async function _getOrgsForOauthToken({
|
|
2948
|
+
oauthToken
|
|
2949
|
+
}) {
|
|
2950
|
+
const profileRes = await fetch(
|
|
2951
|
+
"https://app.vssps.visualstudio.com/_apis/profile/profiles/me?api-version=6.0",
|
|
2952
|
+
{
|
|
2953
|
+
method: "GET",
|
|
2954
|
+
headers: {
|
|
2955
|
+
Authorization: `Bearer ${oauthToken}`
|
|
2956
|
+
}
|
|
2957
|
+
}
|
|
2958
|
+
);
|
|
2959
|
+
const profileJson = await profileRes.json();
|
|
2960
|
+
const profile = profileZ.parse(profileJson);
|
|
2961
|
+
const accountsRes = await fetch(
|
|
2962
|
+
`https://app.vssps.visualstudio.com/_apis/accounts?memberId=${profile.publicAlias}&api-version=6.0`,
|
|
2963
|
+
{
|
|
2964
|
+
method: "GET",
|
|
2965
|
+
headers: {
|
|
2966
|
+
Authorization: `Bearer ${oauthToken}`
|
|
2967
|
+
}
|
|
2968
|
+
}
|
|
2969
|
+
);
|
|
2970
|
+
const accountsJson = await accountsRes.json();
|
|
2971
|
+
const accounts = accountsZ.parse(accountsJson);
|
|
2972
|
+
const orgs = accounts.value.map((account) => account.accountName).filter((value, index, array) => array.indexOf(value) === index);
|
|
2973
|
+
return orgs;
|
|
2974
|
+
}
|
|
2975
|
+
|
|
2976
|
+
// src/features/analysis/scm/ado/ado.ts
|
|
2977
|
+
async function getAdoSdk(params) {
|
|
2978
|
+
const api2 = await getAdoApiClient(params);
|
|
3042
2979
|
return {
|
|
3043
|
-
|
|
3044
|
-
|
|
2980
|
+
async getAdoIsUserCollaborator({ repoUrl }) {
|
|
2981
|
+
try {
|
|
2982
|
+
const { repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
|
|
2983
|
+
const git = await api2.getGitApi();
|
|
2984
|
+
const branches = await git.getBranches(repo, projectName);
|
|
2985
|
+
if (!branches || branches.length === 0) {
|
|
2986
|
+
throw new InvalidRepoUrlError("no branches");
|
|
2987
|
+
}
|
|
2988
|
+
return true;
|
|
2989
|
+
} catch (e) {
|
|
2990
|
+
return false;
|
|
2991
|
+
}
|
|
2992
|
+
},
|
|
2993
|
+
async getAdoPullRequestStatus({
|
|
2994
|
+
repoUrl,
|
|
2995
|
+
prNumber
|
|
2996
|
+
}) {
|
|
2997
|
+
const { repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
|
|
2998
|
+
const git = await api2.getGitApi();
|
|
2999
|
+
const res = await git.getPullRequest(repo, prNumber, projectName);
|
|
3000
|
+
const parsedPullRequestStatus = ValidPullRequestStatusZ.safeParse(
|
|
3001
|
+
res.status
|
|
3002
|
+
);
|
|
3003
|
+
if (!parsedPullRequestStatus.success) {
|
|
3004
|
+
throw new Error("bad pr status for ADO");
|
|
3005
|
+
}
|
|
3006
|
+
return parsedPullRequestStatus.data;
|
|
3007
|
+
},
|
|
3008
|
+
async getAdoIsRemoteBranch({
|
|
3009
|
+
repoUrl,
|
|
3010
|
+
branch
|
|
3011
|
+
}) {
|
|
3012
|
+
const { repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
|
|
3013
|
+
const git = await api2.getGitApi();
|
|
3014
|
+
try {
|
|
3015
|
+
const branchStatus = await git.getBranch(repo, branch, projectName);
|
|
3016
|
+
if (!branchStatus || !branchStatus.commit) {
|
|
3017
|
+
throw new InvalidRepoUrlError("no branch status");
|
|
3018
|
+
}
|
|
3019
|
+
return branchStatus.name === branch;
|
|
3020
|
+
} catch (e) {
|
|
3021
|
+
return false;
|
|
3022
|
+
}
|
|
3023
|
+
},
|
|
3024
|
+
async getAdoPrUrl({ url, prNumber }) {
|
|
3025
|
+
const { repo, projectName } = parseAdoOwnerAndRepo(url);
|
|
3026
|
+
const git = await api2.getGitApi();
|
|
3027
|
+
const getRepositoryRes = await git.getRepository(
|
|
3028
|
+
decodeURI(repo),
|
|
3029
|
+
projectName ? decodeURI(projectName) : void 0
|
|
3030
|
+
);
|
|
3031
|
+
return `${getRepositoryRes.webUrl}/pullrequest/${prNumber}`;
|
|
3032
|
+
},
|
|
3033
|
+
getAdoDownloadUrl({
|
|
3034
|
+
repoUrl,
|
|
3035
|
+
branch
|
|
3036
|
+
}) {
|
|
3037
|
+
const { owner, repo, projectName, prefixPath } = parseAdoOwnerAndRepo(repoUrl);
|
|
3038
|
+
const url = new URL(repoUrl);
|
|
3039
|
+
const origin2 = url.origin.toLowerCase().endsWith(".visualstudio.com") ? DEFUALT_ADO_ORIGIN : url.origin.toLowerCase();
|
|
3040
|
+
const params2 = `path=/&versionDescriptor[versionOptions]=0&versionDescriptor[versionType]=commit&versionDescriptor[version]=${branch}&resolveLfs=true&$format=zip&api-version=5.0&download=true`;
|
|
3041
|
+
const path9 = [
|
|
3042
|
+
prefixPath,
|
|
3043
|
+
owner,
|
|
3044
|
+
projectName,
|
|
3045
|
+
"_apis",
|
|
3046
|
+
"git",
|
|
3047
|
+
"repositories",
|
|
3048
|
+
repo,
|
|
3049
|
+
"items",
|
|
3050
|
+
"items"
|
|
3051
|
+
].filter(Boolean).join("/");
|
|
3052
|
+
return new URL(`${path9}?${params2}`, origin2).toString();
|
|
3053
|
+
},
|
|
3054
|
+
async getAdoBranchList({ repoUrl }) {
|
|
3055
|
+
const { repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
|
|
3056
|
+
const git = await api2.getGitApi();
|
|
3057
|
+
try {
|
|
3058
|
+
const res = await git.getBranches(repo, projectName);
|
|
3059
|
+
res.sort((a, b) => {
|
|
3060
|
+
if (!a.commit?.committer?.date || !b.commit?.committer?.date) {
|
|
3061
|
+
return 0;
|
|
3062
|
+
}
|
|
3063
|
+
return b.commit?.committer?.date.getTime() - a.commit?.committer?.date.getTime();
|
|
3064
|
+
});
|
|
3065
|
+
return res.reduce((acc, branch) => {
|
|
3066
|
+
if (!branch.name) {
|
|
3067
|
+
return acc;
|
|
3068
|
+
}
|
|
3069
|
+
acc.push(branch.name);
|
|
3070
|
+
return acc;
|
|
3071
|
+
}, []);
|
|
3072
|
+
} catch (e) {
|
|
3073
|
+
return [];
|
|
3074
|
+
}
|
|
3075
|
+
},
|
|
3076
|
+
async createAdoPullRequest(options) {
|
|
3077
|
+
const { repoUrl, sourceBranchName, targetBranchName, title, body } = options;
|
|
3078
|
+
const { repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
|
|
3079
|
+
const git = await api2.getGitApi();
|
|
3080
|
+
const res = await git.createPullRequest(
|
|
3081
|
+
{
|
|
3082
|
+
sourceRefName: `refs/heads/${sourceBranchName}`,
|
|
3083
|
+
targetRefName: `refs/heads/${targetBranchName}`,
|
|
3084
|
+
title,
|
|
3085
|
+
description: body
|
|
3086
|
+
},
|
|
3087
|
+
repo,
|
|
3088
|
+
projectName
|
|
3089
|
+
);
|
|
3090
|
+
return res.pullRequestId;
|
|
3091
|
+
},
|
|
3092
|
+
async getAdoRepoDefaultBranch({
|
|
3093
|
+
repoUrl
|
|
3094
|
+
}) {
|
|
3095
|
+
const { repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
|
|
3096
|
+
const git = await api2.getGitApi();
|
|
3097
|
+
const getRepositoryRes = await git.getRepository(
|
|
3098
|
+
decodeURI(repo),
|
|
3099
|
+
projectName ? decodeURI(projectName) : void 0
|
|
3100
|
+
);
|
|
3101
|
+
if (!getRepositoryRes?.defaultBranch) {
|
|
3102
|
+
throw new InvalidRepoUrlError("no default branch");
|
|
3103
|
+
}
|
|
3104
|
+
return getRepositoryRes.defaultBranch.replace("refs/heads/", "");
|
|
3105
|
+
},
|
|
3106
|
+
// todo: refactor this function
|
|
3107
|
+
async getAdoReferenceData({
|
|
3108
|
+
ref,
|
|
3109
|
+
repoUrl
|
|
3110
|
+
}) {
|
|
3111
|
+
const { repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
|
|
3112
|
+
if (!projectName) {
|
|
3113
|
+
throw new InvalidUrlPatternError("no project name");
|
|
3114
|
+
}
|
|
3115
|
+
const git = await api2.getGitApi();
|
|
3116
|
+
const results = await Promise.allSettled([
|
|
3117
|
+
(async () => {
|
|
3118
|
+
const res = await git.getBranch(repo, ref, projectName);
|
|
3119
|
+
if (!res.commit || !res.commit.commitId) {
|
|
3120
|
+
throw new InvalidRepoUrlError("no commit on branch");
|
|
3121
|
+
}
|
|
3122
|
+
return {
|
|
3123
|
+
sha: res.commit.commitId,
|
|
3124
|
+
type: "BRANCH" /* BRANCH */,
|
|
3125
|
+
date: res.commit.committer?.date || /* @__PURE__ */ new Date()
|
|
3126
|
+
};
|
|
3127
|
+
})(),
|
|
3128
|
+
(async () => {
|
|
3129
|
+
const res = await git.getCommits(
|
|
3130
|
+
repo,
|
|
3131
|
+
{
|
|
3132
|
+
fromCommitId: ref,
|
|
3133
|
+
toCommitId: ref,
|
|
3134
|
+
$top: 1
|
|
3135
|
+
},
|
|
3136
|
+
projectName
|
|
3137
|
+
);
|
|
3138
|
+
const commit = res[0];
|
|
3139
|
+
if (!commit || !commit.commitId) {
|
|
3140
|
+
throw new Error("no commit");
|
|
3141
|
+
}
|
|
3142
|
+
return {
|
|
3143
|
+
sha: commit.commitId,
|
|
3144
|
+
type: "COMMIT" /* COMMIT */,
|
|
3145
|
+
date: commit.committer?.date || /* @__PURE__ */ new Date()
|
|
3146
|
+
};
|
|
3147
|
+
})(),
|
|
3148
|
+
(async () => {
|
|
3149
|
+
const res = await git.getRefs(repo, projectName, `tags/${ref}`);
|
|
3150
|
+
if (!res[0] || !res[0].objectId) {
|
|
3151
|
+
throw new Error("no tag ref");
|
|
3152
|
+
}
|
|
3153
|
+
let objectId = res[0].objectId;
|
|
3154
|
+
try {
|
|
3155
|
+
const tag = await git.getAnnotatedTag(projectName, repo, objectId);
|
|
3156
|
+
if (tag.taggedObject?.objectId) {
|
|
3157
|
+
objectId = tag.taggedObject.objectId;
|
|
3158
|
+
}
|
|
3159
|
+
} catch (e) {
|
|
3160
|
+
}
|
|
3161
|
+
const commitRes2 = await git.getCommits(
|
|
3162
|
+
repo,
|
|
3163
|
+
{
|
|
3164
|
+
fromCommitId: objectId,
|
|
3165
|
+
toCommitId: objectId,
|
|
3166
|
+
$top: 1
|
|
3167
|
+
},
|
|
3168
|
+
projectName
|
|
3169
|
+
);
|
|
3170
|
+
const commit = commitRes2[0];
|
|
3171
|
+
if (!commit) {
|
|
3172
|
+
throw new Error("no commit");
|
|
3173
|
+
}
|
|
3174
|
+
return {
|
|
3175
|
+
sha: objectId,
|
|
3176
|
+
type: "TAG" /* TAG */,
|
|
3177
|
+
date: commit.committer?.date || /* @__PURE__ */ new Date()
|
|
3178
|
+
};
|
|
3179
|
+
})()
|
|
3180
|
+
]);
|
|
3181
|
+
const [branchRes, commitRes, tagRes] = results;
|
|
3182
|
+
if (tagRes.status === "fulfilled") {
|
|
3183
|
+
return tagRes.value;
|
|
3184
|
+
}
|
|
3185
|
+
if (branchRes.status === "fulfilled") {
|
|
3186
|
+
return branchRes.value;
|
|
3187
|
+
}
|
|
3188
|
+
if (commitRes.status === "fulfilled") {
|
|
3189
|
+
return commitRes.value;
|
|
3190
|
+
}
|
|
3191
|
+
throw new RefNotFoundError(`ref: ${ref} does not exist`);
|
|
3192
|
+
},
|
|
3193
|
+
getAdoBlameRanges() {
|
|
3194
|
+
return [];
|
|
3195
|
+
}
|
|
3045
3196
|
};
|
|
3046
3197
|
}
|
|
3047
|
-
function
|
|
3048
|
-
|
|
3049
|
-
|
|
3198
|
+
async function getAdoRepoList({
|
|
3199
|
+
orgName,
|
|
3200
|
+
tokenOrg,
|
|
3201
|
+
accessToken
|
|
3202
|
+
}) {
|
|
3203
|
+
let orgs = [];
|
|
3204
|
+
const adoTokenInfo = getAdoTokenInfo(accessToken);
|
|
3205
|
+
if (adoTokenInfo.type === "NONE" /* NONE */) {
|
|
3206
|
+
return [];
|
|
3050
3207
|
}
|
|
3051
|
-
if (
|
|
3052
|
-
|
|
3053
|
-
return getBitbucketSdk({
|
|
3054
|
-
authType: "basic",
|
|
3055
|
-
username,
|
|
3056
|
-
password
|
|
3057
|
-
});
|
|
3208
|
+
if (adoTokenInfo.type === "OAUTH" /* OAUTH */) {
|
|
3209
|
+
orgs = await _getOrgsForOauthToken({ oauthToken: accessToken });
|
|
3058
3210
|
}
|
|
3059
|
-
|
|
3211
|
+
if (orgs.length === 0 && !orgName) {
|
|
3212
|
+
throw new Error(`no orgs for ADO`);
|
|
3213
|
+
} else if (orgs.length === 0 && orgName) {
|
|
3214
|
+
orgs = [orgName];
|
|
3215
|
+
}
|
|
3216
|
+
const repos = (await Promise.allSettled(
|
|
3217
|
+
orgs.map(async (org) => {
|
|
3218
|
+
const orgApi = await getAdoApiClient({
|
|
3219
|
+
...await getAdoClientParams({
|
|
3220
|
+
accessToken,
|
|
3221
|
+
tokenOrg: tokenOrg || org,
|
|
3222
|
+
url: void 0
|
|
3223
|
+
}),
|
|
3224
|
+
orgName: org
|
|
3225
|
+
});
|
|
3226
|
+
const gitOrg = await orgApi.getGitApi();
|
|
3227
|
+
const orgRepos = await gitOrg.getRepositories();
|
|
3228
|
+
const repoInfoList = (await Promise.allSettled(
|
|
3229
|
+
orgRepos.map(async (repo) => {
|
|
3230
|
+
if (!repo.name || !repo.remoteUrl || !repo.defaultBranch) {
|
|
3231
|
+
throw new InvalidRepoUrlError("bad repo");
|
|
3232
|
+
}
|
|
3233
|
+
const branch = await gitOrg.getBranch(
|
|
3234
|
+
repo.name,
|
|
3235
|
+
repo.defaultBranch.replace(/^refs\/heads\//, ""),
|
|
3236
|
+
repo.project?.name
|
|
3237
|
+
);
|
|
3238
|
+
return {
|
|
3239
|
+
repoName: repo.name,
|
|
3240
|
+
repoUrl: repo.remoteUrl.replace(
|
|
3241
|
+
/^[hH][tT][tT][pP][sS]:\/\/[^/]+@/,
|
|
3242
|
+
"https://"
|
|
3243
|
+
),
|
|
3244
|
+
repoOwner: org,
|
|
3245
|
+
repoIsPublic: repo.project?.visibility === 2 /* Public */,
|
|
3246
|
+
repoLanguages: [],
|
|
3247
|
+
repoUpdatedAt: branch.commit?.committer?.date?.toDateString() || repo.project?.lastUpdateTime?.toDateString() || (/* @__PURE__ */ new Date()).toDateString()
|
|
3248
|
+
};
|
|
3249
|
+
})
|
|
3250
|
+
)).reduce((acc, res) => {
|
|
3251
|
+
if (res.status === "fulfilled") {
|
|
3252
|
+
acc.push(res.value);
|
|
3253
|
+
}
|
|
3254
|
+
return acc;
|
|
3255
|
+
}, []);
|
|
3256
|
+
return repoInfoList;
|
|
3257
|
+
})
|
|
3258
|
+
)).reduce((acc, res) => {
|
|
3259
|
+
if (res.status === "fulfilled") {
|
|
3260
|
+
return acc.concat(res.value);
|
|
3261
|
+
}
|
|
3262
|
+
return acc;
|
|
3263
|
+
}, []);
|
|
3264
|
+
return repos;
|
|
3060
3265
|
}
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3266
|
+
|
|
3267
|
+
// src/features/analysis/scm/constants.ts
|
|
3268
|
+
var MOBB_ICON_IMG = "https://app.mobb.ai/gh-action/Logo_Rounded_Icon.svg";
|
|
3269
|
+
|
|
3270
|
+
// src/constants.ts
|
|
3271
|
+
var debug = Debug("mobbdev:constants");
|
|
3272
|
+
var __dirname = path2.dirname(fileURLToPath(import.meta.url));
|
|
3273
|
+
dotenv.config({ path: path2.join(__dirname, "../.env") });
|
|
3274
|
+
var scmFriendlyText = {
|
|
3275
|
+
["Ado" /* Ado */]: "Azure DevOps",
|
|
3276
|
+
["Bitbucket" /* Bitbucket */]: "Bitbucket",
|
|
3277
|
+
["GitHub" /* GitHub */]: "GitGub",
|
|
3278
|
+
["GitLab" /* GitLab */]: "GitLab"
|
|
3279
|
+
};
|
|
3280
|
+
var SCANNERS = {
|
|
3281
|
+
Checkmarx: "checkmarx",
|
|
3282
|
+
Codeql: "codeql",
|
|
3283
|
+
Fortify: "fortify",
|
|
3284
|
+
Snyk: "snyk",
|
|
3285
|
+
Sonarqube: "sonarqube"
|
|
3286
|
+
};
|
|
3287
|
+
var SupportedScannersZ = z10.enum([SCANNERS.Checkmarx, SCANNERS.Snyk]);
|
|
3288
|
+
var envVariablesSchema = z10.object({
|
|
3289
|
+
WEB_APP_URL: z10.string(),
|
|
3290
|
+
API_URL: z10.string(),
|
|
3291
|
+
HASURA_ACCESS_KEY: z10.string(),
|
|
3292
|
+
LOCAL_GRAPHQL_ENDPOINT: z10.string()
|
|
3293
|
+
}).required();
|
|
3294
|
+
var envVariables = envVariablesSchema.parse(process.env);
|
|
3295
|
+
debug("config %o", envVariables);
|
|
3296
|
+
var mobbAscii = `
|
|
3297
|
+
..
|
|
3298
|
+
..........
|
|
3299
|
+
.................
|
|
3300
|
+
...........................
|
|
3301
|
+
..............................
|
|
3302
|
+
................................
|
|
3303
|
+
..................................
|
|
3304
|
+
....................................
|
|
3305
|
+
.....................................
|
|
3306
|
+
.............................................
|
|
3307
|
+
.................................................
|
|
3308
|
+
............................... .................
|
|
3309
|
+
.................................. ............
|
|
3310
|
+
.................. ............. ..........
|
|
3311
|
+
......... ........ ......... ......
|
|
3312
|
+
............... ....
|
|
3313
|
+
.... ..
|
|
3314
|
+
|
|
3315
|
+
. ...
|
|
3316
|
+
..............
|
|
3317
|
+
......................
|
|
3318
|
+
...........................
|
|
3319
|
+
................................
|
|
3320
|
+
......................................
|
|
3321
|
+
...............................
|
|
3322
|
+
.................
|
|
3323
|
+
`;
|
|
3324
|
+
var PROJECT_DEFAULT_NAME = "My first project";
|
|
3325
|
+
var WEB_APP_URL = envVariables.WEB_APP_URL;
|
|
3326
|
+
var API_URL = envVariables.API_URL;
|
|
3327
|
+
var HASURA_ACCESS_KEY = envVariables.HASURA_ACCESS_KEY;
|
|
3328
|
+
var LOCAL_GRAPHQL_ENDPOINT = envVariables.LOCAL_GRAPHQL_ENDPOINT;
|
|
3329
|
+
var errorMessages = {
|
|
3330
|
+
missingCxProjectName: `project name ${chalk.bold(
|
|
3331
|
+
"(--cx-project-name)"
|
|
3332
|
+
)} is needed if you're using checkmarx`,
|
|
3333
|
+
missingUrl: `url ${chalk.bold(
|
|
3334
|
+
"(--url)"
|
|
3335
|
+
)} is needed if you're adding an SCM token`,
|
|
3336
|
+
invalidScmType: `SCM type ${chalk.bold(
|
|
3337
|
+
"(--scm-type)"
|
|
3338
|
+
)} is invalid, please use one of: ${Object.values(ScmType).join(", ")}`,
|
|
3339
|
+
missingToken: `SCM token ${chalk.bold(
|
|
3340
|
+
"(--token)"
|
|
3341
|
+
)} is needed if you're adding an SCM token`
|
|
3342
|
+
};
|
|
3343
|
+
var progressMassages = {
|
|
3344
|
+
processingVulnerabilityReportSuccess: "\u2699\uFE0F Vulnerability report proccessed successfully",
|
|
3345
|
+
processingVulnerabilityReport: "\u2699\uFE0F Proccessing vulnerability report",
|
|
3346
|
+
processingVulnerabilityReportFailed: "\u2699\uFE0F Error Proccessing vulnerability report"
|
|
3347
|
+
};
|
|
3348
|
+
var VUL_REPORT_DIGEST_TIMEOUT_MS = 1e3 * 60 * 20;
|
|
3349
|
+
|
|
3350
|
+
// src/features/analysis/index.ts
|
|
3351
|
+
import crypto from "node:crypto";
|
|
3352
|
+
import fs3 from "node:fs";
|
|
3353
|
+
import os from "node:os";
|
|
3354
|
+
import path6 from "node:path";
|
|
3355
|
+
import { pipeline } from "node:stream/promises";
|
|
3356
|
+
|
|
3357
|
+
// src/generates/client_generates.ts
|
|
3358
|
+
var MeDocument = `
|
|
3359
|
+
query Me {
|
|
3360
|
+
me {
|
|
3361
|
+
id
|
|
3362
|
+
email
|
|
3363
|
+
scmConfigs {
|
|
3364
|
+
id
|
|
3365
|
+
orgId
|
|
3366
|
+
refreshToken
|
|
3367
|
+
scmType
|
|
3368
|
+
scmUrl
|
|
3369
|
+
scmUsername
|
|
3370
|
+
token
|
|
3371
|
+
tokenLastUpdate
|
|
3372
|
+
userId
|
|
3373
|
+
scmOrg
|
|
3374
|
+
isTokenAvailable
|
|
3375
|
+
}
|
|
3067
3376
|
}
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3377
|
+
}
|
|
3378
|
+
`;
|
|
3379
|
+
var GetOrgAndProjectIdDocument = `
|
|
3380
|
+
query getOrgAndProjectId($filters: organization_to_organization_role_bool_exp, $limit: Int) {
|
|
3381
|
+
organization_to_organization_role(
|
|
3382
|
+
where: $filters
|
|
3383
|
+
order_by: {organization: {createdOn: desc}}
|
|
3384
|
+
limit: $limit
|
|
3385
|
+
) {
|
|
3386
|
+
organization {
|
|
3387
|
+
id
|
|
3388
|
+
projects(order_by: {updatedAt: desc}) {
|
|
3389
|
+
id
|
|
3390
|
+
name
|
|
3078
3391
|
}
|
|
3079
|
-
case "public":
|
|
3080
|
-
return { authType };
|
|
3081
3392
|
}
|
|
3082
3393
|
}
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
return String(z7.number().parse(pullRequestRes.id));
|
|
3090
|
-
}
|
|
3091
|
-
async validateParams() {
|
|
3092
|
-
return validateBitbucketParams({
|
|
3093
|
-
bitbucketClient: this.bitbucketSdk,
|
|
3094
|
-
url: this.url
|
|
3095
|
-
});
|
|
3394
|
+
}
|
|
3395
|
+
`;
|
|
3396
|
+
var GetEncryptedApiTokenDocument = `
|
|
3397
|
+
query GetEncryptedApiToken($loginId: uuid!) {
|
|
3398
|
+
cli_login_by_pk(id: $loginId) {
|
|
3399
|
+
encryptedApiToken
|
|
3096
3400
|
}
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3401
|
+
}
|
|
3402
|
+
`;
|
|
3403
|
+
var FixReportStateDocument = `
|
|
3404
|
+
query FixReportState($id: uuid!) {
|
|
3405
|
+
fixReport_by_pk(id: $id) {
|
|
3406
|
+
state
|
|
3102
3407
|
}
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3408
|
+
}
|
|
3409
|
+
`;
|
|
3410
|
+
var GetVulnerabilityReportPathsDocument = `
|
|
3411
|
+
query GetVulnerabilityReportPaths($vulnerabilityReportId: uuid!) {
|
|
3412
|
+
vulnerability_report_path(
|
|
3413
|
+
where: {vulnerabilityReportId: {_eq: $vulnerabilityReportId}}
|
|
3414
|
+
) {
|
|
3415
|
+
path
|
|
3108
3416
|
}
|
|
3109
|
-
|
|
3110
|
-
|
|
3417
|
+
}
|
|
3418
|
+
`;
|
|
3419
|
+
var GetAnalysisDocument = `
|
|
3420
|
+
subscription getAnalysis($analysisId: uuid!) {
|
|
3421
|
+
analysis: fixReport_by_pk(id: $analysisId) {
|
|
3422
|
+
id
|
|
3423
|
+
state
|
|
3111
3424
|
}
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3425
|
+
}
|
|
3426
|
+
`;
|
|
3427
|
+
var GetAnalsyisDocument = `
|
|
3428
|
+
query getAnalsyis($analysisId: uuid!) {
|
|
3429
|
+
analysis: fixReport_by_pk(id: $analysisId) {
|
|
3430
|
+
id
|
|
3431
|
+
state
|
|
3432
|
+
repo {
|
|
3433
|
+
commitSha
|
|
3434
|
+
pullRequest
|
|
3435
|
+
}
|
|
3436
|
+
vulnerabilityReportId
|
|
3437
|
+
vulnerabilityReport {
|
|
3438
|
+
projectId
|
|
3439
|
+
project {
|
|
3440
|
+
organizationId
|
|
3441
|
+
}
|
|
3442
|
+
file {
|
|
3443
|
+
signedFile {
|
|
3444
|
+
url
|
|
3445
|
+
}
|
|
3127
3446
|
}
|
|
3128
3447
|
}
|
|
3129
3448
|
}
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3449
|
+
}
|
|
3450
|
+
`;
|
|
3451
|
+
var GetFixesDocument = `
|
|
3452
|
+
query getFixes($filters: fix_bool_exp!) {
|
|
3453
|
+
fixes: fix(where: $filters) {
|
|
3454
|
+
issueType
|
|
3455
|
+
id
|
|
3456
|
+
patchAndQuestions {
|
|
3457
|
+
__typename
|
|
3458
|
+
... on FixData {
|
|
3459
|
+
patch
|
|
3460
|
+
}
|
|
3139
3461
|
}
|
|
3140
|
-
return user.username;
|
|
3141
3462
|
}
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3463
|
+
}
|
|
3464
|
+
`;
|
|
3465
|
+
var GetVulByNodesMetadataDocument = `
|
|
3466
|
+
query getVulByNodesMetadata($filters: [vulnerability_report_issue_code_node_bool_exp!], $vulnerabilityReportId: uuid!) {
|
|
3467
|
+
vulnerabilityReportIssueCodeNodes: vulnerability_report_issue_code_node(
|
|
3468
|
+
order_by: {index: desc}
|
|
3469
|
+
where: {_or: $filters, vulnerabilityReportIssue: {fixId: {_is_null: false}, vulnerabilityReportId: {_eq: $vulnerabilityReportId}}}
|
|
3470
|
+
) {
|
|
3471
|
+
vulnerabilityReportIssueId
|
|
3472
|
+
path
|
|
3473
|
+
startLine
|
|
3474
|
+
vulnerabilityReportIssue {
|
|
3475
|
+
issueType
|
|
3476
|
+
fixId
|
|
3152
3477
|
}
|
|
3153
3478
|
}
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
this._validateAccessToken();
|
|
3160
|
-
const res = await this.bitbucketSdk.getUser();
|
|
3161
|
-
return z7.string().parse(res.username);
|
|
3162
|
-
}
|
|
3163
|
-
async getSubmitRequestStatus(_scmSubmitRequestId) {
|
|
3164
|
-
this._validateAccessTokenAndUrl();
|
|
3165
|
-
const pullRequestRes = await this.bitbucketSdk.getPullRequest({
|
|
3166
|
-
prNumber: Number(_scmSubmitRequestId),
|
|
3167
|
-
url: this.url
|
|
3168
|
-
});
|
|
3169
|
-
switch (pullRequestRes.state) {
|
|
3170
|
-
case "OPEN":
|
|
3171
|
-
return "open";
|
|
3172
|
-
case "MERGED":
|
|
3173
|
-
return "merged";
|
|
3174
|
-
case "DECLINED":
|
|
3175
|
-
return "closed";
|
|
3176
|
-
default:
|
|
3177
|
-
throw new Error(`unknown state ${pullRequestRes.state} `);
|
|
3479
|
+
fixablePrVuls: vulnerability_report_issue_aggregate(
|
|
3480
|
+
where: {fixId: {_is_null: false}, vulnerabilityReportId: {_eq: $vulnerabilityReportId}, codeNodes: {_or: $filters}}
|
|
3481
|
+
) {
|
|
3482
|
+
aggregate {
|
|
3483
|
+
count
|
|
3178
3484
|
}
|
|
3179
3485
|
}
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
}
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
this._validateUrl();
|
|
3194
|
-
const { repoSlug, workspace } = parseBitbucketOrganizationAndRepo(this.url);
|
|
3195
|
-
return Promise.resolve(
|
|
3196
|
-
`https://bitbucket.org/${workspace}/${repoSlug}/pull-requests/${prNumber}`
|
|
3197
|
-
);
|
|
3198
|
-
}
|
|
3199
|
-
async refreshToken(params) {
|
|
3200
|
-
const getBitbucketTokenResponse = await getBitbucketToken({
|
|
3201
|
-
authType: "refresh_token",
|
|
3202
|
-
...params
|
|
3203
|
-
});
|
|
3204
|
-
return {
|
|
3205
|
-
accessToken: getBitbucketTokenResponse.access_token,
|
|
3206
|
-
refreshToken: getBitbucketTokenResponse.refresh_token
|
|
3207
|
-
};
|
|
3486
|
+
nonFixablePrVuls: vulnerability_report_issue_aggregate(
|
|
3487
|
+
where: {fixId: {_is_null: true}, vulnerabilityReportId: {_eq: $vulnerabilityReportId}, codeNodes: {_or: $filters}}
|
|
3488
|
+
) {
|
|
3489
|
+
aggregate {
|
|
3490
|
+
count
|
|
3491
|
+
}
|
|
3492
|
+
}
|
|
3493
|
+
totalScanVulnerabilities: vulnerability_report_issue_aggregate(
|
|
3494
|
+
where: {vulnerabilityReportId: {_eq: $vulnerabilityReportId}}
|
|
3495
|
+
) {
|
|
3496
|
+
aggregate {
|
|
3497
|
+
count
|
|
3498
|
+
}
|
|
3208
3499
|
}
|
|
3209
|
-
};
|
|
3210
|
-
|
|
3211
|
-
// src/features/analysis/scm/ado/validation.ts
|
|
3212
|
-
import { z as z8 } from "zod";
|
|
3213
|
-
var ValidPullRequestStatusZ = z8.union([
|
|
3214
|
-
z8.literal(1 /* Active */),
|
|
3215
|
-
z8.literal(2 /* Abandoned */),
|
|
3216
|
-
z8.literal(3 /* Completed */)
|
|
3217
|
-
]);
|
|
3218
|
-
var AdoAuthResultZ = z8.object({
|
|
3219
|
-
access_token: z8.string().min(1),
|
|
3220
|
-
token_type: z8.string().min(1),
|
|
3221
|
-
refresh_token: z8.string().min(1)
|
|
3222
|
-
});
|
|
3223
|
-
var profileZ = z8.object({
|
|
3224
|
-
displayName: z8.string(),
|
|
3225
|
-
publicAlias: z8.string().min(1),
|
|
3226
|
-
emailAddress: z8.string(),
|
|
3227
|
-
coreRevision: z8.number(),
|
|
3228
|
-
timeStamp: z8.string(),
|
|
3229
|
-
id: z8.string(),
|
|
3230
|
-
revision: z8.number()
|
|
3231
|
-
});
|
|
3232
|
-
var accountsZ = z8.object({
|
|
3233
|
-
count: z8.number(),
|
|
3234
|
-
value: z8.array(
|
|
3235
|
-
z8.object({
|
|
3236
|
-
accountId: z8.string(),
|
|
3237
|
-
accountUri: z8.string(),
|
|
3238
|
-
accountName: z8.string()
|
|
3239
|
-
})
|
|
3240
|
-
)
|
|
3241
|
-
});
|
|
3242
|
-
|
|
3243
|
-
// src/features/analysis/scm/ado/utils.ts
|
|
3244
|
-
function _getPublicAdoClient({
|
|
3245
|
-
orgName,
|
|
3246
|
-
origin: origin2
|
|
3247
|
-
}) {
|
|
3248
|
-
const orgUrl = `${origin2}/${orgName}`;
|
|
3249
|
-
const authHandler = api.getPersonalAccessTokenHandler("");
|
|
3250
|
-
authHandler.canHandleAuthentication = () => false;
|
|
3251
|
-
authHandler.prepareRequest = (_options) => {
|
|
3252
|
-
return;
|
|
3253
|
-
};
|
|
3254
|
-
const connection = new api.WebApi(orgUrl, authHandler);
|
|
3255
|
-
return connection;
|
|
3256
|
-
}
|
|
3257
|
-
function removeTrailingSlash2(str) {
|
|
3258
|
-
return str.trim().replace(/\/+$/, "");
|
|
3259
3500
|
}
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3501
|
+
`;
|
|
3502
|
+
var UpdateScmTokenDocument = `
|
|
3503
|
+
mutation updateScmToken($scmType: String!, $url: String!, $token: String!, $org: String, $refreshToken: String) {
|
|
3504
|
+
updateScmToken(
|
|
3505
|
+
scmType: $scmType
|
|
3506
|
+
url: $url
|
|
3507
|
+
token: $token
|
|
3508
|
+
org: $org
|
|
3509
|
+
refreshToken: $refreshToken
|
|
3510
|
+
) {
|
|
3511
|
+
__typename
|
|
3512
|
+
... on ScmAccessTokenUpdateSuccess {
|
|
3513
|
+
token
|
|
3514
|
+
}
|
|
3515
|
+
... on InvalidScmTypeError {
|
|
3516
|
+
status
|
|
3517
|
+
error
|
|
3518
|
+
}
|
|
3519
|
+
... on BadScmCredentials {
|
|
3520
|
+
status
|
|
3521
|
+
error
|
|
3522
|
+
}
|
|
3266
3523
|
}
|
|
3267
|
-
const {
|
|
3268
|
-
organization,
|
|
3269
|
-
repoName,
|
|
3270
|
-
projectName,
|
|
3271
|
-
projectPath,
|
|
3272
|
-
pathElements,
|
|
3273
|
-
hostname,
|
|
3274
|
-
protocol
|
|
3275
|
-
} = parsingResult;
|
|
3276
|
-
return {
|
|
3277
|
-
owner: decodeURI(organization),
|
|
3278
|
-
repo: decodeURI(repoName),
|
|
3279
|
-
projectName: projectName ? decodeURI(projectName) : void 0,
|
|
3280
|
-
projectPath,
|
|
3281
|
-
pathElements,
|
|
3282
|
-
origin: `${protocol}//${hostname}`
|
|
3283
|
-
};
|
|
3284
3524
|
}
|
|
3285
|
-
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
|
|
3525
|
+
`;
|
|
3526
|
+
var UploadS3BucketInfoDocument = `
|
|
3527
|
+
mutation uploadS3BucketInfo($fileName: String!) {
|
|
3528
|
+
uploadS3BucketInfo(fileName: $fileName) {
|
|
3529
|
+
status
|
|
3530
|
+
error
|
|
3531
|
+
reportUploadInfo: uploadInfo {
|
|
3532
|
+
url
|
|
3533
|
+
fixReportId
|
|
3534
|
+
uploadFieldsJSON
|
|
3535
|
+
uploadKey
|
|
3536
|
+
}
|
|
3537
|
+
repoUploadInfo {
|
|
3538
|
+
url
|
|
3539
|
+
fixReportId
|
|
3540
|
+
uploadFieldsJSON
|
|
3541
|
+
uploadKey
|
|
3542
|
+
}
|
|
3296
3543
|
}
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3544
|
+
}
|
|
3545
|
+
`;
|
|
3546
|
+
var DigestVulnerabilityReportDocument = `
|
|
3547
|
+
mutation DigestVulnerabilityReport($vulnerabilityReportFileName: String!, $fixReportId: String!, $projectId: String!, $scanSource: String!) {
|
|
3548
|
+
digestVulnerabilityReport(
|
|
3549
|
+
fixReportId: $fixReportId
|
|
3550
|
+
vulnerabilityReportFileName: $vulnerabilityReportFileName
|
|
3551
|
+
projectId: $projectId
|
|
3552
|
+
scanSource: $scanSource
|
|
3553
|
+
) {
|
|
3554
|
+
__typename
|
|
3555
|
+
... on VulnerabilityReport {
|
|
3556
|
+
vulnerabilityReportId
|
|
3557
|
+
fixReportId
|
|
3558
|
+
}
|
|
3559
|
+
... on RabbitSendError {
|
|
3560
|
+
status
|
|
3561
|
+
error
|
|
3562
|
+
}
|
|
3563
|
+
... on ReportValidationError {
|
|
3564
|
+
status
|
|
3565
|
+
error
|
|
3566
|
+
}
|
|
3567
|
+
... on ReferenceNotFoundError {
|
|
3568
|
+
status
|
|
3569
|
+
error
|
|
3306
3570
|
}
|
|
3307
|
-
throw new InvalidRepoUrlError("ADO URL is null");
|
|
3308
3571
|
}
|
|
3309
|
-
return {
|
|
3310
|
-
org: tokenOrg,
|
|
3311
|
-
origin: DEFUALT_ADO_ORIGIN
|
|
3312
|
-
};
|
|
3313
3572
|
}
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3573
|
+
`;
|
|
3574
|
+
var SubmitVulnerabilityReportDocument = `
|
|
3575
|
+
mutation SubmitVulnerabilityReport($fixReportId: String!, $repoUrl: String!, $reference: String!, $projectId: String!, $scanSource: String!, $sha: String, $experimentalEnabled: Boolean, $vulnerabilityReportFileName: String, $pullRequest: Int) {
|
|
3576
|
+
submitVulnerabilityReport(
|
|
3577
|
+
fixReportId: $fixReportId
|
|
3578
|
+
repoUrl: $repoUrl
|
|
3579
|
+
reference: $reference
|
|
3580
|
+
sha: $sha
|
|
3581
|
+
experimentalEnabled: $experimentalEnabled
|
|
3582
|
+
pullRequest: $pullRequest
|
|
3583
|
+
projectId: $projectId
|
|
3584
|
+
vulnerabilityReportFileName: $vulnerabilityReportFileName
|
|
3585
|
+
scanSource: $scanSource
|
|
3586
|
+
) {
|
|
3587
|
+
__typename
|
|
3588
|
+
... on VulnerabilityReport {
|
|
3589
|
+
vulnerabilityReportId
|
|
3590
|
+
fixReportId
|
|
3591
|
+
}
|
|
3319
3592
|
}
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3593
|
+
}
|
|
3594
|
+
`;
|
|
3595
|
+
var CreateCommunityUserDocument = `
|
|
3596
|
+
mutation CreateCommunityUser {
|
|
3597
|
+
initOrganizationAndProject {
|
|
3598
|
+
__typename
|
|
3599
|
+
... on InitOrganizationAndProjectGoodResponse {
|
|
3600
|
+
projectId
|
|
3601
|
+
userId
|
|
3602
|
+
organizationId
|
|
3603
|
+
}
|
|
3604
|
+
... on UserAlreadyInProjectError {
|
|
3605
|
+
error
|
|
3606
|
+
status
|
|
3326
3607
|
}
|
|
3327
|
-
const connection2 = new api.WebApi(
|
|
3328
|
-
orgUrl,
|
|
3329
|
-
api.getBearerHandler(params.accessToken),
|
|
3330
|
-
{}
|
|
3331
|
-
);
|
|
3332
|
-
return connection2;
|
|
3333
3608
|
}
|
|
3334
|
-
const authHandler = api.getPersonalAccessTokenHandler(params.accessToken);
|
|
3335
|
-
const isBroker = BROKERED_HOSTS.includes(new URL(orgUrl).origin);
|
|
3336
|
-
const connection = new api.WebApi(
|
|
3337
|
-
orgUrl,
|
|
3338
|
-
authHandler,
|
|
3339
|
-
isBroker ? {
|
|
3340
|
-
proxy: {
|
|
3341
|
-
proxyUrl: GIT_PROXY_HOST
|
|
3342
|
-
},
|
|
3343
|
-
ignoreSslError: true
|
|
3344
|
-
} : void 0
|
|
3345
|
-
);
|
|
3346
|
-
return connection;
|
|
3347
3609
|
}
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3610
|
+
`;
|
|
3611
|
+
var CreateCliLoginDocument = `
|
|
3612
|
+
mutation CreateCliLogin($publicKey: String!) {
|
|
3613
|
+
insert_cli_login_one(object: {publicKey: $publicKey}) {
|
|
3614
|
+
id
|
|
3351
3615
|
}
|
|
3352
|
-
|
|
3353
|
-
|
|
3616
|
+
}
|
|
3617
|
+
`;
|
|
3618
|
+
var PerformCliLoginDocument = `
|
|
3619
|
+
mutation performCliLogin($loginId: String!) {
|
|
3620
|
+
performCliLogin(loginId: $loginId) {
|
|
3621
|
+
status
|
|
3354
3622
|
}
|
|
3355
|
-
return { type: "PAT" /* PAT */, accessToken: token };
|
|
3356
3623
|
}
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
tokenOrg,
|
|
3363
|
-
adoTokenInfo
|
|
3364
|
-
});
|
|
3365
|
-
switch (adoTokenInfo.type) {
|
|
3366
|
-
case "NONE" /* NONE */:
|
|
3367
|
-
return {
|
|
3368
|
-
tokenType: "NONE" /* NONE */,
|
|
3369
|
-
origin: origin2,
|
|
3370
|
-
orgName: org.toLowerCase()
|
|
3371
|
-
};
|
|
3372
|
-
case "OAUTH" /* OAUTH */: {
|
|
3373
|
-
return {
|
|
3374
|
-
tokenType: "OAUTH" /* OAUTH */,
|
|
3375
|
-
accessToken: adoTokenInfo.accessToken,
|
|
3376
|
-
origin: origin2,
|
|
3377
|
-
orgName: org.toLowerCase()
|
|
3378
|
-
};
|
|
3379
|
-
}
|
|
3380
|
-
case "PAT" /* PAT */: {
|
|
3381
|
-
return {
|
|
3382
|
-
tokenType: "PAT" /* PAT */,
|
|
3383
|
-
accessToken: adoTokenInfo.accessToken,
|
|
3384
|
-
patTokenOrg: z9.string().parse(tokenOrg).toLowerCase(),
|
|
3385
|
-
origin: origin2,
|
|
3386
|
-
orgName: org.toLowerCase()
|
|
3387
|
-
};
|
|
3388
|
-
}
|
|
3624
|
+
`;
|
|
3625
|
+
var CreateProjectDocument = `
|
|
3626
|
+
mutation CreateProject($organizationId: String!, $projectName: String!) {
|
|
3627
|
+
createProject(organizationId: $organizationId, projectName: $projectName) {
|
|
3628
|
+
projectId
|
|
3389
3629
|
}
|
|
3390
3630
|
}
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
console.log("adoValidateParams error", e);
|
|
3403
|
-
const error = e;
|
|
3404
|
-
const code = error.code || error.status || error.statusCode || error.response?.status || error.response?.statusCode || error.response?.code;
|
|
3405
|
-
const description = error.description || `${e}`;
|
|
3406
|
-
if (code === 401 || code === 403 || description.includes("401") || description.includes("403")) {
|
|
3407
|
-
throw new InvalidAccessTokenError(`invalid ADO access token`);
|
|
3631
|
+
`;
|
|
3632
|
+
var ValidateRepoUrlDocument = `
|
|
3633
|
+
query validateRepoUrl($repoUrl: String!) {
|
|
3634
|
+
validateRepoUrl(repoUrl: $repoUrl) {
|
|
3635
|
+
__typename
|
|
3636
|
+
... on RepoValidationSuccess {
|
|
3637
|
+
status
|
|
3638
|
+
defaultBranch
|
|
3639
|
+
defaultBranchLastModified
|
|
3640
|
+
defaultBranchSha
|
|
3641
|
+
scmType
|
|
3408
3642
|
}
|
|
3409
|
-
|
|
3410
|
-
|
|
3643
|
+
... on RepoUnreachableError {
|
|
3644
|
+
status
|
|
3645
|
+
error
|
|
3646
|
+
scmType
|
|
3647
|
+
}
|
|
3648
|
+
... on BadScmCredentials {
|
|
3649
|
+
status
|
|
3650
|
+
error
|
|
3651
|
+
scmType
|
|
3411
3652
|
}
|
|
3412
|
-
throw e;
|
|
3413
3653
|
}
|
|
3414
3654
|
}
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
{
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
}
|
|
3655
|
+
`;
|
|
3656
|
+
var GitReferenceDocument = `
|
|
3657
|
+
query gitReference($repoUrl: String!, $reference: String!) {
|
|
3658
|
+
gitReference(repoUrl: $repoUrl, reference: $reference) {
|
|
3659
|
+
__typename
|
|
3660
|
+
... on GitReferenceData {
|
|
3661
|
+
status
|
|
3662
|
+
sha
|
|
3663
|
+
date
|
|
3425
3664
|
}
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
|
|
3429
|
-
const accountsRes = await fetch(
|
|
3430
|
-
`https://app.vssps.visualstudio.com/_apis/accounts?memberId=${profile.publicAlias}&api-version=6.0`,
|
|
3431
|
-
{
|
|
3432
|
-
method: "GET",
|
|
3433
|
-
headers: {
|
|
3434
|
-
Authorization: `Bearer ${oauthToken}`
|
|
3435
|
-
}
|
|
3665
|
+
... on ReferenceNotFoundError {
|
|
3666
|
+
status
|
|
3667
|
+
error
|
|
3436
3668
|
}
|
|
3437
|
-
|
|
3438
|
-
const accountsJson = await accountsRes.json();
|
|
3439
|
-
const accounts = accountsZ.parse(accountsJson);
|
|
3440
|
-
const orgs = accounts.value.map((account) => account.accountName).filter((value, index, array) => array.indexOf(value) === index);
|
|
3441
|
-
return orgs;
|
|
3669
|
+
}
|
|
3442
3670
|
}
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
|
|
3446
|
-
const api2 = await getAdoApiClient(params);
|
|
3671
|
+
`;
|
|
3672
|
+
var defaultWrapper = (action, _operationName, _operationType, _variables) => action();
|
|
3673
|
+
function getSdk(client, withWrapper = defaultWrapper) {
|
|
3447
3674
|
return {
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
const { repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
|
|
3451
|
-
const git = await api2.getGitApi();
|
|
3452
|
-
const branches = await git.getBranches(repo, projectName);
|
|
3453
|
-
if (!branches || branches.length === 0) {
|
|
3454
|
-
throw new InvalidRepoUrlError("no branches");
|
|
3455
|
-
}
|
|
3456
|
-
return true;
|
|
3457
|
-
} catch (e) {
|
|
3458
|
-
return false;
|
|
3459
|
-
}
|
|
3675
|
+
Me(variables, requestHeaders) {
|
|
3676
|
+
return withWrapper((wrappedRequestHeaders) => client.request(MeDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "Me", "query", variables);
|
|
3460
3677
|
},
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
prNumber
|
|
3464
|
-
}) {
|
|
3465
|
-
const { repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
|
|
3466
|
-
const git = await api2.getGitApi();
|
|
3467
|
-
const res = await git.getPullRequest(repo, prNumber, projectName);
|
|
3468
|
-
const parsedPullRequestStatus = ValidPullRequestStatusZ.safeParse(
|
|
3469
|
-
res.status
|
|
3470
|
-
);
|
|
3471
|
-
if (!parsedPullRequestStatus.success) {
|
|
3472
|
-
throw new Error("bad pr status for ADO");
|
|
3473
|
-
}
|
|
3474
|
-
return parsedPullRequestStatus.data;
|
|
3678
|
+
getOrgAndProjectId(variables, requestHeaders) {
|
|
3679
|
+
return withWrapper((wrappedRequestHeaders) => client.request(GetOrgAndProjectIdDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "getOrgAndProjectId", "query", variables);
|
|
3475
3680
|
},
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
branch
|
|
3479
|
-
}) {
|
|
3480
|
-
const { repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
|
|
3481
|
-
const git = await api2.getGitApi();
|
|
3482
|
-
try {
|
|
3483
|
-
const branchStatus = await git.getBranch(repo, branch, projectName);
|
|
3484
|
-
if (!branchStatus || !branchStatus.commit) {
|
|
3485
|
-
throw new InvalidRepoUrlError("no branch status");
|
|
3486
|
-
}
|
|
3487
|
-
return branchStatus.name === branch;
|
|
3488
|
-
} catch (e) {
|
|
3489
|
-
return false;
|
|
3490
|
-
}
|
|
3681
|
+
GetEncryptedApiToken(variables, requestHeaders) {
|
|
3682
|
+
return withWrapper((wrappedRequestHeaders) => client.request(GetEncryptedApiTokenDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "GetEncryptedApiToken", "query", variables);
|
|
3491
3683
|
},
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
const git = await api2.getGitApi();
|
|
3495
|
-
const getRepositoryRes = await git.getRepository(
|
|
3496
|
-
decodeURI(repo),
|
|
3497
|
-
projectName ? decodeURI(projectName) : void 0
|
|
3498
|
-
);
|
|
3499
|
-
return `${getRepositoryRes.webUrl}/pullrequest/${prNumber}`;
|
|
3684
|
+
FixReportState(variables, requestHeaders) {
|
|
3685
|
+
return withWrapper((wrappedRequestHeaders) => client.request(FixReportStateDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "FixReportState", "query", variables);
|
|
3500
3686
|
},
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
branch
|
|
3504
|
-
}) {
|
|
3505
|
-
const { owner, repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
|
|
3506
|
-
const url = new URL(repoUrl);
|
|
3507
|
-
const origin2 = url.origin.toLowerCase().endsWith(".visualstudio.com") ? DEFUALT_ADO_ORIGIN : url.origin.toLowerCase();
|
|
3508
|
-
return `${origin2}/${owner}/${projectName}/_apis/git/repositories/${repo}/items/items?path=/&versionDescriptor[versionOptions]=0&versionDescriptor[versionType]=commit&versionDescriptor[version]=${branch}&resolveLfs=true&$format=zip&api-version=5.0&download=true`;
|
|
3687
|
+
GetVulnerabilityReportPaths(variables, requestHeaders) {
|
|
3688
|
+
return withWrapper((wrappedRequestHeaders) => client.request(GetVulnerabilityReportPathsDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "GetVulnerabilityReportPaths", "query", variables);
|
|
3509
3689
|
},
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
const git = await api2.getGitApi();
|
|
3513
|
-
try {
|
|
3514
|
-
const res = await git.getBranches(repo, projectName);
|
|
3515
|
-
res.sort((a, b) => {
|
|
3516
|
-
if (!a.commit?.committer?.date || !b.commit?.committer?.date) {
|
|
3517
|
-
return 0;
|
|
3518
|
-
}
|
|
3519
|
-
return b.commit?.committer?.date.getTime() - a.commit?.committer?.date.getTime();
|
|
3520
|
-
});
|
|
3521
|
-
return res.reduce((acc, branch) => {
|
|
3522
|
-
if (!branch.name) {
|
|
3523
|
-
return acc;
|
|
3524
|
-
}
|
|
3525
|
-
acc.push(branch.name);
|
|
3526
|
-
return acc;
|
|
3527
|
-
}, []);
|
|
3528
|
-
} catch (e) {
|
|
3529
|
-
return [];
|
|
3530
|
-
}
|
|
3690
|
+
getAnalysis(variables, requestHeaders) {
|
|
3691
|
+
return withWrapper((wrappedRequestHeaders) => client.request(GetAnalysisDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "getAnalysis", "subscription", variables);
|
|
3531
3692
|
},
|
|
3532
|
-
|
|
3533
|
-
|
|
3534
|
-
const { repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
|
|
3535
|
-
const git = await api2.getGitApi();
|
|
3536
|
-
const res = await git.createPullRequest(
|
|
3537
|
-
{
|
|
3538
|
-
sourceRefName: `refs/heads/${sourceBranchName}`,
|
|
3539
|
-
targetRefName: `refs/heads/${targetBranchName}`,
|
|
3540
|
-
title,
|
|
3541
|
-
description: body
|
|
3542
|
-
},
|
|
3543
|
-
repo,
|
|
3544
|
-
projectName
|
|
3545
|
-
);
|
|
3546
|
-
return res.pullRequestId;
|
|
3693
|
+
getAnalsyis(variables, requestHeaders) {
|
|
3694
|
+
return withWrapper((wrappedRequestHeaders) => client.request(GetAnalsyisDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "getAnalsyis", "query", variables);
|
|
3547
3695
|
},
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
}) {
|
|
3551
|
-
const { repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
|
|
3552
|
-
const git = await api2.getGitApi();
|
|
3553
|
-
const getRepositoryRes = await git.getRepository(
|
|
3554
|
-
decodeURI(repo),
|
|
3555
|
-
projectName ? decodeURI(projectName) : void 0
|
|
3556
|
-
);
|
|
3557
|
-
if (!getRepositoryRes?.defaultBranch) {
|
|
3558
|
-
throw new InvalidRepoUrlError("no default branch");
|
|
3559
|
-
}
|
|
3560
|
-
return getRepositoryRes.defaultBranch.replace("refs/heads/", "");
|
|
3696
|
+
getFixes(variables, requestHeaders) {
|
|
3697
|
+
return withWrapper((wrappedRequestHeaders) => client.request(GetFixesDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "getFixes", "query", variables);
|
|
3561
3698
|
},
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
const { repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
|
|
3568
|
-
if (!projectName) {
|
|
3569
|
-
throw new InvalidUrlPatternError("no project name");
|
|
3570
|
-
}
|
|
3571
|
-
const git = await api2.getGitApi();
|
|
3572
|
-
const results = await Promise.allSettled([
|
|
3573
|
-
(async () => {
|
|
3574
|
-
const res = await git.getBranch(repo, ref, projectName);
|
|
3575
|
-
if (!res.commit || !res.commit.commitId) {
|
|
3576
|
-
throw new InvalidRepoUrlError("no commit on branch");
|
|
3577
|
-
}
|
|
3578
|
-
return {
|
|
3579
|
-
sha: res.commit.commitId,
|
|
3580
|
-
type: "BRANCH" /* BRANCH */,
|
|
3581
|
-
date: res.commit.committer?.date || /* @__PURE__ */ new Date()
|
|
3582
|
-
};
|
|
3583
|
-
})(),
|
|
3584
|
-
(async () => {
|
|
3585
|
-
const res = await git.getCommits(
|
|
3586
|
-
repo,
|
|
3587
|
-
{
|
|
3588
|
-
fromCommitId: ref,
|
|
3589
|
-
toCommitId: ref,
|
|
3590
|
-
$top: 1
|
|
3591
|
-
},
|
|
3592
|
-
projectName
|
|
3593
|
-
);
|
|
3594
|
-
const commit = res[0];
|
|
3595
|
-
if (!commit || !commit.commitId) {
|
|
3596
|
-
throw new Error("no commit");
|
|
3597
|
-
}
|
|
3598
|
-
return {
|
|
3599
|
-
sha: commit.commitId,
|
|
3600
|
-
type: "COMMIT" /* COMMIT */,
|
|
3601
|
-
date: commit.committer?.date || /* @__PURE__ */ new Date()
|
|
3602
|
-
};
|
|
3603
|
-
})(),
|
|
3604
|
-
(async () => {
|
|
3605
|
-
const res = await git.getRefs(repo, projectName, `tags/${ref}`);
|
|
3606
|
-
if (!res[0] || !res[0].objectId) {
|
|
3607
|
-
throw new Error("no tag ref");
|
|
3608
|
-
}
|
|
3609
|
-
let objectId = res[0].objectId;
|
|
3610
|
-
try {
|
|
3611
|
-
const tag = await git.getAnnotatedTag(projectName, repo, objectId);
|
|
3612
|
-
if (tag.taggedObject?.objectId) {
|
|
3613
|
-
objectId = tag.taggedObject.objectId;
|
|
3614
|
-
}
|
|
3615
|
-
} catch (e) {
|
|
3616
|
-
}
|
|
3617
|
-
const commitRes2 = await git.getCommits(
|
|
3618
|
-
repo,
|
|
3619
|
-
{
|
|
3620
|
-
fromCommitId: objectId,
|
|
3621
|
-
toCommitId: objectId,
|
|
3622
|
-
$top: 1
|
|
3623
|
-
},
|
|
3624
|
-
projectName
|
|
3625
|
-
);
|
|
3626
|
-
const commit = commitRes2[0];
|
|
3627
|
-
if (!commit) {
|
|
3628
|
-
throw new Error("no commit");
|
|
3629
|
-
}
|
|
3630
|
-
return {
|
|
3631
|
-
sha: objectId,
|
|
3632
|
-
type: "TAG" /* TAG */,
|
|
3633
|
-
date: commit.committer?.date || /* @__PURE__ */ new Date()
|
|
3634
|
-
};
|
|
3635
|
-
})()
|
|
3636
|
-
]);
|
|
3637
|
-
const [branchRes, commitRes, tagRes] = results;
|
|
3638
|
-
if (tagRes.status === "fulfilled") {
|
|
3639
|
-
return tagRes.value;
|
|
3640
|
-
}
|
|
3641
|
-
if (branchRes.status === "fulfilled") {
|
|
3642
|
-
return branchRes.value;
|
|
3643
|
-
}
|
|
3644
|
-
if (commitRes.status === "fulfilled") {
|
|
3645
|
-
return commitRes.value;
|
|
3646
|
-
}
|
|
3647
|
-
throw new RefNotFoundError(`ref: ${ref} does not exist`);
|
|
3699
|
+
getVulByNodesMetadata(variables, requestHeaders) {
|
|
3700
|
+
return withWrapper((wrappedRequestHeaders) => client.request(GetVulByNodesMetadataDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "getVulByNodesMetadata", "query", variables);
|
|
3701
|
+
},
|
|
3702
|
+
updateScmToken(variables, requestHeaders) {
|
|
3703
|
+
return withWrapper((wrappedRequestHeaders) => client.request(UpdateScmTokenDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "updateScmToken", "mutation", variables);
|
|
3648
3704
|
},
|
|
3649
|
-
|
|
3650
|
-
return
|
|
3705
|
+
uploadS3BucketInfo(variables, requestHeaders) {
|
|
3706
|
+
return withWrapper((wrappedRequestHeaders) => client.request(UploadS3BucketInfoDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "uploadS3BucketInfo", "mutation", variables);
|
|
3707
|
+
},
|
|
3708
|
+
DigestVulnerabilityReport(variables, requestHeaders) {
|
|
3709
|
+
return withWrapper((wrappedRequestHeaders) => client.request(DigestVulnerabilityReportDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "DigestVulnerabilityReport", "mutation", variables);
|
|
3710
|
+
},
|
|
3711
|
+
SubmitVulnerabilityReport(variables, requestHeaders) {
|
|
3712
|
+
return withWrapper((wrappedRequestHeaders) => client.request(SubmitVulnerabilityReportDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "SubmitVulnerabilityReport", "mutation", variables);
|
|
3713
|
+
},
|
|
3714
|
+
CreateCommunityUser(variables, requestHeaders) {
|
|
3715
|
+
return withWrapper((wrappedRequestHeaders) => client.request(CreateCommunityUserDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "CreateCommunityUser", "mutation", variables);
|
|
3716
|
+
},
|
|
3717
|
+
CreateCliLogin(variables, requestHeaders) {
|
|
3718
|
+
return withWrapper((wrappedRequestHeaders) => client.request(CreateCliLoginDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "CreateCliLogin", "mutation", variables);
|
|
3719
|
+
},
|
|
3720
|
+
performCliLogin(variables, requestHeaders) {
|
|
3721
|
+
return withWrapper((wrappedRequestHeaders) => client.request(PerformCliLoginDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "performCliLogin", "mutation", variables);
|
|
3722
|
+
},
|
|
3723
|
+
CreateProject(variables, requestHeaders) {
|
|
3724
|
+
return withWrapper((wrappedRequestHeaders) => client.request(CreateProjectDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "CreateProject", "mutation", variables);
|
|
3725
|
+
},
|
|
3726
|
+
validateRepoUrl(variables, requestHeaders) {
|
|
3727
|
+
return withWrapper((wrappedRequestHeaders) => client.request(ValidateRepoUrlDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "validateRepoUrl", "query", variables);
|
|
3728
|
+
},
|
|
3729
|
+
gitReference(variables, requestHeaders) {
|
|
3730
|
+
return withWrapper((wrappedRequestHeaders) => client.request(GitReferenceDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "gitReference", "query", variables);
|
|
3651
3731
|
}
|
|
3652
3732
|
};
|
|
3653
3733
|
}
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
const orgApi = await getAdoApiClient({
|
|
3675
|
-
...await getAdoClientParams({
|
|
3676
|
-
accessToken,
|
|
3677
|
-
tokenOrg: tokenOrg || org,
|
|
3678
|
-
url: void 0
|
|
3679
|
-
}),
|
|
3680
|
-
orgName: org
|
|
3681
|
-
});
|
|
3682
|
-
const gitOrg = await orgApi.getGitApi();
|
|
3683
|
-
const orgRepos = await gitOrg.getRepositories();
|
|
3684
|
-
const repoInfoList = (await Promise.allSettled(
|
|
3685
|
-
orgRepos.map(async (repo) => {
|
|
3686
|
-
if (!repo.name || !repo.remoteUrl || !repo.defaultBranch) {
|
|
3687
|
-
throw new InvalidRepoUrlError("bad repo");
|
|
3688
|
-
}
|
|
3689
|
-
const branch = await gitOrg.getBranch(
|
|
3690
|
-
repo.name,
|
|
3691
|
-
repo.defaultBranch.replace(/^refs\/heads\//, ""),
|
|
3692
|
-
repo.project?.name
|
|
3693
|
-
);
|
|
3694
|
-
return {
|
|
3695
|
-
repoName: repo.name,
|
|
3696
|
-
repoUrl: repo.remoteUrl.replace(
|
|
3697
|
-
/^[hH][tT][tT][pP][sS]:\/\/[^/]+@/,
|
|
3698
|
-
"https://"
|
|
3699
|
-
),
|
|
3700
|
-
repoOwner: org,
|
|
3701
|
-
repoIsPublic: repo.project?.visibility === 2 /* Public */,
|
|
3702
|
-
repoLanguages: [],
|
|
3703
|
-
repoUpdatedAt: branch.commit?.committer?.date?.toDateString() || repo.project?.lastUpdateTime?.toDateString() || (/* @__PURE__ */ new Date()).toDateString()
|
|
3704
|
-
};
|
|
3705
|
-
})
|
|
3706
|
-
)).reduce((acc, res) => {
|
|
3707
|
-
if (res.status === "fulfilled") {
|
|
3708
|
-
acc.push(res.value);
|
|
3709
|
-
}
|
|
3710
|
-
return acc;
|
|
3711
|
-
}, []);
|
|
3712
|
-
return repoInfoList;
|
|
3713
|
-
})
|
|
3714
|
-
)).reduce((acc, res) => {
|
|
3715
|
-
if (res.status === "fulfilled") {
|
|
3716
|
-
return acc.concat(res.value);
|
|
3717
|
-
}
|
|
3718
|
-
return acc;
|
|
3719
|
-
}, []);
|
|
3720
|
-
return repos;
|
|
3734
|
+
|
|
3735
|
+
// src/utils/index.ts
|
|
3736
|
+
var utils_exports = {};
|
|
3737
|
+
__export(utils_exports, {
|
|
3738
|
+
CliError: () => CliError,
|
|
3739
|
+
Spinner: () => Spinner,
|
|
3740
|
+
getDirName: () => getDirName,
|
|
3741
|
+
getTopLevelDirName: () => getTopLevelDirName,
|
|
3742
|
+
keypress: () => keypress,
|
|
3743
|
+
sleep: () => sleep
|
|
3744
|
+
});
|
|
3745
|
+
|
|
3746
|
+
// src/utils/dirname.ts
|
|
3747
|
+
import path3 from "node:path";
|
|
3748
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
3749
|
+
function getDirName() {
|
|
3750
|
+
return path3.dirname(fileURLToPath2(import.meta.url));
|
|
3751
|
+
}
|
|
3752
|
+
function getTopLevelDirName(fullPath) {
|
|
3753
|
+
return path3.parse(fullPath).name;
|
|
3721
3754
|
}
|
|
3722
3755
|
|
|
3723
|
-
// src/
|
|
3724
|
-
|
|
3756
|
+
// src/utils/keypress.ts
|
|
3757
|
+
import readline from "node:readline";
|
|
3758
|
+
async function keypress() {
|
|
3759
|
+
const rl = readline.createInterface({
|
|
3760
|
+
input: process.stdin,
|
|
3761
|
+
output: process.stdout
|
|
3762
|
+
});
|
|
3763
|
+
return new Promise((resolve) => {
|
|
3764
|
+
rl.question("", (answer) => {
|
|
3765
|
+
rl.close();
|
|
3766
|
+
process.stderr.moveCursor(0, -1);
|
|
3767
|
+
process.stderr.clearLine(1);
|
|
3768
|
+
resolve(answer);
|
|
3769
|
+
});
|
|
3770
|
+
});
|
|
3771
|
+
}
|
|
3772
|
+
|
|
3773
|
+
// src/utils/spinner.ts
|
|
3774
|
+
import {
|
|
3775
|
+
createSpinner as _createSpinner
|
|
3776
|
+
} from "nanospinner";
|
|
3777
|
+
var mockSpinner = {
|
|
3778
|
+
success: () => mockSpinner,
|
|
3779
|
+
error: () => mockSpinner,
|
|
3780
|
+
warn: () => mockSpinner,
|
|
3781
|
+
stop: () => mockSpinner,
|
|
3782
|
+
start: () => mockSpinner,
|
|
3783
|
+
update: () => mockSpinner,
|
|
3784
|
+
reset: () => mockSpinner,
|
|
3785
|
+
clear: () => mockSpinner,
|
|
3786
|
+
spin: () => mockSpinner
|
|
3787
|
+
};
|
|
3788
|
+
function Spinner({ ci = false } = {}) {
|
|
3789
|
+
return {
|
|
3790
|
+
createSpinner: (text, options) => ci ? mockSpinner : _createSpinner(text, options)
|
|
3791
|
+
};
|
|
3792
|
+
}
|
|
3793
|
+
|
|
3794
|
+
// src/utils/index.ts
|
|
3795
|
+
var sleep = (ms = 2e3) => new Promise((r) => setTimeout(r, ms));
|
|
3796
|
+
var CliError = class extends Error {
|
|
3797
|
+
};
|
|
3798
|
+
|
|
3799
|
+
// src/features/analysis/index.ts
|
|
3800
|
+
import chalk4 from "chalk";
|
|
3801
|
+
import Configstore from "configstore";
|
|
3802
|
+
import Debug12 from "debug";
|
|
3803
|
+
import extract from "extract-zip";
|
|
3804
|
+
import fetch4 from "node-fetch";
|
|
3805
|
+
import open2 from "open";
|
|
3806
|
+
import semver from "semver";
|
|
3807
|
+
import tmp2 from "tmp";
|
|
3808
|
+
import { z as z13 } from "zod";
|
|
3809
|
+
|
|
3810
|
+
// src/features/analysis/add_fix_comments_for_pr/add_fix_comments_for_pr.ts
|
|
3811
|
+
import Debug4 from "debug";
|
|
3725
3812
|
|
|
3726
3813
|
// src/features/analysis/add_fix_comments_for_pr/utils.ts
|
|
3727
3814
|
import Debug3 from "debug";
|
|
3728
3815
|
import parseDiff2 from "parse-diff";
|
|
3729
|
-
import { z as
|
|
3816
|
+
import { z as z11 } from "zod";
|
|
3730
3817
|
|
|
3731
3818
|
// src/features/analysis/utils/by_key.ts
|
|
3732
3819
|
function keyBy(array, keyBy2) {
|
|
@@ -3877,7 +3964,8 @@ async function postFixComment(params) {
|
|
|
3877
3964
|
patchAndQuestions: { patch }
|
|
3878
3965
|
} = fix;
|
|
3879
3966
|
const commentRes = await scm.postPrComment({
|
|
3880
|
-
body:
|
|
3967
|
+
body: `# ${MobbIconMarkdown} Your fix is ready!
|
|
3968
|
+
Refresh the page in order to see the changes.`,
|
|
3881
3969
|
pull_number: pullRequest,
|
|
3882
3970
|
commit_id: commitSha,
|
|
3883
3971
|
path: path9,
|
|
@@ -3957,7 +4045,7 @@ async function getRelevantVulenrabilitiesFromDiff(params) {
|
|
|
3957
4045
|
});
|
|
3958
4046
|
const lineAddedRanges = calculateRanges(fileNumbers);
|
|
3959
4047
|
const fileFilter = {
|
|
3960
|
-
path:
|
|
4048
|
+
path: z11.string().parse(file.to),
|
|
3961
4049
|
ranges: lineAddedRanges.map(([startLine, endLine]) => ({
|
|
3962
4050
|
endLine,
|
|
3963
4051
|
startLine
|
|
@@ -4264,30 +4352,30 @@ function subscribe(query, variables, callback, wsClientOptions) {
|
|
|
4264
4352
|
}
|
|
4265
4353
|
|
|
4266
4354
|
// src/features/analysis/graphql/types.ts
|
|
4267
|
-
import { z as
|
|
4268
|
-
var VulnerabilityReportIssueCodeNodeZ =
|
|
4269
|
-
vulnerabilityReportIssueId:
|
|
4270
|
-
path:
|
|
4271
|
-
startLine:
|
|
4272
|
-
vulnerabilityReportIssue:
|
|
4273
|
-
fixId:
|
|
4355
|
+
import { z as z12 } from "zod";
|
|
4356
|
+
var VulnerabilityReportIssueCodeNodeZ = z12.object({
|
|
4357
|
+
vulnerabilityReportIssueId: z12.string(),
|
|
4358
|
+
path: z12.string(),
|
|
4359
|
+
startLine: z12.number(),
|
|
4360
|
+
vulnerabilityReportIssue: z12.object({
|
|
4361
|
+
fixId: z12.string()
|
|
4274
4362
|
})
|
|
4275
4363
|
});
|
|
4276
|
-
var GetVulByNodesMetadataZ =
|
|
4277
|
-
vulnerabilityReportIssueCodeNodes:
|
|
4278
|
-
nonFixablePrVuls:
|
|
4279
|
-
aggregate:
|
|
4280
|
-
count:
|
|
4364
|
+
var GetVulByNodesMetadataZ = z12.object({
|
|
4365
|
+
vulnerabilityReportIssueCodeNodes: z12.array(VulnerabilityReportIssueCodeNodeZ),
|
|
4366
|
+
nonFixablePrVuls: z12.object({
|
|
4367
|
+
aggregate: z12.object({
|
|
4368
|
+
count: z12.number()
|
|
4281
4369
|
})
|
|
4282
4370
|
}),
|
|
4283
|
-
fixablePrVuls:
|
|
4284
|
-
aggregate:
|
|
4285
|
-
count:
|
|
4371
|
+
fixablePrVuls: z12.object({
|
|
4372
|
+
aggregate: z12.object({
|
|
4373
|
+
count: z12.number()
|
|
4286
4374
|
})
|
|
4287
4375
|
}),
|
|
4288
|
-
totalScanVulnerabilities:
|
|
4289
|
-
aggregate:
|
|
4290
|
-
count:
|
|
4376
|
+
totalScanVulnerabilities: z12.object({
|
|
4377
|
+
aggregate: z12.object({
|
|
4378
|
+
count: z12.number()
|
|
4291
4379
|
})
|
|
4292
4380
|
})
|
|
4293
4381
|
});
|
|
@@ -4560,6 +4648,12 @@ var GQLClient = class {
|
|
|
4560
4648
|
});
|
|
4561
4649
|
return res;
|
|
4562
4650
|
}
|
|
4651
|
+
async validateRepoUrl(args) {
|
|
4652
|
+
return this._clientSdk.validateRepoUrl(args);
|
|
4653
|
+
}
|
|
4654
|
+
async getReferenceData(args) {
|
|
4655
|
+
return this._clientSdk.gitReference(args);
|
|
4656
|
+
}
|
|
4563
4657
|
};
|
|
4564
4658
|
|
|
4565
4659
|
// src/features/analysis/pack.ts
|
|
@@ -5060,6 +5154,70 @@ function _getUrlForScmType({
|
|
|
5060
5154
|
};
|
|
5061
5155
|
}
|
|
5062
5156
|
}
|
|
5157
|
+
async function getScmTokenInfo(params) {
|
|
5158
|
+
const { gqlClient, repo } = params;
|
|
5159
|
+
const userInfo = await gqlClient.getUserInfo();
|
|
5160
|
+
if (!userInfo) {
|
|
5161
|
+
throw new Error("userInfo is null");
|
|
5162
|
+
}
|
|
5163
|
+
const scmConfigs = getFromArraySafe(userInfo.scmConfigs);
|
|
5164
|
+
return getScmConfig({
|
|
5165
|
+
url: repo,
|
|
5166
|
+
scmConfigs,
|
|
5167
|
+
includeOrgTokens: false
|
|
5168
|
+
});
|
|
5169
|
+
}
|
|
5170
|
+
async function getReport(params, { skipPrompts }) {
|
|
5171
|
+
const {
|
|
5172
|
+
scanner,
|
|
5173
|
+
repoUrl,
|
|
5174
|
+
gqlClient,
|
|
5175
|
+
sha,
|
|
5176
|
+
dirname,
|
|
5177
|
+
reference,
|
|
5178
|
+
cxProjectName,
|
|
5179
|
+
ci
|
|
5180
|
+
} = params;
|
|
5181
|
+
const tokenInfo = await getScmTokenInfo({ gqlClient, repo: repoUrl });
|
|
5182
|
+
const scm = await SCMLib.init(
|
|
5183
|
+
{
|
|
5184
|
+
url: repoUrl,
|
|
5185
|
+
accessToken: tokenInfo.accessToken,
|
|
5186
|
+
scmOrg: tokenInfo.scmOrg,
|
|
5187
|
+
scmType: tokenInfo.scmLibType
|
|
5188
|
+
},
|
|
5189
|
+
{ propagateExceptions: true }
|
|
5190
|
+
);
|
|
5191
|
+
const downloadUrl = await scm.getDownloadUrl(sha);
|
|
5192
|
+
const repositoryRoot = await downloadRepo({
|
|
5193
|
+
repoUrl,
|
|
5194
|
+
dirname,
|
|
5195
|
+
ci,
|
|
5196
|
+
authHeaders: scm.getAuthHeaders(),
|
|
5197
|
+
downloadUrl
|
|
5198
|
+
});
|
|
5199
|
+
const reportPath = path6.join(dirname, "report.json");
|
|
5200
|
+
switch (scanner) {
|
|
5201
|
+
case "snyk":
|
|
5202
|
+
await getSnykReport(reportPath, repositoryRoot, { skipPrompts });
|
|
5203
|
+
break;
|
|
5204
|
+
case "checkmarx":
|
|
5205
|
+
if (!cxProjectName) {
|
|
5206
|
+
throw new Error("cxProjectName is required for checkmarx scanner");
|
|
5207
|
+
}
|
|
5208
|
+
await getCheckmarxReport(
|
|
5209
|
+
{
|
|
5210
|
+
reportPath,
|
|
5211
|
+
repositoryRoot,
|
|
5212
|
+
branch: reference,
|
|
5213
|
+
projectName: cxProjectName
|
|
5214
|
+
},
|
|
5215
|
+
{ skipPrompts }
|
|
5216
|
+
);
|
|
5217
|
+
break;
|
|
5218
|
+
}
|
|
5219
|
+
return reportPath;
|
|
5220
|
+
}
|
|
5063
5221
|
async function _scan(params, { skipPrompts = false } = {}) {
|
|
5064
5222
|
const {
|
|
5065
5223
|
dirname,
|
|
@@ -5103,68 +5261,64 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
5103
5261
|
if (!repo) {
|
|
5104
5262
|
throw new Error("repo is required in case srcPath is not provided");
|
|
5105
5263
|
}
|
|
5106
|
-
const
|
|
5107
|
-
|
|
5108
|
-
|
|
5109
|
-
}
|
|
5110
|
-
const scmConfigs = getFromArraySafe(userInfo.scmConfigs);
|
|
5111
|
-
const tokenInfo = getScmConfig({
|
|
5112
|
-
url: repo,
|
|
5113
|
-
scmConfigs,
|
|
5114
|
-
includeOrgTokens: false
|
|
5115
|
-
});
|
|
5116
|
-
const isRepoAvailable = await scmCanReachRepo({
|
|
5117
|
-
repoUrl: repo,
|
|
5118
|
-
accessToken: tokenInfo.accessToken,
|
|
5119
|
-
scmOrg: tokenInfo.scmOrg,
|
|
5120
|
-
scmType: getScmTypeFromScmLibType(tokenInfo.scmLibType)
|
|
5121
|
-
});
|
|
5264
|
+
const tokenInfo = await getScmTokenInfo({ gqlClient, repo });
|
|
5265
|
+
const validateRes = await gqlClient.validateRepoUrl({ repoUrl: repo });
|
|
5266
|
+
const isRepoAvailable = validateRes.validateRepoUrl?.__typename === "RepoValidationSuccess";
|
|
5122
5267
|
const cloudScmLibType = getCloudScmLibTypeFromUrl(repo);
|
|
5123
5268
|
const { authUrl: scmAuthUrl } = _getUrlForScmType({
|
|
5124
5269
|
scmLibType: cloudScmLibType
|
|
5125
5270
|
});
|
|
5126
|
-
let myToken = tokenInfo.accessToken;
|
|
5127
5271
|
if (!isRepoAvailable) {
|
|
5128
5272
|
if (ci || !cloudScmLibType || !scmAuthUrl) {
|
|
5129
5273
|
const errorMessage = scmAuthUrl ? `Cannot access repo ${repo}` : `Cannot access repo ${repo} with the provided token, please visit ${scmAuthUrl} to refresh your source control management system token`;
|
|
5130
5274
|
throw new Error(errorMessage);
|
|
5131
5275
|
}
|
|
5132
5276
|
if (cloudScmLibType && scmAuthUrl) {
|
|
5133
|
-
|
|
5134
|
-
const
|
|
5135
|
-
repoUrl: repo
|
|
5136
|
-
accessToken: myToken,
|
|
5137
|
-
scmOrg: tokenInfo.scmOrg,
|
|
5138
|
-
scmType: getScmTypeFromScmLibType(tokenInfo.scmLibType)
|
|
5277
|
+
await handleScmIntegration(tokenInfo.accessToken, scmAuthUrl, repo);
|
|
5278
|
+
const repoValidationResponse = await gqlClient.validateRepoUrl({
|
|
5279
|
+
repoUrl: repo
|
|
5139
5280
|
});
|
|
5281
|
+
const isRepoAvailable2 = repoValidationResponse.validateRepoUrl?.__typename === "RepoValidationSuccess";
|
|
5140
5282
|
if (!isRepoAvailable2) {
|
|
5141
5283
|
throw new Error(
|
|
5142
|
-
`Cannot access repo ${repo} with the provided credentials`
|
|
5284
|
+
`Cannot access repo ${repo} with the provided credentials: ${repoValidationResponse.validateRepoUrl?.__typename}`
|
|
5143
5285
|
);
|
|
5144
5286
|
}
|
|
5145
5287
|
}
|
|
5146
5288
|
}
|
|
5147
|
-
const
|
|
5148
|
-
|
|
5149
|
-
|
|
5150
|
-
|
|
5151
|
-
|
|
5289
|
+
const revalidateRes = await gqlClient.validateRepoUrl({ repoUrl: repo });
|
|
5290
|
+
if (revalidateRes.validateRepoUrl?.__typename !== "RepoValidationSuccess") {
|
|
5291
|
+
throw new Error(
|
|
5292
|
+
`could not reach repo ${repo}: ${revalidateRes.validateRepoUrl?.__typename}`
|
|
5293
|
+
);
|
|
5294
|
+
}
|
|
5295
|
+
const reference = ref ?? revalidateRes.validateRepoUrl.defaultBranch;
|
|
5296
|
+
const getReferenceDataRes = await gqlClient.getReferenceData({
|
|
5297
|
+
reference,
|
|
5298
|
+
repoUrl: repo
|
|
5152
5299
|
});
|
|
5153
|
-
|
|
5154
|
-
|
|
5155
|
-
|
|
5156
|
-
|
|
5300
|
+
if (getReferenceDataRes.gitReference?.__typename !== "GitReferenceData") {
|
|
5301
|
+
throw new Error(
|
|
5302
|
+
`Could not get reference data for ${reference}: ${getReferenceDataRes.gitReference?.__typename}`
|
|
5303
|
+
);
|
|
5304
|
+
}
|
|
5305
|
+
const { sha } = getReferenceDataRes.gitReference;
|
|
5157
5306
|
debug11("project id %s", projectId);
|
|
5158
5307
|
debug11("default branch %s", reference);
|
|
5159
|
-
const repositoryRoot = await downloadRepo({
|
|
5160
|
-
repoUrl: repo,
|
|
5161
|
-
dirname,
|
|
5162
|
-
ci,
|
|
5163
|
-
authHeaders: scm.getAuthHeaders(),
|
|
5164
|
-
downloadUrl
|
|
5165
|
-
});
|
|
5166
5308
|
if (command === "scan") {
|
|
5167
|
-
reportPath = await getReport(
|
|
5309
|
+
reportPath = await getReport(
|
|
5310
|
+
{
|
|
5311
|
+
scanner: SupportedScannersZ.parse(scanner),
|
|
5312
|
+
repoUrl: repo,
|
|
5313
|
+
sha,
|
|
5314
|
+
gqlClient,
|
|
5315
|
+
cxProjectName,
|
|
5316
|
+
dirname,
|
|
5317
|
+
reference,
|
|
5318
|
+
ci
|
|
5319
|
+
},
|
|
5320
|
+
{ skipPrompts }
|
|
5321
|
+
);
|
|
5168
5322
|
}
|
|
5169
5323
|
if (!reportPath) {
|
|
5170
5324
|
throw new Error("reportPath is null");
|
|
@@ -5188,7 +5342,7 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
5188
5342
|
spinner: mobbSpinner,
|
|
5189
5343
|
submitVulnerabilityReportVariables: {
|
|
5190
5344
|
fixReportId: reportUploadInfo.fixReportId,
|
|
5191
|
-
repoUrl:
|
|
5345
|
+
repoUrl: z13.string().parse(repo),
|
|
5192
5346
|
reference,
|
|
5193
5347
|
projectId,
|
|
5194
5348
|
vulnerabilityReportFileName: "report.json",
|
|
@@ -5207,29 +5361,6 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
5207
5361
|
});
|
|
5208
5362
|
await askToOpenAnalysis();
|
|
5209
5363
|
return reportUploadInfo.fixReportId;
|
|
5210
|
-
async function getReport(scanner2) {
|
|
5211
|
-
const reportPath2 = path6.join(dirname, "report.json");
|
|
5212
|
-
switch (scanner2) {
|
|
5213
|
-
case "snyk":
|
|
5214
|
-
await getSnykReport(reportPath2, repositoryRoot, { skipPrompts });
|
|
5215
|
-
break;
|
|
5216
|
-
case "checkmarx":
|
|
5217
|
-
if (!cxProjectName) {
|
|
5218
|
-
throw new Error("cxProjectName is required for checkmarx scanner");
|
|
5219
|
-
}
|
|
5220
|
-
await getCheckmarxReport(
|
|
5221
|
-
{
|
|
5222
|
-
reportPath: reportPath2,
|
|
5223
|
-
repositoryRoot,
|
|
5224
|
-
branch: reference,
|
|
5225
|
-
projectName: cxProjectName
|
|
5226
|
-
},
|
|
5227
|
-
{ skipPrompts }
|
|
5228
|
-
);
|
|
5229
|
-
break;
|
|
5230
|
-
}
|
|
5231
|
-
return reportPath2;
|
|
5232
|
-
}
|
|
5233
5364
|
async function askToOpenAnalysis() {
|
|
5234
5365
|
if (!repoUploadInfo || !reportUploadInfo) {
|
|
5235
5366
|
throw new Error("uploadS3BucketInfo is null");
|
|
@@ -5326,14 +5457,14 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
5326
5457
|
);
|
|
5327
5458
|
await open2(scmAuthUrl2);
|
|
5328
5459
|
for (let i = 0; i < LOGIN_MAX_WAIT / LOGIN_CHECK_DELAY; i++) {
|
|
5329
|
-
const
|
|
5330
|
-
if (!
|
|
5460
|
+
const userInfo = await gqlClient.getUserInfo();
|
|
5461
|
+
if (!userInfo) {
|
|
5331
5462
|
throw new CliError2("User info not found");
|
|
5332
5463
|
}
|
|
5333
|
-
const
|
|
5464
|
+
const scmConfigs = getFromArraySafe(userInfo.scmConfigs);
|
|
5334
5465
|
const tokenInfo2 = getScmConfig({
|
|
5335
5466
|
url: repoUrl,
|
|
5336
|
-
scmConfigs
|
|
5467
|
+
scmConfigs,
|
|
5337
5468
|
includeOrgTokens: false
|
|
5338
5469
|
});
|
|
5339
5470
|
if (tokenInfo2.accessToken && tokenInfo2.accessToken !== oldToken) {
|
|
@@ -5440,16 +5571,21 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
5440
5571
|
}
|
|
5441
5572
|
});
|
|
5442
5573
|
if (command === "review") {
|
|
5443
|
-
const params2 =
|
|
5444
|
-
repo:
|
|
5445
|
-
githubActionToken:
|
|
5574
|
+
const params2 = z13.object({
|
|
5575
|
+
repo: z13.string().url(),
|
|
5576
|
+
githubActionToken: z13.string()
|
|
5446
5577
|
}).parse({ repo, githubActionToken });
|
|
5447
|
-
const
|
|
5448
|
-
|
|
5449
|
-
|
|
5450
|
-
|
|
5451
|
-
|
|
5452
|
-
|
|
5578
|
+
const scm = await SCMLib.init(
|
|
5579
|
+
{
|
|
5580
|
+
url: params2.repo,
|
|
5581
|
+
accessToken: params2.githubActionToken,
|
|
5582
|
+
scmOrg: "",
|
|
5583
|
+
scmType: "GITHUB" /* GITHUB */
|
|
5584
|
+
},
|
|
5585
|
+
{
|
|
5586
|
+
propagateExceptions: true
|
|
5587
|
+
}
|
|
5588
|
+
);
|
|
5453
5589
|
await gqlClient.subscribeToAnalysis({
|
|
5454
5590
|
subscribeToAnalysisParams: {
|
|
5455
5591
|
analysisId: reportUploadInfo.fixReportId
|
|
@@ -5458,8 +5594,8 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
5458
5594
|
return addFixCommentsForPr({
|
|
5459
5595
|
analysisId,
|
|
5460
5596
|
gqlClient,
|
|
5461
|
-
scm
|
|
5462
|
-
scanner:
|
|
5597
|
+
scm,
|
|
5598
|
+
scanner: z13.nativeEnum(SCANNERS).parse(scanner)
|
|
5463
5599
|
});
|
|
5464
5600
|
},
|
|
5465
5601
|
callbackStates: ["Finished" /* Finished */]
|
|
@@ -5645,12 +5781,12 @@ var commitHashOption = {
|
|
|
5645
5781
|
};
|
|
5646
5782
|
var scmTypeOption = {
|
|
5647
5783
|
demandOption: true,
|
|
5648
|
-
describe: chalk5.bold("SCM type
|
|
5649
|
-
|
|
5784
|
+
describe: chalk5.bold("SCM type"),
|
|
5785
|
+
choices: Object.values(ScmType)
|
|
5650
5786
|
};
|
|
5651
5787
|
var urlOption = {
|
|
5652
5788
|
describe: chalk5.bold(
|
|
5653
|
-
|
|
5789
|
+
`URL of the repository (used in ${Object.values(ScmType).join(", ")})`
|
|
5654
5790
|
),
|
|
5655
5791
|
type: "string",
|
|
5656
5792
|
demandOption: true
|
|
@@ -5672,7 +5808,7 @@ var scmTokenOption = {
|
|
|
5672
5808
|
// src/args/validation.ts
|
|
5673
5809
|
import chalk6 from "chalk";
|
|
5674
5810
|
import path8 from "path";
|
|
5675
|
-
import { z as
|
|
5811
|
+
import { z as z14 } from "zod";
|
|
5676
5812
|
function throwRepoUrlErrorMessage({
|
|
5677
5813
|
error,
|
|
5678
5814
|
repoUrl,
|
|
@@ -5689,13 +5825,13 @@ Example:
|
|
|
5689
5825
|
)}`;
|
|
5690
5826
|
throw new CliError(formattedErrorMessage);
|
|
5691
5827
|
}
|
|
5692
|
-
var UrlZ =
|
|
5693
|
-
invalid_type_error:
|
|
5828
|
+
var UrlZ = z14.string({
|
|
5829
|
+
invalid_type_error: `is not a valid ${Object.values(ScmType).join("/ ")} URL`
|
|
5694
5830
|
}).refine((data) => !!sanityRepoURL(data), {
|
|
5695
|
-
message:
|
|
5831
|
+
message: `is not a valid ${Object.values(ScmType).join(" / ")} URL`
|
|
5696
5832
|
});
|
|
5697
5833
|
function validateOrganizationId(organizationId) {
|
|
5698
|
-
const orgIdValidation =
|
|
5834
|
+
const orgIdValidation = z14.string().uuid().nullish().safeParse(organizationId);
|
|
5699
5835
|
if (!orgIdValidation.success) {
|
|
5700
5836
|
throw new CliError(`organizationId: ${organizationId} is not a valid UUID`);
|
|
5701
5837
|
}
|
|
@@ -5852,20 +5988,15 @@ async function scanHandler(args) {
|
|
|
5852
5988
|
}
|
|
5853
5989
|
|
|
5854
5990
|
// src/args/commands/token.ts
|
|
5855
|
-
import { z as z14 } from "zod";
|
|
5856
5991
|
function addScmTokenBuilder(args) {
|
|
5857
5992
|
return args.option("scm-type", scmTypeOption).option("url", urlOption).option("token", scmTokenOption).option("organization", scmOrgOption).option("refresh-token", scmRefreshTokenOption).option("api-key", apiKeyOption).example(
|
|
5858
5993
|
"$0 add-scm-token --scm-type Ado --url https://dev.azure.com/adoorg/test/_git/repo --token abcdef0123456 --organization myOrg",
|
|
5859
|
-
|
|
5994
|
+
`Add your SCM (${Object.values(scmFriendlyText).join(", ")}) token to Mobb to enable automated fixes.`
|
|
5860
5995
|
).help().demandOption(["url", "token"]);
|
|
5861
5996
|
}
|
|
5862
|
-
function validateAddScmTokenOptions(argv) {
|
|
5863
|
-
|
|
5864
|
-
|
|
5865
|
-
"\nError: --scm-type must reference a valid SCM type (GitHub, GitLab, Ado, Bitbutcket)"
|
|
5866
|
-
);
|
|
5867
|
-
}
|
|
5868
|
-
Object.values(scmValidationMap).forEach((validate) => validate(argv));
|
|
5997
|
+
async function validateAddScmTokenOptions(argv) {
|
|
5998
|
+
const scmType = argv["scm-type"];
|
|
5999
|
+
scmValidationMap[scmType];
|
|
5869
6000
|
}
|
|
5870
6001
|
var scmValidationMap = {
|
|
5871
6002
|
["GitHub" /* GitHub */]: () => {
|
|
@@ -5880,15 +6011,14 @@ var scmValidationMap = {
|
|
|
5880
6011
|
}
|
|
5881
6012
|
};
|
|
5882
6013
|
function validateAdo(argv) {
|
|
5883
|
-
|
|
5884
|
-
if ((urlObj.hostname.toLowerCase() === scmCloudHostname.Ado || urlObj.hostname.toLowerCase().endsWith(".visualstudio.com")) && !argv.organization) {
|
|
6014
|
+
if (!argv.organization) {
|
|
5885
6015
|
throw new CliError(
|
|
5886
6016
|
"\nError: --organization flag is required for Azure DevOps"
|
|
5887
6017
|
);
|
|
5888
6018
|
}
|
|
5889
6019
|
}
|
|
5890
6020
|
async function addScmTokenHandler(args) {
|
|
5891
|
-
validateAddScmTokenOptions(args);
|
|
6021
|
+
await validateAddScmTokenOptions(args);
|
|
5892
6022
|
await addScmToken(args);
|
|
5893
6023
|
}
|
|
5894
6024
|
|