mobbdev 1.0.67 → 1.0.74
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 +1598 -1519
- package/package.json +13 -13
package/dist/index.mjs
CHANGED
|
@@ -111,6 +111,7 @@ var IssueLanguage_Enum = /* @__PURE__ */ ((IssueLanguage_Enum2) => {
|
|
|
111
111
|
})(IssueLanguage_Enum || {});
|
|
112
112
|
var IssueType_Enum = /* @__PURE__ */ ((IssueType_Enum2) => {
|
|
113
113
|
IssueType_Enum2["AutoEscapeFalse"] = "AUTO_ESCAPE_FALSE";
|
|
114
|
+
IssueType_Enum2["AvoidIdentityComparisonCachedTypes"] = "AVOID_IDENTITY_COMPARISON_CACHED_TYPES";
|
|
114
115
|
IssueType_Enum2["ClientDomStoredCodeInjection"] = "CLIENT_DOM_STORED_CODE_INJECTION";
|
|
115
116
|
IssueType_Enum2["CmDi"] = "CMDi";
|
|
116
117
|
IssueType_Enum2["CmDiRelativePathCommand"] = "CMDi_relative_path_command";
|
|
@@ -146,6 +147,7 @@ var IssueType_Enum = /* @__PURE__ */ ((IssueType_Enum2) => {
|
|
|
146
147
|
IssueType_Enum2["InsecureBinderConfiguration"] = "INSECURE_BINDER_CONFIGURATION";
|
|
147
148
|
IssueType_Enum2["InsecureCookie"] = "INSECURE_COOKIE";
|
|
148
149
|
IssueType_Enum2["InsecureRandomness"] = "INSECURE_RANDOMNESS";
|
|
150
|
+
IssueType_Enum2["InsecureTmpFile"] = "INSECURE_TMP_FILE";
|
|
149
151
|
IssueType_Enum2["InsecureUuidVersion"] = "INSECURE_UUID_VERSION";
|
|
150
152
|
IssueType_Enum2["InsufficientLogging"] = "INSUFFICIENT_LOGGING";
|
|
151
153
|
IssueType_Enum2["JqueryDeprecatedSymbols"] = "JQUERY_DEPRECATED_SYMBOLS";
|
|
@@ -158,10 +160,13 @@ var IssueType_Enum = /* @__PURE__ */ ((IssueType_Enum2) => {
|
|
|
158
160
|
IssueType_Enum2["MissingEqualsOrHashcode"] = "MISSING_EQUALS_OR_HASHCODE";
|
|
159
161
|
IssueType_Enum2["MissingHstsHeader"] = "MISSING_HSTS_HEADER";
|
|
160
162
|
IssueType_Enum2["MissingSslMinversion"] = "MISSING_SSL_MINVERSION";
|
|
163
|
+
IssueType_Enum2["ModifiedDefaultParam"] = "MODIFIED_DEFAULT_PARAM";
|
|
161
164
|
IssueType_Enum2["NonFinalPublicStaticField"] = "NON_FINAL_PUBLIC_STATIC_FIELD";
|
|
162
165
|
IssueType_Enum2["NonReadonlyField"] = "NON_READONLY_FIELD";
|
|
163
166
|
IssueType_Enum2["NoEquivalenceMethod"] = "NO_EQUIVALENCE_METHOD";
|
|
164
167
|
IssueType_Enum2["NoLimitsOrThrottling"] = "NO_LIMITS_OR_THROTTLING";
|
|
168
|
+
IssueType_Enum2["NoReturnInFinally"] = "NO_RETURN_IN_FINALLY";
|
|
169
|
+
IssueType_Enum2["NoVar"] = "NO_VAR";
|
|
165
170
|
IssueType_Enum2["NullDereference"] = "NULL_DEREFERENCE";
|
|
166
171
|
IssueType_Enum2["OpenRedirect"] = "OPEN_REDIRECT";
|
|
167
172
|
IssueType_Enum2["OverlyBroadCatch"] = "OVERLY_BROAD_CATCH";
|
|
@@ -177,6 +182,7 @@ var IssueType_Enum = /* @__PURE__ */ ((IssueType_Enum2) => {
|
|
|
177
182
|
IssueType_Enum2["SqlInjection"] = "SQL_Injection";
|
|
178
183
|
IssueType_Enum2["Ssrf"] = "SSRF";
|
|
179
184
|
IssueType_Enum2["StringFormatMisuse"] = "STRING_FORMAT_MISUSE";
|
|
185
|
+
IssueType_Enum2["SystemExitShouldReraise"] = "SYSTEM_EXIT_SHOULD_RERAISE";
|
|
180
186
|
IssueType_Enum2["SystemInformationLeak"] = "SYSTEM_INFORMATION_LEAK";
|
|
181
187
|
IssueType_Enum2["SystemInformationLeakExternal"] = "SYSTEM_INFORMATION_LEAK_EXTERNAL";
|
|
182
188
|
IssueType_Enum2["TrustBoundaryViolation"] = "TRUST_BOUNDARY_VIOLATION";
|
|
@@ -459,10 +465,24 @@ var GetVulByNodesMetadataDocument = `
|
|
|
459
465
|
vulnerabilityReportIssueTags {
|
|
460
466
|
tag: vulnerability_report_issue_tag_value
|
|
461
467
|
}
|
|
462
|
-
codeNodes(order_by: {index: desc}, where: {_or: $filters}) {
|
|
468
|
+
codeNodes(order_by: {index: desc}, where: {_or: $filters}, limit: 1) {
|
|
463
469
|
path
|
|
464
470
|
startLine
|
|
465
471
|
}
|
|
472
|
+
fpId
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
`;
|
|
477
|
+
var GetFalsePositiveDocument = `
|
|
478
|
+
query getFalsePositive($fpId: uuid!) {
|
|
479
|
+
getFalsePositive(fpId: $fpId) {
|
|
480
|
+
... on FalsePositiveData {
|
|
481
|
+
extraContext {
|
|
482
|
+
key
|
|
483
|
+
value
|
|
484
|
+
}
|
|
485
|
+
fixDescription
|
|
466
486
|
}
|
|
467
487
|
}
|
|
468
488
|
}
|
|
@@ -693,6 +713,9 @@ function getSdk(client, withWrapper = defaultWrapper) {
|
|
|
693
713
|
getVulByNodesMetadata(variables, requestHeaders) {
|
|
694
714
|
return withWrapper((wrappedRequestHeaders) => client.request(GetVulByNodesMetadataDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "getVulByNodesMetadata", "query", variables);
|
|
695
715
|
},
|
|
716
|
+
getFalsePositive(variables, requestHeaders) {
|
|
717
|
+
return withWrapper((wrappedRequestHeaders) => client.request(GetFalsePositiveDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "getFalsePositive", "query", variables);
|
|
718
|
+
},
|
|
696
719
|
updateScmToken(variables, requestHeaders) {
|
|
697
720
|
return withWrapper((wrappedRequestHeaders) => client.request(UpdateScmTokenDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), "updateScmToken", "mutation", variables);
|
|
698
721
|
},
|
|
@@ -1146,7 +1169,13 @@ var issueTypeMap = {
|
|
|
1146
1169
|
["DUPLICATED_STRINGS" /* DuplicatedStrings */]: "String Literals Should not Be Duplicated",
|
|
1147
1170
|
["INSECURE_UUID_VERSION" /* InsecureUuidVersion */]: "Insecure UUID Version",
|
|
1148
1171
|
["GH_ACTIONS_SHELL_INJECTION" /* GhActionsShellInjection */]: "GitHub Actions Shell Injection",
|
|
1149
|
-
["
|
|
1172
|
+
["MODIFIED_DEFAULT_PARAM" /* ModifiedDefaultParam */]: "Modified Default Param",
|
|
1173
|
+
["UNSAFE_WEB_THREAD" /* UnsafeWebThread */]: "Unsafe Web Thread",
|
|
1174
|
+
["NO_VAR" /* NoVar */]: 'Prefer "let" or "const"',
|
|
1175
|
+
["INSECURE_TMP_FILE" /* InsecureTmpFile */]: "Insecure Temporary File",
|
|
1176
|
+
["SYSTEM_EXIT_SHOULD_RERAISE" /* SystemExitShouldReraise */]: "SystemExit Should Reraise",
|
|
1177
|
+
["NO_RETURN_IN_FINALLY" /* NoReturnInFinally */]: "No Return in Finally Block",
|
|
1178
|
+
["AVOID_IDENTITY_COMPARISON_CACHED_TYPES" /* AvoidIdentityComparisonCachedTypes */]: "Avoid Identity Comparison of Cached Types"
|
|
1150
1179
|
};
|
|
1151
1180
|
var issueTypeZ = z5.nativeEnum(IssueType_Enum);
|
|
1152
1181
|
var getIssueTypeFriendlyString = (issueType) => {
|
|
@@ -1179,6 +1208,22 @@ var issueDescription = {
|
|
|
1179
1208
|
["TEST_CODE" /* TestCode */]: "The flagged code resides in a test-specific path or context. This categorization indicates that **it supports testing scenarios and is isolated from production use**.",
|
|
1180
1209
|
["VENDOR_CODE" /* VendorCode */]: "The flagged code originates from a third-party library or dependency maintained externally. This categorization suggests that **the issue lies outside the application\u2019s direct control** and should be addressed by the vendor if necessary."
|
|
1181
1210
|
};
|
|
1211
|
+
function replaceKeysWithValues(fixDescription, extraContext) {
|
|
1212
|
+
let result = fixDescription;
|
|
1213
|
+
extraContext.forEach(({ key, value }) => {
|
|
1214
|
+
result = result.replace(`\${${key}}`, value);
|
|
1215
|
+
});
|
|
1216
|
+
return result;
|
|
1217
|
+
}
|
|
1218
|
+
function getParsedFalsePositiveMessage(data) {
|
|
1219
|
+
const { fixDescription, extraContext } = data;
|
|
1220
|
+
const containsTemplate = extraContext.some(
|
|
1221
|
+
(context) => fixDescription.includes(`\${${context.key}}`)
|
|
1222
|
+
);
|
|
1223
|
+
const description = containsTemplate ? replaceKeysWithValues(fixDescription, extraContext) : fixDescription;
|
|
1224
|
+
const contextString = containsTemplate ? null : `\`\`\`${extraContext.map(({ value }) => value).join(" ")} \`\`\``;
|
|
1225
|
+
return { description, contextString };
|
|
1226
|
+
}
|
|
1182
1227
|
|
|
1183
1228
|
// src/features/analysis/scm/shared/src/validations.ts
|
|
1184
1229
|
var IssueTypeSettingZ = z6.object({
|
|
@@ -1260,7 +1305,9 @@ var ReportQueryResultZ = z7.object({
|
|
|
1260
1305
|
}),
|
|
1261
1306
|
fixesDoneCount: z7.number(),
|
|
1262
1307
|
fixesInprogressCount: z7.number(),
|
|
1263
|
-
fixesReadyCount: z7.
|
|
1308
|
+
fixesReadyCount: z7.object({
|
|
1309
|
+
aggregate: z7.object({ count: z7.number() })
|
|
1310
|
+
}),
|
|
1264
1311
|
issueTypes: z7.record(z7.string(), z7.number()).nullable(),
|
|
1265
1312
|
issueLanguages: z7.record(z7.string(), z7.number()).nullable(),
|
|
1266
1313
|
fixesCountByEffort: z7.record(z7.string(), z7.number()).nullable(),
|
|
@@ -1799,9 +1846,6 @@ import { z as z29 } from "zod";
|
|
|
1799
1846
|
// src/features/analysis/add_fix_comments_for_pr/add_fix_comments_for_pr.ts
|
|
1800
1847
|
import Debug8 from "debug";
|
|
1801
1848
|
|
|
1802
|
-
// src/features/analysis/scm/github/GithubSCMLib.ts
|
|
1803
|
-
import { z as z24 } from "zod";
|
|
1804
|
-
|
|
1805
1849
|
// src/features/analysis/scm/errors.ts
|
|
1806
1850
|
var InvalidRepoUrlError = class extends Error {
|
|
1807
1851
|
constructor(m) {
|
|
@@ -1830,26 +1874,26 @@ var RepoNoTokenAccessError = class extends Error {
|
|
|
1830
1874
|
}
|
|
1831
1875
|
};
|
|
1832
1876
|
|
|
1833
|
-
// src/features/analysis/scm/
|
|
1834
|
-
|
|
1835
|
-
var isValidBranchName = async (branchName) => {
|
|
1836
|
-
const git = simpleGit();
|
|
1837
|
-
try {
|
|
1838
|
-
const res = await git.raw(["check-ref-format", "--branch", branchName]);
|
|
1839
|
-
if (res) {
|
|
1840
|
-
return true;
|
|
1841
|
-
}
|
|
1842
|
-
return false;
|
|
1843
|
-
} catch (e) {
|
|
1844
|
-
return false;
|
|
1845
|
-
}
|
|
1846
|
-
};
|
|
1877
|
+
// src/features/analysis/scm/ado/constants.ts
|
|
1878
|
+
var DEFUALT_ADO_ORIGIN = scmCloudUrl.Ado;
|
|
1847
1879
|
|
|
1848
|
-
// src/features/analysis/scm/
|
|
1849
|
-
import
|
|
1880
|
+
// src/features/analysis/scm/ado/utils.ts
|
|
1881
|
+
import querystring from "node:querystring";
|
|
1882
|
+
import * as api from "azure-devops-node-api";
|
|
1883
|
+
import Debug2 from "debug";
|
|
1884
|
+
import { z as z18 } from "zod";
|
|
1850
1885
|
|
|
1851
|
-
// src/features/analysis/scm/
|
|
1886
|
+
// src/features/analysis/scm/env.ts
|
|
1852
1887
|
import { z as z9 } from "zod";
|
|
1888
|
+
var EnvVariablesZod = z9.object({
|
|
1889
|
+
GITLAB_API_TOKEN: z9.string().optional(),
|
|
1890
|
+
GITHUB_API_TOKEN: z9.string().optional(),
|
|
1891
|
+
GIT_PROXY_HOST: z9.string()
|
|
1892
|
+
});
|
|
1893
|
+
var { GITLAB_API_TOKEN, GITHUB_API_TOKEN, GIT_PROXY_HOST } = EnvVariablesZod.parse(process.env);
|
|
1894
|
+
|
|
1895
|
+
// src/features/analysis/scm/shared/src/commitDescriptionMarkup.ts
|
|
1896
|
+
import { z as z10 } from "zod";
|
|
1853
1897
|
|
|
1854
1898
|
// src/features/analysis/scm/shared/src/fixDetailsData.ts
|
|
1855
1899
|
var fixDetailsData = {
|
|
@@ -2094,7 +2138,13 @@ var fixDetailsData = {
|
|
|
2094
2138
|
["DUPLICATED_STRINGS" /* DuplicatedStrings */]: void 0,
|
|
2095
2139
|
["INSECURE_UUID_VERSION" /* InsecureUuidVersion */]: void 0,
|
|
2096
2140
|
["GH_ACTIONS_SHELL_INJECTION" /* GhActionsShellInjection */]: void 0,
|
|
2097
|
-
["
|
|
2141
|
+
["MODIFIED_DEFAULT_PARAM" /* ModifiedDefaultParam */]: void 0,
|
|
2142
|
+
["UNSAFE_WEB_THREAD" /* UnsafeWebThread */]: void 0,
|
|
2143
|
+
["NO_VAR" /* NoVar */]: void 0,
|
|
2144
|
+
["INSECURE_TMP_FILE" /* InsecureTmpFile */]: void 0,
|
|
2145
|
+
["SYSTEM_EXIT_SHOULD_RERAISE" /* SystemExitShouldReraise */]: void 0,
|
|
2146
|
+
["NO_RETURN_IN_FINALLY" /* NoReturnInFinally */]: void 0,
|
|
2147
|
+
["AVOID_IDENTITY_COMPARISON_CACHED_TYPES" /* AvoidIdentityComparisonCachedTypes */]: void 0
|
|
2098
2148
|
};
|
|
2099
2149
|
|
|
2100
2150
|
// src/features/analysis/scm/shared/src/commitDescriptionMarkup.ts
|
|
@@ -2125,7 +2175,7 @@ var getCommitDescription = ({
|
|
|
2125
2175
|
)}**.
|
|
2126
2176
|
|
|
2127
2177
|
`;
|
|
2128
|
-
const parseIssueTypeRes =
|
|
2178
|
+
const parseIssueTypeRes = z10.nativeEnum(IssueType_Enum).safeParse(issueType);
|
|
2129
2179
|
if (issueType && parseIssueTypeRes.success) {
|
|
2130
2180
|
if (irrelevantIssueWithTags?.[0]?.tag) {
|
|
2131
2181
|
description += `
|
|
@@ -2162,22 +2212,24 @@ ${guidances.map(({ guidance }) => `## Additional actions required
|
|
|
2162
2212
|
var getCommitIssueDescription = ({
|
|
2163
2213
|
vendor,
|
|
2164
2214
|
issueType,
|
|
2165
|
-
irrelevantIssueWithTags
|
|
2215
|
+
irrelevantIssueWithTags,
|
|
2216
|
+
fpDescription
|
|
2166
2217
|
}) => {
|
|
2167
2218
|
const issueTypeString = getIssueTypeFriendlyString(issueType);
|
|
2168
2219
|
let description = `The following issues reported by ${capitalizeFirstLetter(vendor)} on this PR were found to be irrelevant to your project:
|
|
2169
2220
|
`;
|
|
2170
|
-
const parseIssueTypeRes =
|
|
2221
|
+
const parseIssueTypeRes = z10.nativeEnum(IssueType_Enum).safeParse(issueType);
|
|
2171
2222
|
if (issueType && parseIssueTypeRes.success) {
|
|
2172
2223
|
if (irrelevantIssueWithTags?.[0]?.tag) {
|
|
2173
|
-
description
|
|
2224
|
+
description = `
|
|
2174
2225
|
> [!tip]
|
|
2226
|
+
> The following issues reported by ${capitalizeFirstLetter(vendor)} on this PR were found to be irrelevant to your project:
|
|
2175
2227
|
> ${issueTypeString} - ${lowercaseFirstLetter(getTagTooltip(irrelevantIssueWithTags[0].tag))}.
|
|
2176
2228
|
> Mobb recommends to ignore this issue, however fix is available if you think differently.
|
|
2177
2229
|
|
|
2178
2230
|
|
|
2179
2231
|
## Justification
|
|
2180
|
-
${issueDescription[irrelevantIssueWithTags[0].tag]}
|
|
2232
|
+
${fpDescription ?? issueDescription[irrelevantIssueWithTags[0].tag]}
|
|
2181
2233
|
`;
|
|
2182
2234
|
}
|
|
2183
2235
|
const staticData = fixDetailsData[parseIssueTypeRes.data];
|
|
@@ -2191,10 +2243,10 @@ ${staticData.issueDescription}
|
|
|
2191
2243
|
};
|
|
2192
2244
|
|
|
2193
2245
|
// src/features/analysis/scm/shared/src/guidances.ts
|
|
2194
|
-
import { z as
|
|
2246
|
+
import { z as z13 } from "zod";
|
|
2195
2247
|
|
|
2196
2248
|
// src/features/analysis/scm/shared/src/storedFixData/index.ts
|
|
2197
|
-
import { z as
|
|
2249
|
+
import { z as z11 } from "zod";
|
|
2198
2250
|
|
|
2199
2251
|
// src/features/analysis/scm/shared/src/storedFixData/passwordInComment.ts
|
|
2200
2252
|
var passwordInComment = {
|
|
@@ -2370,8 +2422,8 @@ var vulnerabilities8 = {
|
|
|
2370
2422
|
var xml_default = vulnerabilities8;
|
|
2371
2423
|
|
|
2372
2424
|
// src/features/analysis/scm/shared/src/storedFixData/index.ts
|
|
2373
|
-
var StoredFixDataItemZ =
|
|
2374
|
-
guidance:
|
|
2425
|
+
var StoredFixDataItemZ = z11.object({
|
|
2426
|
+
guidance: z11.function().returns(z11.string())
|
|
2375
2427
|
});
|
|
2376
2428
|
var languages = {
|
|
2377
2429
|
["Java" /* Java */]: java_default,
|
|
@@ -2385,7 +2437,7 @@ var languages = {
|
|
|
2385
2437
|
};
|
|
2386
2438
|
|
|
2387
2439
|
// src/features/analysis/scm/shared/src/storedQuestionData/index.ts
|
|
2388
|
-
import { z as
|
|
2440
|
+
import { z as z12 } from "zod";
|
|
2389
2441
|
|
|
2390
2442
|
// src/features/analysis/scm/shared/src/storedQuestionData/csharp/httpOnlyCookie.ts
|
|
2391
2443
|
var httpOnlyCookie = {
|
|
@@ -3584,10 +3636,10 @@ var vulnerabilities14 = {
|
|
|
3584
3636
|
var xml_default2 = vulnerabilities14;
|
|
3585
3637
|
|
|
3586
3638
|
// src/features/analysis/scm/shared/src/storedQuestionData/index.ts
|
|
3587
|
-
var StoredQuestionDataItemZ =
|
|
3588
|
-
content:
|
|
3589
|
-
description:
|
|
3590
|
-
guidance:
|
|
3639
|
+
var StoredQuestionDataItemZ = z12.object({
|
|
3640
|
+
content: z12.function().args(z12.any()).returns(z12.string()),
|
|
3641
|
+
description: z12.function().args(z12.any()).returns(z12.string()),
|
|
3642
|
+
guidance: z12.function().args(z12.any()).returns(z12.string())
|
|
3591
3643
|
});
|
|
3592
3644
|
var languages2 = {
|
|
3593
3645
|
["Java" /* Java */]: java_default2,
|
|
@@ -3682,9 +3734,9 @@ function getFixGuidances({
|
|
|
3682
3734
|
const fixGuidance = storeFixResult.success ? [storeFixResult.data.guidance({ questions, ...extraContext })] : [];
|
|
3683
3735
|
return libGuidances.concat(fixGuidance).filter((guidance) => !!guidance);
|
|
3684
3736
|
}
|
|
3685
|
-
var IssueTypeAndLanguageZ =
|
|
3686
|
-
issueType:
|
|
3687
|
-
issueLanguage:
|
|
3737
|
+
var IssueTypeAndLanguageZ = z13.object({
|
|
3738
|
+
issueType: z13.nativeEnum(IssueType_Enum),
|
|
3739
|
+
issueLanguage: z13.nativeEnum(IssueLanguage_Enum)
|
|
3688
3740
|
});
|
|
3689
3741
|
function getGuidances(args) {
|
|
3690
3742
|
const safeIssueTypeAndLanguage = IssueTypeAndLanguageZ.safeParse({
|
|
@@ -3722,7 +3774,7 @@ function getGuidances(args) {
|
|
|
3722
3774
|
}
|
|
3723
3775
|
|
|
3724
3776
|
// src/features/analysis/scm/shared/src/urlParser/urlParser.ts
|
|
3725
|
-
import { z as
|
|
3777
|
+
import { z as z14 } from "zod";
|
|
3726
3778
|
var ADO_PREFIX_PATH = "tfs";
|
|
3727
3779
|
var NAME_REGEX = /[a-z0-9\-_.+]+/i;
|
|
3728
3780
|
function detectAdoUrl(args) {
|
|
@@ -3739,7 +3791,7 @@ function detectAdoUrl(args) {
|
|
|
3739
3791
|
scmType: "Ado" /* Ado */,
|
|
3740
3792
|
organization,
|
|
3741
3793
|
// project has single repo - repoName === projectName
|
|
3742
|
-
projectName:
|
|
3794
|
+
projectName: z14.string().parse(projectName),
|
|
3743
3795
|
repoName: projectName,
|
|
3744
3796
|
prefixPath
|
|
3745
3797
|
};
|
|
@@ -3750,7 +3802,7 @@ function detectAdoUrl(args) {
|
|
|
3750
3802
|
return {
|
|
3751
3803
|
scmType: "Ado" /* Ado */,
|
|
3752
3804
|
organization,
|
|
3753
|
-
projectName:
|
|
3805
|
+
projectName: z14.string().parse(projectName),
|
|
3754
3806
|
repoName,
|
|
3755
3807
|
prefixPath
|
|
3756
3808
|
};
|
|
@@ -3764,7 +3816,7 @@ function detectAdoUrl(args) {
|
|
|
3764
3816
|
scmType: "Ado" /* Ado */,
|
|
3765
3817
|
organization,
|
|
3766
3818
|
// project has only one repo - repoName === projectName
|
|
3767
|
-
projectName:
|
|
3819
|
+
projectName: z14.string().parse(repoName),
|
|
3768
3820
|
repoName,
|
|
3769
3821
|
prefixPath
|
|
3770
3822
|
};
|
|
@@ -3774,7 +3826,7 @@ function detectAdoUrl(args) {
|
|
|
3774
3826
|
return {
|
|
3775
3827
|
scmType: "Ado" /* Ado */,
|
|
3776
3828
|
organization,
|
|
3777
|
-
projectName:
|
|
3829
|
+
projectName: z14.string().parse(projectName),
|
|
3778
3830
|
repoName,
|
|
3779
3831
|
prefixPath
|
|
3780
3832
|
};
|
|
@@ -3900,7 +3952,11 @@ function getIssueUrl({
|
|
|
3900
3952
|
return `${appBaseUrl}/organization/${organizationId}/project/${projectId}/report/${analysisId}/issue/${issueId}`;
|
|
3901
3953
|
}
|
|
3902
3954
|
|
|
3955
|
+
// src/features/analysis/scm/utils/index.ts
|
|
3956
|
+
import { z as z16 } from "zod";
|
|
3957
|
+
|
|
3903
3958
|
// src/features/analysis/scm/types.ts
|
|
3959
|
+
import { z as z15 } from "zod";
|
|
3904
3960
|
var ReferenceType = /* @__PURE__ */ ((ReferenceType2) => {
|
|
3905
3961
|
ReferenceType2["BRANCH"] = "BRANCH";
|
|
3906
3962
|
ReferenceType2["COMMIT"] = "COMMIT";
|
|
@@ -3932,14 +3988,13 @@ var scmTypeToScmLibScmType = {
|
|
|
3932
3988
|
["Ado" /* Ado */]: "ADO" /* ADO */,
|
|
3933
3989
|
["Bitbucket" /* Bitbucket */]: "BITBUCKET" /* BITBUCKET */
|
|
3934
3990
|
};
|
|
3935
|
-
var GetRefererenceResultZ =
|
|
3936
|
-
date:
|
|
3937
|
-
sha:
|
|
3938
|
-
type:
|
|
3991
|
+
var GetRefererenceResultZ = z15.object({
|
|
3992
|
+
date: z15.date().optional(),
|
|
3993
|
+
sha: z15.string(),
|
|
3994
|
+
type: z15.nativeEnum(ReferenceType)
|
|
3939
3995
|
});
|
|
3940
3996
|
|
|
3941
3997
|
// src/features/analysis/scm/utils/index.ts
|
|
3942
|
-
import { z as z15 } from "zod";
|
|
3943
3998
|
function getFixUrlWithRedirect(params) {
|
|
3944
3999
|
const {
|
|
3945
4000
|
fixId,
|
|
@@ -4050,7 +4105,7 @@ function shouldValidateUrl(repoUrl) {
|
|
|
4050
4105
|
return repoUrl && isUrlHasPath(repoUrl);
|
|
4051
4106
|
}
|
|
4052
4107
|
function isBrokerUrl(url) {
|
|
4053
|
-
return
|
|
4108
|
+
return z16.string().uuid().safeParse(new URL(url).host).success;
|
|
4054
4109
|
}
|
|
4055
4110
|
function buildAuthorizedRepoUrl(args) {
|
|
4056
4111
|
const { url, username, password } = args;
|
|
@@ -4086,7 +4141,7 @@ function getCloudScmLibTypeFromUrl(url) {
|
|
|
4086
4141
|
return void 0;
|
|
4087
4142
|
}
|
|
4088
4143
|
function getScmLibTypeFromScmType(scmType) {
|
|
4089
|
-
const parsedScmType =
|
|
4144
|
+
const parsedScmType = z16.nativeEnum(ScmType).parse(scmType);
|
|
4090
4145
|
return scmTypeToScmLibScmType[parsedScmType];
|
|
4091
4146
|
}
|
|
4092
4147
|
function getScmConfig({
|
|
@@ -4152,162 +4207,6 @@ function getScmConfig({
|
|
|
4152
4207
|
};
|
|
4153
4208
|
}
|
|
4154
4209
|
|
|
4155
|
-
// src/features/analysis/scm/scm.ts
|
|
4156
|
-
var SCMLib = class {
|
|
4157
|
-
constructor(url, accessToken, scmOrg) {
|
|
4158
|
-
__publicField(this, "url");
|
|
4159
|
-
__publicField(this, "accessToken");
|
|
4160
|
-
__publicField(this, "scmOrg");
|
|
4161
|
-
this.accessToken = accessToken;
|
|
4162
|
-
this.url = url;
|
|
4163
|
-
this.scmOrg = scmOrg;
|
|
4164
|
-
}
|
|
4165
|
-
async getUrlWithCredentials() {
|
|
4166
|
-
if (!this.url) {
|
|
4167
|
-
console.error("no url for getUrlWithCredentials()");
|
|
4168
|
-
throw new Error("no url");
|
|
4169
|
-
}
|
|
4170
|
-
const trimmedUrl = this.url.trim().replace(/\/$/, "");
|
|
4171
|
-
const accessToken = this.getAccessToken();
|
|
4172
|
-
if (!accessToken) {
|
|
4173
|
-
return trimmedUrl;
|
|
4174
|
-
}
|
|
4175
|
-
if (this.scmLibType === "ADO" /* ADO */) {
|
|
4176
|
-
const { host, protocol, pathname } = new URL(trimmedUrl);
|
|
4177
|
-
return `${protocol}//${accessToken}@${host}${pathname}`;
|
|
4178
|
-
}
|
|
4179
|
-
const finalUrl = this.scmLibType === "GITLAB" /* GITLAB */ ? `${trimmedUrl}.git` : trimmedUrl;
|
|
4180
|
-
const username = await this._getUsernameForAuthUrl();
|
|
4181
|
-
return buildAuthorizedRepoUrl({
|
|
4182
|
-
url: finalUrl,
|
|
4183
|
-
username,
|
|
4184
|
-
password: accessToken
|
|
4185
|
-
});
|
|
4186
|
-
}
|
|
4187
|
-
getAccessToken() {
|
|
4188
|
-
return this.accessToken || "";
|
|
4189
|
-
}
|
|
4190
|
-
getUrl() {
|
|
4191
|
-
return this.url;
|
|
4192
|
-
}
|
|
4193
|
-
getName() {
|
|
4194
|
-
if (!this.url) {
|
|
4195
|
-
return "";
|
|
4196
|
-
}
|
|
4197
|
-
return this.url.split("/").at(-1) || "";
|
|
4198
|
-
}
|
|
4199
|
-
_validateAccessToken() {
|
|
4200
|
-
if (!this.accessToken) {
|
|
4201
|
-
console.error("no access token");
|
|
4202
|
-
throw new Error("no access token");
|
|
4203
|
-
}
|
|
4204
|
-
}
|
|
4205
|
-
static async getIsValidBranchName(branchName) {
|
|
4206
|
-
return isValidBranchName(branchName);
|
|
4207
|
-
}
|
|
4208
|
-
_validateAccessTokenAndUrl() {
|
|
4209
|
-
this._validateAccessToken();
|
|
4210
|
-
this._validateUrl();
|
|
4211
|
-
}
|
|
4212
|
-
_validateUrl() {
|
|
4213
|
-
if (!this.url) {
|
|
4214
|
-
console.error("no url");
|
|
4215
|
-
throw new InvalidRepoUrlError("no url");
|
|
4216
|
-
}
|
|
4217
|
-
}
|
|
4218
|
-
};
|
|
4219
|
-
|
|
4220
|
-
// src/features/analysis/scm/github/github.ts
|
|
4221
|
-
import { RequestError } from "@octokit/request-error";
|
|
4222
|
-
|
|
4223
|
-
// src/features/analysis/scm/constants.ts
|
|
4224
|
-
var MOBB_ICON_IMG = "https://app.mobb.ai/gh-action/Logo_Rounded_Icon.svg";
|
|
4225
|
-
var MAX_BRANCHES_FETCH = 1e3;
|
|
4226
|
-
|
|
4227
|
-
// src/features/analysis/scm/github/consts.ts
|
|
4228
|
-
var POST_COMMENT_PATH = "POST /repos/{owner}/{repo}/pulls/{pull_number}/comments";
|
|
4229
|
-
var DELETE_COMMENT_PATH = "DELETE /repos/{owner}/{repo}/pulls/comments/{comment_id}";
|
|
4230
|
-
var UPDATE_COMMENT_PATH = "PATCH /repos/{owner}/{repo}/pulls/comments/{comment_id}";
|
|
4231
|
-
var GET_PR_COMMENTS_PATH = "GET /repos/{owner}/{repo}/pulls/{pull_number}/comments";
|
|
4232
|
-
var GET_PR_COMMENT_PATH = "GET /repos/{owner}/{repo}/pulls/comments/{comment_id}";
|
|
4233
|
-
var REPLY_TO_CODE_REVIEW_COMMENT_PATH = "POST /repos/{owner}/{repo}/pulls/{pull_number}/comments/{comment_id}/replies";
|
|
4234
|
-
var GET_PR = "GET /repos/{owner}/{repo}/pulls/{pull_number}";
|
|
4235
|
-
var POST_GENERAL_PR_COMMENT = "POST /repos/{owner}/{repo}/issues/{issue_number}/comments";
|
|
4236
|
-
var GET_GENERAL_PR_COMMENTS = "GET /repos/{owner}/{repo}/issues/{issue_number}/comments";
|
|
4237
|
-
var DELETE_GENERAL_PR_COMMENT = "DELETE /repos/{owner}/{repo}/issues/comments/{comment_id}";
|
|
4238
|
-
var CREATE_OR_UPDATE_A_REPOSITORY_SECRET = "PUT /repos/{owner}/{repo}/actions/secrets/{secret_name}";
|
|
4239
|
-
var GET_A_REPOSITORY_PUBLIC_KEY = "GET /repos/{owner}/{repo}/actions/secrets/public-key";
|
|
4240
|
-
var GET_USER = "GET /user";
|
|
4241
|
-
var GET_USER_REPOS = "GET /user/repos";
|
|
4242
|
-
var GET_REPO_BRANCHES = "GET /repos/{owner}/{repo}/branches";
|
|
4243
|
-
var GET_BLAME_DOCUMENT = `
|
|
4244
|
-
query GetBlame(
|
|
4245
|
-
$owner: String!
|
|
4246
|
-
$repo: String!
|
|
4247
|
-
$ref: String!
|
|
4248
|
-
$path: String!
|
|
4249
|
-
) {
|
|
4250
|
-
repository(name: $repo, owner: $owner) {
|
|
4251
|
-
# branch name
|
|
4252
|
-
object(expression: $ref) {
|
|
4253
|
-
# cast Target to a Commit
|
|
4254
|
-
... on Commit {
|
|
4255
|
-
# full repo-relative path to blame file
|
|
4256
|
-
blame(path: $path) {
|
|
4257
|
-
ranges {
|
|
4258
|
-
commit {
|
|
4259
|
-
author {
|
|
4260
|
-
user {
|
|
4261
|
-
name
|
|
4262
|
-
login
|
|
4263
|
-
}
|
|
4264
|
-
}
|
|
4265
|
-
authoredDate
|
|
4266
|
-
}
|
|
4267
|
-
startingLine
|
|
4268
|
-
endingLine
|
|
4269
|
-
age
|
|
4270
|
-
}
|
|
4271
|
-
}
|
|
4272
|
-
}
|
|
4273
|
-
|
|
4274
|
-
}
|
|
4275
|
-
}
|
|
4276
|
-
}
|
|
4277
|
-
`;
|
|
4278
|
-
|
|
4279
|
-
// src/features/analysis/scm/github/utils/encrypt_secret.ts
|
|
4280
|
-
import sodium from "libsodium-wrappers";
|
|
4281
|
-
async function encryptSecret(secret, key) {
|
|
4282
|
-
await sodium.ready;
|
|
4283
|
-
const binkey = sodium.from_base64(key, sodium.base64_variants.ORIGINAL);
|
|
4284
|
-
const binsec = sodium.from_string(secret);
|
|
4285
|
-
const encBytes = sodium.crypto_box_seal(binsec, binkey);
|
|
4286
|
-
return sodium.to_base64(encBytes, sodium.base64_variants.ORIGINAL);
|
|
4287
|
-
}
|
|
4288
|
-
|
|
4289
|
-
// src/features/analysis/scm/github/utils/utils.ts
|
|
4290
|
-
import { Octokit } from "octokit";
|
|
4291
|
-
import { fetch as fetch2, ProxyAgent as ProxyAgent2 } from "undici";
|
|
4292
|
-
|
|
4293
|
-
// src/features/analysis/scm/ado/constants.ts
|
|
4294
|
-
var DEFUALT_ADO_ORIGIN = scmCloudUrl.Ado;
|
|
4295
|
-
|
|
4296
|
-
// src/features/analysis/scm/ado/utils.ts
|
|
4297
|
-
import querystring from "node:querystring";
|
|
4298
|
-
import * as api from "azure-devops-node-api";
|
|
4299
|
-
import Debug2 from "debug";
|
|
4300
|
-
import { z as z18 } from "zod";
|
|
4301
|
-
|
|
4302
|
-
// src/features/analysis/scm/env.ts
|
|
4303
|
-
import { z as z16 } from "zod";
|
|
4304
|
-
var EnvVariablesZod = z16.object({
|
|
4305
|
-
GITLAB_API_TOKEN: z16.string().optional(),
|
|
4306
|
-
GITHUB_API_TOKEN: z16.string().optional(),
|
|
4307
|
-
GIT_PROXY_HOST: z16.string()
|
|
4308
|
-
});
|
|
4309
|
-
var { GITLAB_API_TOKEN, GITHUB_API_TOKEN, GIT_PROXY_HOST } = EnvVariablesZod.parse(process.env);
|
|
4310
|
-
|
|
4311
4210
|
// src/features/analysis/scm/ado/validation.ts
|
|
4312
4211
|
import { z as z17 } from "zod";
|
|
4313
4212
|
var ValidPullRequestStatusZ = z17.union([
|
|
@@ -4918,39 +4817,121 @@ async function getAdoRepoList({
|
|
|
4918
4817
|
|
|
4919
4818
|
// src/features/analysis/scm/ado/AdoSCMLib.ts
|
|
4920
4819
|
import { setTimeout as setTimeout2 } from "node:timers/promises";
|
|
4921
|
-
|
|
4922
|
-
|
|
4923
|
-
|
|
4924
|
-
|
|
4925
|
-
|
|
4926
|
-
|
|
4927
|
-
|
|
4928
|
-
|
|
4929
|
-
|
|
4930
|
-
var AdoSCMLib = class extends SCMLib {
|
|
4931
|
-
constructor(url, accessToken, scmOrg) {
|
|
4932
|
-
super(url, accessToken, scmOrg);
|
|
4933
|
-
__publicField(this, "_adoSdkPromise");
|
|
4934
|
-
this._adoSdkPromise = initAdoSdk({ accessToken, url, scmOrg });
|
|
4935
|
-
}
|
|
4936
|
-
async getAdoSdk() {
|
|
4937
|
-
if (!this._adoSdkPromise) {
|
|
4938
|
-
console.error("ado sdk was not initialized");
|
|
4939
|
-
throw new InvalidAccessTokenError("ado sdk was not initialized");
|
|
4820
|
+
|
|
4821
|
+
// src/features/analysis/scm/scmSubmit/index.ts
|
|
4822
|
+
import { simpleGit } from "simple-git";
|
|
4823
|
+
var isValidBranchName = async (branchName) => {
|
|
4824
|
+
const git = simpleGit();
|
|
4825
|
+
try {
|
|
4826
|
+
const res = await git.raw(["check-ref-format", "--branch", branchName]);
|
|
4827
|
+
if (res) {
|
|
4828
|
+
return true;
|
|
4940
4829
|
}
|
|
4941
|
-
return
|
|
4830
|
+
return false;
|
|
4831
|
+
} catch (e) {
|
|
4832
|
+
return false;
|
|
4942
4833
|
}
|
|
4943
|
-
|
|
4944
|
-
|
|
4945
|
-
|
|
4946
|
-
|
|
4947
|
-
|
|
4948
|
-
|
|
4949
|
-
|
|
4950
|
-
|
|
4951
|
-
|
|
4952
|
-
|
|
4953
|
-
|
|
4834
|
+
};
|
|
4835
|
+
|
|
4836
|
+
// src/features/analysis/scm/scm.ts
|
|
4837
|
+
var SCMLib = class {
|
|
4838
|
+
constructor(url, accessToken, scmOrg) {
|
|
4839
|
+
__publicField(this, "url");
|
|
4840
|
+
__publicField(this, "accessToken");
|
|
4841
|
+
__publicField(this, "scmOrg");
|
|
4842
|
+
this.accessToken = accessToken;
|
|
4843
|
+
this.url = url;
|
|
4844
|
+
this.scmOrg = scmOrg;
|
|
4845
|
+
}
|
|
4846
|
+
async getUrlWithCredentials() {
|
|
4847
|
+
if (!this.url) {
|
|
4848
|
+
console.error("no url for getUrlWithCredentials()");
|
|
4849
|
+
throw new Error("no url");
|
|
4850
|
+
}
|
|
4851
|
+
const trimmedUrl = this.url.trim().replace(/\/$/, "");
|
|
4852
|
+
const accessToken = this.getAccessToken();
|
|
4853
|
+
if (!accessToken) {
|
|
4854
|
+
return trimmedUrl;
|
|
4855
|
+
}
|
|
4856
|
+
if (this.scmLibType === "ADO" /* ADO */) {
|
|
4857
|
+
const { host, protocol, pathname } = new URL(trimmedUrl);
|
|
4858
|
+
return `${protocol}//${accessToken}@${host}${pathname}`;
|
|
4859
|
+
}
|
|
4860
|
+
const finalUrl = this.scmLibType === "GITLAB" /* GITLAB */ ? `${trimmedUrl}.git` : trimmedUrl;
|
|
4861
|
+
const username = await this._getUsernameForAuthUrl();
|
|
4862
|
+
return buildAuthorizedRepoUrl({
|
|
4863
|
+
url: finalUrl,
|
|
4864
|
+
username,
|
|
4865
|
+
password: accessToken
|
|
4866
|
+
});
|
|
4867
|
+
}
|
|
4868
|
+
getAccessToken() {
|
|
4869
|
+
return this.accessToken || "";
|
|
4870
|
+
}
|
|
4871
|
+
getUrl() {
|
|
4872
|
+
return this.url;
|
|
4873
|
+
}
|
|
4874
|
+
getName() {
|
|
4875
|
+
if (!this.url) {
|
|
4876
|
+
return "";
|
|
4877
|
+
}
|
|
4878
|
+
return this.url.split("/").at(-1) || "";
|
|
4879
|
+
}
|
|
4880
|
+
_validateAccessToken() {
|
|
4881
|
+
if (!this.accessToken) {
|
|
4882
|
+
console.error("no access token");
|
|
4883
|
+
throw new Error("no access token");
|
|
4884
|
+
}
|
|
4885
|
+
}
|
|
4886
|
+
static async getIsValidBranchName(branchName) {
|
|
4887
|
+
return isValidBranchName(branchName);
|
|
4888
|
+
}
|
|
4889
|
+
_validateAccessTokenAndUrl() {
|
|
4890
|
+
this._validateAccessToken();
|
|
4891
|
+
this._validateUrl();
|
|
4892
|
+
}
|
|
4893
|
+
_validateUrl() {
|
|
4894
|
+
if (!this.url) {
|
|
4895
|
+
console.error("no url");
|
|
4896
|
+
throw new InvalidRepoUrlError("no url");
|
|
4897
|
+
}
|
|
4898
|
+
}
|
|
4899
|
+
};
|
|
4900
|
+
|
|
4901
|
+
// src/features/analysis/scm/ado/AdoSCMLib.ts
|
|
4902
|
+
async function initAdoSdk(params) {
|
|
4903
|
+
const { url, accessToken, scmOrg } = params;
|
|
4904
|
+
const adoClientParams = await getAdoClientParams({
|
|
4905
|
+
tokenOrg: scmOrg,
|
|
4906
|
+
accessToken,
|
|
4907
|
+
url
|
|
4908
|
+
});
|
|
4909
|
+
return getAdoSdk(adoClientParams);
|
|
4910
|
+
}
|
|
4911
|
+
var AdoSCMLib = class extends SCMLib {
|
|
4912
|
+
constructor(url, accessToken, scmOrg) {
|
|
4913
|
+
super(url, accessToken, scmOrg);
|
|
4914
|
+
__publicField(this, "_adoSdkPromise");
|
|
4915
|
+
this._adoSdkPromise = initAdoSdk({ accessToken, url, scmOrg });
|
|
4916
|
+
}
|
|
4917
|
+
async getAdoSdk() {
|
|
4918
|
+
if (!this._adoSdkPromise) {
|
|
4919
|
+
console.error("ado sdk was not initialized");
|
|
4920
|
+
throw new InvalidAccessTokenError("ado sdk was not initialized");
|
|
4921
|
+
}
|
|
4922
|
+
return this._adoSdkPromise;
|
|
4923
|
+
}
|
|
4924
|
+
async createSubmitRequest(params) {
|
|
4925
|
+
this._validateAccessTokenAndUrl();
|
|
4926
|
+
for (let i = 0; i < 5; i++) {
|
|
4927
|
+
try {
|
|
4928
|
+
const { targetBranchName, sourceBranchName, title, body } = params;
|
|
4929
|
+
const adoSdk = await this.getAdoSdk();
|
|
4930
|
+
const pullRequestId = await adoSdk.createAdoPullRequest({
|
|
4931
|
+
title,
|
|
4932
|
+
body,
|
|
4933
|
+
targetBranchName,
|
|
4934
|
+
sourceBranchName,
|
|
4954
4935
|
repoUrl: this.url
|
|
4955
4936
|
});
|
|
4956
4937
|
return String(pullRequestId);
|
|
@@ -5662,1408 +5643,1482 @@ var BitbucketSCMLib = class extends SCMLib {
|
|
|
5662
5643
|
}
|
|
5663
5644
|
};
|
|
5664
5645
|
|
|
5665
|
-
// src/features/analysis/scm/
|
|
5666
|
-
|
|
5667
|
-
|
|
5668
|
-
createRequesterFn
|
|
5669
|
-
} from "@gitbeaker/requester-utils";
|
|
5670
|
-
import {
|
|
5671
|
-
AccessLevel,
|
|
5672
|
-
Gitlab
|
|
5673
|
-
} from "@gitbeaker/rest";
|
|
5674
|
-
import Debug4 from "debug";
|
|
5675
|
-
import {
|
|
5676
|
-
fetch as undiciFetch,
|
|
5677
|
-
ProxyAgent
|
|
5678
|
-
} from "undici";
|
|
5646
|
+
// src/features/analysis/scm/constants.ts
|
|
5647
|
+
var MOBB_ICON_IMG = "https://app.mobb.ai/gh-action/Logo_Rounded_Icon.svg";
|
|
5648
|
+
var MAX_BRANCHES_FETCH = 1e3;
|
|
5679
5649
|
|
|
5680
|
-
// src/features/analysis/scm/
|
|
5650
|
+
// src/features/analysis/scm/github/GithubSCMLib.ts
|
|
5681
5651
|
import { z as z22 } from "zod";
|
|
5682
|
-
var GitlabAuthResultZ = z22.object({
|
|
5683
|
-
access_token: z22.string(),
|
|
5684
|
-
token_type: z22.string(),
|
|
5685
|
-
refresh_token: z22.string()
|
|
5686
|
-
});
|
|
5687
5652
|
|
|
5688
|
-
// src/features/analysis/scm/
|
|
5689
|
-
|
|
5690
|
-
|
|
5691
|
-
|
|
5653
|
+
// src/features/analysis/scm/github/github.ts
|
|
5654
|
+
import { RequestError } from "@octokit/request-error";
|
|
5655
|
+
|
|
5656
|
+
// src/features/analysis/scm/github/consts.ts
|
|
5657
|
+
var POST_COMMENT_PATH = "POST /repos/{owner}/{repo}/pulls/{pull_number}/comments";
|
|
5658
|
+
var DELETE_COMMENT_PATH = "DELETE /repos/{owner}/{repo}/pulls/comments/{comment_id}";
|
|
5659
|
+
var UPDATE_COMMENT_PATH = "PATCH /repos/{owner}/{repo}/pulls/comments/{comment_id}";
|
|
5660
|
+
var GET_PR_COMMENTS_PATH = "GET /repos/{owner}/{repo}/pulls/{pull_number}/comments";
|
|
5661
|
+
var GET_PR_COMMENT_PATH = "GET /repos/{owner}/{repo}/pulls/comments/{comment_id}";
|
|
5662
|
+
var REPLY_TO_CODE_REVIEW_COMMENT_PATH = "POST /repos/{owner}/{repo}/pulls/{pull_number}/comments/{comment_id}/replies";
|
|
5663
|
+
var GET_PR = "GET /repos/{owner}/{repo}/pulls/{pull_number}";
|
|
5664
|
+
var POST_GENERAL_PR_COMMENT = "POST /repos/{owner}/{repo}/issues/{issue_number}/comments";
|
|
5665
|
+
var GET_GENERAL_PR_COMMENTS = "GET /repos/{owner}/{repo}/issues/{issue_number}/comments";
|
|
5666
|
+
var DELETE_GENERAL_PR_COMMENT = "DELETE /repos/{owner}/{repo}/issues/comments/{comment_id}";
|
|
5667
|
+
var CREATE_OR_UPDATE_A_REPOSITORY_SECRET = "PUT /repos/{owner}/{repo}/actions/secrets/{secret_name}";
|
|
5668
|
+
var GET_A_REPOSITORY_PUBLIC_KEY = "GET /repos/{owner}/{repo}/actions/secrets/public-key";
|
|
5669
|
+
var GET_USER = "GET /user";
|
|
5670
|
+
var GET_USER_REPOS = "GET /user/repos";
|
|
5671
|
+
var GET_REPO_BRANCHES = "GET /repos/{owner}/{repo}/branches";
|
|
5672
|
+
var GET_BLAME_DOCUMENT = `
|
|
5673
|
+
query GetBlame(
|
|
5674
|
+
$owner: String!
|
|
5675
|
+
$repo: String!
|
|
5676
|
+
$ref: String!
|
|
5677
|
+
$path: String!
|
|
5678
|
+
) {
|
|
5679
|
+
repository(name: $repo, owner: $owner) {
|
|
5680
|
+
# branch name
|
|
5681
|
+
object(expression: $ref) {
|
|
5682
|
+
# cast Target to a Commit
|
|
5683
|
+
... on Commit {
|
|
5684
|
+
# full repo-relative path to blame file
|
|
5685
|
+
blame(path: $path) {
|
|
5686
|
+
ranges {
|
|
5687
|
+
commit {
|
|
5688
|
+
author {
|
|
5689
|
+
user {
|
|
5690
|
+
name
|
|
5691
|
+
login
|
|
5692
|
+
}
|
|
5693
|
+
}
|
|
5694
|
+
authoredDate
|
|
5695
|
+
}
|
|
5696
|
+
startingLine
|
|
5697
|
+
endingLine
|
|
5698
|
+
age
|
|
5699
|
+
}
|
|
5700
|
+
}
|
|
5701
|
+
}
|
|
5702
|
+
|
|
5703
|
+
}
|
|
5704
|
+
}
|
|
5705
|
+
}
|
|
5706
|
+
`;
|
|
5707
|
+
|
|
5708
|
+
// src/features/analysis/scm/github/utils/encrypt_secret.ts
|
|
5709
|
+
import sodium from "libsodium-wrappers";
|
|
5710
|
+
async function encryptSecret(secret, key) {
|
|
5711
|
+
await sodium.ready;
|
|
5712
|
+
const binkey = sodium.from_base64(key, sodium.base64_variants.ORIGINAL);
|
|
5713
|
+
const binsec = sodium.from_string(secret);
|
|
5714
|
+
const encBytes = sodium.crypto_box_seal(binsec, binkey);
|
|
5715
|
+
return sodium.to_base64(encBytes, sodium.base64_variants.ORIGINAL);
|
|
5692
5716
|
}
|
|
5693
|
-
|
|
5694
|
-
|
|
5695
|
-
|
|
5717
|
+
|
|
5718
|
+
// src/features/analysis/scm/github/utils/utils.ts
|
|
5719
|
+
import { Octokit } from "octokit";
|
|
5720
|
+
import { fetch as fetch2, ProxyAgent } from "undici";
|
|
5721
|
+
function parseGithubOwnerAndRepo(gitHubUrl) {
|
|
5722
|
+
gitHubUrl = normalizeUrl(gitHubUrl);
|
|
5723
|
+
const parsingResult = parseScmURL(gitHubUrl, "GitHub" /* GitHub */);
|
|
5724
|
+
if (!parsingResult) {
|
|
5725
|
+
throw new InvalidUrlPatternError(`invalid github repo Url ${gitHubUrl}`);
|
|
5696
5726
|
}
|
|
5697
|
-
const
|
|
5698
|
-
|
|
5727
|
+
const { organization, repoName } = parsingResult;
|
|
5728
|
+
if (!organization || !repoName) {
|
|
5729
|
+
throw new InvalidUrlPatternError(`invalid github repo Url ${gitHubUrl}`);
|
|
5730
|
+
}
|
|
5731
|
+
return { owner: organization, repo: repoName };
|
|
5699
5732
|
}
|
|
5700
|
-
function
|
|
5701
|
-
|
|
5702
|
-
|
|
5703
|
-
|
|
5704
|
-
|
|
5705
|
-
|
|
5706
|
-
|
|
5707
|
-
|
|
5708
|
-
|
|
5709
|
-
|
|
5710
|
-
|
|
5711
|
-
|
|
5733
|
+
function isGithubOnPrem(url) {
|
|
5734
|
+
if (!url) {
|
|
5735
|
+
return false;
|
|
5736
|
+
}
|
|
5737
|
+
return !url.includes(scmCloudUrl.GitHub);
|
|
5738
|
+
}
|
|
5739
|
+
function getFetch(url) {
|
|
5740
|
+
if (url && isBrokerUrl(url)) {
|
|
5741
|
+
const dispatcher = new ProxyAgent({
|
|
5742
|
+
uri: GIT_PROXY_HOST,
|
|
5743
|
+
requestTls: {
|
|
5744
|
+
rejectUnauthorized: false
|
|
5745
|
+
}
|
|
5712
5746
|
});
|
|
5747
|
+
return (input, init) => {
|
|
5748
|
+
return fetch2(input, {
|
|
5749
|
+
...init,
|
|
5750
|
+
dispatcher
|
|
5751
|
+
});
|
|
5752
|
+
};
|
|
5713
5753
|
}
|
|
5714
|
-
return
|
|
5715
|
-
oauthToken: token,
|
|
5716
|
-
host,
|
|
5717
|
-
requesterFn: createRequesterFn(
|
|
5718
|
-
(_, reqo) => Promise.resolve(reqo),
|
|
5719
|
-
brokerRequestHandler
|
|
5720
|
-
)
|
|
5721
|
-
});
|
|
5754
|
+
return fetch2;
|
|
5722
5755
|
}
|
|
5723
|
-
|
|
5724
|
-
|
|
5725
|
-
|
|
5726
|
-
}
|
|
5727
|
-
|
|
5728
|
-
|
|
5729
|
-
|
|
5730
|
-
|
|
5731
|
-
|
|
5732
|
-
|
|
5733
|
-
|
|
5734
|
-
|
|
5756
|
+
function getRandomGithubCloudAnonToken() {
|
|
5757
|
+
if (!GITHUB_API_TOKEN || typeof GITHUB_API_TOKEN !== "string") {
|
|
5758
|
+
return void 0;
|
|
5759
|
+
}
|
|
5760
|
+
const tokens = GITHUB_API_TOKEN.split(",");
|
|
5761
|
+
return tokens[Math.floor(Math.random() * tokens.length)];
|
|
5762
|
+
}
|
|
5763
|
+
function getOctoKit(options) {
|
|
5764
|
+
const token = !options?.auth && !isGithubOnPrem(options?.url) ? getRandomGithubCloudAnonToken() : options?.auth;
|
|
5765
|
+
const baseUrl = options?.url && isGithubOnPrem(options.url) ? `${new URL(options.url).origin}/api/v3` : void 0;
|
|
5766
|
+
return new Octokit({
|
|
5767
|
+
...options,
|
|
5768
|
+
auth: token,
|
|
5769
|
+
baseUrl,
|
|
5770
|
+
//GITHUB_API_TOKEN is only defined in the backend and not when running Bugsy as CLI. We want to enable these debug logs in the backend
|
|
5771
|
+
//to debug the performance of these API calls.
|
|
5772
|
+
log: GITHUB_API_TOKEN ? console : void 0,
|
|
5773
|
+
request: {
|
|
5774
|
+
fetch: getFetch(baseUrl)
|
|
5775
|
+
},
|
|
5776
|
+
retry: {
|
|
5777
|
+
enabled: false
|
|
5778
|
+
},
|
|
5779
|
+
throttle: {
|
|
5780
|
+
enabled: false
|
|
5781
|
+
}
|
|
5782
|
+
});
|
|
5783
|
+
}
|
|
5784
|
+
function isGithubActionActionToken(token) {
|
|
5785
|
+
return token.startsWith("ghs_");
|
|
5786
|
+
}
|
|
5787
|
+
async function githubValidateParams(url, accessToken) {
|
|
5788
|
+
try {
|
|
5789
|
+
const oktoKit = getOctoKit({ auth: accessToken, url });
|
|
5790
|
+
if (accessToken && !isGithubActionActionToken(accessToken)) {
|
|
5791
|
+
await oktoKit.rest.users.getAuthenticated();
|
|
5792
|
+
}
|
|
5793
|
+
if (url && shouldValidateUrl(url)) {
|
|
5794
|
+
const { owner, repo } = parseGithubOwnerAndRepo(url);
|
|
5795
|
+
await oktoKit.request(GET_REPO_BRANCHES, {
|
|
5796
|
+
owner,
|
|
5797
|
+
repo,
|
|
5798
|
+
per_page: 1
|
|
5799
|
+
});
|
|
5735
5800
|
}
|
|
5736
5801
|
} catch (e) {
|
|
5802
|
+
console.log("could not init github scm", e);
|
|
5737
5803
|
const error = e;
|
|
5738
|
-
const code = error.
|
|
5739
|
-
|
|
5740
|
-
|
|
5741
|
-
throw new InvalidAccessTokenError(`invalid gitlab access token`);
|
|
5804
|
+
const code = error.status || error.statusCode || error.response?.status || error.response?.statusCode || error.response?.code;
|
|
5805
|
+
if (code === 401 || code === 403) {
|
|
5806
|
+
throw new InvalidAccessTokenError(`invalid github access token`);
|
|
5742
5807
|
}
|
|
5743
|
-
if (code === 404
|
|
5744
|
-
throw new InvalidRepoUrlError(`invalid
|
|
5808
|
+
if (code === 404) {
|
|
5809
|
+
throw new InvalidRepoUrlError(`invalid github repo Url ${url}`);
|
|
5745
5810
|
}
|
|
5746
|
-
console.log("
|
|
5811
|
+
console.log("githubValidateParams error", e);
|
|
5747
5812
|
throw new InvalidRepoUrlError(
|
|
5748
|
-
`cannot access
|
|
5813
|
+
`cannot access GH repo URL: ${url} with the provided access token`
|
|
5749
5814
|
);
|
|
5750
5815
|
}
|
|
5751
5816
|
}
|
|
5752
|
-
|
|
5753
|
-
|
|
5754
|
-
|
|
5755
|
-
|
|
5756
|
-
|
|
5757
|
-
async
|
|
5758
|
-
|
|
5759
|
-
|
|
5760
|
-
|
|
5761
|
-
|
|
5762
|
-
|
|
5763
|
-
|
|
5764
|
-
|
|
5765
|
-
|
|
5766
|
-
|
|
5767
|
-
|
|
5768
|
-
|
|
5769
|
-
|
|
5770
|
-
|
|
5771
|
-
|
|
5772
|
-
|
|
5773
|
-
|
|
5774
|
-
|
|
5775
|
-
|
|
5776
|
-
|
|
5777
|
-
|
|
5778
|
-
|
|
5779
|
-
|
|
5780
|
-
|
|
5781
|
-
|
|
5782
|
-
};
|
|
5783
|
-
|
|
5784
|
-
|
|
5785
|
-
|
|
5786
|
-
|
|
5787
|
-
|
|
5788
|
-
|
|
5789
|
-
|
|
5790
|
-
|
|
5791
|
-
|
|
5792
|
-
|
|
5793
|
-
|
|
5794
|
-
|
|
5795
|
-
|
|
5796
|
-
|
|
5797
|
-
|
|
5798
|
-
|
|
5799
|
-
|
|
5800
|
-
|
|
5801
|
-
|
|
5802
|
-
|
|
5803
|
-
|
|
5804
|
-
|
|
5805
|
-
|
|
5806
|
-
|
|
5807
|
-
|
|
5808
|
-
|
|
5809
|
-
|
|
5810
|
-
|
|
5811
|
-
|
|
5812
|
-
|
|
5813
|
-
|
|
5814
|
-
}
|
|
5815
|
-
|
|
5816
|
-
|
|
5817
|
-
try {
|
|
5818
|
-
const res = await api2.Branches.show(projectPath, branch);
|
|
5819
|
-
return res.name === branch;
|
|
5820
|
-
} catch (e) {
|
|
5821
|
-
return false;
|
|
5822
|
-
}
|
|
5823
|
-
}
|
|
5824
|
-
async function getGitlabRepoList(url, accessToken) {
|
|
5825
|
-
const api2 = getGitBeaker({ url, gitlabAuthToken: accessToken });
|
|
5826
|
-
const res = await api2.Projects.all({
|
|
5827
|
-
membership: true,
|
|
5828
|
-
//TODO: a bug in the sorting mechanism of this api call
|
|
5829
|
-
//disallows us to sort by updated_at in descending order
|
|
5830
|
-
//so we have to sort by updated_at in ascending order.
|
|
5831
|
-
//We can wait for the bug to be fixed or call the api
|
|
5832
|
-
//directly with fetch()
|
|
5833
|
-
sort: "asc",
|
|
5834
|
-
orderBy: "updated_at",
|
|
5835
|
-
perPage: 100
|
|
5836
|
-
});
|
|
5837
|
-
return Promise.all(
|
|
5838
|
-
res.map(async (project) => {
|
|
5839
|
-
const proj = await api2.Projects.show(project.id);
|
|
5840
|
-
const owner = proj.namespace.name;
|
|
5841
|
-
const repoLanguages = await api2.Projects.showLanguages(project.id);
|
|
5842
|
-
return {
|
|
5843
|
-
repoName: project.path,
|
|
5844
|
-
repoUrl: project.web_url,
|
|
5845
|
-
repoOwner: owner,
|
|
5846
|
-
repoLanguages: Object.keys(repoLanguages),
|
|
5847
|
-
repoIsPublic: project.visibility === "public",
|
|
5848
|
-
repoUpdatedAt: project.last_activity_at
|
|
5849
|
-
};
|
|
5850
|
-
})
|
|
5851
|
-
);
|
|
5852
|
-
}
|
|
5853
|
-
async function getGitlabBranchList({
|
|
5854
|
-
accessToken,
|
|
5855
|
-
repoUrl
|
|
5856
|
-
}) {
|
|
5857
|
-
const { projectPath } = parseGitlabOwnerAndRepo(repoUrl);
|
|
5858
|
-
const api2 = getGitBeaker({ url: repoUrl, gitlabAuthToken: accessToken });
|
|
5859
|
-
try {
|
|
5860
|
-
const res = await api2.Branches.all(projectPath, {
|
|
5861
|
-
//keyset API pagination is not supported by GL for the branch list (at least not the on-prem version)
|
|
5862
|
-
//so for now we stick with the default pagination and just return the first page and limit the results to 1000 entries.
|
|
5863
|
-
//This is a temporary solution until we implement list branches with name search.
|
|
5864
|
-
perPage: MAX_BRANCHES_FETCH,
|
|
5865
|
-
page: 1
|
|
5866
|
-
});
|
|
5867
|
-
res.sort((a, b) => {
|
|
5868
|
-
if (!a.commit?.committed_date || !b.commit?.committed_date) {
|
|
5869
|
-
return 0;
|
|
5817
|
+
|
|
5818
|
+
// src/features/analysis/scm/github/github.ts
|
|
5819
|
+
function getGithubSdk(params = {}) {
|
|
5820
|
+
const octokit = getOctoKit(params);
|
|
5821
|
+
return {
|
|
5822
|
+
async postPrComment(params2) {
|
|
5823
|
+
return octokit.request(POST_COMMENT_PATH, params2);
|
|
5824
|
+
},
|
|
5825
|
+
async updatePrComment(params2) {
|
|
5826
|
+
return octokit.request(UPDATE_COMMENT_PATH, params2);
|
|
5827
|
+
},
|
|
5828
|
+
async getPrComments(params2) {
|
|
5829
|
+
return octokit.request(GET_PR_COMMENTS_PATH, params2);
|
|
5830
|
+
},
|
|
5831
|
+
async getPrComment(params2) {
|
|
5832
|
+
return octokit.request(GET_PR_COMMENT_PATH, params2);
|
|
5833
|
+
},
|
|
5834
|
+
async deleteComment(params2) {
|
|
5835
|
+
return octokit.request(DELETE_COMMENT_PATH, params2);
|
|
5836
|
+
},
|
|
5837
|
+
async replyToCodeReviewComment(params2) {
|
|
5838
|
+
return octokit.request(REPLY_TO_CODE_REVIEW_COMMENT_PATH, params2);
|
|
5839
|
+
},
|
|
5840
|
+
async getPrDiff(params2) {
|
|
5841
|
+
return octokit.request(GET_PR, {
|
|
5842
|
+
...params2,
|
|
5843
|
+
mediaType: { format: "diff" }
|
|
5844
|
+
});
|
|
5845
|
+
},
|
|
5846
|
+
async getPr(params2) {
|
|
5847
|
+
return octokit.request(GET_PR, { ...params2 });
|
|
5848
|
+
},
|
|
5849
|
+
async createOrUpdateRepositorySecret(params2) {
|
|
5850
|
+
return octokit.request(CREATE_OR_UPDATE_A_REPOSITORY_SECRET, params2);
|
|
5851
|
+
},
|
|
5852
|
+
async getRepositoryPublicKey(params2) {
|
|
5853
|
+
return octokit.request(GET_A_REPOSITORY_PUBLIC_KEY, params2);
|
|
5854
|
+
},
|
|
5855
|
+
async postGeneralPrComment(params2) {
|
|
5856
|
+
return octokit.request(POST_GENERAL_PR_COMMENT, params2);
|
|
5857
|
+
},
|
|
5858
|
+
async getGeneralPrComments(params2) {
|
|
5859
|
+
return octokit.request(GET_GENERAL_PR_COMMENTS, params2);
|
|
5860
|
+
},
|
|
5861
|
+
async deleteGeneralPrComment(params2) {
|
|
5862
|
+
return octokit.request(DELETE_GENERAL_PR_COMMENT, params2);
|
|
5863
|
+
},
|
|
5864
|
+
async getGithubUsername() {
|
|
5865
|
+
const res = await octokit.rest.users.getAuthenticated();
|
|
5866
|
+
return res.data.login;
|
|
5867
|
+
},
|
|
5868
|
+
async getGithubIsUserCollaborator(params2) {
|
|
5869
|
+
const { username, repoUrl } = params2;
|
|
5870
|
+
try {
|
|
5871
|
+
const { owner, repo } = parseGithubOwnerAndRepo(repoUrl);
|
|
5872
|
+
const res = await octokit.rest.repos.checkCollaborator({
|
|
5873
|
+
owner,
|
|
5874
|
+
repo,
|
|
5875
|
+
username
|
|
5876
|
+
});
|
|
5877
|
+
if (res.status === 204) {
|
|
5878
|
+
return true;
|
|
5879
|
+
}
|
|
5880
|
+
} catch (e) {
|
|
5881
|
+
return false;
|
|
5870
5882
|
}
|
|
5871
|
-
return
|
|
5872
|
-
}
|
|
5873
|
-
|
|
5874
|
-
|
|
5875
|
-
|
|
5876
|
-
|
|
5877
|
-
|
|
5878
|
-
|
|
5879
|
-
|
|
5880
|
-
|
|
5881
|
-
|
|
5882
|
-
|
|
5883
|
-
|
|
5884
|
-
|
|
5885
|
-
|
|
5886
|
-
|
|
5887
|
-
|
|
5888
|
-
|
|
5889
|
-
{
|
|
5890
|
-
|
|
5891
|
-
|
|
5892
|
-
|
|
5893
|
-
|
|
5894
|
-
|
|
5895
|
-
|
|
5896
|
-
|
|
5897
|
-
|
|
5898
|
-
|
|
5899
|
-
|
|
5900
|
-
|
|
5901
|
-
|
|
5902
|
-
|
|
5903
|
-
|
|
5904
|
-
|
|
5905
|
-
|
|
5906
|
-
|
|
5907
|
-
|
|
5908
|
-
|
|
5909
|
-
|
|
5910
|
-
|
|
5911
|
-
}
|
|
5912
|
-
|
|
5913
|
-
|
|
5914
|
-
|
|
5915
|
-
|
|
5916
|
-
|
|
5917
|
-
|
|
5918
|
-
|
|
5919
|
-
|
|
5920
|
-
|
|
5921
|
-
|
|
5922
|
-
|
|
5923
|
-
|
|
5924
|
-
|
|
5925
|
-
|
|
5926
|
-
|
|
5927
|
-
|
|
5928
|
-
|
|
5929
|
-
|
|
5930
|
-
|
|
5931
|
-
|
|
5932
|
-
|
|
5933
|
-
|
|
5934
|
-
|
|
5935
|
-
|
|
5936
|
-
|
|
5937
|
-
|
|
5938
|
-
|
|
5939
|
-
|
|
5940
|
-
|
|
5941
|
-
|
|
5942
|
-
|
|
5943
|
-
|
|
5944
|
-
|
|
5945
|
-
|
|
5946
|
-
|
|
5947
|
-
|
|
5948
|
-
|
|
5949
|
-
|
|
5950
|
-
|
|
5951
|
-
|
|
5952
|
-
|
|
5953
|
-
|
|
5954
|
-
|
|
5955
|
-
|
|
5883
|
+
return false;
|
|
5884
|
+
},
|
|
5885
|
+
async getGithubPullRequestStatus(params2) {
|
|
5886
|
+
const { repoUrl, prNumber } = params2;
|
|
5887
|
+
const { owner, repo } = parseGithubOwnerAndRepo(repoUrl);
|
|
5888
|
+
const res = await octokit.rest.pulls.get({
|
|
5889
|
+
owner,
|
|
5890
|
+
repo,
|
|
5891
|
+
pull_number: prNumber
|
|
5892
|
+
});
|
|
5893
|
+
if (res.data.merged) {
|
|
5894
|
+
return "merged";
|
|
5895
|
+
}
|
|
5896
|
+
if (res.data.draft) {
|
|
5897
|
+
return "draft";
|
|
5898
|
+
}
|
|
5899
|
+
return res.data.state;
|
|
5900
|
+
},
|
|
5901
|
+
async createMarkdownCommentOnPullRequest(params2) {
|
|
5902
|
+
const { repoUrl, prNumber, markdownComment } = params2;
|
|
5903
|
+
const { owner, repo } = parseGithubOwnerAndRepo(repoUrl);
|
|
5904
|
+
return octokit.rest.issues.createComment({
|
|
5905
|
+
owner,
|
|
5906
|
+
repo,
|
|
5907
|
+
issue_number: prNumber,
|
|
5908
|
+
body: markdownComment
|
|
5909
|
+
});
|
|
5910
|
+
},
|
|
5911
|
+
async getGithubIsRemoteBranch(params2) {
|
|
5912
|
+
const { repoUrl, branch } = params2;
|
|
5913
|
+
const { owner, repo } = parseGithubOwnerAndRepo(repoUrl);
|
|
5914
|
+
try {
|
|
5915
|
+
const res = await octokit.rest.repos.getBranch({
|
|
5916
|
+
owner,
|
|
5917
|
+
repo,
|
|
5918
|
+
branch
|
|
5919
|
+
});
|
|
5920
|
+
return branch === res.data.name;
|
|
5921
|
+
} catch (e) {
|
|
5922
|
+
return false;
|
|
5923
|
+
}
|
|
5924
|
+
},
|
|
5925
|
+
async getGithubRepoList() {
|
|
5926
|
+
try {
|
|
5927
|
+
const githubRepos = await octokit.request(GET_USER_REPOS, {
|
|
5928
|
+
sort: "updated"
|
|
5929
|
+
});
|
|
5930
|
+
return githubRepos.data.map((repo) => ({
|
|
5931
|
+
repoName: repo.name,
|
|
5932
|
+
repoUrl: repo.html_url,
|
|
5933
|
+
repoOwner: repo.owner.login,
|
|
5934
|
+
repoLanguages: repo.language ? [repo.language] : [],
|
|
5935
|
+
repoIsPublic: !repo.private,
|
|
5936
|
+
repoUpdatedAt: repo.updated_at
|
|
5937
|
+
}));
|
|
5938
|
+
} catch (e) {
|
|
5939
|
+
if (e instanceof RequestError && e.status === 401) {
|
|
5940
|
+
return [];
|
|
5941
|
+
}
|
|
5942
|
+
if (e instanceof RequestError && e.status === 404) {
|
|
5943
|
+
return [];
|
|
5944
|
+
}
|
|
5945
|
+
throw e;
|
|
5946
|
+
}
|
|
5947
|
+
},
|
|
5948
|
+
async getGithubRepoDefaultBranch(repoUrl) {
|
|
5949
|
+
const { owner, repo } = parseGithubOwnerAndRepo(repoUrl);
|
|
5950
|
+
const repos = await octokit.rest.repos.get({ repo, owner });
|
|
5951
|
+
return repos.data.default_branch;
|
|
5952
|
+
},
|
|
5953
|
+
async getGithubReferenceData({
|
|
5954
|
+
ref,
|
|
5955
|
+
gitHubUrl
|
|
5956
|
+
}) {
|
|
5957
|
+
const { owner, repo } = parseGithubOwnerAndRepo(gitHubUrl);
|
|
5958
|
+
let res;
|
|
5959
|
+
try {
|
|
5960
|
+
res = await Promise.any([
|
|
5961
|
+
this.getBranch({ owner, repo, branch: ref }).then((result) => ({
|
|
5962
|
+
date: result.data.commit.commit.committer?.date ? new Date(result.data.commit.commit.committer?.date) : void 0,
|
|
5963
|
+
type: "BRANCH" /* BRANCH */,
|
|
5964
|
+
sha: result.data.commit.sha
|
|
5965
|
+
})),
|
|
5966
|
+
this.getCommit({ commitSha: ref, repo, owner }).then((commit) => ({
|
|
5967
|
+
date: new Date(commit.data.committer.date),
|
|
5968
|
+
type: "COMMIT" /* COMMIT */,
|
|
5969
|
+
sha: commit.data.sha
|
|
5970
|
+
})),
|
|
5971
|
+
this.getTagDate({ owner, repo, tag: ref }).then((data) => ({
|
|
5972
|
+
date: new Date(data.date),
|
|
5973
|
+
type: "TAG" /* TAG */,
|
|
5974
|
+
sha: data.sha
|
|
5975
|
+
}))
|
|
5976
|
+
]);
|
|
5977
|
+
return res;
|
|
5978
|
+
} catch (e) {
|
|
5979
|
+
if (e instanceof AggregateError) {
|
|
5980
|
+
throw new RefNotFoundError(`ref: ${ref} does not exist`);
|
|
5981
|
+
}
|
|
5982
|
+
throw e;
|
|
5983
|
+
}
|
|
5984
|
+
},
|
|
5985
|
+
async getBranch({
|
|
5986
|
+
branch,
|
|
5987
|
+
owner,
|
|
5988
|
+
repo
|
|
5989
|
+
}) {
|
|
5990
|
+
return octokit.rest.repos.getBranch({
|
|
5991
|
+
branch,
|
|
5992
|
+
owner,
|
|
5993
|
+
repo
|
|
5994
|
+
});
|
|
5995
|
+
},
|
|
5996
|
+
async getCommit({
|
|
5997
|
+
commitSha,
|
|
5998
|
+
owner,
|
|
5999
|
+
repo
|
|
6000
|
+
}) {
|
|
6001
|
+
return octokit.rest.git.getCommit({
|
|
6002
|
+
repo,
|
|
6003
|
+
owner,
|
|
6004
|
+
commit_sha: commitSha
|
|
6005
|
+
});
|
|
6006
|
+
},
|
|
6007
|
+
async getTagDate({
|
|
6008
|
+
tag,
|
|
6009
|
+
owner,
|
|
6010
|
+
repo
|
|
6011
|
+
}) {
|
|
6012
|
+
const refResponse = await octokit.rest.git.getRef({
|
|
6013
|
+
ref: `tags/${tag}`,
|
|
6014
|
+
owner,
|
|
6015
|
+
repo
|
|
6016
|
+
});
|
|
6017
|
+
const tagSha = refResponse.data.object.sha;
|
|
6018
|
+
if (refResponse.data.object.type === "commit") {
|
|
6019
|
+
const res2 = await octokit.rest.git.getCommit({
|
|
6020
|
+
commit_sha: tagSha,
|
|
6021
|
+
owner,
|
|
6022
|
+
repo
|
|
6023
|
+
});
|
|
6024
|
+
return {
|
|
6025
|
+
date: res2.data.committer.date,
|
|
6026
|
+
sha: res2.data.sha
|
|
6027
|
+
};
|
|
6028
|
+
}
|
|
6029
|
+
const res = await octokit.rest.git.getTag({
|
|
6030
|
+
tag_sha: tagSha,
|
|
6031
|
+
owner,
|
|
6032
|
+
repo
|
|
6033
|
+
});
|
|
5956
6034
|
return {
|
|
5957
|
-
|
|
5958
|
-
|
|
5959
|
-
date: res.commit.committed_date ? new Date(res.commit.committed_date) : void 0
|
|
6035
|
+
date: res.data.tagger.date,
|
|
6036
|
+
sha: res.data.sha
|
|
5960
6037
|
};
|
|
5961
|
-
}
|
|
5962
|
-
|
|
5963
|
-
|
|
5964
|
-
|
|
5965
|
-
|
|
5966
|
-
|
|
5967
|
-
|
|
5968
|
-
|
|
5969
|
-
|
|
5970
|
-
|
|
5971
|
-
|
|
5972
|
-
|
|
5973
|
-
|
|
5974
|
-
|
|
5975
|
-
|
|
5976
|
-
|
|
5977
|
-
|
|
5978
|
-
|
|
5979
|
-
|
|
5980
|
-
|
|
5981
|
-
|
|
5982
|
-
|
|
5983
|
-
}
|
|
5984
|
-
|
|
5985
|
-
|
|
5986
|
-
|
|
5987
|
-
|
|
5988
|
-
|
|
5989
|
-
|
|
5990
|
-
|
|
5991
|
-
|
|
5992
|
-
|
|
5993
|
-
|
|
5994
|
-
|
|
5995
|
-
|
|
5996
|
-
|
|
5997
|
-
|
|
5998
|
-
|
|
5999
|
-
|
|
6000
|
-
|
|
6001
|
-
|
|
6002
|
-
|
|
6003
|
-
|
|
6004
|
-
|
|
6005
|
-
|
|
6006
|
-
|
|
6007
|
-
|
|
6008
|
-
|
|
6009
|
-
|
|
6010
|
-
|
|
6011
|
-
|
|
6012
|
-
|
|
6013
|
-
|
|
6014
|
-
|
|
6015
|
-
|
|
6016
|
-
|
|
6017
|
-
|
|
6018
|
-
|
|
6019
|
-
|
|
6020
|
-
|
|
6021
|
-
|
|
6022
|
-
|
|
6023
|
-
|
|
6024
|
-
|
|
6025
|
-
|
|
6026
|
-
|
|
6027
|
-
|
|
6028
|
-
|
|
6029
|
-
|
|
6030
|
-
|
|
6031
|
-
|
|
6032
|
-
|
|
6033
|
-
|
|
6034
|
-
|
|
6038
|
+
},
|
|
6039
|
+
async getGithubBlameRanges(params2) {
|
|
6040
|
+
const { ref, gitHubUrl, path: path8 } = params2;
|
|
6041
|
+
const { owner, repo } = parseGithubOwnerAndRepo(gitHubUrl);
|
|
6042
|
+
const res = await octokit.graphql(
|
|
6043
|
+
GET_BLAME_DOCUMENT,
|
|
6044
|
+
{
|
|
6045
|
+
owner,
|
|
6046
|
+
repo,
|
|
6047
|
+
path: path8,
|
|
6048
|
+
ref
|
|
6049
|
+
}
|
|
6050
|
+
);
|
|
6051
|
+
if (!res?.repository?.object?.blame?.ranges) {
|
|
6052
|
+
return [];
|
|
6053
|
+
}
|
|
6054
|
+
return res.repository.object.blame.ranges.map((range) => ({
|
|
6055
|
+
startingLine: range.startingLine,
|
|
6056
|
+
endingLine: range.endingLine,
|
|
6057
|
+
email: range.commit.author.user?.email || "",
|
|
6058
|
+
name: range.commit.author.user?.name || "",
|
|
6059
|
+
login: range.commit.author.user?.login || ""
|
|
6060
|
+
}));
|
|
6061
|
+
},
|
|
6062
|
+
// todo: refactor the name for this function
|
|
6063
|
+
async createPr(params2) {
|
|
6064
|
+
const { sourceRepoUrl, filesPaths, userRepoUrl, title, body } = params2;
|
|
6065
|
+
const { owner: sourceOwner, repo: sourceRepo } = parseGithubOwnerAndRepo(sourceRepoUrl);
|
|
6066
|
+
const { owner, repo } = parseGithubOwnerAndRepo(userRepoUrl);
|
|
6067
|
+
const [sourceFilePath, secondFilePath] = filesPaths;
|
|
6068
|
+
const sourceFileContentResponse = await octokit.rest.repos.getContent({
|
|
6069
|
+
owner: sourceOwner,
|
|
6070
|
+
repo: sourceRepo,
|
|
6071
|
+
path: "/" + sourceFilePath
|
|
6072
|
+
});
|
|
6073
|
+
const { data: repository } = await octokit.rest.repos.get({ owner, repo });
|
|
6074
|
+
const defaultBranch = repository.default_branch;
|
|
6075
|
+
const newBranchName = `mobb/workflow-${Date.now()}`;
|
|
6076
|
+
await octokit.rest.git.createRef({
|
|
6077
|
+
owner,
|
|
6078
|
+
repo,
|
|
6079
|
+
ref: `refs/heads/${newBranchName}`,
|
|
6080
|
+
sha: await octokit.rest.git.getRef({ owner, repo, ref: `heads/${defaultBranch}` }).then((response) => response.data.object.sha)
|
|
6081
|
+
});
|
|
6082
|
+
const decodedContent = Buffer.from(
|
|
6083
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
6084
|
+
// @ts-ignore
|
|
6085
|
+
sourceFileContentResponse.data.content,
|
|
6086
|
+
"base64"
|
|
6087
|
+
).toString("utf-8");
|
|
6088
|
+
const tree = [
|
|
6089
|
+
{
|
|
6090
|
+
path: sourceFilePath,
|
|
6091
|
+
mode: "100644",
|
|
6092
|
+
type: "blob",
|
|
6093
|
+
content: decodedContent
|
|
6094
|
+
}
|
|
6095
|
+
];
|
|
6096
|
+
if (secondFilePath) {
|
|
6097
|
+
const secondFileContentResponse = await octokit.rest.repos.getContent({
|
|
6098
|
+
owner: sourceOwner,
|
|
6099
|
+
repo: sourceRepo,
|
|
6100
|
+
path: "/" + secondFilePath
|
|
6101
|
+
});
|
|
6102
|
+
const secondDecodedContent = Buffer.from(
|
|
6103
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
6104
|
+
// @ts-ignore
|
|
6105
|
+
secondFileContentResponse.data.content,
|
|
6106
|
+
"base64"
|
|
6107
|
+
).toString("utf-8");
|
|
6108
|
+
tree.push({
|
|
6109
|
+
path: secondFilePath,
|
|
6110
|
+
mode: "100644",
|
|
6111
|
+
type: "blob",
|
|
6112
|
+
content: secondDecodedContent
|
|
6113
|
+
});
|
|
6114
|
+
}
|
|
6115
|
+
const createTreeResponse = await octokit.rest.git.createTree({
|
|
6116
|
+
owner,
|
|
6117
|
+
repo,
|
|
6118
|
+
base_tree: await octokit.rest.git.getRef({ owner, repo, ref: `heads/${defaultBranch}` }).then((response) => response.data.object.sha),
|
|
6119
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
6120
|
+
// @ts-ignore
|
|
6121
|
+
tree
|
|
6122
|
+
});
|
|
6123
|
+
const createCommitResponse = await octokit.rest.git.createCommit({
|
|
6124
|
+
owner,
|
|
6125
|
+
repo,
|
|
6126
|
+
message: "Add new yaml file",
|
|
6127
|
+
tree: createTreeResponse.data.sha,
|
|
6128
|
+
parents: [
|
|
6129
|
+
await octokit.rest.git.getRef({ owner, repo, ref: `heads/${defaultBranch}` }).then((response) => response.data.object.sha)
|
|
6130
|
+
]
|
|
6131
|
+
});
|
|
6132
|
+
await octokit.rest.git.updateRef({
|
|
6133
|
+
owner,
|
|
6134
|
+
repo,
|
|
6135
|
+
ref: `heads/${newBranchName}`,
|
|
6136
|
+
sha: createCommitResponse.data.sha
|
|
6137
|
+
});
|
|
6138
|
+
const createPRResponse = await octokit.rest.pulls.create({
|
|
6139
|
+
owner,
|
|
6140
|
+
repo,
|
|
6141
|
+
title,
|
|
6142
|
+
head: newBranchName,
|
|
6143
|
+
head_repo: sourceRepo,
|
|
6144
|
+
body,
|
|
6145
|
+
base: defaultBranch
|
|
6146
|
+
});
|
|
6147
|
+
return {
|
|
6148
|
+
pull_request_url: createPRResponse.data.html_url
|
|
6149
|
+
};
|
|
6150
|
+
},
|
|
6151
|
+
async getGithubBranchList(repoUrl) {
|
|
6152
|
+
const { owner, repo } = parseGithubOwnerAndRepo(repoUrl);
|
|
6153
|
+
return octokit.rest.repos.listBranches({
|
|
6154
|
+
owner,
|
|
6155
|
+
repo,
|
|
6156
|
+
per_page: MAX_BRANCHES_FETCH,
|
|
6157
|
+
page: 1
|
|
6158
|
+
});
|
|
6159
|
+
},
|
|
6160
|
+
async createPullRequest(options) {
|
|
6161
|
+
const { owner, repo } = parseGithubOwnerAndRepo(options.repoUrl);
|
|
6162
|
+
return octokit.rest.pulls.create({
|
|
6163
|
+
owner,
|
|
6164
|
+
repo,
|
|
6165
|
+
title: options.title,
|
|
6166
|
+
body: options.body,
|
|
6167
|
+
head: options.sourceBranchName,
|
|
6168
|
+
base: options.targetBranchName,
|
|
6169
|
+
draft: false,
|
|
6170
|
+
maintainer_can_modify: true
|
|
6171
|
+
});
|
|
6172
|
+
},
|
|
6173
|
+
async forkRepo(options) {
|
|
6174
|
+
const { owner, repo } = parseGithubOwnerAndRepo(options.repoUrl);
|
|
6175
|
+
const createForkRes = await octokit.rest.repos.createFork({
|
|
6176
|
+
owner,
|
|
6177
|
+
repo,
|
|
6178
|
+
default_branch_only: false
|
|
6179
|
+
});
|
|
6180
|
+
return { url: createForkRes.data.html_url };
|
|
6181
|
+
},
|
|
6182
|
+
async getUserInfo() {
|
|
6183
|
+
return octokit.request(GET_USER);
|
|
6035
6184
|
}
|
|
6036
|
-
|
|
6037
|
-
});
|
|
6038
|
-
if (response.ok)
|
|
6039
|
-
return {
|
|
6040
|
-
body: await processBody(response),
|
|
6041
|
-
headers: Object.fromEntries(response.headers.entries()),
|
|
6042
|
-
status: response.status
|
|
6043
|
-
};
|
|
6044
|
-
throw new Error(`gitbeaker: ${response.statusText}`);
|
|
6185
|
+
};
|
|
6045
6186
|
}
|
|
6046
6187
|
|
|
6047
|
-
// src/features/analysis/scm/
|
|
6048
|
-
var
|
|
6188
|
+
// src/features/analysis/scm/github/GithubSCMLib.ts
|
|
6189
|
+
var GithubSCMLib = class extends SCMLib {
|
|
6190
|
+
// we don't always need a url, what's important is that we have an access token
|
|
6049
6191
|
constructor(url, accessToken, scmOrg) {
|
|
6050
6192
|
super(url, accessToken, scmOrg);
|
|
6193
|
+
__publicField(this, "githubSdk");
|
|
6194
|
+
this.githubSdk = getGithubSdk({
|
|
6195
|
+
auth: accessToken,
|
|
6196
|
+
url
|
|
6197
|
+
});
|
|
6051
6198
|
}
|
|
6052
6199
|
async createSubmitRequest(params) {
|
|
6053
6200
|
this._validateAccessTokenAndUrl();
|
|
6054
6201
|
const { targetBranchName, sourceBranchName, title, body } = params;
|
|
6055
|
-
|
|
6056
|
-
|
|
6057
|
-
|
|
6058
|
-
|
|
6059
|
-
|
|
6060
|
-
sourceBranchName,
|
|
6061
|
-
repoUrl: this.url,
|
|
6062
|
-
accessToken: this.accessToken
|
|
6063
|
-
})
|
|
6064
|
-
);
|
|
6065
|
-
}
|
|
6066
|
-
async validateParams() {
|
|
6067
|
-
return gitlabValidateParams({
|
|
6068
|
-
url: this.url,
|
|
6069
|
-
accessToken: this.accessToken
|
|
6070
|
-
});
|
|
6071
|
-
}
|
|
6072
|
-
async getRepoList(_scmOrg) {
|
|
6073
|
-
if (!this.accessToken) {
|
|
6074
|
-
console.error("no access token");
|
|
6075
|
-
throw new Error("no access token");
|
|
6076
|
-
}
|
|
6077
|
-
return getGitlabRepoList(this.url, this.accessToken);
|
|
6078
|
-
}
|
|
6079
|
-
async getBranchList() {
|
|
6080
|
-
this._validateAccessTokenAndUrl();
|
|
6081
|
-
return getGitlabBranchList({
|
|
6082
|
-
accessToken: this.accessToken,
|
|
6202
|
+
const pullRequestResult = await this.githubSdk.createPullRequest({
|
|
6203
|
+
title,
|
|
6204
|
+
body,
|
|
6205
|
+
targetBranchName,
|
|
6206
|
+
sourceBranchName,
|
|
6083
6207
|
repoUrl: this.url
|
|
6084
6208
|
});
|
|
6209
|
+
return String(pullRequestResult.data.number);
|
|
6085
6210
|
}
|
|
6086
|
-
|
|
6087
|
-
|
|
6088
|
-
|
|
6089
|
-
|
|
6090
|
-
if (!this.accessToken) {
|
|
6091
|
-
return {};
|
|
6092
|
-
}
|
|
6093
|
-
if (this.accessToken.startsWith("glpat-")) {
|
|
6094
|
-
return {
|
|
6095
|
-
"Private-Token": this.accessToken
|
|
6096
|
-
};
|
|
6097
|
-
} else {
|
|
6098
|
-
return { authorization: `Bearer ${this.accessToken}` };
|
|
6099
|
-
}
|
|
6100
|
-
}
|
|
6101
|
-
getDownloadUrl(sha) {
|
|
6102
|
-
const urlObj = new URL(this.url || "");
|
|
6103
|
-
const ProjectId = encodeURIComponent(
|
|
6104
|
-
urlObj.pathname.replace(/^\//, "").replace(/\/$/, "")
|
|
6105
|
-
);
|
|
6106
|
-
return Promise.resolve(
|
|
6107
|
-
//We are moving away from this form as it doesn't work when using a non-human token (group/project token)
|
|
6108
|
-
//Where as the API zip endpoint works with any token
|
|
6109
|
-
//`${this.url}/-/archive/${sha}/${repoName}-${sha}.zip`
|
|
6110
|
-
`${urlObj.origin}/api/v4/projects/${ProjectId}/repository/archive.zip?sha=${sha}`
|
|
6111
|
-
);
|
|
6112
|
-
}
|
|
6113
|
-
async _getUsernameForAuthUrl() {
|
|
6114
|
-
if (this?.accessToken?.startsWith("glpat-")) {
|
|
6115
|
-
return this.getUsername();
|
|
6116
|
-
} else {
|
|
6117
|
-
return "oauth2";
|
|
6118
|
-
}
|
|
6119
|
-
}
|
|
6120
|
-
async getIsRemoteBranch(branch) {
|
|
6121
|
-
this._validateAccessTokenAndUrl();
|
|
6122
|
-
return getGitlabIsRemoteBranch({
|
|
6123
|
-
accessToken: this.accessToken,
|
|
6124
|
-
repoUrl: this.url,
|
|
6125
|
-
branch
|
|
6126
|
-
});
|
|
6127
|
-
}
|
|
6128
|
-
async getUserHasAccessToRepo() {
|
|
6129
|
-
this._validateAccessTokenAndUrl();
|
|
6130
|
-
return getGitlabIsUserCollaborator({
|
|
6131
|
-
accessToken: this.accessToken,
|
|
6132
|
-
repoUrl: this.url
|
|
6211
|
+
async forkRepo(repoUrl) {
|
|
6212
|
+
this._validateAccessToken();
|
|
6213
|
+
return this.githubSdk.forkRepo({
|
|
6214
|
+
repoUrl
|
|
6133
6215
|
});
|
|
6134
6216
|
}
|
|
6135
|
-
async
|
|
6136
|
-
this._validateAccessTokenAndUrl();
|
|
6137
|
-
return getGitlabUsername(this.url, this.accessToken);
|
|
6138
|
-
}
|
|
6139
|
-
async getSubmitRequestStatus(scmSubmitRequestId) {
|
|
6217
|
+
async createOrUpdateRepositorySecret(params) {
|
|
6140
6218
|
this._validateAccessTokenAndUrl();
|
|
6141
|
-
const
|
|
6142
|
-
|
|
6143
|
-
|
|
6144
|
-
|
|
6219
|
+
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
6220
|
+
const { data: repositoryPublicKeyResponse } = await this.githubSdk.getRepositoryPublicKey({ owner, repo });
|
|
6221
|
+
const { key_id, key } = repositoryPublicKeyResponse;
|
|
6222
|
+
const encryptedValue = await encryptSecret(params.value, key);
|
|
6223
|
+
return this.githubSdk.createOrUpdateRepositorySecret({
|
|
6224
|
+
encrypted_value: encryptedValue,
|
|
6225
|
+
secret_name: params.name,
|
|
6226
|
+
key_id,
|
|
6227
|
+
owner,
|
|
6228
|
+
repo
|
|
6145
6229
|
});
|
|
6146
|
-
switch (state) {
|
|
6147
|
-
case gitlabMergeRequestStatus.merged:
|
|
6148
|
-
return "merged";
|
|
6149
|
-
case gitlabMergeRequestStatus.opened:
|
|
6150
|
-
return "open";
|
|
6151
|
-
case gitlabMergeRequestStatus.closed:
|
|
6152
|
-
return "closed";
|
|
6153
|
-
default:
|
|
6154
|
-
throw new Error(`unknown state ${state}`);
|
|
6155
|
-
}
|
|
6156
6230
|
}
|
|
6157
|
-
async
|
|
6158
|
-
this.
|
|
6159
|
-
|
|
6160
|
-
|
|
6161
|
-
|
|
6162
|
-
|
|
6163
|
-
|
|
6231
|
+
async createPullRequestWithNewFile(sourceRepoUrl, filesPaths, userRepoUrl, title, body) {
|
|
6232
|
+
const { pull_request_url } = await this.githubSdk.createPr({
|
|
6233
|
+
sourceRepoUrl,
|
|
6234
|
+
filesPaths,
|
|
6235
|
+
userRepoUrl,
|
|
6236
|
+
title,
|
|
6237
|
+
body
|
|
6164
6238
|
});
|
|
6239
|
+
return { pull_request_url };
|
|
6165
6240
|
}
|
|
6166
|
-
async
|
|
6167
|
-
this.
|
|
6168
|
-
|
|
6169
|
-
|
|
6170
|
-
|
|
6171
|
-
|
|
6172
|
-
|
|
6173
|
-
|
|
6174
|
-
|
|
6175
|
-
|
|
6176
|
-
async getReferenceData(ref) {
|
|
6177
|
-
this._validateUrl();
|
|
6178
|
-
return await getGitlabReferenceData(
|
|
6179
|
-
{ ref, gitlabUrl: this.url },
|
|
6180
|
-
{
|
|
6181
|
-
url: this.url,
|
|
6182
|
-
gitlabAuthToken: this.accessToken
|
|
6183
|
-
}
|
|
6184
|
-
);
|
|
6185
|
-
}
|
|
6186
|
-
async getRepoDefaultBranch() {
|
|
6187
|
-
this._validateUrl();
|
|
6188
|
-
return await getGitlabRepoDefaultBranch(this.url, {
|
|
6189
|
-
url: this.url,
|
|
6190
|
-
gitlabAuthToken: this.accessToken
|
|
6241
|
+
async validateParams() {
|
|
6242
|
+
return githubValidateParams(this.url, this.accessToken);
|
|
6243
|
+
}
|
|
6244
|
+
async postPrComment(params) {
|
|
6245
|
+
this._validateAccessTokenAndUrl();
|
|
6246
|
+
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
6247
|
+
return this.githubSdk.postPrComment({
|
|
6248
|
+
...params,
|
|
6249
|
+
owner,
|
|
6250
|
+
repo
|
|
6191
6251
|
});
|
|
6192
6252
|
}
|
|
6193
|
-
async
|
|
6253
|
+
async updatePrComment(params) {
|
|
6194
6254
|
this._validateAccessTokenAndUrl();
|
|
6195
|
-
const
|
|
6196
|
-
|
|
6197
|
-
|
|
6198
|
-
|
|
6255
|
+
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
6256
|
+
return this.githubSdk.updatePrComment({
|
|
6257
|
+
...params,
|
|
6258
|
+
owner,
|
|
6259
|
+
repo
|
|
6199
6260
|
});
|
|
6200
|
-
return res.web_url;
|
|
6201
6261
|
}
|
|
6202
|
-
async
|
|
6203
|
-
|
|
6204
|
-
|
|
6262
|
+
async deleteComment(params) {
|
|
6263
|
+
this._validateAccessTokenAndUrl();
|
|
6264
|
+
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
6265
|
+
return this.githubSdk.deleteComment({
|
|
6266
|
+
...params,
|
|
6267
|
+
owner,
|
|
6268
|
+
repo
|
|
6269
|
+
});
|
|
6205
6270
|
}
|
|
6206
|
-
async
|
|
6271
|
+
async getPrComments(params) {
|
|
6207
6272
|
this._validateAccessTokenAndUrl();
|
|
6208
|
-
const
|
|
6209
|
-
|
|
6210
|
-
|
|
6211
|
-
|
|
6273
|
+
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
6274
|
+
return this.githubSdk.getPrComments({
|
|
6275
|
+
per_page: 100,
|
|
6276
|
+
...params,
|
|
6277
|
+
owner,
|
|
6278
|
+
repo
|
|
6212
6279
|
});
|
|
6213
|
-
return res.web_url;
|
|
6214
6280
|
}
|
|
6215
|
-
|
|
6216
|
-
|
|
6217
|
-
|
|
6218
|
-
|
|
6219
|
-
|
|
6220
|
-
|
|
6221
|
-
|
|
6222
|
-
|
|
6223
|
-
|
|
6281
|
+
async getPrDiff(params) {
|
|
6282
|
+
this._validateAccessTokenAndUrl();
|
|
6283
|
+
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
6284
|
+
const prRes = await this.githubSdk.getPrDiff({
|
|
6285
|
+
...params,
|
|
6286
|
+
owner,
|
|
6287
|
+
repo
|
|
6288
|
+
});
|
|
6289
|
+
return z22.string().parse(prRes.data);
|
|
6224
6290
|
}
|
|
6225
|
-
async
|
|
6226
|
-
|
|
6227
|
-
return
|
|
6291
|
+
async getRepoList(_scmOrg) {
|
|
6292
|
+
this._validateAccessToken();
|
|
6293
|
+
return this.githubSdk.getGithubRepoList();
|
|
6228
6294
|
}
|
|
6229
|
-
async
|
|
6230
|
-
|
|
6231
|
-
|
|
6295
|
+
async getBranchList() {
|
|
6296
|
+
this._validateAccessTokenAndUrl();
|
|
6297
|
+
const branches = await this.githubSdk.getGithubBranchList(this.url);
|
|
6298
|
+
return branches.data.map((branch) => branch.name);
|
|
6232
6299
|
}
|
|
6233
6300
|
get scmLibType() {
|
|
6234
|
-
console.warn("scmLibType returning GITHUB as default");
|
|
6235
6301
|
return "GITHUB" /* GITHUB */;
|
|
6236
6302
|
}
|
|
6237
6303
|
getAuthHeaders() {
|
|
6238
|
-
|
|
6304
|
+
if (this.accessToken) {
|
|
6305
|
+
return { authorization: `Bearer ${this.accessToken}` };
|
|
6306
|
+
}
|
|
6239
6307
|
return {};
|
|
6240
6308
|
}
|
|
6241
|
-
|
|
6242
|
-
|
|
6243
|
-
|
|
6244
|
-
|
|
6245
|
-
|
|
6246
|
-
|
|
6247
|
-
|
|
6248
|
-
|
|
6249
|
-
|
|
6250
|
-
console.warn("validateParams() no-op");
|
|
6251
|
-
}
|
|
6252
|
-
async getRepoList(_scmOrg) {
|
|
6253
|
-
console.warn("getRepoList() returning empty array");
|
|
6254
|
-
return [];
|
|
6255
|
-
}
|
|
6256
|
-
async getBranchList() {
|
|
6257
|
-
console.warn("getBranchList() returning empty array");
|
|
6258
|
-
return [];
|
|
6309
|
+
getDownloadUrl(sha) {
|
|
6310
|
+
this._validateUrl();
|
|
6311
|
+
const res = parseScmURL(this.url, "GitHub" /* GitHub */);
|
|
6312
|
+
if (!res) {
|
|
6313
|
+
throw new InvalidRepoUrlError("invalid repo url");
|
|
6314
|
+
}
|
|
6315
|
+
const { protocol, hostname, organization, repoName } = res;
|
|
6316
|
+
const downloadUrl = isGithubOnPrem(this.url) ? `${protocol}//${hostname}/api/v3/repos/${organization}/${repoName}/zipball/${sha}` : `https://api.${hostname}/repos/${organization}/${repoName}/zipball/${sha}`;
|
|
6317
|
+
return Promise.resolve(downloadUrl);
|
|
6259
6318
|
}
|
|
6260
|
-
async
|
|
6261
|
-
|
|
6262
|
-
return "";
|
|
6319
|
+
async _getUsernameForAuthUrl() {
|
|
6320
|
+
return this.getUsername();
|
|
6263
6321
|
}
|
|
6264
|
-
async
|
|
6265
|
-
|
|
6266
|
-
return
|
|
6322
|
+
async getIsRemoteBranch(branch) {
|
|
6323
|
+
this._validateUrl();
|
|
6324
|
+
return this.githubSdk.getGithubIsRemoteBranch({ branch, repoUrl: this.url });
|
|
6267
6325
|
}
|
|
6268
6326
|
async getUserHasAccessToRepo() {
|
|
6269
|
-
|
|
6270
|
-
|
|
6271
|
-
|
|
6272
|
-
|
|
6273
|
-
|
|
6274
|
-
|
|
6275
|
-
}
|
|
6276
|
-
async getReferenceData(_ref) {
|
|
6277
|
-
console.warn("getReferenceData() returning null/empty defaults");
|
|
6278
|
-
return {
|
|
6279
|
-
type: "BRANCH" /* BRANCH */,
|
|
6280
|
-
sha: "",
|
|
6281
|
-
date: void 0
|
|
6282
|
-
};
|
|
6283
|
-
}
|
|
6284
|
-
async getRepoDefaultBranch() {
|
|
6285
|
-
console.warn("getRepoDefaultBranch() returning empty string");
|
|
6286
|
-
return "";
|
|
6287
|
-
}
|
|
6288
|
-
async getSubmitRequestUrl(_submitRequestIdNumber) {
|
|
6289
|
-
console.warn("getSubmitRequestUrl() returning empty string");
|
|
6290
|
-
return "";
|
|
6291
|
-
}
|
|
6292
|
-
async getSubmitRequestId(_submitRequestUrl) {
|
|
6293
|
-
console.warn("getSubmitRequestId() returning empty string");
|
|
6294
|
-
return "";
|
|
6295
|
-
}
|
|
6296
|
-
async getCommitUrl(_commitId) {
|
|
6297
|
-
console.warn("getCommitUrl() returning empty string");
|
|
6298
|
-
return "";
|
|
6299
|
-
}
|
|
6300
|
-
async _getUsernameForAuthUrl() {
|
|
6301
|
-
console.warn("_getUsernameForAuthUrl() returning empty string");
|
|
6302
|
-
return "";
|
|
6327
|
+
this._validateAccessTokenAndUrl();
|
|
6328
|
+
const username = await this.getUsername();
|
|
6329
|
+
return this.githubSdk.getGithubIsUserCollaborator({
|
|
6330
|
+
repoUrl: this.url,
|
|
6331
|
+
username
|
|
6332
|
+
});
|
|
6303
6333
|
}
|
|
6304
|
-
async
|
|
6305
|
-
|
|
6334
|
+
async getUsername() {
|
|
6335
|
+
this._validateAccessToken();
|
|
6336
|
+
return this.githubSdk.getGithubUsername();
|
|
6306
6337
|
}
|
|
6307
|
-
|
|
6308
|
-
|
|
6309
|
-
|
|
6310
|
-
|
|
6311
|
-
|
|
6312
|
-
|
|
6313
|
-
switch (scmType) {
|
|
6314
|
-
case "GITHUB" /* GITHUB */: {
|
|
6315
|
-
const scm = new GithubSCMLib(trimmedUrl, accessToken, scmOrg);
|
|
6316
|
-
await scm.validateParams();
|
|
6317
|
-
return scm;
|
|
6318
|
-
}
|
|
6319
|
-
case "GITLAB" /* GITLAB */: {
|
|
6320
|
-
const scm = new GitlabSCMLib(trimmedUrl, accessToken, scmOrg);
|
|
6321
|
-
await scm.validateParams();
|
|
6322
|
-
return scm;
|
|
6323
|
-
}
|
|
6324
|
-
case "ADO" /* ADO */: {
|
|
6325
|
-
const scm = new AdoSCMLib(trimmedUrl, accessToken, scmOrg);
|
|
6326
|
-
await scm.getAdoSdk();
|
|
6327
|
-
await scm.validateParams();
|
|
6328
|
-
return scm;
|
|
6329
|
-
}
|
|
6330
|
-
case "BITBUCKET" /* BITBUCKET */: {
|
|
6331
|
-
const scm = new BitbucketSCMLib(trimmedUrl, accessToken, scmOrg);
|
|
6332
|
-
await scm.validateParams();
|
|
6333
|
-
return scm;
|
|
6334
|
-
}
|
|
6335
|
-
}
|
|
6336
|
-
} catch (e) {
|
|
6337
|
-
if (e instanceof InvalidRepoUrlError && url) {
|
|
6338
|
-
throw new RepoNoTokenAccessError(
|
|
6339
|
-
"no access to repo",
|
|
6340
|
-
scmLibScmTypeToScmType[z23.nativeEnum(ScmLibScmType).parse(scmType)]
|
|
6341
|
-
);
|
|
6342
|
-
}
|
|
6343
|
-
console.error(`error validating scm: ${scmType} `, e);
|
|
6344
|
-
if (propagateExceptions) {
|
|
6345
|
-
throw e;
|
|
6346
|
-
}
|
|
6338
|
+
async getSubmitRequestStatus(scmSubmitRequestId) {
|
|
6339
|
+
this._validateAccessTokenAndUrl();
|
|
6340
|
+
return this.githubSdk.getGithubPullRequestStatus({
|
|
6341
|
+
repoUrl: this.url,
|
|
6342
|
+
prNumber: Number(scmSubmitRequestId)
|
|
6343
|
+
});
|
|
6347
6344
|
}
|
|
6348
|
-
|
|
6349
|
-
|
|
6350
|
-
|
|
6351
|
-
|
|
6352
|
-
|
|
6353
|
-
|
|
6354
|
-
|
|
6355
|
-
if (!parsingResult) {
|
|
6356
|
-
throw new InvalidUrlPatternError(`invalid github repo Url ${gitHubUrl}`);
|
|
6345
|
+
async addCommentToSubmitRequest(submitRequestId, comment) {
|
|
6346
|
+
this._validateAccessTokenAndUrl();
|
|
6347
|
+
await this.githubSdk.createMarkdownCommentOnPullRequest({
|
|
6348
|
+
repoUrl: this.url,
|
|
6349
|
+
prNumber: Number(submitRequestId),
|
|
6350
|
+
markdownComment: comment
|
|
6351
|
+
});
|
|
6357
6352
|
}
|
|
6358
|
-
|
|
6359
|
-
|
|
6360
|
-
|
|
6353
|
+
async getRepoBlameRanges(ref, path8) {
|
|
6354
|
+
this._validateUrl();
|
|
6355
|
+
return await this.githubSdk.getGithubBlameRanges({
|
|
6356
|
+
ref,
|
|
6357
|
+
path: path8,
|
|
6358
|
+
gitHubUrl: this.url
|
|
6359
|
+
});
|
|
6361
6360
|
}
|
|
6362
|
-
|
|
6363
|
-
|
|
6364
|
-
|
|
6365
|
-
if (!url) {
|
|
6366
|
-
return false;
|
|
6361
|
+
async getReferenceData(ref) {
|
|
6362
|
+
this._validateUrl();
|
|
6363
|
+
return this.githubSdk.getGithubReferenceData({ ref, gitHubUrl: this.url });
|
|
6367
6364
|
}
|
|
6368
|
-
|
|
6369
|
-
|
|
6370
|
-
|
|
6371
|
-
|
|
6372
|
-
|
|
6373
|
-
|
|
6374
|
-
|
|
6375
|
-
rejectUnauthorized: false
|
|
6376
|
-
}
|
|
6365
|
+
async getPrComment(commentId) {
|
|
6366
|
+
this._validateUrl();
|
|
6367
|
+
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
6368
|
+
return await this.githubSdk.getPrComment({
|
|
6369
|
+
repo,
|
|
6370
|
+
owner,
|
|
6371
|
+
comment_id: commentId
|
|
6377
6372
|
});
|
|
6378
|
-
return (input, init) => {
|
|
6379
|
-
return fetch2(input, {
|
|
6380
|
-
...init,
|
|
6381
|
-
dispatcher
|
|
6382
|
-
});
|
|
6383
|
-
};
|
|
6384
6373
|
}
|
|
6385
|
-
|
|
6386
|
-
|
|
6387
|
-
|
|
6388
|
-
if (!GITHUB_API_TOKEN || typeof GITHUB_API_TOKEN !== "string") {
|
|
6389
|
-
return void 0;
|
|
6374
|
+
async getRepoDefaultBranch() {
|
|
6375
|
+
this._validateUrl();
|
|
6376
|
+
return await this.githubSdk.getGithubRepoDefaultBranch(this.url);
|
|
6390
6377
|
}
|
|
6391
|
-
|
|
6392
|
-
|
|
6393
|
-
}
|
|
6394
|
-
|
|
6395
|
-
|
|
6396
|
-
|
|
6397
|
-
|
|
6398
|
-
|
|
6399
|
-
|
|
6400
|
-
baseUrl,
|
|
6401
|
-
//GITHUB_API_TOKEN is only defined in the backend and not when running Bugsy as CLI. We want to enable these debug logs in the backend
|
|
6402
|
-
//to debug the performance of these API calls.
|
|
6403
|
-
log: GITHUB_API_TOKEN ? console : void 0,
|
|
6404
|
-
request: {
|
|
6405
|
-
fetch: getFetch(baseUrl)
|
|
6406
|
-
},
|
|
6407
|
-
retry: {
|
|
6408
|
-
enabled: false
|
|
6409
|
-
},
|
|
6410
|
-
throttle: {
|
|
6411
|
-
enabled: false
|
|
6412
|
-
}
|
|
6413
|
-
});
|
|
6414
|
-
}
|
|
6415
|
-
function isGithubActionActionToken(token) {
|
|
6416
|
-
return token.startsWith("ghs_");
|
|
6417
|
-
}
|
|
6418
|
-
async function githubValidateParams(url, accessToken) {
|
|
6419
|
-
try {
|
|
6420
|
-
const oktoKit = getOctoKit({ auth: accessToken, url });
|
|
6421
|
-
if (accessToken && !isGithubActionActionToken(accessToken)) {
|
|
6422
|
-
await oktoKit.rest.users.getAuthenticated();
|
|
6423
|
-
}
|
|
6424
|
-
if (url && shouldValidateUrl(url)) {
|
|
6425
|
-
const { owner, repo } = parseGithubOwnerAndRepo(url);
|
|
6426
|
-
await oktoKit.request(GET_REPO_BRANCHES, {
|
|
6427
|
-
owner,
|
|
6428
|
-
repo,
|
|
6429
|
-
per_page: 1
|
|
6430
|
-
});
|
|
6431
|
-
}
|
|
6432
|
-
} catch (e) {
|
|
6433
|
-
console.log("could not init github scm", e);
|
|
6434
|
-
const error = e;
|
|
6435
|
-
const code = error.status || error.statusCode || error.response?.status || error.response?.statusCode || error.response?.code;
|
|
6436
|
-
if (code === 401 || code === 403) {
|
|
6437
|
-
throw new InvalidAccessTokenError(`invalid github access token`);
|
|
6438
|
-
}
|
|
6439
|
-
if (code === 404) {
|
|
6440
|
-
throw new InvalidRepoUrlError(`invalid github repo Url ${url}`);
|
|
6441
|
-
}
|
|
6442
|
-
console.log("githubValidateParams error", e);
|
|
6443
|
-
throw new InvalidRepoUrlError(
|
|
6444
|
-
`cannot access GH repo URL: ${url} with the provided access token`
|
|
6445
|
-
);
|
|
6378
|
+
async getSubmitRequestUrl(submitRequestUrl) {
|
|
6379
|
+
this._validateAccessTokenAndUrl();
|
|
6380
|
+
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
6381
|
+
const getPrRes = await this.githubSdk.getPr({
|
|
6382
|
+
owner,
|
|
6383
|
+
repo,
|
|
6384
|
+
pull_number: submitRequestUrl
|
|
6385
|
+
});
|
|
6386
|
+
return getPrRes.data.html_url;
|
|
6446
6387
|
}
|
|
6447
|
-
|
|
6448
|
-
|
|
6449
|
-
|
|
6450
|
-
|
|
6451
|
-
|
|
6452
|
-
|
|
6453
|
-
|
|
6454
|
-
|
|
6455
|
-
},
|
|
6456
|
-
async updatePrComment(params2) {
|
|
6457
|
-
return octokit.request(UPDATE_COMMENT_PATH, params2);
|
|
6458
|
-
},
|
|
6459
|
-
async getPrComments(params2) {
|
|
6460
|
-
return octokit.request(GET_PR_COMMENTS_PATH, params2);
|
|
6461
|
-
},
|
|
6462
|
-
async getPrComment(params2) {
|
|
6463
|
-
return octokit.request(GET_PR_COMMENT_PATH, params2);
|
|
6464
|
-
},
|
|
6465
|
-
async deleteComment(params2) {
|
|
6466
|
-
return octokit.request(DELETE_COMMENT_PATH, params2);
|
|
6467
|
-
},
|
|
6468
|
-
async replyToCodeReviewComment(params2) {
|
|
6469
|
-
return octokit.request(REPLY_TO_CODE_REVIEW_COMMENT_PATH, params2);
|
|
6470
|
-
},
|
|
6471
|
-
async getPrDiff(params2) {
|
|
6472
|
-
return octokit.request(GET_PR, {
|
|
6473
|
-
...params2,
|
|
6474
|
-
mediaType: { format: "diff" }
|
|
6475
|
-
});
|
|
6476
|
-
},
|
|
6477
|
-
async getPr(params2) {
|
|
6478
|
-
return octokit.request(GET_PR, { ...params2 });
|
|
6479
|
-
},
|
|
6480
|
-
async createOrUpdateRepositorySecret(params2) {
|
|
6481
|
-
return octokit.request(CREATE_OR_UPDATE_A_REPOSITORY_SECRET, params2);
|
|
6482
|
-
},
|
|
6483
|
-
async getRepositoryPublicKey(params2) {
|
|
6484
|
-
return octokit.request(GET_A_REPOSITORY_PUBLIC_KEY, params2);
|
|
6485
|
-
},
|
|
6486
|
-
async postGeneralPrComment(params2) {
|
|
6487
|
-
return octokit.request(POST_GENERAL_PR_COMMENT, params2);
|
|
6488
|
-
},
|
|
6489
|
-
async getGeneralPrComments(params2) {
|
|
6490
|
-
return octokit.request(GET_GENERAL_PR_COMMENTS, params2);
|
|
6491
|
-
},
|
|
6492
|
-
async deleteGeneralPrComment(params2) {
|
|
6493
|
-
return octokit.request(DELETE_GENERAL_PR_COMMENT, params2);
|
|
6494
|
-
},
|
|
6495
|
-
async getGithubUsername() {
|
|
6496
|
-
const res = await octokit.rest.users.getAuthenticated();
|
|
6497
|
-
return res.data.login;
|
|
6498
|
-
},
|
|
6499
|
-
async getGithubIsUserCollaborator(params2) {
|
|
6500
|
-
const { username, repoUrl } = params2;
|
|
6501
|
-
try {
|
|
6502
|
-
const { owner, repo } = parseGithubOwnerAndRepo(repoUrl);
|
|
6503
|
-
const res = await octokit.rest.repos.checkCollaborator({
|
|
6504
|
-
owner,
|
|
6505
|
-
repo,
|
|
6506
|
-
username
|
|
6507
|
-
});
|
|
6508
|
-
if (res.status === 204) {
|
|
6509
|
-
return true;
|
|
6510
|
-
}
|
|
6511
|
-
} catch (e) {
|
|
6512
|
-
return false;
|
|
6513
|
-
}
|
|
6514
|
-
return false;
|
|
6515
|
-
},
|
|
6516
|
-
async getGithubPullRequestStatus(params2) {
|
|
6517
|
-
const { repoUrl, prNumber } = params2;
|
|
6518
|
-
const { owner, repo } = parseGithubOwnerAndRepo(repoUrl);
|
|
6519
|
-
const res = await octokit.rest.pulls.get({
|
|
6520
|
-
owner,
|
|
6521
|
-
repo,
|
|
6522
|
-
pull_number: prNumber
|
|
6523
|
-
});
|
|
6524
|
-
if (res.data.merged) {
|
|
6525
|
-
return "merged";
|
|
6526
|
-
}
|
|
6527
|
-
if (res.data.draft) {
|
|
6528
|
-
return "draft";
|
|
6529
|
-
}
|
|
6530
|
-
return res.data.state;
|
|
6531
|
-
},
|
|
6532
|
-
async createMarkdownCommentOnPullRequest(params2) {
|
|
6533
|
-
const { repoUrl, prNumber, markdownComment } = params2;
|
|
6534
|
-
const { owner, repo } = parseGithubOwnerAndRepo(repoUrl);
|
|
6535
|
-
return octokit.rest.issues.createComment({
|
|
6536
|
-
owner,
|
|
6537
|
-
repo,
|
|
6538
|
-
issue_number: prNumber,
|
|
6539
|
-
body: markdownComment
|
|
6540
|
-
});
|
|
6541
|
-
},
|
|
6542
|
-
async getGithubIsRemoteBranch(params2) {
|
|
6543
|
-
const { repoUrl, branch } = params2;
|
|
6544
|
-
const { owner, repo } = parseGithubOwnerAndRepo(repoUrl);
|
|
6545
|
-
try {
|
|
6546
|
-
const res = await octokit.rest.repos.getBranch({
|
|
6547
|
-
owner,
|
|
6548
|
-
repo,
|
|
6549
|
-
branch
|
|
6550
|
-
});
|
|
6551
|
-
return branch === res.data.name;
|
|
6552
|
-
} catch (e) {
|
|
6553
|
-
return false;
|
|
6554
|
-
}
|
|
6555
|
-
},
|
|
6556
|
-
async getGithubRepoList() {
|
|
6557
|
-
try {
|
|
6558
|
-
const githubRepos = await octokit.request(GET_USER_REPOS, {
|
|
6559
|
-
sort: "updated"
|
|
6560
|
-
});
|
|
6561
|
-
return githubRepos.data.map((repo) => ({
|
|
6562
|
-
repoName: repo.name,
|
|
6563
|
-
repoUrl: repo.html_url,
|
|
6564
|
-
repoOwner: repo.owner.login,
|
|
6565
|
-
repoLanguages: repo.language ? [repo.language] : [],
|
|
6566
|
-
repoIsPublic: !repo.private,
|
|
6567
|
-
repoUpdatedAt: repo.updated_at
|
|
6568
|
-
}));
|
|
6569
|
-
} catch (e) {
|
|
6570
|
-
if (e instanceof RequestError && e.status === 401) {
|
|
6571
|
-
return [];
|
|
6572
|
-
}
|
|
6573
|
-
if (e instanceof RequestError && e.status === 404) {
|
|
6574
|
-
return [];
|
|
6575
|
-
}
|
|
6576
|
-
throw e;
|
|
6577
|
-
}
|
|
6578
|
-
},
|
|
6579
|
-
async getGithubRepoDefaultBranch(repoUrl) {
|
|
6580
|
-
const { owner, repo } = parseGithubOwnerAndRepo(repoUrl);
|
|
6581
|
-
const repos = await octokit.rest.repos.get({ repo, owner });
|
|
6582
|
-
return repos.data.default_branch;
|
|
6583
|
-
},
|
|
6584
|
-
async getGithubReferenceData({
|
|
6585
|
-
ref,
|
|
6586
|
-
gitHubUrl
|
|
6587
|
-
}) {
|
|
6588
|
-
const { owner, repo } = parseGithubOwnerAndRepo(gitHubUrl);
|
|
6589
|
-
let res;
|
|
6590
|
-
try {
|
|
6591
|
-
res = await Promise.any([
|
|
6592
|
-
this.getBranch({ owner, repo, branch: ref }).then((result) => ({
|
|
6593
|
-
date: result.data.commit.commit.committer?.date ? new Date(result.data.commit.commit.committer?.date) : void 0,
|
|
6594
|
-
type: "BRANCH" /* BRANCH */,
|
|
6595
|
-
sha: result.data.commit.sha
|
|
6596
|
-
})),
|
|
6597
|
-
this.getCommit({ commitSha: ref, repo, owner }).then((commit) => ({
|
|
6598
|
-
date: new Date(commit.data.committer.date),
|
|
6599
|
-
type: "COMMIT" /* COMMIT */,
|
|
6600
|
-
sha: commit.data.sha
|
|
6601
|
-
})),
|
|
6602
|
-
this.getTagDate({ owner, repo, tag: ref }).then((data) => ({
|
|
6603
|
-
date: new Date(data.date),
|
|
6604
|
-
type: "TAG" /* TAG */,
|
|
6605
|
-
sha: data.sha
|
|
6606
|
-
}))
|
|
6607
|
-
]);
|
|
6608
|
-
return res;
|
|
6609
|
-
} catch (e) {
|
|
6610
|
-
if (e instanceof AggregateError) {
|
|
6611
|
-
throw new RefNotFoundError(`ref: ${ref} does not exist`);
|
|
6612
|
-
}
|
|
6613
|
-
throw e;
|
|
6614
|
-
}
|
|
6615
|
-
},
|
|
6616
|
-
async getBranch({
|
|
6617
|
-
branch,
|
|
6388
|
+
async getSubmitRequestId(submitRequestUrl) {
|
|
6389
|
+
const match = submitRequestUrl.match(/\/pull\/(\d+)/);
|
|
6390
|
+
return match?.[1] || "";
|
|
6391
|
+
}
|
|
6392
|
+
async getCommitUrl(commitId) {
|
|
6393
|
+
this._validateAccessTokenAndUrl();
|
|
6394
|
+
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
6395
|
+
const getCommitRes = await this.githubSdk.getCommit({
|
|
6618
6396
|
owner,
|
|
6619
|
-
repo
|
|
6620
|
-
|
|
6621
|
-
|
|
6622
|
-
|
|
6623
|
-
|
|
6624
|
-
|
|
6625
|
-
|
|
6626
|
-
|
|
6627
|
-
|
|
6628
|
-
|
|
6397
|
+
repo,
|
|
6398
|
+
commitSha: commitId
|
|
6399
|
+
});
|
|
6400
|
+
return getCommitRes.data.html_url;
|
|
6401
|
+
}
|
|
6402
|
+
async postGeneralPrComment(params) {
|
|
6403
|
+
const { prNumber, body } = params;
|
|
6404
|
+
this._validateAccessTokenAndUrl();
|
|
6405
|
+
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
6406
|
+
return await this.githubSdk.postGeneralPrComment({
|
|
6407
|
+
issue_number: prNumber,
|
|
6629
6408
|
owner,
|
|
6630
|
-
repo
|
|
6631
|
-
|
|
6632
|
-
|
|
6633
|
-
|
|
6634
|
-
|
|
6635
|
-
|
|
6636
|
-
|
|
6637
|
-
}
|
|
6638
|
-
|
|
6639
|
-
|
|
6409
|
+
repo,
|
|
6410
|
+
body
|
|
6411
|
+
});
|
|
6412
|
+
}
|
|
6413
|
+
async getGeneralPrComments(params) {
|
|
6414
|
+
const { prNumber } = params;
|
|
6415
|
+
this._validateAccessTokenAndUrl();
|
|
6416
|
+
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
6417
|
+
return await this.githubSdk.getGeneralPrComments({
|
|
6418
|
+
issue_number: prNumber,
|
|
6640
6419
|
owner,
|
|
6641
6420
|
repo
|
|
6642
|
-
})
|
|
6643
|
-
|
|
6644
|
-
|
|
6645
|
-
|
|
6646
|
-
|
|
6647
|
-
|
|
6648
|
-
|
|
6649
|
-
|
|
6650
|
-
|
|
6651
|
-
|
|
6652
|
-
|
|
6653
|
-
|
|
6654
|
-
|
|
6655
|
-
|
|
6656
|
-
|
|
6657
|
-
|
|
6658
|
-
|
|
6421
|
+
});
|
|
6422
|
+
}
|
|
6423
|
+
async deleteGeneralPrComment({
|
|
6424
|
+
commentId
|
|
6425
|
+
}) {
|
|
6426
|
+
this._validateAccessTokenAndUrl();
|
|
6427
|
+
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
6428
|
+
return this.githubSdk.deleteGeneralPrComment({
|
|
6429
|
+
owner,
|
|
6430
|
+
repo,
|
|
6431
|
+
comment_id: commentId
|
|
6432
|
+
});
|
|
6433
|
+
}
|
|
6434
|
+
};
|
|
6435
|
+
|
|
6436
|
+
// src/features/analysis/scm/gitlab/gitlab.ts
|
|
6437
|
+
import querystring3 from "node:querystring";
|
|
6438
|
+
import {
|
|
6439
|
+
createRequesterFn
|
|
6440
|
+
} from "@gitbeaker/requester-utils";
|
|
6441
|
+
import {
|
|
6442
|
+
AccessLevel,
|
|
6443
|
+
Gitlab
|
|
6444
|
+
} from "@gitbeaker/rest";
|
|
6445
|
+
import Debug4 from "debug";
|
|
6446
|
+
import {
|
|
6447
|
+
fetch as undiciFetch,
|
|
6448
|
+
ProxyAgent as ProxyAgent2
|
|
6449
|
+
} from "undici";
|
|
6450
|
+
|
|
6451
|
+
// src/features/analysis/scm/gitlab/types.ts
|
|
6452
|
+
import { z as z23 } from "zod";
|
|
6453
|
+
var GitlabAuthResultZ = z23.object({
|
|
6454
|
+
access_token: z23.string(),
|
|
6455
|
+
token_type: z23.string(),
|
|
6456
|
+
refresh_token: z23.string()
|
|
6457
|
+
});
|
|
6458
|
+
|
|
6459
|
+
// src/features/analysis/scm/gitlab/gitlab.ts
|
|
6460
|
+
var debug4 = Debug4("scm:gitlab");
|
|
6461
|
+
function removeTrailingSlash2(str) {
|
|
6462
|
+
return str.trim().replace(/\/+$/, "");
|
|
6463
|
+
}
|
|
6464
|
+
function getRandomGitlabCloudAnonToken() {
|
|
6465
|
+
if (!GITLAB_API_TOKEN || typeof GITLAB_API_TOKEN !== "string") {
|
|
6466
|
+
return void 0;
|
|
6467
|
+
}
|
|
6468
|
+
const tokens = GITLAB_API_TOKEN.split(",");
|
|
6469
|
+
return tokens[Math.floor(Math.random() * tokens.length)];
|
|
6470
|
+
}
|
|
6471
|
+
function getGitBeaker(options) {
|
|
6472
|
+
const token = options?.gitlabAuthToken ?? getRandomGitlabCloudAnonToken() ?? "";
|
|
6473
|
+
const url = options.url;
|
|
6474
|
+
const host = url ? new URL(url).origin : "https://gitlab.com";
|
|
6475
|
+
if (token?.startsWith("glpat-") || token === "") {
|
|
6476
|
+
return new Gitlab({
|
|
6477
|
+
token,
|
|
6478
|
+
host,
|
|
6479
|
+
requesterFn: createRequesterFn(
|
|
6480
|
+
(_, reqo) => Promise.resolve(reqo),
|
|
6481
|
+
brokerRequestHandler
|
|
6482
|
+
)
|
|
6483
|
+
});
|
|
6484
|
+
}
|
|
6485
|
+
return new Gitlab({
|
|
6486
|
+
oauthToken: token,
|
|
6487
|
+
host,
|
|
6488
|
+
requesterFn: createRequesterFn(
|
|
6489
|
+
(_, reqo) => Promise.resolve(reqo),
|
|
6490
|
+
brokerRequestHandler
|
|
6491
|
+
)
|
|
6492
|
+
});
|
|
6493
|
+
}
|
|
6494
|
+
async function gitlabValidateParams({
|
|
6495
|
+
url,
|
|
6496
|
+
accessToken
|
|
6497
|
+
}) {
|
|
6498
|
+
try {
|
|
6499
|
+
const api2 = getGitBeaker({ url, gitlabAuthToken: accessToken });
|
|
6500
|
+
if (accessToken) {
|
|
6501
|
+
await api2.Users.showCurrentUser();
|
|
6502
|
+
}
|
|
6503
|
+
if (url && shouldValidateUrl(url)) {
|
|
6504
|
+
const { projectPath } = parseGitlabOwnerAndRepo(url);
|
|
6505
|
+
await api2.Projects.show(projectPath);
|
|
6506
|
+
}
|
|
6507
|
+
} catch (e) {
|
|
6508
|
+
const error = e;
|
|
6509
|
+
const code = error.code || error.status || error.statusCode || error.response?.status || error.response?.statusCode || error.response?.code;
|
|
6510
|
+
const description = error.description || `${e}`;
|
|
6511
|
+
if (code === 401 || code === 403 || description.includes("401") || description.includes("403")) {
|
|
6512
|
+
throw new InvalidAccessTokenError(`invalid gitlab access token`);
|
|
6513
|
+
}
|
|
6514
|
+
if (code === 404 || description.includes("404") || description.includes("Not Found")) {
|
|
6515
|
+
throw new InvalidRepoUrlError(`invalid gitlab repo URL: ${url}`);
|
|
6516
|
+
}
|
|
6517
|
+
console.log("gitlabValidateParams error", e);
|
|
6518
|
+
throw new InvalidRepoUrlError(
|
|
6519
|
+
`cannot access gitlab repo URL: ${url} with the provided access token`
|
|
6520
|
+
);
|
|
6521
|
+
}
|
|
6522
|
+
}
|
|
6523
|
+
async function getGitlabUsername(url, accessToken) {
|
|
6524
|
+
const api2 = getGitBeaker({ url, gitlabAuthToken: accessToken });
|
|
6525
|
+
const res = await api2.Users.showCurrentUser();
|
|
6526
|
+
return res.username;
|
|
6527
|
+
}
|
|
6528
|
+
async function getGitlabIsUserCollaborator({
|
|
6529
|
+
accessToken,
|
|
6530
|
+
repoUrl
|
|
6531
|
+
}) {
|
|
6532
|
+
try {
|
|
6533
|
+
const { projectPath } = parseGitlabOwnerAndRepo(repoUrl);
|
|
6534
|
+
const api2 = getGitBeaker({ url: repoUrl, gitlabAuthToken: accessToken });
|
|
6535
|
+
const proj = await api2.Projects.show(projectPath);
|
|
6536
|
+
const groupAccess = proj.permissions?.group_access?.access_level || 0;
|
|
6537
|
+
const projectAccess = proj.permissions?.project_access?.access_level || 0;
|
|
6538
|
+
const accessLevelWithWriteAccess = [
|
|
6539
|
+
AccessLevel.DEVELOPER,
|
|
6540
|
+
AccessLevel.MAINTAINER,
|
|
6541
|
+
AccessLevel.OWNER,
|
|
6542
|
+
AccessLevel.ADMIN
|
|
6543
|
+
];
|
|
6544
|
+
return accessLevelWithWriteAccess.includes(groupAccess) || accessLevelWithWriteAccess.includes(projectAccess);
|
|
6545
|
+
} catch (e) {
|
|
6546
|
+
return false;
|
|
6547
|
+
}
|
|
6548
|
+
}
|
|
6549
|
+
var gitlabMergeRequestStatus = {
|
|
6550
|
+
merged: "merged",
|
|
6551
|
+
opened: "opened",
|
|
6552
|
+
closed: "closed"
|
|
6553
|
+
};
|
|
6554
|
+
async function getGitlabMergeRequestStatus({
|
|
6555
|
+
accessToken,
|
|
6556
|
+
repoUrl,
|
|
6557
|
+
mrNumber
|
|
6558
|
+
}) {
|
|
6559
|
+
const { projectPath } = parseGitlabOwnerAndRepo(repoUrl);
|
|
6560
|
+
const api2 = getGitBeaker({ url: repoUrl, gitlabAuthToken: accessToken });
|
|
6561
|
+
const res = await api2.MergeRequests.show(projectPath, mrNumber);
|
|
6562
|
+
switch (res.state) {
|
|
6563
|
+
case gitlabMergeRequestStatus.merged:
|
|
6564
|
+
case gitlabMergeRequestStatus.opened:
|
|
6565
|
+
case gitlabMergeRequestStatus.closed:
|
|
6566
|
+
return res.state;
|
|
6567
|
+
default:
|
|
6568
|
+
throw new Error(`unknown merge request state ${res.state}`);
|
|
6569
|
+
}
|
|
6570
|
+
}
|
|
6571
|
+
async function createMarkdownCommentOnPullRequest({
|
|
6572
|
+
markdownComment,
|
|
6573
|
+
accessToken,
|
|
6574
|
+
repoUrl,
|
|
6575
|
+
mrNumber
|
|
6576
|
+
}) {
|
|
6577
|
+
const { projectPath } = parseGitlabOwnerAndRepo(repoUrl);
|
|
6578
|
+
const api2 = getGitBeaker({ url: repoUrl, gitlabAuthToken: accessToken });
|
|
6579
|
+
return api2.MergeRequestNotes.create(projectPath, mrNumber, markdownComment);
|
|
6580
|
+
}
|
|
6581
|
+
async function getGitlabIsRemoteBranch({
|
|
6582
|
+
accessToken,
|
|
6583
|
+
repoUrl,
|
|
6584
|
+
branch
|
|
6585
|
+
}) {
|
|
6586
|
+
const { projectPath } = parseGitlabOwnerAndRepo(repoUrl);
|
|
6587
|
+
const api2 = getGitBeaker({ url: repoUrl, gitlabAuthToken: accessToken });
|
|
6588
|
+
try {
|
|
6589
|
+
const res = await api2.Branches.show(projectPath, branch);
|
|
6590
|
+
return res.name === branch;
|
|
6591
|
+
} catch (e) {
|
|
6592
|
+
return false;
|
|
6593
|
+
}
|
|
6594
|
+
}
|
|
6595
|
+
async function getGitlabRepoList(url, accessToken) {
|
|
6596
|
+
const api2 = getGitBeaker({ url, gitlabAuthToken: accessToken });
|
|
6597
|
+
const res = await api2.Projects.all({
|
|
6598
|
+
membership: true,
|
|
6599
|
+
//TODO: a bug in the sorting mechanism of this api call
|
|
6600
|
+
//disallows us to sort by updated_at in descending order
|
|
6601
|
+
//so we have to sort by updated_at in ascending order.
|
|
6602
|
+
//We can wait for the bug to be fixed or call the api
|
|
6603
|
+
//directly with fetch()
|
|
6604
|
+
sort: "asc",
|
|
6605
|
+
orderBy: "updated_at",
|
|
6606
|
+
perPage: 100
|
|
6607
|
+
});
|
|
6608
|
+
return Promise.all(
|
|
6609
|
+
res.map(async (project) => {
|
|
6610
|
+
const proj = await api2.Projects.show(project.id);
|
|
6611
|
+
const owner = proj.namespace.name;
|
|
6612
|
+
const repoLanguages = await api2.Projects.showLanguages(project.id);
|
|
6613
|
+
return {
|
|
6614
|
+
repoName: project.path,
|
|
6615
|
+
repoUrl: project.web_url,
|
|
6616
|
+
repoOwner: owner,
|
|
6617
|
+
repoLanguages: Object.keys(repoLanguages),
|
|
6618
|
+
repoIsPublic: project.visibility === "public",
|
|
6619
|
+
repoUpdatedAt: project.last_activity_at
|
|
6620
|
+
};
|
|
6621
|
+
})
|
|
6622
|
+
);
|
|
6623
|
+
}
|
|
6624
|
+
async function getGitlabBranchList({
|
|
6625
|
+
accessToken,
|
|
6626
|
+
repoUrl
|
|
6627
|
+
}) {
|
|
6628
|
+
const { projectPath } = parseGitlabOwnerAndRepo(repoUrl);
|
|
6629
|
+
const api2 = getGitBeaker({ url: repoUrl, gitlabAuthToken: accessToken });
|
|
6630
|
+
try {
|
|
6631
|
+
const res = await api2.Branches.all(projectPath, {
|
|
6632
|
+
//keyset API pagination is not supported by GL for the branch list (at least not the on-prem version)
|
|
6633
|
+
//so for now we stick with the default pagination and just return the first page and limit the results to 1000 entries.
|
|
6634
|
+
//This is a temporary solution until we implement list branches with name search.
|
|
6635
|
+
perPage: MAX_BRANCHES_FETCH,
|
|
6636
|
+
page: 1
|
|
6637
|
+
});
|
|
6638
|
+
res.sort((a, b) => {
|
|
6639
|
+
if (!a.commit?.committed_date || !b.commit?.committed_date) {
|
|
6640
|
+
return 0;
|
|
6659
6641
|
}
|
|
6660
|
-
|
|
6661
|
-
|
|
6662
|
-
|
|
6663
|
-
|
|
6664
|
-
|
|
6642
|
+
return new Date(b.commit?.committed_date).getTime() - new Date(a.commit?.committed_date).getTime();
|
|
6643
|
+
});
|
|
6644
|
+
return res.map((branch) => branch.name).slice(0, MAX_BRANCHES_FETCH);
|
|
6645
|
+
} catch (e) {
|
|
6646
|
+
return [];
|
|
6647
|
+
}
|
|
6648
|
+
}
|
|
6649
|
+
async function createMergeRequest(options) {
|
|
6650
|
+
const { projectPath } = parseGitlabOwnerAndRepo(options.repoUrl);
|
|
6651
|
+
const api2 = getGitBeaker({
|
|
6652
|
+
url: options.repoUrl,
|
|
6653
|
+
gitlabAuthToken: options.accessToken
|
|
6654
|
+
});
|
|
6655
|
+
const res = await api2.MergeRequests.create(
|
|
6656
|
+
projectPath,
|
|
6657
|
+
options.sourceBranchName,
|
|
6658
|
+
options.targetBranchName,
|
|
6659
|
+
options.title,
|
|
6660
|
+
{
|
|
6661
|
+
description: options.body
|
|
6662
|
+
}
|
|
6663
|
+
);
|
|
6664
|
+
return res.iid;
|
|
6665
|
+
}
|
|
6666
|
+
async function getGitlabMergeRequest({
|
|
6667
|
+
url,
|
|
6668
|
+
prNumber,
|
|
6669
|
+
accessToken
|
|
6670
|
+
}) {
|
|
6671
|
+
const { projectPath } = parseGitlabOwnerAndRepo(url);
|
|
6672
|
+
const api2 = getGitBeaker({
|
|
6673
|
+
url,
|
|
6674
|
+
gitlabAuthToken: accessToken
|
|
6675
|
+
});
|
|
6676
|
+
return await api2.MergeRequests.show(projectPath, prNumber);
|
|
6677
|
+
}
|
|
6678
|
+
async function getGitlabCommitUrl({
|
|
6679
|
+
url,
|
|
6680
|
+
commitSha,
|
|
6681
|
+
accessToken
|
|
6682
|
+
}) {
|
|
6683
|
+
const { projectPath } = parseGitlabOwnerAndRepo(url);
|
|
6684
|
+
const api2 = getGitBeaker({
|
|
6685
|
+
url,
|
|
6686
|
+
gitlabAuthToken: accessToken
|
|
6687
|
+
});
|
|
6688
|
+
return await api2.Commits.show(projectPath, commitSha);
|
|
6689
|
+
}
|
|
6690
|
+
async function getGitlabRepoDefaultBranch(repoUrl, options) {
|
|
6691
|
+
const api2 = getGitBeaker({
|
|
6692
|
+
url: repoUrl,
|
|
6693
|
+
gitlabAuthToken: options?.gitlabAuthToken
|
|
6694
|
+
});
|
|
6695
|
+
const { projectPath } = parseGitlabOwnerAndRepo(repoUrl);
|
|
6696
|
+
const project = await api2.Projects.show(projectPath);
|
|
6697
|
+
if (!project.default_branch) {
|
|
6698
|
+
throw new Error("no default branch");
|
|
6699
|
+
}
|
|
6700
|
+
return project.default_branch;
|
|
6701
|
+
}
|
|
6702
|
+
async function getGitlabReferenceData({ ref, gitlabUrl }, options) {
|
|
6703
|
+
const { projectPath } = parseGitlabOwnerAndRepo(gitlabUrl);
|
|
6704
|
+
const api2 = getGitBeaker({
|
|
6705
|
+
url: gitlabUrl,
|
|
6706
|
+
gitlabAuthToken: options?.gitlabAuthToken
|
|
6707
|
+
});
|
|
6708
|
+
const results = await Promise.allSettled([
|
|
6709
|
+
(async () => {
|
|
6710
|
+
const res = await api2.Branches.show(projectPath, ref);
|
|
6665
6711
|
return {
|
|
6666
|
-
|
|
6667
|
-
|
|
6712
|
+
sha: res.commit.id,
|
|
6713
|
+
type: "BRANCH" /* BRANCH */,
|
|
6714
|
+
date: res.commit.committed_date ? new Date(res.commit.committed_date) : void 0
|
|
6668
6715
|
};
|
|
6669
|
-
},
|
|
6670
|
-
async
|
|
6671
|
-
const
|
|
6672
|
-
const { owner, repo } = parseGithubOwnerAndRepo(gitHubUrl);
|
|
6673
|
-
const res = await octokit.graphql(
|
|
6674
|
-
GET_BLAME_DOCUMENT,
|
|
6675
|
-
{
|
|
6676
|
-
owner,
|
|
6677
|
-
repo,
|
|
6678
|
-
path: path8,
|
|
6679
|
-
ref
|
|
6680
|
-
}
|
|
6681
|
-
);
|
|
6682
|
-
if (!res?.repository?.object?.blame?.ranges) {
|
|
6683
|
-
return [];
|
|
6684
|
-
}
|
|
6685
|
-
return res.repository.object.blame.ranges.map((range) => ({
|
|
6686
|
-
startingLine: range.startingLine,
|
|
6687
|
-
endingLine: range.endingLine,
|
|
6688
|
-
email: range.commit.author.user?.email || "",
|
|
6689
|
-
name: range.commit.author.user?.name || "",
|
|
6690
|
-
login: range.commit.author.user?.login || ""
|
|
6691
|
-
}));
|
|
6692
|
-
},
|
|
6693
|
-
// todo: refactor the name for this function
|
|
6694
|
-
async createPr(params2) {
|
|
6695
|
-
const { sourceRepoUrl, filesPaths, userRepoUrl, title, body } = params2;
|
|
6696
|
-
const { owner: sourceOwner, repo: sourceRepo } = parseGithubOwnerAndRepo(sourceRepoUrl);
|
|
6697
|
-
const { owner, repo } = parseGithubOwnerAndRepo(userRepoUrl);
|
|
6698
|
-
const [sourceFilePath, secondFilePath] = filesPaths;
|
|
6699
|
-
const sourceFileContentResponse = await octokit.rest.repos.getContent({
|
|
6700
|
-
owner: sourceOwner,
|
|
6701
|
-
repo: sourceRepo,
|
|
6702
|
-
path: "/" + sourceFilePath
|
|
6703
|
-
});
|
|
6704
|
-
const { data: repository } = await octokit.rest.repos.get({ owner, repo });
|
|
6705
|
-
const defaultBranch = repository.default_branch;
|
|
6706
|
-
const newBranchName = `mobb/workflow-${Date.now()}`;
|
|
6707
|
-
await octokit.rest.git.createRef({
|
|
6708
|
-
owner,
|
|
6709
|
-
repo,
|
|
6710
|
-
ref: `refs/heads/${newBranchName}`,
|
|
6711
|
-
sha: await octokit.rest.git.getRef({ owner, repo, ref: `heads/${defaultBranch}` }).then((response) => response.data.object.sha)
|
|
6712
|
-
});
|
|
6713
|
-
const decodedContent = Buffer.from(
|
|
6714
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
6715
|
-
// @ts-ignore
|
|
6716
|
-
sourceFileContentResponse.data.content,
|
|
6717
|
-
"base64"
|
|
6718
|
-
).toString("utf-8");
|
|
6719
|
-
const tree = [
|
|
6720
|
-
{
|
|
6721
|
-
path: sourceFilePath,
|
|
6722
|
-
mode: "100644",
|
|
6723
|
-
type: "blob",
|
|
6724
|
-
content: decodedContent
|
|
6725
|
-
}
|
|
6726
|
-
];
|
|
6727
|
-
if (secondFilePath) {
|
|
6728
|
-
const secondFileContentResponse = await octokit.rest.repos.getContent({
|
|
6729
|
-
owner: sourceOwner,
|
|
6730
|
-
repo: sourceRepo,
|
|
6731
|
-
path: "/" + secondFilePath
|
|
6732
|
-
});
|
|
6733
|
-
const secondDecodedContent = Buffer.from(
|
|
6734
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
6735
|
-
// @ts-ignore
|
|
6736
|
-
secondFileContentResponse.data.content,
|
|
6737
|
-
"base64"
|
|
6738
|
-
).toString("utf-8");
|
|
6739
|
-
tree.push({
|
|
6740
|
-
path: secondFilePath,
|
|
6741
|
-
mode: "100644",
|
|
6742
|
-
type: "blob",
|
|
6743
|
-
content: secondDecodedContent
|
|
6744
|
-
});
|
|
6745
|
-
}
|
|
6746
|
-
const createTreeResponse = await octokit.rest.git.createTree({
|
|
6747
|
-
owner,
|
|
6748
|
-
repo,
|
|
6749
|
-
base_tree: await octokit.rest.git.getRef({ owner, repo, ref: `heads/${defaultBranch}` }).then((response) => response.data.object.sha),
|
|
6750
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
6751
|
-
// @ts-ignore
|
|
6752
|
-
tree
|
|
6753
|
-
});
|
|
6754
|
-
const createCommitResponse = await octokit.rest.git.createCommit({
|
|
6755
|
-
owner,
|
|
6756
|
-
repo,
|
|
6757
|
-
message: "Add new yaml file",
|
|
6758
|
-
tree: createTreeResponse.data.sha,
|
|
6759
|
-
parents: [
|
|
6760
|
-
await octokit.rest.git.getRef({ owner, repo, ref: `heads/${defaultBranch}` }).then((response) => response.data.object.sha)
|
|
6761
|
-
]
|
|
6762
|
-
});
|
|
6763
|
-
await octokit.rest.git.updateRef({
|
|
6764
|
-
owner,
|
|
6765
|
-
repo,
|
|
6766
|
-
ref: `heads/${newBranchName}`,
|
|
6767
|
-
sha: createCommitResponse.data.sha
|
|
6768
|
-
});
|
|
6769
|
-
const createPRResponse = await octokit.rest.pulls.create({
|
|
6770
|
-
owner,
|
|
6771
|
-
repo,
|
|
6772
|
-
title,
|
|
6773
|
-
head: newBranchName,
|
|
6774
|
-
head_repo: sourceRepo,
|
|
6775
|
-
body,
|
|
6776
|
-
base: defaultBranch
|
|
6777
|
-
});
|
|
6716
|
+
})(),
|
|
6717
|
+
(async () => {
|
|
6718
|
+
const res = await api2.Commits.show(projectPath, ref);
|
|
6778
6719
|
return {
|
|
6779
|
-
|
|
6720
|
+
sha: res.id,
|
|
6721
|
+
type: "COMMIT" /* COMMIT */,
|
|
6722
|
+
date: res.committed_date ? new Date(res.committed_date) : void 0
|
|
6780
6723
|
};
|
|
6781
|
-
},
|
|
6782
|
-
async
|
|
6783
|
-
const
|
|
6784
|
-
return
|
|
6785
|
-
|
|
6786
|
-
|
|
6787
|
-
|
|
6788
|
-
|
|
6789
|
-
|
|
6790
|
-
|
|
6791
|
-
|
|
6792
|
-
|
|
6793
|
-
|
|
6794
|
-
|
|
6795
|
-
|
|
6796
|
-
|
|
6797
|
-
|
|
6798
|
-
|
|
6799
|
-
|
|
6800
|
-
|
|
6801
|
-
|
|
6802
|
-
|
|
6803
|
-
|
|
6804
|
-
|
|
6805
|
-
|
|
6806
|
-
|
|
6807
|
-
|
|
6808
|
-
|
|
6809
|
-
|
|
6810
|
-
|
|
6811
|
-
|
|
6812
|
-
|
|
6813
|
-
|
|
6814
|
-
|
|
6724
|
+
})(),
|
|
6725
|
+
(async () => {
|
|
6726
|
+
const res = await api2.Tags.show(projectPath, ref);
|
|
6727
|
+
return {
|
|
6728
|
+
sha: res.commit.id,
|
|
6729
|
+
type: "TAG" /* TAG */,
|
|
6730
|
+
date: res.commit.committed_date ? new Date(res.commit.committed_date) : void 0
|
|
6731
|
+
};
|
|
6732
|
+
})()
|
|
6733
|
+
]);
|
|
6734
|
+
const [branchRes, commitRes, tagRes] = results;
|
|
6735
|
+
if (tagRes.status === "fulfilled") {
|
|
6736
|
+
return tagRes.value;
|
|
6737
|
+
}
|
|
6738
|
+
if (branchRes.status === "fulfilled") {
|
|
6739
|
+
return branchRes.value;
|
|
6740
|
+
}
|
|
6741
|
+
if (commitRes.status === "fulfilled") {
|
|
6742
|
+
return commitRes.value;
|
|
6743
|
+
}
|
|
6744
|
+
throw new RefNotFoundError(`ref: ${ref} does not exist`);
|
|
6745
|
+
}
|
|
6746
|
+
function parseGitlabOwnerAndRepo(gitlabUrl) {
|
|
6747
|
+
gitlabUrl = removeTrailingSlash2(gitlabUrl);
|
|
6748
|
+
const parsingResult = parseScmURL(gitlabUrl, "GitLab" /* GitLab */);
|
|
6749
|
+
if (!parsingResult || !parsingResult.repoName) {
|
|
6750
|
+
throw new InvalidUrlPatternError(`invalid gitlab repo Url ${gitlabUrl}`);
|
|
6751
|
+
}
|
|
6752
|
+
const { organization, repoName, projectPath } = parsingResult;
|
|
6753
|
+
return { owner: organization, repo: repoName, projectPath };
|
|
6754
|
+
}
|
|
6755
|
+
async function getGitlabBlameRanges({ ref, gitlabUrl, path: path8 }, options) {
|
|
6756
|
+
const { projectPath } = parseGitlabOwnerAndRepo(gitlabUrl);
|
|
6757
|
+
const api2 = getGitBeaker({
|
|
6758
|
+
url: gitlabUrl,
|
|
6759
|
+
gitlabAuthToken: options?.gitlabAuthToken
|
|
6760
|
+
});
|
|
6761
|
+
const resp = await api2.RepositoryFiles.allFileBlames(projectPath, path8, ref);
|
|
6762
|
+
let lineNumber = 1;
|
|
6763
|
+
return resp.filter((range) => range.lines).map((range) => {
|
|
6764
|
+
const oldLineNumber = lineNumber;
|
|
6765
|
+
if (!range.lines) {
|
|
6766
|
+
throw new Error("range.lines should not be undefined");
|
|
6815
6767
|
}
|
|
6816
|
-
|
|
6768
|
+
lineNumber += range.lines.length;
|
|
6769
|
+
return {
|
|
6770
|
+
startingLine: oldLineNumber,
|
|
6771
|
+
endingLine: lineNumber - 1,
|
|
6772
|
+
login: range.commit.author_email,
|
|
6773
|
+
email: range.commit.author_email,
|
|
6774
|
+
name: range.commit.author_name
|
|
6775
|
+
};
|
|
6776
|
+
});
|
|
6777
|
+
}
|
|
6778
|
+
async function processBody(response) {
|
|
6779
|
+
const headers = response.headers;
|
|
6780
|
+
const type2 = headers.get("content-type")?.split(";")[0]?.trim();
|
|
6781
|
+
if (type2 === "application/json") {
|
|
6782
|
+
return await response.json();
|
|
6783
|
+
}
|
|
6784
|
+
return await response.text();
|
|
6785
|
+
}
|
|
6786
|
+
async function brokerRequestHandler(endpoint, options) {
|
|
6787
|
+
const { prefixUrl, searchParams } = options || {};
|
|
6788
|
+
let baseUrl;
|
|
6789
|
+
if (prefixUrl) baseUrl = prefixUrl.endsWith("/") ? prefixUrl : `${prefixUrl}/`;
|
|
6790
|
+
const url = new URL(endpoint, baseUrl);
|
|
6791
|
+
url.search = searchParams || "";
|
|
6792
|
+
const dispatcher = url && isBrokerUrl(url.href) ? new ProxyAgent2({
|
|
6793
|
+
uri: GIT_PROXY_HOST,
|
|
6794
|
+
requestTls: {
|
|
6795
|
+
rejectUnauthorized: false
|
|
6796
|
+
}
|
|
6797
|
+
}) : void 0;
|
|
6798
|
+
const response = await undiciFetch(url, {
|
|
6799
|
+
headers: options?.headers,
|
|
6800
|
+
method: options?.method,
|
|
6801
|
+
body: options?.body ? String(options?.body) : void 0,
|
|
6802
|
+
dispatcher
|
|
6803
|
+
}).catch((e) => {
|
|
6804
|
+
if (e.name === "TimeoutError" || e.name === "AbortError") {
|
|
6805
|
+
throw new Error("Query timeout was reached");
|
|
6806
|
+
}
|
|
6807
|
+
throw e;
|
|
6808
|
+
});
|
|
6809
|
+
if (response.ok)
|
|
6810
|
+
return {
|
|
6811
|
+
body: await processBody(response),
|
|
6812
|
+
headers: Object.fromEntries(response.headers.entries()),
|
|
6813
|
+
status: response.status
|
|
6814
|
+
};
|
|
6815
|
+
throw new Error(`gitbeaker: ${response.statusText}`);
|
|
6817
6816
|
}
|
|
6818
6817
|
|
|
6819
|
-
// src/features/analysis/scm/
|
|
6820
|
-
var
|
|
6821
|
-
// we don't always need a url, what's important is that we have an access token
|
|
6818
|
+
// src/features/analysis/scm/gitlab/GitlabSCMLib.ts
|
|
6819
|
+
var GitlabSCMLib = class extends SCMLib {
|
|
6822
6820
|
constructor(url, accessToken, scmOrg) {
|
|
6823
6821
|
super(url, accessToken, scmOrg);
|
|
6824
|
-
__publicField(this, "githubSdk");
|
|
6825
|
-
this.githubSdk = getGithubSdk({
|
|
6826
|
-
auth: accessToken,
|
|
6827
|
-
url
|
|
6828
|
-
});
|
|
6829
6822
|
}
|
|
6830
6823
|
async createSubmitRequest(params) {
|
|
6831
6824
|
this._validateAccessTokenAndUrl();
|
|
6832
6825
|
const { targetBranchName, sourceBranchName, title, body } = params;
|
|
6833
|
-
|
|
6834
|
-
|
|
6835
|
-
|
|
6836
|
-
|
|
6837
|
-
|
|
6838
|
-
|
|
6839
|
-
|
|
6840
|
-
|
|
6841
|
-
|
|
6842
|
-
|
|
6843
|
-
this._validateAccessToken();
|
|
6844
|
-
return this.githubSdk.forkRepo({
|
|
6845
|
-
repoUrl
|
|
6846
|
-
});
|
|
6847
|
-
}
|
|
6848
|
-
async createOrUpdateRepositorySecret(params) {
|
|
6849
|
-
this._validateAccessTokenAndUrl();
|
|
6850
|
-
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
6851
|
-
const { data: repositoryPublicKeyResponse } = await this.githubSdk.getRepositoryPublicKey({ owner, repo });
|
|
6852
|
-
const { key_id, key } = repositoryPublicKeyResponse;
|
|
6853
|
-
const encryptedValue = await encryptSecret(params.value, key);
|
|
6854
|
-
return this.githubSdk.createOrUpdateRepositorySecret({
|
|
6855
|
-
encrypted_value: encryptedValue,
|
|
6856
|
-
secret_name: params.name,
|
|
6857
|
-
key_id,
|
|
6858
|
-
owner,
|
|
6859
|
-
repo
|
|
6860
|
-
});
|
|
6861
|
-
}
|
|
6862
|
-
async createPullRequestWithNewFile(sourceRepoUrl, filesPaths, userRepoUrl, title, body) {
|
|
6863
|
-
const { pull_request_url } = await this.githubSdk.createPr({
|
|
6864
|
-
sourceRepoUrl,
|
|
6865
|
-
filesPaths,
|
|
6866
|
-
userRepoUrl,
|
|
6867
|
-
title,
|
|
6868
|
-
body
|
|
6869
|
-
});
|
|
6870
|
-
return { pull_request_url };
|
|
6826
|
+
return String(
|
|
6827
|
+
await createMergeRequest({
|
|
6828
|
+
title,
|
|
6829
|
+
body,
|
|
6830
|
+
targetBranchName,
|
|
6831
|
+
sourceBranchName,
|
|
6832
|
+
repoUrl: this.url,
|
|
6833
|
+
accessToken: this.accessToken
|
|
6834
|
+
})
|
|
6835
|
+
);
|
|
6871
6836
|
}
|
|
6872
6837
|
async validateParams() {
|
|
6873
|
-
return
|
|
6874
|
-
|
|
6875
|
-
|
|
6876
|
-
this._validateAccessTokenAndUrl();
|
|
6877
|
-
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
6878
|
-
return this.githubSdk.postPrComment({
|
|
6879
|
-
...params,
|
|
6880
|
-
owner,
|
|
6881
|
-
repo
|
|
6882
|
-
});
|
|
6883
|
-
}
|
|
6884
|
-
async updatePrComment(params) {
|
|
6885
|
-
this._validateAccessTokenAndUrl();
|
|
6886
|
-
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
6887
|
-
return this.githubSdk.updatePrComment({
|
|
6888
|
-
...params,
|
|
6889
|
-
owner,
|
|
6890
|
-
repo
|
|
6891
|
-
});
|
|
6892
|
-
}
|
|
6893
|
-
async deleteComment(params) {
|
|
6894
|
-
this._validateAccessTokenAndUrl();
|
|
6895
|
-
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
6896
|
-
return this.githubSdk.deleteComment({
|
|
6897
|
-
...params,
|
|
6898
|
-
owner,
|
|
6899
|
-
repo
|
|
6900
|
-
});
|
|
6901
|
-
}
|
|
6902
|
-
async getPrComments(params) {
|
|
6903
|
-
this._validateAccessTokenAndUrl();
|
|
6904
|
-
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
6905
|
-
return this.githubSdk.getPrComments({
|
|
6906
|
-
per_page: 100,
|
|
6907
|
-
...params,
|
|
6908
|
-
owner,
|
|
6909
|
-
repo
|
|
6910
|
-
});
|
|
6911
|
-
}
|
|
6912
|
-
async getPrDiff(params) {
|
|
6913
|
-
this._validateAccessTokenAndUrl();
|
|
6914
|
-
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
6915
|
-
const prRes = await this.githubSdk.getPrDiff({
|
|
6916
|
-
...params,
|
|
6917
|
-
owner,
|
|
6918
|
-
repo
|
|
6838
|
+
return gitlabValidateParams({
|
|
6839
|
+
url: this.url,
|
|
6840
|
+
accessToken: this.accessToken
|
|
6919
6841
|
});
|
|
6920
|
-
return z24.string().parse(prRes.data);
|
|
6921
6842
|
}
|
|
6922
6843
|
async getRepoList(_scmOrg) {
|
|
6923
|
-
this.
|
|
6924
|
-
|
|
6844
|
+
if (!this.accessToken) {
|
|
6845
|
+
console.error("no access token");
|
|
6846
|
+
throw new Error("no access token");
|
|
6847
|
+
}
|
|
6848
|
+
return getGitlabRepoList(this.url, this.accessToken);
|
|
6925
6849
|
}
|
|
6926
6850
|
async getBranchList() {
|
|
6927
6851
|
this._validateAccessTokenAndUrl();
|
|
6928
|
-
|
|
6929
|
-
|
|
6852
|
+
return getGitlabBranchList({
|
|
6853
|
+
accessToken: this.accessToken,
|
|
6854
|
+
repoUrl: this.url
|
|
6855
|
+
});
|
|
6930
6856
|
}
|
|
6931
6857
|
get scmLibType() {
|
|
6932
|
-
return "
|
|
6858
|
+
return "GITLAB" /* GITLAB */;
|
|
6933
6859
|
}
|
|
6934
6860
|
getAuthHeaders() {
|
|
6935
|
-
if (this.accessToken) {
|
|
6861
|
+
if (!this.accessToken) {
|
|
6862
|
+
return {};
|
|
6863
|
+
}
|
|
6864
|
+
if (this.accessToken.startsWith("glpat-")) {
|
|
6865
|
+
return {
|
|
6866
|
+
"Private-Token": this.accessToken
|
|
6867
|
+
};
|
|
6868
|
+
} else {
|
|
6936
6869
|
return { authorization: `Bearer ${this.accessToken}` };
|
|
6937
6870
|
}
|
|
6938
|
-
return {};
|
|
6939
6871
|
}
|
|
6940
6872
|
getDownloadUrl(sha) {
|
|
6941
|
-
this.
|
|
6942
|
-
const
|
|
6943
|
-
|
|
6944
|
-
|
|
6945
|
-
|
|
6946
|
-
|
|
6947
|
-
|
|
6948
|
-
|
|
6873
|
+
const urlObj = new URL(this.url || "");
|
|
6874
|
+
const ProjectId = encodeURIComponent(
|
|
6875
|
+
urlObj.pathname.replace(/^\//, "").replace(/\/$/, "")
|
|
6876
|
+
);
|
|
6877
|
+
return Promise.resolve(
|
|
6878
|
+
//We are moving away from this form as it doesn't work when using a non-human token (group/project token)
|
|
6879
|
+
//Where as the API zip endpoint works with any token
|
|
6880
|
+
//`${this.url}/-/archive/${sha}/${repoName}-${sha}.zip`
|
|
6881
|
+
`${urlObj.origin}/api/v4/projects/${ProjectId}/repository/archive.zip?sha=${sha}`
|
|
6882
|
+
);
|
|
6949
6883
|
}
|
|
6950
6884
|
async _getUsernameForAuthUrl() {
|
|
6951
|
-
|
|
6885
|
+
if (this?.accessToken?.startsWith("glpat-")) {
|
|
6886
|
+
return this.getUsername();
|
|
6887
|
+
} else {
|
|
6888
|
+
return "oauth2";
|
|
6889
|
+
}
|
|
6952
6890
|
}
|
|
6953
6891
|
async getIsRemoteBranch(branch) {
|
|
6954
|
-
this.
|
|
6955
|
-
return
|
|
6892
|
+
this._validateAccessTokenAndUrl();
|
|
6893
|
+
return getGitlabIsRemoteBranch({
|
|
6894
|
+
accessToken: this.accessToken,
|
|
6895
|
+
repoUrl: this.url,
|
|
6896
|
+
branch
|
|
6897
|
+
});
|
|
6956
6898
|
}
|
|
6957
6899
|
async getUserHasAccessToRepo() {
|
|
6958
6900
|
this._validateAccessTokenAndUrl();
|
|
6959
|
-
|
|
6960
|
-
|
|
6961
|
-
repoUrl: this.url
|
|
6962
|
-
username
|
|
6901
|
+
return getGitlabIsUserCollaborator({
|
|
6902
|
+
accessToken: this.accessToken,
|
|
6903
|
+
repoUrl: this.url
|
|
6963
6904
|
});
|
|
6964
6905
|
}
|
|
6965
6906
|
async getUsername() {
|
|
6966
|
-
this.
|
|
6967
|
-
return this.
|
|
6907
|
+
this._validateAccessTokenAndUrl();
|
|
6908
|
+
return getGitlabUsername(this.url, this.accessToken);
|
|
6968
6909
|
}
|
|
6969
6910
|
async getSubmitRequestStatus(scmSubmitRequestId) {
|
|
6970
6911
|
this._validateAccessTokenAndUrl();
|
|
6971
|
-
|
|
6912
|
+
const state = await getGitlabMergeRequestStatus({
|
|
6913
|
+
accessToken: this.accessToken,
|
|
6972
6914
|
repoUrl: this.url,
|
|
6973
|
-
|
|
6915
|
+
mrNumber: Number(scmSubmitRequestId)
|
|
6974
6916
|
});
|
|
6917
|
+
switch (state) {
|
|
6918
|
+
case gitlabMergeRequestStatus.merged:
|
|
6919
|
+
return "merged";
|
|
6920
|
+
case gitlabMergeRequestStatus.opened:
|
|
6921
|
+
return "open";
|
|
6922
|
+
case gitlabMergeRequestStatus.closed:
|
|
6923
|
+
return "closed";
|
|
6924
|
+
default:
|
|
6925
|
+
throw new Error(`unknown state ${state}`);
|
|
6926
|
+
}
|
|
6975
6927
|
}
|
|
6976
6928
|
async addCommentToSubmitRequest(submitRequestId, comment) {
|
|
6977
6929
|
this._validateAccessTokenAndUrl();
|
|
6978
|
-
await
|
|
6930
|
+
await createMarkdownCommentOnPullRequest({
|
|
6931
|
+
accessToken: this.accessToken,
|
|
6979
6932
|
repoUrl: this.url,
|
|
6980
|
-
|
|
6933
|
+
mrNumber: Number(submitRequestId),
|
|
6981
6934
|
markdownComment: comment
|
|
6982
6935
|
});
|
|
6983
6936
|
}
|
|
6984
6937
|
async getRepoBlameRanges(ref, path8) {
|
|
6985
6938
|
this._validateUrl();
|
|
6986
|
-
return await
|
|
6987
|
-
ref,
|
|
6988
|
-
|
|
6989
|
-
|
|
6990
|
-
|
|
6939
|
+
return await getGitlabBlameRanges(
|
|
6940
|
+
{ ref, path: path8, gitlabUrl: this.url },
|
|
6941
|
+
{
|
|
6942
|
+
url: this.url,
|
|
6943
|
+
gitlabAuthToken: this.accessToken
|
|
6944
|
+
}
|
|
6945
|
+
);
|
|
6991
6946
|
}
|
|
6992
6947
|
async getReferenceData(ref) {
|
|
6993
6948
|
this._validateUrl();
|
|
6994
|
-
return
|
|
6995
|
-
|
|
6996
|
-
|
|
6997
|
-
|
|
6998
|
-
|
|
6999
|
-
|
|
7000
|
-
|
|
7001
|
-
owner,
|
|
7002
|
-
comment_id: commentId
|
|
7003
|
-
});
|
|
6949
|
+
return await getGitlabReferenceData(
|
|
6950
|
+
{ ref, gitlabUrl: this.url },
|
|
6951
|
+
{
|
|
6952
|
+
url: this.url,
|
|
6953
|
+
gitlabAuthToken: this.accessToken
|
|
6954
|
+
}
|
|
6955
|
+
);
|
|
7004
6956
|
}
|
|
7005
6957
|
async getRepoDefaultBranch() {
|
|
7006
6958
|
this._validateUrl();
|
|
7007
|
-
return await
|
|
6959
|
+
return await getGitlabRepoDefaultBranch(this.url, {
|
|
6960
|
+
url: this.url,
|
|
6961
|
+
gitlabAuthToken: this.accessToken
|
|
6962
|
+
});
|
|
7008
6963
|
}
|
|
7009
6964
|
async getSubmitRequestUrl(submitRequestUrl) {
|
|
7010
6965
|
this._validateAccessTokenAndUrl();
|
|
7011
|
-
const
|
|
7012
|
-
|
|
7013
|
-
|
|
7014
|
-
|
|
7015
|
-
pull_number: submitRequestUrl
|
|
6966
|
+
const res = await getGitlabMergeRequest({
|
|
6967
|
+
url: this.url,
|
|
6968
|
+
prNumber: submitRequestUrl,
|
|
6969
|
+
accessToken: this.accessToken
|
|
7016
6970
|
});
|
|
7017
|
-
return
|
|
6971
|
+
return res.web_url;
|
|
7018
6972
|
}
|
|
7019
6973
|
async getSubmitRequestId(submitRequestUrl) {
|
|
7020
|
-
const match = submitRequestUrl.match(/\/
|
|
6974
|
+
const match = submitRequestUrl.match(/\/merge_requests\/(\d+)/);
|
|
7021
6975
|
return match?.[1] || "";
|
|
7022
6976
|
}
|
|
7023
6977
|
async getCommitUrl(commitId) {
|
|
7024
6978
|
this._validateAccessTokenAndUrl();
|
|
7025
|
-
const
|
|
7026
|
-
|
|
7027
|
-
|
|
7028
|
-
|
|
7029
|
-
commitSha: commitId
|
|
6979
|
+
const res = await getGitlabCommitUrl({
|
|
6980
|
+
url: this.url,
|
|
6981
|
+
commitSha: commitId,
|
|
6982
|
+
accessToken: this.accessToken
|
|
7030
6983
|
});
|
|
7031
|
-
return
|
|
6984
|
+
return res.web_url;
|
|
7032
6985
|
}
|
|
7033
|
-
|
|
7034
|
-
|
|
7035
|
-
|
|
7036
|
-
|
|
7037
|
-
|
|
7038
|
-
|
|
7039
|
-
|
|
7040
|
-
|
|
7041
|
-
|
|
7042
|
-
});
|
|
6986
|
+
};
|
|
6987
|
+
|
|
6988
|
+
// src/features/analysis/scm/scmFactory.ts
|
|
6989
|
+
import { z as z24 } from "zod";
|
|
6990
|
+
|
|
6991
|
+
// src/features/analysis/scm/StubSCMLib.ts
|
|
6992
|
+
var StubSCMLib = class extends SCMLib {
|
|
6993
|
+
constructor(url, accessToken, scmOrg) {
|
|
6994
|
+
super(url, accessToken, scmOrg);
|
|
7043
6995
|
}
|
|
7044
|
-
async
|
|
7045
|
-
|
|
7046
|
-
|
|
7047
|
-
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
7048
|
-
return await this.githubSdk.getGeneralPrComments({
|
|
7049
|
-
issue_number: prNumber,
|
|
7050
|
-
owner,
|
|
7051
|
-
repo
|
|
7052
|
-
});
|
|
6996
|
+
async getUrlWithCredentials() {
|
|
6997
|
+
console.warn("getUrlWithCredentials() returning empty string");
|
|
6998
|
+
return "";
|
|
7053
6999
|
}
|
|
7054
|
-
async
|
|
7055
|
-
|
|
7056
|
-
|
|
7057
|
-
|
|
7058
|
-
|
|
7059
|
-
|
|
7060
|
-
|
|
7061
|
-
|
|
7062
|
-
|
|
7063
|
-
|
|
7000
|
+
async createSubmitRequest(_params) {
|
|
7001
|
+
console.warn("createSubmitRequest() returning empty string");
|
|
7002
|
+
return "";
|
|
7003
|
+
}
|
|
7004
|
+
get scmLibType() {
|
|
7005
|
+
console.warn("scmLibType returning GITHUB as default");
|
|
7006
|
+
return "GITHUB" /* GITHUB */;
|
|
7007
|
+
}
|
|
7008
|
+
getAuthHeaders() {
|
|
7009
|
+
console.warn("getAuthHeaders() returning empty object");
|
|
7010
|
+
return {};
|
|
7011
|
+
}
|
|
7012
|
+
async getDownloadUrl(_sha) {
|
|
7013
|
+
console.warn("getDownloadUrl() returning empty string");
|
|
7014
|
+
return "";
|
|
7015
|
+
}
|
|
7016
|
+
async getIsRemoteBranch(_branch) {
|
|
7017
|
+
console.warn("getIsRemoteBranch() returning false");
|
|
7018
|
+
return false;
|
|
7019
|
+
}
|
|
7020
|
+
async validateParams() {
|
|
7021
|
+
console.warn("validateParams() no-op");
|
|
7022
|
+
}
|
|
7023
|
+
async getRepoList(_scmOrg) {
|
|
7024
|
+
console.warn("getRepoList() returning empty array");
|
|
7025
|
+
return [];
|
|
7026
|
+
}
|
|
7027
|
+
async getBranchList() {
|
|
7028
|
+
console.warn("getBranchList() returning empty array");
|
|
7029
|
+
return [];
|
|
7030
|
+
}
|
|
7031
|
+
async getUsername() {
|
|
7032
|
+
console.warn("getUsername() returning empty string");
|
|
7033
|
+
return "";
|
|
7034
|
+
}
|
|
7035
|
+
async getSubmitRequestStatus(_scmSubmitRequestId) {
|
|
7036
|
+
console.warn("getSubmitRequestStatus() returning ERROR");
|
|
7037
|
+
return "error";
|
|
7038
|
+
}
|
|
7039
|
+
async getUserHasAccessToRepo() {
|
|
7040
|
+
console.warn("getUserHasAccessToRepo() returning false");
|
|
7041
|
+
return false;
|
|
7042
|
+
}
|
|
7043
|
+
async getRepoBlameRanges(_ref, _path) {
|
|
7044
|
+
console.warn("getRepoBlameRanges() returning empty array");
|
|
7045
|
+
return [];
|
|
7046
|
+
}
|
|
7047
|
+
async getReferenceData(_ref) {
|
|
7048
|
+
console.warn("getReferenceData() returning null/empty defaults");
|
|
7049
|
+
return {
|
|
7050
|
+
type: "BRANCH" /* BRANCH */,
|
|
7051
|
+
sha: "",
|
|
7052
|
+
date: void 0
|
|
7053
|
+
};
|
|
7054
|
+
}
|
|
7055
|
+
async getRepoDefaultBranch() {
|
|
7056
|
+
console.warn("getRepoDefaultBranch() returning empty string");
|
|
7057
|
+
return "";
|
|
7058
|
+
}
|
|
7059
|
+
async getSubmitRequestUrl(_submitRequestIdNumber) {
|
|
7060
|
+
console.warn("getSubmitRequestUrl() returning empty string");
|
|
7061
|
+
return "";
|
|
7062
|
+
}
|
|
7063
|
+
async getSubmitRequestId(_submitRequestUrl) {
|
|
7064
|
+
console.warn("getSubmitRequestId() returning empty string");
|
|
7065
|
+
return "";
|
|
7066
|
+
}
|
|
7067
|
+
async getCommitUrl(_commitId) {
|
|
7068
|
+
console.warn("getCommitUrl() returning empty string");
|
|
7069
|
+
return "";
|
|
7070
|
+
}
|
|
7071
|
+
async _getUsernameForAuthUrl() {
|
|
7072
|
+
console.warn("_getUsernameForAuthUrl() returning empty string");
|
|
7073
|
+
return "";
|
|
7074
|
+
}
|
|
7075
|
+
async addCommentToSubmitRequest(_submitRequestId, _comment) {
|
|
7076
|
+
console.warn("addCommentToSubmitRequest() no-op");
|
|
7064
7077
|
}
|
|
7065
7078
|
};
|
|
7066
7079
|
|
|
7080
|
+
// src/features/analysis/scm/scmFactory.ts
|
|
7081
|
+
async function createScmLib({ url, accessToken, scmType, scmOrg }, { propagateExceptions = false } = {}) {
|
|
7082
|
+
const trimmedUrl = url ? url.trim().replace(/\/$/, "").replace(/.git$/i, "") : void 0;
|
|
7083
|
+
try {
|
|
7084
|
+
switch (scmType) {
|
|
7085
|
+
case "GITHUB" /* GITHUB */: {
|
|
7086
|
+
const scm = new GithubSCMLib(trimmedUrl, accessToken, scmOrg);
|
|
7087
|
+
await scm.validateParams();
|
|
7088
|
+
return scm;
|
|
7089
|
+
}
|
|
7090
|
+
case "GITLAB" /* GITLAB */: {
|
|
7091
|
+
const scm = new GitlabSCMLib(trimmedUrl, accessToken, scmOrg);
|
|
7092
|
+
await scm.validateParams();
|
|
7093
|
+
return scm;
|
|
7094
|
+
}
|
|
7095
|
+
case "ADO" /* ADO */: {
|
|
7096
|
+
const scm = new AdoSCMLib(trimmedUrl, accessToken, scmOrg);
|
|
7097
|
+
await scm.getAdoSdk();
|
|
7098
|
+
await scm.validateParams();
|
|
7099
|
+
return scm;
|
|
7100
|
+
}
|
|
7101
|
+
case "BITBUCKET" /* BITBUCKET */: {
|
|
7102
|
+
const scm = new BitbucketSCMLib(trimmedUrl, accessToken, scmOrg);
|
|
7103
|
+
await scm.validateParams();
|
|
7104
|
+
return scm;
|
|
7105
|
+
}
|
|
7106
|
+
}
|
|
7107
|
+
} catch (e) {
|
|
7108
|
+
if (e instanceof InvalidRepoUrlError && url) {
|
|
7109
|
+
throw new RepoNoTokenAccessError(
|
|
7110
|
+
"no access to repo",
|
|
7111
|
+
scmLibScmTypeToScmType[z24.nativeEnum(ScmLibScmType).parse(scmType)]
|
|
7112
|
+
);
|
|
7113
|
+
}
|
|
7114
|
+
console.error(`error validating scm: ${scmType} `, e);
|
|
7115
|
+
if (propagateExceptions) {
|
|
7116
|
+
throw e;
|
|
7117
|
+
}
|
|
7118
|
+
}
|
|
7119
|
+
return new StubSCMLib(trimmedUrl, void 0, void 0);
|
|
7120
|
+
}
|
|
7121
|
+
|
|
7067
7122
|
// src/features/analysis/add_fix_comments_for_pr/utils/utils.ts
|
|
7068
7123
|
import Debug7 from "debug";
|
|
7069
7124
|
import parseDiff from "parse-diff";
|
|
@@ -7238,7 +7293,8 @@ function buildIssueCommentBody({
|
|
|
7238
7293
|
projectId,
|
|
7239
7294
|
analysisId,
|
|
7240
7295
|
organizationId,
|
|
7241
|
-
irrelevantIssueWithTags
|
|
7296
|
+
irrelevantIssueWithTags,
|
|
7297
|
+
fpDescription
|
|
7242
7298
|
}) {
|
|
7243
7299
|
const issueUrl = getIssueUrlWithRedirect({
|
|
7244
7300
|
appBaseUrl: WEB_APP_URL,
|
|
@@ -7253,9 +7309,10 @@ function buildIssueCommentBody({
|
|
|
7253
7309
|
const subTitle = getCommitIssueDescription({
|
|
7254
7310
|
issueType,
|
|
7255
7311
|
vendor: scannerToVulnerability_Report_Vendor_Enum[scanner],
|
|
7256
|
-
irrelevantIssueWithTags
|
|
7312
|
+
irrelevantIssueWithTags,
|
|
7313
|
+
fpDescription
|
|
7257
7314
|
});
|
|
7258
|
-
const issuePageLink = `[Learn more
|
|
7315
|
+
const issuePageLink = `[Learn more about this issue](${issueUrl})`;
|
|
7259
7316
|
return `${title}
|
|
7260
7317
|
${subTitle}
|
|
7261
7318
|
${issuePageLink}`;
|
|
@@ -7326,7 +7383,8 @@ async function postIssueComment(params) {
|
|
|
7326
7383
|
scm,
|
|
7327
7384
|
commitSha,
|
|
7328
7385
|
pullRequest,
|
|
7329
|
-
scanner
|
|
7386
|
+
scanner,
|
|
7387
|
+
fpDescription
|
|
7330
7388
|
} = params;
|
|
7331
7389
|
const {
|
|
7332
7390
|
path: path8,
|
|
@@ -7357,7 +7415,8 @@ Refresh the page in order to see the changes.`,
|
|
|
7357
7415
|
scanner,
|
|
7358
7416
|
projectId,
|
|
7359
7417
|
analysisId,
|
|
7360
|
-
organizationId
|
|
7418
|
+
organizationId,
|
|
7419
|
+
fpDescription
|
|
7361
7420
|
});
|
|
7362
7421
|
return await scm.updatePrComment({
|
|
7363
7422
|
body: commentBody,
|
|
@@ -7570,33 +7629,49 @@ async function addFixCommentsForPr({
|
|
|
7570
7629
|
});
|
|
7571
7630
|
}
|
|
7572
7631
|
),
|
|
7573
|
-
...irrelevantVulnerabilityReportIssues.map(
|
|
7574
|
-
|
|
7575
|
-
|
|
7576
|
-
|
|
7577
|
-
|
|
7578
|
-
|
|
7579
|
-
startLine: vulnerabilityReportIssueCodeNode.startLine,
|
|
7580
|
-
vulnerabilityReportIssue: {
|
|
7581
|
-
fixId: "",
|
|
7582
|
-
safeIssueType: vulnerabilityReportIssue.safeIssueType,
|
|
7583
|
-
vulnerabilityReportIssueTags: vulnerabilityReportIssue.vulnerabilityReportIssueTags,
|
|
7584
|
-
category: vulnerabilityReportIssue.category
|
|
7585
|
-
},
|
|
7586
|
-
vulnerabilityReportIssueId: vulnerabilityReportIssue.id
|
|
7587
|
-
},
|
|
7588
|
-
projectId,
|
|
7589
|
-
analysisId,
|
|
7590
|
-
organizationId,
|
|
7591
|
-
fixesById,
|
|
7592
|
-
scm,
|
|
7593
|
-
pullRequest,
|
|
7594
|
-
scanner,
|
|
7595
|
-
commitSha
|
|
7632
|
+
...irrelevantVulnerabilityReportIssues.map(
|
|
7633
|
+
async (vulnerabilityReportIssue) => {
|
|
7634
|
+
let fpDescription = null;
|
|
7635
|
+
if (vulnerabilityReportIssue.fpId) {
|
|
7636
|
+
const fpRes = await gqlClient.getFalsePositive({
|
|
7637
|
+
fpId: vulnerabilityReportIssue.fpId
|
|
7596
7638
|
});
|
|
7639
|
+
const parsedFpRes = await FalsePositivePartsZ.parseAsync(
|
|
7640
|
+
fpRes?.getFalsePositive
|
|
7641
|
+
);
|
|
7642
|
+
const { description, contextString } = getParsedFalsePositiveMessage(parsedFpRes);
|
|
7643
|
+
fpDescription = contextString ? `${description}
|
|
7644
|
+
|
|
7645
|
+
${contextString}` : description;
|
|
7597
7646
|
}
|
|
7598
|
-
|
|
7599
|
-
|
|
7647
|
+
return vulnerabilityReportIssue.codeNodes.map(
|
|
7648
|
+
(vulnerabilityReportIssueCodeNode) => {
|
|
7649
|
+
return postIssueComment({
|
|
7650
|
+
vulnerabilityReportIssueCodeNode: {
|
|
7651
|
+
path: vulnerabilityReportIssueCodeNode.path,
|
|
7652
|
+
startLine: vulnerabilityReportIssueCodeNode.startLine,
|
|
7653
|
+
vulnerabilityReportIssue: {
|
|
7654
|
+
fixId: "",
|
|
7655
|
+
safeIssueType: vulnerabilityReportIssue.safeIssueType,
|
|
7656
|
+
vulnerabilityReportIssueTags: vulnerabilityReportIssue.vulnerabilityReportIssueTags,
|
|
7657
|
+
category: vulnerabilityReportIssue.category
|
|
7658
|
+
},
|
|
7659
|
+
vulnerabilityReportIssueId: vulnerabilityReportIssue.id
|
|
7660
|
+
},
|
|
7661
|
+
projectId,
|
|
7662
|
+
analysisId,
|
|
7663
|
+
organizationId,
|
|
7664
|
+
fixesById,
|
|
7665
|
+
scm,
|
|
7666
|
+
pullRequest,
|
|
7667
|
+
scanner,
|
|
7668
|
+
commitSha,
|
|
7669
|
+
fpDescription
|
|
7670
|
+
});
|
|
7671
|
+
}
|
|
7672
|
+
);
|
|
7673
|
+
}
|
|
7674
|
+
),
|
|
7600
7675
|
postAnalysisInsightComment({
|
|
7601
7676
|
prVulenrabilities,
|
|
7602
7677
|
pullRequest,
|
|
@@ -7827,6 +7902,7 @@ var VulnerabilityReportIssueNoFixCodeNodeZ = z27.object({
|
|
|
7827
7902
|
fixId: z27.string().nullable(),
|
|
7828
7903
|
category: ValidCategoriesZ,
|
|
7829
7904
|
safeIssueType: z27.string(),
|
|
7905
|
+
fpId: z27.string().uuid().nullable(),
|
|
7830
7906
|
codeNodes: z27.array(
|
|
7831
7907
|
z27.object({
|
|
7832
7908
|
path: z27.string(),
|
|
@@ -8190,6 +8266,9 @@ var GQLClient = class {
|
|
|
8190
8266
|
async getReferenceData(args) {
|
|
8191
8267
|
return this._clientSdk.gitReference(args);
|
|
8192
8268
|
}
|
|
8269
|
+
async getFalsePositive(args) {
|
|
8270
|
+
return this._clientSdk.getFalsePositive(args);
|
|
8271
|
+
}
|
|
8193
8272
|
};
|
|
8194
8273
|
|
|
8195
8274
|
// src/features/analysis/pack.ts
|