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