@zereight/mcp-gitlab 2.0.13 → 2.0.19
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/README.md +75 -9
- package/build/gitlab-client-pool.js +113 -0
- package/build/index.js +450 -356
- package/build/oauth.js +20 -11
- package/build/test/client-pool-test.js +109 -0
- package/build/test/dynamic-api-url-test.js +304 -0
- package/build/test/dynamic-routing-tests.js +442 -0
- package/build/test/multi-server-test.js +182 -0
- package/build/test/remote-auth-simple-test.js +2 -0
- package/build/test/utils/mock-gitlab-server.js +73 -4
- package/build/test/utils/server-launcher.js +25 -9
- package/package.json +8 -4
package/build/index.js
CHANGED
|
@@ -18,6 +18,7 @@ import { fileURLToPath } from "url";
|
|
|
18
18
|
import { z } from "zod";
|
|
19
19
|
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
20
20
|
import { initializeOAuth } from "./oauth.js";
|
|
21
|
+
import { GitLabClientPool } from "./gitlab-client-pool.js";
|
|
21
22
|
// Add type imports for proxy agents
|
|
22
23
|
import { Agent } from "http";
|
|
23
24
|
import { Agent as HttpsAgent } from "https";
|
|
@@ -120,13 +121,15 @@ function validateConfiguration() {
|
|
|
120
121
|
}
|
|
121
122
|
}
|
|
122
123
|
// Validate GITLAB_API_URL format
|
|
123
|
-
const
|
|
124
|
-
if (
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
124
|
+
const apiUrls = process.env.GITLAB_API_URL?.split(',') || [];
|
|
125
|
+
if (apiUrls.length > 0) {
|
|
126
|
+
for (const url of apiUrls) {
|
|
127
|
+
try {
|
|
128
|
+
new URL(url.trim());
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
errors.push(`GITLAB_API_URL contains an invalid URL: ${url.trim()}`);
|
|
132
|
+
}
|
|
130
133
|
}
|
|
131
134
|
}
|
|
132
135
|
// Validate auth configuration
|
|
@@ -137,6 +140,9 @@ function validateConfiguration() {
|
|
|
137
140
|
if (!remoteAuth && !useOAuth && !hasToken && !hasCookie) {
|
|
138
141
|
errors.push('Either GITLAB_PERSONAL_ACCESS_TOKEN, GITLAB_AUTH_COOKIE_PATH, GITLAB_USE_OAUTH=true, or REMOTE_AUTHORIZATION=true must be set');
|
|
139
142
|
}
|
|
143
|
+
if (ENABLE_DYNAMIC_API_URL && !REMOTE_AUTHORIZATION) {
|
|
144
|
+
errors.push('ENABLE_DYNAMIC_API_URL=true requires REMOTE_AUTHORIZATION=true');
|
|
145
|
+
}
|
|
140
146
|
if (errors.length > 0) {
|
|
141
147
|
logger.error('Configuration validation failed:');
|
|
142
148
|
errors.forEach(err => logger.error(` - ${err}`));
|
|
@@ -157,6 +163,7 @@ const USE_PIPELINE = process.env.USE_PIPELINE === "true";
|
|
|
157
163
|
const SSE = process.env.SSE === "true";
|
|
158
164
|
const STREAMABLE_HTTP = process.env.STREAMABLE_HTTP === "true";
|
|
159
165
|
const REMOTE_AUTHORIZATION = process.env.REMOTE_AUTHORIZATION === "true";
|
|
166
|
+
const ENABLE_DYNAMIC_API_URL = process.env.ENABLE_DYNAMIC_API_URL === "true";
|
|
160
167
|
const SESSION_TIMEOUT_SECONDS = process.env.SESSION_TIMEOUT_SECONDS ? parseInt(process.env.SESSION_TIMEOUT_SECONDS) : 3600;
|
|
161
168
|
const HOST = process.env.HOST || "0.0.0.0";
|
|
162
169
|
const PORT = process.env.PORT || 3002;
|
|
@@ -165,6 +172,7 @@ const HTTP_PROXY = process.env.HTTP_PROXY;
|
|
|
165
172
|
const HTTPS_PROXY = process.env.HTTPS_PROXY;
|
|
166
173
|
const NODE_TLS_REJECT_UNAUTHORIZED = process.env.NODE_TLS_REJECT_UNAUTHORIZED;
|
|
167
174
|
const GITLAB_CA_CERT_PATH = process.env.GITLAB_CA_CERT_PATH;
|
|
175
|
+
const GITLAB_POOL_MAX_SIZE = process.env.GITLAB_POOL_MAX_SIZE ? parseInt(process.env.GITLAB_POOL_MAX_SIZE) : 100;
|
|
168
176
|
let sslOptions = undefined;
|
|
169
177
|
if (NODE_TLS_REJECT_UNAUTHORIZED === "0") {
|
|
170
178
|
sslOptions = { rejectUnauthorized: false };
|
|
@@ -194,6 +202,15 @@ if (HTTPS_PROXY) {
|
|
|
194
202
|
}
|
|
195
203
|
httpsAgent = httpsAgent || new HttpsAgent(sslOptions);
|
|
196
204
|
httpAgent = httpAgent || new Agent();
|
|
205
|
+
// Initialize the client pool for managing multiple GitLab instances
|
|
206
|
+
const clientPool = new GitLabClientPool({
|
|
207
|
+
apiUrls: (process.env.GITLAB_API_URL || "https://gitlab.com").split(',').map(normalizeGitLabApiUrl),
|
|
208
|
+
httpProxy: HTTP_PROXY,
|
|
209
|
+
httpsProxy: HTTPS_PROXY,
|
|
210
|
+
rejectUnauthorized: NODE_TLS_REJECT_UNAUTHORIZED !== "0",
|
|
211
|
+
caCertPath: GITLAB_CA_CERT_PATH,
|
|
212
|
+
poolMaxSize: GITLAB_POOL_MAX_SIZE,
|
|
213
|
+
});
|
|
197
214
|
// Create cookie jar with clean Netscape file parsing
|
|
198
215
|
const createCookieJar = () => {
|
|
199
216
|
if (!GITLAB_AUTH_COOKIE_PATH)
|
|
@@ -251,7 +268,7 @@ async function ensureSessionForRequest() {
|
|
|
251
268
|
try {
|
|
252
269
|
// Establish session with a lightweight request
|
|
253
270
|
await fetch(`${GITLAB_API_URL}/user`, {
|
|
254
|
-
...
|
|
271
|
+
...getFetchConfig(),
|
|
255
272
|
redirect: "follow",
|
|
256
273
|
}).catch(() => {
|
|
257
274
|
// Ignore errors - the important thing is that cookies get set during redirects
|
|
@@ -265,6 +282,9 @@ async function ensureSessionForRequest() {
|
|
|
265
282
|
}
|
|
266
283
|
}
|
|
267
284
|
const sessionAuthStore = new AsyncLocalStorage();
|
|
285
|
+
// Session context map for storing auth data by session ID
|
|
286
|
+
// This survives async boundaries where AsyncLocalStorage might not
|
|
287
|
+
const authBySession = {};
|
|
268
288
|
// Base headers without authentication
|
|
269
289
|
const BASE_HEADERS = {
|
|
270
290
|
Accept: "application/json",
|
|
@@ -278,6 +298,7 @@ const BASE_HEADERS = {
|
|
|
278
298
|
function buildAuthHeaders() {
|
|
279
299
|
if (REMOTE_AUTHORIZATION) {
|
|
280
300
|
const ctx = sessionAuthStore.getStore();
|
|
301
|
+
logger.debug({ context: ctx }, "buildAuthHeaders: session context");
|
|
281
302
|
if (ctx && ctx.token) {
|
|
282
303
|
return {
|
|
283
304
|
[ctx.header]: ctx.header === 'Authorization' ? `Bearer ${ctx.token}` : ctx.token
|
|
@@ -295,17 +316,38 @@ function buildAuthHeaders() {
|
|
|
295
316
|
}
|
|
296
317
|
return {};
|
|
297
318
|
}
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
319
|
+
/**
|
|
320
|
+
* Get the effective GitLab API URL for the current request
|
|
321
|
+
* In REMOTE_AUTHORIZATION mode with ENABLE_DYNAMIC_API_URL, reads from session context
|
|
322
|
+
* Otherwise, uses environment GITLAB_API_URL
|
|
323
|
+
*/
|
|
324
|
+
function getEffectiveApiUrl() {
|
|
325
|
+
if (ENABLE_DYNAMIC_API_URL) {
|
|
326
|
+
const ctx = sessionAuthStore.getStore();
|
|
327
|
+
if (ctx && ctx.apiUrl) {
|
|
328
|
+
return ctx.apiUrl;
|
|
306
329
|
}
|
|
307
|
-
|
|
308
|
-
}
|
|
330
|
+
logger.warn({ ctx }, "getEffectiveApiUrl: No context or apiUrl found, falling back to default");
|
|
331
|
+
}
|
|
332
|
+
return GITLAB_API_URL;
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Get fetch configuration with proper client from pool
|
|
336
|
+
* Uses connection pooling when dynamic API URLs are enabled
|
|
337
|
+
*/
|
|
338
|
+
/**
|
|
339
|
+
* Constructs the fetch configuration dynamically.
|
|
340
|
+
* This function is called immediately before each `fetch` to ensure it runs
|
|
341
|
+
* within the correct AsyncLocalStorage context, capturing the necessary auth
|
|
342
|
+
* and API URL information for the current request.
|
|
343
|
+
*/
|
|
344
|
+
const getFetchConfig = () => {
|
|
345
|
+
const effectiveApiUrl = getEffectiveApiUrl();
|
|
346
|
+
const agent = clientPool.getOrCreateAgentForUrl(effectiveApiUrl);
|
|
347
|
+
return {
|
|
348
|
+
headers: { ...BASE_HEADERS, ...buildAuthHeaders() },
|
|
349
|
+
agent: agent,
|
|
350
|
+
};
|
|
309
351
|
};
|
|
310
352
|
const toJSONSchema = (schema) => zodToJsonSchema(schema, { $refStrategy: 'none' });
|
|
311
353
|
// Define all available tools
|
|
@@ -924,17 +966,18 @@ function normalizeGitLabApiUrl(url) {
|
|
|
924
966
|
if (!url) {
|
|
925
967
|
return "https://gitlab.com/api/v4";
|
|
926
968
|
}
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
969
|
+
let normalizedUrl = url.trim();
|
|
970
|
+
if (normalizedUrl.endsWith("/")) {
|
|
971
|
+
normalizedUrl = normalizedUrl.slice(0, -1);
|
|
972
|
+
}
|
|
973
|
+
if (!normalizedUrl.endsWith("/api/v4")) {
|
|
932
974
|
normalizedUrl = `${normalizedUrl}/api/v4`;
|
|
933
975
|
}
|
|
934
976
|
return normalizedUrl;
|
|
935
977
|
}
|
|
936
978
|
// Use the normalizeGitLabApiUrl function to handle various URL formats
|
|
937
|
-
const
|
|
979
|
+
const GITLAB_API_URLS = (process.env.GITLAB_API_URL || "https://gitlab.com").split(',').map(normalizeGitLabApiUrl);
|
|
980
|
+
const GITLAB_API_URL = GITLAB_API_URLS[0];
|
|
938
981
|
const GITLAB_PROJECT_ID = process.env.GITLAB_PROJECT_ID;
|
|
939
982
|
const GITLAB_ALLOWED_PROJECT_IDS = process.env.GITLAB_ALLOWED_PROJECT_IDS?.split(',').map(id => id.trim()).filter(Boolean) || [];
|
|
940
983
|
const GITLAB_COMMIT_FILES_PER_PAGE = process.env.GITLAB_COMMIT_FILES_PER_PAGE ? parseInt(process.env.GITLAB_COMMIT_FILES_PER_PAGE) : 20;
|
|
@@ -1015,12 +1058,12 @@ function getEffectiveProjectId(projectId) {
|
|
|
1015
1058
|
async function forkProject(projectId, namespace) {
|
|
1016
1059
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
1017
1060
|
const effectiveProjectId = getEffectiveProjectId(projectId);
|
|
1018
|
-
const url = new URL(`${
|
|
1061
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(effectiveProjectId)}/fork`);
|
|
1019
1062
|
if (namespace) {
|
|
1020
1063
|
url.searchParams.append("namespace", namespace);
|
|
1021
1064
|
}
|
|
1022
1065
|
const response = await fetch(url.toString(), {
|
|
1023
|
-
...
|
|
1066
|
+
...getFetchConfig(),
|
|
1024
1067
|
method: "POST",
|
|
1025
1068
|
});
|
|
1026
1069
|
// 이미 존재하는 프로젝트인 경우 처리
|
|
@@ -1042,9 +1085,9 @@ async function forkProject(projectId, namespace) {
|
|
|
1042
1085
|
async function createBranch(projectId, options) {
|
|
1043
1086
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
1044
1087
|
const effectiveProjectId = getEffectiveProjectId(projectId);
|
|
1045
|
-
const url = new URL(`${
|
|
1088
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(effectiveProjectId)}/repository/branches`);
|
|
1046
1089
|
const response = await fetch(url.toString(), {
|
|
1047
|
-
...
|
|
1090
|
+
...getFetchConfig(),
|
|
1048
1091
|
method: "POST",
|
|
1049
1092
|
body: JSON.stringify({
|
|
1050
1093
|
branch: options.name,
|
|
@@ -1064,9 +1107,9 @@ async function createBranch(projectId, options) {
|
|
|
1064
1107
|
async function getDefaultBranchRef(projectId) {
|
|
1065
1108
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
1066
1109
|
const effectiveProjectId = getEffectiveProjectId(projectId);
|
|
1067
|
-
const url = new URL(`${
|
|
1110
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(effectiveProjectId)}`);
|
|
1068
1111
|
const response = await fetch(url.toString(), {
|
|
1069
|
-
...
|
|
1112
|
+
...getFetchConfig(),
|
|
1070
1113
|
});
|
|
1071
1114
|
await handleGitLabError(response);
|
|
1072
1115
|
const project = GitLabRepositorySchema.parse(await response.json());
|
|
@@ -1089,10 +1132,10 @@ async function getFileContents(projectId, filePath, ref) {
|
|
|
1089
1132
|
if (!ref) {
|
|
1090
1133
|
ref = await getDefaultBranchRef(projectId);
|
|
1091
1134
|
}
|
|
1092
|
-
const url = new URL(`${
|
|
1135
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(effectiveProjectId)}/repository/files/${encodedPath}`);
|
|
1093
1136
|
url.searchParams.append("ref", ref);
|
|
1094
1137
|
const response = await fetch(url.toString(), {
|
|
1095
|
-
...
|
|
1138
|
+
...getFetchConfig(),
|
|
1096
1139
|
});
|
|
1097
1140
|
// 파일을 찾을 수 없는 경우 처리
|
|
1098
1141
|
if (response.status === 404) {
|
|
@@ -1119,9 +1162,9 @@ async function getFileContents(projectId, filePath, ref) {
|
|
|
1119
1162
|
async function createIssue(projectId, options) {
|
|
1120
1163
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
1121
1164
|
const effectiveProjectId = getEffectiveProjectId(projectId);
|
|
1122
|
-
const url = new URL(`${
|
|
1165
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(effectiveProjectId)}/issues`);
|
|
1123
1166
|
const response = await fetch(url.toString(), {
|
|
1124
|
-
...
|
|
1167
|
+
...getFetchConfig(),
|
|
1125
1168
|
method: "POST",
|
|
1126
1169
|
body: JSON.stringify({
|
|
1127
1170
|
title: options.title,
|
|
@@ -1153,10 +1196,10 @@ async function listIssues(projectId, options = {}) {
|
|
|
1153
1196
|
if (projectId) {
|
|
1154
1197
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
1155
1198
|
const effectiveProjectId = getEffectiveProjectId(projectId);
|
|
1156
|
-
url = new URL(`${
|
|
1199
|
+
url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(effectiveProjectId)}/issues`);
|
|
1157
1200
|
}
|
|
1158
1201
|
else {
|
|
1159
|
-
url = new URL(`${
|
|
1202
|
+
url = new URL(`${getEffectiveApiUrl()}/issues`);
|
|
1160
1203
|
}
|
|
1161
1204
|
// Add all query parameters
|
|
1162
1205
|
Object.entries(options).forEach(([key, value]) => {
|
|
@@ -1179,7 +1222,7 @@ async function listIssues(projectId, options = {}) {
|
|
|
1179
1222
|
}
|
|
1180
1223
|
});
|
|
1181
1224
|
const response = await fetch(url.toString(), {
|
|
1182
|
-
...
|
|
1225
|
+
...getFetchConfig(),
|
|
1183
1226
|
});
|
|
1184
1227
|
await handleGitLabError(response);
|
|
1185
1228
|
const data = await response.json();
|
|
@@ -1194,7 +1237,7 @@ async function listIssues(projectId, options = {}) {
|
|
|
1194
1237
|
*/
|
|
1195
1238
|
async function listMergeRequests(projectId, options = {}) {
|
|
1196
1239
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
1197
|
-
const url = new URL(`${
|
|
1240
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/merge_requests`);
|
|
1198
1241
|
// Add all query parameters
|
|
1199
1242
|
Object.entries(options).forEach(([key, value]) => {
|
|
1200
1243
|
if (value !== undefined) {
|
|
@@ -1208,7 +1251,7 @@ async function listMergeRequests(projectId, options = {}) {
|
|
|
1208
1251
|
}
|
|
1209
1252
|
});
|
|
1210
1253
|
const response = await fetch(url.toString(), {
|
|
1211
|
-
...
|
|
1254
|
+
...getFetchConfig(),
|
|
1212
1255
|
});
|
|
1213
1256
|
await handleGitLabError(response);
|
|
1214
1257
|
const data = await response.json();
|
|
@@ -1224,9 +1267,9 @@ async function listMergeRequests(projectId, options = {}) {
|
|
|
1224
1267
|
*/
|
|
1225
1268
|
async function getIssue(projectId, issueIid) {
|
|
1226
1269
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
1227
|
-
const url = new URL(`${
|
|
1270
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/issues/${issueIid}`);
|
|
1228
1271
|
const response = await fetch(url.toString(), {
|
|
1229
|
-
...
|
|
1272
|
+
...getFetchConfig(),
|
|
1230
1273
|
});
|
|
1231
1274
|
await handleGitLabError(response);
|
|
1232
1275
|
const data = await response.json();
|
|
@@ -1243,14 +1286,14 @@ async function getIssue(projectId, issueIid) {
|
|
|
1243
1286
|
*/
|
|
1244
1287
|
async function updateIssue(projectId, issueIid, options) {
|
|
1245
1288
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
1246
|
-
const url = new URL(`${
|
|
1289
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/issues/${issueIid}`);
|
|
1247
1290
|
// Convert labels array to comma-separated string if present
|
|
1248
1291
|
const body = { ...options };
|
|
1249
1292
|
if (body.labels && Array.isArray(body.labels)) {
|
|
1250
1293
|
body.labels = body.labels.join(",");
|
|
1251
1294
|
}
|
|
1252
1295
|
const response = await fetch(url.toString(), {
|
|
1253
|
-
...
|
|
1296
|
+
...getFetchConfig(),
|
|
1254
1297
|
method: "PUT",
|
|
1255
1298
|
body: JSON.stringify(body),
|
|
1256
1299
|
});
|
|
@@ -1268,9 +1311,9 @@ async function updateIssue(projectId, issueIid, options) {
|
|
|
1268
1311
|
*/
|
|
1269
1312
|
async function deleteIssue(projectId, issueIid) {
|
|
1270
1313
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
1271
|
-
const url = new URL(`${
|
|
1314
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/issues/${issueIid}`);
|
|
1272
1315
|
const response = await fetch(url.toString(), {
|
|
1273
|
-
...
|
|
1316
|
+
...getFetchConfig(),
|
|
1274
1317
|
method: "DELETE",
|
|
1275
1318
|
});
|
|
1276
1319
|
await handleGitLabError(response);
|
|
@@ -1285,9 +1328,9 @@ async function deleteIssue(projectId, issueIid) {
|
|
|
1285
1328
|
*/
|
|
1286
1329
|
async function listIssueLinks(projectId, issueIid) {
|
|
1287
1330
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
1288
|
-
const url = new URL(`${
|
|
1331
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/issues/${issueIid}/links`);
|
|
1289
1332
|
const response = await fetch(url.toString(), {
|
|
1290
|
-
...
|
|
1333
|
+
...getFetchConfig(),
|
|
1291
1334
|
});
|
|
1292
1335
|
await handleGitLabError(response);
|
|
1293
1336
|
const data = await response.json();
|
|
@@ -1304,9 +1347,9 @@ async function listIssueLinks(projectId, issueIid) {
|
|
|
1304
1347
|
*/
|
|
1305
1348
|
async function getIssueLink(projectId, issueIid, issueLinkId) {
|
|
1306
1349
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
1307
|
-
const url = new URL(`${
|
|
1350
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/issues/${issueIid}/links/${issueLinkId}`);
|
|
1308
1351
|
const response = await fetch(url.toString(), {
|
|
1309
|
-
...
|
|
1352
|
+
...getFetchConfig(),
|
|
1310
1353
|
});
|
|
1311
1354
|
await handleGitLabError(response);
|
|
1312
1355
|
const data = await response.json();
|
|
@@ -1326,9 +1369,9 @@ async function getIssueLink(projectId, issueIid, issueLinkId) {
|
|
|
1326
1369
|
async function createIssueLink(projectId, issueIid, targetProjectId, targetIssueIid, linkType = "relates_to") {
|
|
1327
1370
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
1328
1371
|
targetProjectId = decodeURIComponent(targetProjectId); // Decode target project ID as well
|
|
1329
|
-
const url = new URL(`${
|
|
1372
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/issues/${issueIid}/links`);
|
|
1330
1373
|
const response = await fetch(url.toString(), {
|
|
1331
|
-
...
|
|
1374
|
+
...getFetchConfig(),
|
|
1332
1375
|
method: "POST",
|
|
1333
1376
|
body: JSON.stringify({
|
|
1334
1377
|
target_project_id: targetProjectId,
|
|
@@ -1351,9 +1394,9 @@ async function createIssueLink(projectId, issueIid, targetProjectId, targetIssue
|
|
|
1351
1394
|
*/
|
|
1352
1395
|
async function deleteIssueLink(projectId, issueIid, issueLinkId) {
|
|
1353
1396
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
1354
|
-
const url = new URL(`${
|
|
1397
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/issues/${issueIid}/links/${issueLinkId}`);
|
|
1355
1398
|
const response = await fetch(url.toString(), {
|
|
1356
|
-
...
|
|
1399
|
+
...getFetchConfig(),
|
|
1357
1400
|
method: "DELETE",
|
|
1358
1401
|
});
|
|
1359
1402
|
await handleGitLabError(response);
|
|
@@ -1368,9 +1411,9 @@ async function deleteIssueLink(projectId, issueIid, issueLinkId) {
|
|
|
1368
1411
|
*/
|
|
1369
1412
|
async function createMergeRequest(projectId, options) {
|
|
1370
1413
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
1371
|
-
const url = new URL(`${
|
|
1414
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/merge_requests`);
|
|
1372
1415
|
const response = await fetch(url.toString(), {
|
|
1373
|
-
...
|
|
1416
|
+
...getFetchConfig(),
|
|
1374
1417
|
method: "POST",
|
|
1375
1418
|
body: JSON.stringify({
|
|
1376
1419
|
title: options.title,
|
|
@@ -1410,7 +1453,7 @@ async function createMergeRequest(projectId, options) {
|
|
|
1410
1453
|
*/
|
|
1411
1454
|
async function listDiscussions(projectId, resourceType, resourceIid, options = {}) {
|
|
1412
1455
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
1413
|
-
const url = new URL(`${
|
|
1456
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/${resourceType}/${resourceIid}/discussions`);
|
|
1414
1457
|
// Add query parameters for pagination and sorting
|
|
1415
1458
|
if (options.page) {
|
|
1416
1459
|
url.searchParams.append("page", options.page.toString());
|
|
@@ -1419,7 +1462,7 @@ async function listDiscussions(projectId, resourceType, resourceIid, options = {
|
|
|
1419
1462
|
url.searchParams.append("per_page", options.per_page.toString());
|
|
1420
1463
|
}
|
|
1421
1464
|
const response = await fetch(url.toString(), {
|
|
1422
|
-
...
|
|
1465
|
+
...getFetchConfig(),
|
|
1423
1466
|
});
|
|
1424
1467
|
await handleGitLabError(response);
|
|
1425
1468
|
const discussions = await response.json();
|
|
@@ -1470,9 +1513,9 @@ async function listIssueDiscussions(projectId, issueIid, options = {}) {
|
|
|
1470
1513
|
}
|
|
1471
1514
|
async function deleteMergeRequestDiscussionNote(projectId, mergeRequestIid, discussionId, noteId) {
|
|
1472
1515
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
1473
|
-
const url = new URL(`${
|
|
1516
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/merge_requests/${mergeRequestIid}/discussions/${discussionId}/notes/${noteId}`);
|
|
1474
1517
|
const response = await fetch(url.toString(), {
|
|
1475
|
-
...
|
|
1518
|
+
...getFetchConfig(),
|
|
1476
1519
|
method: "DELETE",
|
|
1477
1520
|
});
|
|
1478
1521
|
if (!response.ok) {
|
|
@@ -1494,7 +1537,7 @@ async function deleteMergeRequestDiscussionNote(projectId, mergeRequestIid, disc
|
|
|
1494
1537
|
*/
|
|
1495
1538
|
async function updateMergeRequestDiscussionNote(projectId, mergeRequestIid, discussionId, noteId, body, resolved) {
|
|
1496
1539
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
1497
|
-
const url = new URL(`${
|
|
1540
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/merge_requests/${mergeRequestIid}/discussions/${discussionId}/notes/${noteId}`);
|
|
1498
1541
|
// Only one of body or resolved can be sent according to GitLab API
|
|
1499
1542
|
const payload = {};
|
|
1500
1543
|
if (body !== undefined) {
|
|
@@ -1504,7 +1547,7 @@ async function updateMergeRequestDiscussionNote(projectId, mergeRequestIid, disc
|
|
|
1504
1547
|
payload.resolved = resolved;
|
|
1505
1548
|
}
|
|
1506
1549
|
const response = await fetch(url.toString(), {
|
|
1507
|
-
...
|
|
1550
|
+
...getFetchConfig(),
|
|
1508
1551
|
method: "PUT",
|
|
1509
1552
|
body: JSON.stringify(payload),
|
|
1510
1553
|
});
|
|
@@ -1523,10 +1566,10 @@ async function updateMergeRequestDiscussionNote(projectId, mergeRequestIid, disc
|
|
|
1523
1566
|
*/
|
|
1524
1567
|
async function updateIssueNote(projectId, issueIid, discussionId, noteId, body) {
|
|
1525
1568
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
1526
|
-
const url = new URL(`${
|
|
1569
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/issues/${issueIid}/discussions/${discussionId}/notes/${noteId}`);
|
|
1527
1570
|
const payload = { body };
|
|
1528
1571
|
const response = await fetch(url.toString(), {
|
|
1529
|
-
...
|
|
1572
|
+
...getFetchConfig(),
|
|
1530
1573
|
method: "PUT",
|
|
1531
1574
|
body: JSON.stringify(payload),
|
|
1532
1575
|
});
|
|
@@ -1545,13 +1588,13 @@ async function updateIssueNote(projectId, issueIid, discussionId, noteId, body)
|
|
|
1545
1588
|
*/
|
|
1546
1589
|
async function createIssueNote(projectId, issueIid, discussionId, body, createdAt) {
|
|
1547
1590
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
1548
|
-
const url = new URL(`${
|
|
1591
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/issues/${issueIid}/discussions/${discussionId}/notes`);
|
|
1549
1592
|
const payload = { body };
|
|
1550
1593
|
if (createdAt) {
|
|
1551
1594
|
payload.created_at = createdAt;
|
|
1552
1595
|
}
|
|
1553
1596
|
const response = await fetch(url.toString(), {
|
|
1554
|
-
...
|
|
1597
|
+
...getFetchConfig(),
|
|
1555
1598
|
method: "POST",
|
|
1556
1599
|
body: JSON.stringify(payload),
|
|
1557
1600
|
});
|
|
@@ -1572,13 +1615,13 @@ async function createIssueNote(projectId, issueIid, discussionId, body, createdA
|
|
|
1572
1615
|
*/
|
|
1573
1616
|
async function createMergeRequestDiscussionNote(projectId, mergeRequestIid, discussionId, body, createdAt) {
|
|
1574
1617
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
1575
|
-
const url = new URL(`${
|
|
1618
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/merge_requests/${mergeRequestIid}/discussions/${discussionId}/notes`);
|
|
1576
1619
|
const payload = { body };
|
|
1577
1620
|
if (createdAt) {
|
|
1578
1621
|
payload.created_at = createdAt;
|
|
1579
1622
|
}
|
|
1580
1623
|
const response = await fetch(url.toString(), {
|
|
1581
|
-
...
|
|
1624
|
+
...getFetchConfig(),
|
|
1582
1625
|
method: "POST",
|
|
1583
1626
|
body: JSON.stringify(payload),
|
|
1584
1627
|
});
|
|
@@ -1588,14 +1631,14 @@ async function createMergeRequestDiscussionNote(projectId, mergeRequestIid, disc
|
|
|
1588
1631
|
}
|
|
1589
1632
|
async function createMergeRequestNote(projectId, mergeRequestIid, body) {
|
|
1590
1633
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
1591
|
-
const url = new URL(`${
|
|
1634
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/merge_requests/${mergeRequestIid}/notes`);
|
|
1592
1635
|
const payload = {
|
|
1593
1636
|
id: projectId,
|
|
1594
1637
|
merge_request_iid: mergeRequestIid,
|
|
1595
1638
|
body,
|
|
1596
1639
|
};
|
|
1597
1640
|
const response = await fetch(url.toString(), {
|
|
1598
|
-
...
|
|
1641
|
+
...getFetchConfig(),
|
|
1599
1642
|
method: "POST",
|
|
1600
1643
|
body: JSON.stringify(payload),
|
|
1601
1644
|
});
|
|
@@ -1605,9 +1648,9 @@ async function createMergeRequestNote(projectId, mergeRequestIid, body) {
|
|
|
1605
1648
|
}
|
|
1606
1649
|
async function deleteMergeRequestNote(projectId, mergeRequestIid, noteId) {
|
|
1607
1650
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
1608
|
-
const url = new URL(`${
|
|
1651
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/merge_requests/${mergeRequestIid}/notes/${noteId}`);
|
|
1609
1652
|
const response = await fetch(url.toString(), {
|
|
1610
|
-
...
|
|
1653
|
+
...getFetchConfig(),
|
|
1611
1654
|
method: "DELETE",
|
|
1612
1655
|
});
|
|
1613
1656
|
if (!response.ok) {
|
|
@@ -1617,9 +1660,9 @@ async function deleteMergeRequestNote(projectId, mergeRequestIid, noteId) {
|
|
|
1617
1660
|
}
|
|
1618
1661
|
async function getMergeRequestNote(projectId, mergeRequestIid, noteId) {
|
|
1619
1662
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
1620
|
-
const url = new URL(`${
|
|
1663
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/merge_requests/${mergeRequestIid}/notes/${noteId}`);
|
|
1621
1664
|
const response = await fetch(url.toString(), {
|
|
1622
|
-
...
|
|
1665
|
+
...getFetchConfig(),
|
|
1623
1666
|
method: "GET",
|
|
1624
1667
|
});
|
|
1625
1668
|
await handleGitLabError(response);
|
|
@@ -1628,7 +1671,7 @@ async function getMergeRequestNote(projectId, mergeRequestIid, noteId) {
|
|
|
1628
1671
|
}
|
|
1629
1672
|
async function getMergeRequestNotes(projectId, mergeRequestIid, sort, order_by) {
|
|
1630
1673
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
1631
|
-
const url = new URL(`${
|
|
1674
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/merge_requests/${mergeRequestIid}/notes`);
|
|
1632
1675
|
if (sort) {
|
|
1633
1676
|
url.searchParams.append("sort", sort);
|
|
1634
1677
|
}
|
|
@@ -1636,7 +1679,7 @@ async function getMergeRequestNotes(projectId, mergeRequestIid, sort, order_by)
|
|
|
1636
1679
|
url.searchParams.append("order_by", order_by);
|
|
1637
1680
|
}
|
|
1638
1681
|
const response = await fetch(url.toString(), {
|
|
1639
|
-
...
|
|
1682
|
+
...getFetchConfig(),
|
|
1640
1683
|
method: "GET",
|
|
1641
1684
|
});
|
|
1642
1685
|
await handleGitLabError(response);
|
|
@@ -1645,7 +1688,7 @@ async function getMergeRequestNotes(projectId, mergeRequestIid, sort, order_by)
|
|
|
1645
1688
|
}
|
|
1646
1689
|
async function updateMergeRequestNote(projectId, mergeRequestIid, noteId, body) {
|
|
1647
1690
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
1648
|
-
const url = new URL(`${
|
|
1691
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/merge_requests/${mergeRequestIid}/notes/${noteId}`);
|
|
1649
1692
|
const payload = {
|
|
1650
1693
|
id: projectId,
|
|
1651
1694
|
merge_request_iid: mergeRequestIid,
|
|
@@ -1653,7 +1696,7 @@ async function updateMergeRequestNote(projectId, mergeRequestIid, noteId, body)
|
|
|
1653
1696
|
body,
|
|
1654
1697
|
};
|
|
1655
1698
|
const response = await fetch(url.toString(), {
|
|
1656
|
-
...
|
|
1699
|
+
...getFetchConfig(),
|
|
1657
1700
|
method: "PUT",
|
|
1658
1701
|
body: JSON.stringify(payload),
|
|
1659
1702
|
});
|
|
@@ -1676,7 +1719,7 @@ async function updateMergeRequestNote(projectId, mergeRequestIid, noteId, body)
|
|
|
1676
1719
|
async function createOrUpdateFile(projectId, filePath, content, commitMessage, branch, previousPath, last_commit_id, commit_id) {
|
|
1677
1720
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
1678
1721
|
const encodedPath = encodeURIComponent(filePath);
|
|
1679
|
-
const url = new URL(`${
|
|
1722
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/repository/files/${encodedPath}`);
|
|
1680
1723
|
const body = {
|
|
1681
1724
|
branch,
|
|
1682
1725
|
content,
|
|
@@ -1721,7 +1764,7 @@ async function createOrUpdateFile(projectId, filePath, content, commitMessage, b
|
|
|
1721
1764
|
}
|
|
1722
1765
|
}
|
|
1723
1766
|
const response = await fetch(url.toString(), {
|
|
1724
|
-
...
|
|
1767
|
+
...getFetchConfig(),
|
|
1725
1768
|
method,
|
|
1726
1769
|
body: JSON.stringify(body),
|
|
1727
1770
|
});
|
|
@@ -1743,12 +1786,12 @@ async function createOrUpdateFile(projectId, filePath, content, commitMessage, b
|
|
|
1743
1786
|
*/
|
|
1744
1787
|
async function createTree(projectId, files, ref) {
|
|
1745
1788
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
1746
|
-
const url = new URL(`${
|
|
1789
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/repository/tree`);
|
|
1747
1790
|
if (ref) {
|
|
1748
1791
|
url.searchParams.append("ref", ref);
|
|
1749
1792
|
}
|
|
1750
1793
|
const response = await fetch(url.toString(), {
|
|
1751
|
-
...
|
|
1794
|
+
...getFetchConfig(),
|
|
1752
1795
|
method: "POST",
|
|
1753
1796
|
body: JSON.stringify({
|
|
1754
1797
|
files: files.map(file => ({
|
|
@@ -1781,9 +1824,9 @@ async function createTree(projectId, files, ref) {
|
|
|
1781
1824
|
*/
|
|
1782
1825
|
async function createCommit(projectId, message, branch, actions) {
|
|
1783
1826
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
1784
|
-
const url = new URL(`${
|
|
1827
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/repository/commits`);
|
|
1785
1828
|
const response = await fetch(url.toString(), {
|
|
1786
|
-
...
|
|
1829
|
+
...getFetchConfig(),
|
|
1787
1830
|
method: "POST",
|
|
1788
1831
|
body: JSON.stringify({
|
|
1789
1832
|
branch,
|
|
@@ -1817,14 +1860,14 @@ async function createCommit(projectId, message, branch, actions) {
|
|
|
1817
1860
|
* @returns {Promise<GitLabSearchResponse>} The search results
|
|
1818
1861
|
*/
|
|
1819
1862
|
async function searchProjects(query, page = 1, perPage = 20) {
|
|
1820
|
-
const url = new URL(`${
|
|
1863
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects`);
|
|
1821
1864
|
url.searchParams.append("search", query);
|
|
1822
1865
|
url.searchParams.append("page", page.toString());
|
|
1823
1866
|
url.searchParams.append("per_page", perPage.toString());
|
|
1824
1867
|
url.searchParams.append("order_by", "id");
|
|
1825
1868
|
url.searchParams.append("sort", "desc");
|
|
1826
1869
|
const response = await fetch(url.toString(), {
|
|
1827
|
-
...
|
|
1870
|
+
...getFetchConfig(),
|
|
1828
1871
|
});
|
|
1829
1872
|
if (!response.ok) {
|
|
1830
1873
|
const errorBody = await response.text();
|
|
@@ -1850,8 +1893,8 @@ async function searchProjects(query, page = 1, perPage = 20) {
|
|
|
1850
1893
|
* @returns {Promise<GitLabRepository>} The created repository
|
|
1851
1894
|
*/
|
|
1852
1895
|
async function createRepository(options) {
|
|
1853
|
-
const response = await fetch(`${
|
|
1854
|
-
...
|
|
1896
|
+
const response = await fetch(`${getEffectiveApiUrl()}/projects`, {
|
|
1897
|
+
...getFetchConfig(),
|
|
1855
1898
|
method: "POST",
|
|
1856
1899
|
body: JSON.stringify({
|
|
1857
1900
|
name: options.name,
|
|
@@ -1882,16 +1925,16 @@ async function getMergeRequest(projectId, mergeRequestIid, branchName) {
|
|
|
1882
1925
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
1883
1926
|
let url;
|
|
1884
1927
|
if (mergeRequestIid) {
|
|
1885
|
-
url = new URL(`${
|
|
1928
|
+
url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/merge_requests/${mergeRequestIid}`);
|
|
1886
1929
|
}
|
|
1887
1930
|
else if (branchName) {
|
|
1888
|
-
url = new URL(`${
|
|
1931
|
+
url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/merge_requests?source_branch=${encodeURIComponent(branchName)}`);
|
|
1889
1932
|
}
|
|
1890
1933
|
else {
|
|
1891
1934
|
throw new Error("Either mergeRequestIid or branchName must be provided");
|
|
1892
1935
|
}
|
|
1893
1936
|
const response = await fetch(url.toString(), {
|
|
1894
|
-
...
|
|
1937
|
+
...getFetchConfig(),
|
|
1895
1938
|
});
|
|
1896
1939
|
await handleGitLabError(response);
|
|
1897
1940
|
const data = await response.json();
|
|
@@ -1920,12 +1963,12 @@ async function getMergeRequestDiffs(projectId, mergeRequestIid, branchName, view
|
|
|
1920
1963
|
const mergeRequest = await getMergeRequest(projectId, undefined, branchName);
|
|
1921
1964
|
mergeRequestIid = mergeRequest.iid;
|
|
1922
1965
|
}
|
|
1923
|
-
const url = new URL(`${
|
|
1966
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/merge_requests/${mergeRequestIid}/changes`);
|
|
1924
1967
|
if (view) {
|
|
1925
1968
|
url.searchParams.append("view", view);
|
|
1926
1969
|
}
|
|
1927
1970
|
const response = await fetch(url.toString(), {
|
|
1928
|
-
...
|
|
1971
|
+
...getFetchConfig(),
|
|
1929
1972
|
});
|
|
1930
1973
|
await handleGitLabError(response);
|
|
1931
1974
|
const data = (await response.json());
|
|
@@ -1950,7 +1993,7 @@ async function listMergeRequestDiffs(projectId, mergeRequestIid, branchName, pag
|
|
|
1950
1993
|
const mergeRequest = await getMergeRequest(projectId, undefined, branchName);
|
|
1951
1994
|
mergeRequestIid = mergeRequest.iid;
|
|
1952
1995
|
}
|
|
1953
|
-
const url = new URL(`${
|
|
1996
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/merge_requests/${mergeRequestIid}/diffs`);
|
|
1954
1997
|
if (page) {
|
|
1955
1998
|
url.searchParams.append("page", page.toString());
|
|
1956
1999
|
}
|
|
@@ -1961,7 +2004,7 @@ async function listMergeRequestDiffs(projectId, mergeRequestIid, branchName, pag
|
|
|
1961
2004
|
url.searchParams.append("unidiff", "true");
|
|
1962
2005
|
}
|
|
1963
2006
|
const response = await fetch(url.toString(), {
|
|
1964
|
-
...
|
|
2007
|
+
...getFetchConfig(),
|
|
1965
2008
|
});
|
|
1966
2009
|
await handleGitLabError(response);
|
|
1967
2010
|
return await response.json(); // Return full response including commits, diff_refs, changes, etc.
|
|
@@ -1977,14 +2020,14 @@ async function listMergeRequestDiffs(projectId, mergeRequestIid, branchName, pag
|
|
|
1977
2020
|
*/
|
|
1978
2021
|
async function getBranchDiffs(projectId, from, to, straight) {
|
|
1979
2022
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
1980
|
-
const url = new URL(`${
|
|
2023
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/repository/compare`);
|
|
1981
2024
|
url.searchParams.append("from", from);
|
|
1982
2025
|
url.searchParams.append("to", to);
|
|
1983
2026
|
if (straight !== undefined) {
|
|
1984
2027
|
url.searchParams.append("straight", straight.toString());
|
|
1985
2028
|
}
|
|
1986
2029
|
const response = await fetch(url.toString(), {
|
|
1987
|
-
...
|
|
2030
|
+
...getFetchConfig(),
|
|
1988
2031
|
});
|
|
1989
2032
|
if (!response.ok) {
|
|
1990
2033
|
const errorBody = await response.text();
|
|
@@ -2012,9 +2055,9 @@ async function updateMergeRequest(projectId, options, mergeRequestIid, branchNam
|
|
|
2012
2055
|
const mergeRequest = await getMergeRequest(projectId, undefined, branchName);
|
|
2013
2056
|
mergeRequestIid = mergeRequest.iid;
|
|
2014
2057
|
}
|
|
2015
|
-
const url = new URL(`${
|
|
2058
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/merge_requests/${mergeRequestIid}`);
|
|
2016
2059
|
const response = await fetch(url.toString(), {
|
|
2017
|
-
...
|
|
2060
|
+
...getFetchConfig(),
|
|
2018
2061
|
method: "PUT",
|
|
2019
2062
|
body: JSON.stringify(options),
|
|
2020
2063
|
});
|
|
@@ -2032,9 +2075,9 @@ async function updateMergeRequest(projectId, options, mergeRequestIid, branchNam
|
|
|
2032
2075
|
*/
|
|
2033
2076
|
async function mergeMergeRequest(projectId, options, mergeRequestIid) {
|
|
2034
2077
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
2035
|
-
const url = new URL(`${
|
|
2078
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/merge_requests/${mergeRequestIid}/merge`);
|
|
2036
2079
|
const response = await fetch(url.toString(), {
|
|
2037
|
-
...
|
|
2080
|
+
...getFetchConfig(),
|
|
2038
2081
|
method: "PUT",
|
|
2039
2082
|
body: JSON.stringify(options),
|
|
2040
2083
|
});
|
|
@@ -2056,10 +2099,10 @@ async function createNote(projectId, noteableType, // 'issue' 또는 'merge_requ
|
|
|
2056
2099
|
noteableIid, body) {
|
|
2057
2100
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
2058
2101
|
// ⚙️ 응답 타입은 GitLab API 문서에 따라 조정 가능
|
|
2059
|
-
const url = new URL(`${
|
|
2102
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/${noteableType}s/${noteableIid}/notes` // Using plural form (issues/merge_requests) as per GitLab API documentation
|
|
2060
2103
|
);
|
|
2061
2104
|
const response = await fetch(url.toString(), {
|
|
2062
|
-
...
|
|
2105
|
+
...getFetchConfig(),
|
|
2063
2106
|
method: "POST",
|
|
2064
2107
|
body: JSON.stringify({ body }),
|
|
2065
2108
|
});
|
|
@@ -2076,7 +2119,7 @@ noteableIid, body) {
|
|
|
2076
2119
|
* @returns {Promise<GitLabDraftNote[]>} Array of draft notes
|
|
2077
2120
|
*/
|
|
2078
2121
|
async function getDraftNote(project_id, merge_request_iid, draft_note_id) {
|
|
2079
|
-
const response = await fetch(
|
|
2122
|
+
const response = await fetch(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(project_id)}/merge_requests/${merge_request_iid}/draft_notes/${draft_note_id}`);
|
|
2080
2123
|
if (!response.ok) {
|
|
2081
2124
|
const errorText = await response.text();
|
|
2082
2125
|
throw new Error(`GitLab API error: ${response.status} ${response.statusText}\n${errorText}`);
|
|
@@ -2086,9 +2129,9 @@ async function getDraftNote(project_id, merge_request_iid, draft_note_id) {
|
|
|
2086
2129
|
}
|
|
2087
2130
|
async function listDraftNotes(projectId, mergeRequestIid) {
|
|
2088
2131
|
projectId = decodeURIComponent(projectId);
|
|
2089
|
-
const url = new URL(`${
|
|
2132
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/merge_requests/${mergeRequestIid}/draft_notes`);
|
|
2090
2133
|
const response = await fetch(url.toString(), {
|
|
2091
|
-
...
|
|
2134
|
+
...getFetchConfig(),
|
|
2092
2135
|
method: "GET",
|
|
2093
2136
|
});
|
|
2094
2137
|
if (!response.ok) {
|
|
@@ -2109,7 +2152,7 @@ async function listDraftNotes(projectId, mergeRequestIid) {
|
|
|
2109
2152
|
*/
|
|
2110
2153
|
async function createDraftNote(projectId, mergeRequestIid, body, position, resolveDiscussion) {
|
|
2111
2154
|
projectId = decodeURIComponent(projectId);
|
|
2112
|
-
const url = new URL(`${
|
|
2155
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/merge_requests/${mergeRequestIid}/draft_notes`);
|
|
2113
2156
|
const requestBody = { note: body };
|
|
2114
2157
|
if (position) {
|
|
2115
2158
|
requestBody.position = position;
|
|
@@ -2118,7 +2161,7 @@ async function createDraftNote(projectId, mergeRequestIid, body, position, resol
|
|
|
2118
2161
|
requestBody.resolve_discussion = resolveDiscussion;
|
|
2119
2162
|
}
|
|
2120
2163
|
const response = await fetch(url.toString(), {
|
|
2121
|
-
...
|
|
2164
|
+
...getFetchConfig(),
|
|
2122
2165
|
method: "POST",
|
|
2123
2166
|
body: JSON.stringify(requestBody),
|
|
2124
2167
|
});
|
|
@@ -2141,7 +2184,7 @@ async function createDraftNote(projectId, mergeRequestIid, body, position, resol
|
|
|
2141
2184
|
*/
|
|
2142
2185
|
async function updateDraftNote(projectId, mergeRequestIid, draftNoteId, body, position, resolveDiscussion) {
|
|
2143
2186
|
projectId = decodeURIComponent(projectId);
|
|
2144
|
-
const url = new URL(`${
|
|
2187
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/merge_requests/${mergeRequestIid}/draft_notes/${draftNoteId}`);
|
|
2145
2188
|
const requestBody = {};
|
|
2146
2189
|
if (body !== undefined) {
|
|
2147
2190
|
requestBody.note = body;
|
|
@@ -2153,7 +2196,7 @@ async function updateDraftNote(projectId, mergeRequestIid, draftNoteId, body, po
|
|
|
2153
2196
|
requestBody.resolve_discussion = resolveDiscussion;
|
|
2154
2197
|
}
|
|
2155
2198
|
const response = await fetch(url.toString(), {
|
|
2156
|
-
...
|
|
2199
|
+
...getFetchConfig(),
|
|
2157
2200
|
method: "PUT",
|
|
2158
2201
|
body: JSON.stringify(requestBody),
|
|
2159
2202
|
});
|
|
@@ -2173,9 +2216,9 @@ async function updateDraftNote(projectId, mergeRequestIid, draftNoteId, body, po
|
|
|
2173
2216
|
*/
|
|
2174
2217
|
async function deleteDraftNote(projectId, mergeRequestIid, draftNoteId) {
|
|
2175
2218
|
projectId = decodeURIComponent(projectId);
|
|
2176
|
-
const url = new URL(`${
|
|
2219
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/merge_requests/${mergeRequestIid}/draft_notes/${draftNoteId}`);
|
|
2177
2220
|
const response = await fetch(url.toString(), {
|
|
2178
|
-
...
|
|
2221
|
+
...getFetchConfig(),
|
|
2179
2222
|
method: "DELETE",
|
|
2180
2223
|
});
|
|
2181
2224
|
if (!response.ok) {
|
|
@@ -2192,9 +2235,9 @@ async function deleteDraftNote(projectId, mergeRequestIid, draftNoteId) {
|
|
|
2192
2235
|
*/
|
|
2193
2236
|
async function publishDraftNote(projectId, mergeRequestIid, draftNoteId) {
|
|
2194
2237
|
projectId = decodeURIComponent(projectId);
|
|
2195
|
-
const url = new URL(`${
|
|
2238
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/merge_requests/${mergeRequestIid}/draft_notes/${draftNoteId}/publish`);
|
|
2196
2239
|
const response = await fetch(url.toString(), {
|
|
2197
|
-
...
|
|
2240
|
+
...getFetchConfig(),
|
|
2198
2241
|
method: "PUT",
|
|
2199
2242
|
});
|
|
2200
2243
|
if (!response.ok) {
|
|
@@ -2244,9 +2287,9 @@ async function publishDraftNote(projectId, mergeRequestIid, draftNoteId) {
|
|
|
2244
2287
|
*/
|
|
2245
2288
|
async function bulkPublishDraftNotes(projectId, mergeRequestIid) {
|
|
2246
2289
|
projectId = decodeURIComponent(projectId);
|
|
2247
|
-
const url = new URL(`${
|
|
2290
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/merge_requests/${mergeRequestIid}/draft_notes/bulk_publish`);
|
|
2248
2291
|
const response = await fetch(url.toString(), {
|
|
2249
|
-
...
|
|
2292
|
+
...getFetchConfig(),
|
|
2250
2293
|
method: "POST", // Changed from PUT to POST
|
|
2251
2294
|
body: JSON.stringify({}), // Send empty body for POST request
|
|
2252
2295
|
});
|
|
@@ -2273,12 +2316,12 @@ async function bulkPublishDraftNotes(projectId, mergeRequestIid) {
|
|
|
2273
2316
|
}
|
|
2274
2317
|
async function resolveMergeRequestThread(projectId, mergeRequestIid, discussionId, resolved) {
|
|
2275
2318
|
projectId = decodeURIComponent(projectId);
|
|
2276
|
-
const url = new URL(`${
|
|
2319
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/merge_requests/${mergeRequestIid}/discussions/${discussionId}`);
|
|
2277
2320
|
if (resolved !== undefined) {
|
|
2278
2321
|
url.searchParams.append("resolved", resolved ? "true" : "false");
|
|
2279
2322
|
}
|
|
2280
2323
|
const response = await fetch(url.toString(), {
|
|
2281
|
-
...
|
|
2324
|
+
...getFetchConfig(),
|
|
2282
2325
|
method: "PUT",
|
|
2283
2326
|
});
|
|
2284
2327
|
if (!response.ok) {
|
|
@@ -2305,7 +2348,7 @@ async function resolveMergeRequestThread(projectId, mergeRequestIid, discussionI
|
|
|
2305
2348
|
*/
|
|
2306
2349
|
async function createMergeRequestThread(projectId, mergeRequestIid, body, position, createdAt) {
|
|
2307
2350
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
2308
|
-
const url = new URL(`${
|
|
2351
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/merge_requests/${mergeRequestIid}/discussions`);
|
|
2309
2352
|
const payload = { body };
|
|
2310
2353
|
// Add optional parameters if provided
|
|
2311
2354
|
if (position) {
|
|
@@ -2315,7 +2358,7 @@ async function createMergeRequestThread(projectId, mergeRequestIid, body, positi
|
|
|
2315
2358
|
payload.created_at = createdAt;
|
|
2316
2359
|
}
|
|
2317
2360
|
const response = await fetch(url.toString(), {
|
|
2318
|
-
...
|
|
2361
|
+
...getFetchConfig(),
|
|
2319
2362
|
method: "POST",
|
|
2320
2363
|
body: JSON.stringify(payload),
|
|
2321
2364
|
});
|
|
@@ -2334,7 +2377,7 @@ async function createMergeRequestThread(projectId, mergeRequestIid, body, positi
|
|
|
2334
2377
|
* @returns {Promise<GitLabNamespace[]>} List of namespaces
|
|
2335
2378
|
*/
|
|
2336
2379
|
async function listNamespaces(options) {
|
|
2337
|
-
const url = new URL(`${
|
|
2380
|
+
const url = new URL(`${getEffectiveApiUrl()}/namespaces`);
|
|
2338
2381
|
if (options.search) {
|
|
2339
2382
|
url.searchParams.append("search", options.search);
|
|
2340
2383
|
}
|
|
@@ -2345,7 +2388,7 @@ async function listNamespaces(options) {
|
|
|
2345
2388
|
url.searchParams.append("top_level_only", "true");
|
|
2346
2389
|
}
|
|
2347
2390
|
const response = await fetch(url.toString(), {
|
|
2348
|
-
...
|
|
2391
|
+
...getFetchConfig(),
|
|
2349
2392
|
});
|
|
2350
2393
|
await handleGitLabError(response);
|
|
2351
2394
|
const data = await response.json();
|
|
@@ -2359,9 +2402,9 @@ async function listNamespaces(options) {
|
|
|
2359
2402
|
* @returns {Promise<GitLabNamespace>} The namespace details
|
|
2360
2403
|
*/
|
|
2361
2404
|
async function getNamespace(id) {
|
|
2362
|
-
const url = new URL(`${
|
|
2405
|
+
const url = new URL(`${getEffectiveApiUrl()}/namespaces/${encodeURIComponent(id)}`);
|
|
2363
2406
|
const response = await fetch(url.toString(), {
|
|
2364
|
-
...
|
|
2407
|
+
...getFetchConfig(),
|
|
2365
2408
|
});
|
|
2366
2409
|
await handleGitLabError(response);
|
|
2367
2410
|
const data = await response.json();
|
|
@@ -2376,12 +2419,12 @@ async function getNamespace(id) {
|
|
|
2376
2419
|
* @returns {Promise<GitLabNamespaceExistsResponse>} The verification result
|
|
2377
2420
|
*/
|
|
2378
2421
|
async function verifyNamespaceExistence(namespacePath, parentId) {
|
|
2379
|
-
const url = new URL(`${
|
|
2422
|
+
const url = new URL(`${getEffectiveApiUrl()}/namespaces/${encodeURIComponent(namespacePath)}/exists`);
|
|
2380
2423
|
if (parentId) {
|
|
2381
2424
|
url.searchParams.append("parent_id", parentId.toString());
|
|
2382
2425
|
}
|
|
2383
2426
|
const response = await fetch(url.toString(), {
|
|
2384
|
-
...
|
|
2427
|
+
...getFetchConfig(),
|
|
2385
2428
|
});
|
|
2386
2429
|
await handleGitLabError(response);
|
|
2387
2430
|
const data = await response.json();
|
|
@@ -2400,7 +2443,7 @@ async function verifyNamespaceExistence(namespacePath, parentId) {
|
|
|
2400
2443
|
*/
|
|
2401
2444
|
async function getProject(projectId, options = {}) {
|
|
2402
2445
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
2403
|
-
const url = new URL(`${
|
|
2446
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}`);
|
|
2404
2447
|
if (options.license) {
|
|
2405
2448
|
url.searchParams.append("license", "true");
|
|
2406
2449
|
}
|
|
@@ -2411,7 +2454,7 @@ async function getProject(projectId, options = {}) {
|
|
|
2411
2454
|
url.searchParams.append("with_custom_attributes", "true");
|
|
2412
2455
|
}
|
|
2413
2456
|
const response = await fetch(url.toString(), {
|
|
2414
|
-
...
|
|
2457
|
+
...getFetchConfig(),
|
|
2415
2458
|
});
|
|
2416
2459
|
await handleGitLabError(response);
|
|
2417
2460
|
const data = await response.json();
|
|
@@ -2438,8 +2481,8 @@ async function listProjects(options = {}) {
|
|
|
2438
2481
|
}
|
|
2439
2482
|
}
|
|
2440
2483
|
// Make the API request
|
|
2441
|
-
const response = await fetch(`${
|
|
2442
|
-
...
|
|
2484
|
+
const response = await fetch(`${getEffectiveApiUrl()}/projects?${params.toString()}`, {
|
|
2485
|
+
...getFetchConfig(),
|
|
2443
2486
|
});
|
|
2444
2487
|
// Handle errors
|
|
2445
2488
|
await handleGitLabError(response);
|
|
@@ -2457,7 +2500,7 @@ async function listProjects(options = {}) {
|
|
|
2457
2500
|
async function listLabels(projectId, options = {}) {
|
|
2458
2501
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
2459
2502
|
// Construct the URL with project path
|
|
2460
|
-
const url = new URL(`${
|
|
2503
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/labels`);
|
|
2461
2504
|
// Add query parameters
|
|
2462
2505
|
Object.entries(options).forEach(([key, value]) => {
|
|
2463
2506
|
if (value !== undefined) {
|
|
@@ -2471,7 +2514,7 @@ async function listLabels(projectId, options = {}) {
|
|
|
2471
2514
|
});
|
|
2472
2515
|
// Make the API request
|
|
2473
2516
|
const response = await fetch(url.toString(), {
|
|
2474
|
-
...
|
|
2517
|
+
...getFetchConfig(),
|
|
2475
2518
|
});
|
|
2476
2519
|
// Handle errors
|
|
2477
2520
|
await handleGitLabError(response);
|
|
@@ -2489,14 +2532,14 @@ async function listLabels(projectId, options = {}) {
|
|
|
2489
2532
|
*/
|
|
2490
2533
|
async function getLabel(projectId, labelId, includeAncestorGroups) {
|
|
2491
2534
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
2492
|
-
const url = new URL(`${
|
|
2535
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/labels/${encodeURIComponent(String(labelId))}`);
|
|
2493
2536
|
// Add query parameters
|
|
2494
2537
|
if (includeAncestorGroups !== undefined) {
|
|
2495
2538
|
url.searchParams.append("include_ancestor_groups", includeAncestorGroups ? "true" : "false");
|
|
2496
2539
|
}
|
|
2497
2540
|
// Make the API request
|
|
2498
2541
|
const response = await fetch(url.toString(), {
|
|
2499
|
-
...
|
|
2542
|
+
...getFetchConfig(),
|
|
2500
2543
|
});
|
|
2501
2544
|
// Handle errors
|
|
2502
2545
|
await handleGitLabError(response);
|
|
@@ -2514,8 +2557,8 @@ async function getLabel(projectId, labelId, includeAncestorGroups) {
|
|
|
2514
2557
|
async function createLabel(projectId, options) {
|
|
2515
2558
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
2516
2559
|
// Make the API request
|
|
2517
|
-
const response = await fetch(`${
|
|
2518
|
-
...
|
|
2560
|
+
const response = await fetch(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/labels`, {
|
|
2561
|
+
...getFetchConfig(),
|
|
2519
2562
|
method: "POST",
|
|
2520
2563
|
body: JSON.stringify(options),
|
|
2521
2564
|
});
|
|
@@ -2536,8 +2579,8 @@ async function createLabel(projectId, options) {
|
|
|
2536
2579
|
async function updateLabel(projectId, labelId, options) {
|
|
2537
2580
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
2538
2581
|
// Make the API request
|
|
2539
|
-
const response = await fetch(`${
|
|
2540
|
-
...
|
|
2582
|
+
const response = await fetch(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/labels/${encodeURIComponent(String(labelId))}`, {
|
|
2583
|
+
...getFetchConfig(),
|
|
2541
2584
|
method: "PUT",
|
|
2542
2585
|
body: JSON.stringify(options),
|
|
2543
2586
|
});
|
|
@@ -2556,8 +2599,8 @@ async function updateLabel(projectId, labelId, options) {
|
|
|
2556
2599
|
async function deleteLabel(projectId, labelId) {
|
|
2557
2600
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
2558
2601
|
// Make the API request
|
|
2559
|
-
const response = await fetch(`${
|
|
2560
|
-
...
|
|
2602
|
+
const response = await fetch(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/labels/${encodeURIComponent(String(labelId))}`, {
|
|
2603
|
+
...getFetchConfig(),
|
|
2561
2604
|
method: "DELETE",
|
|
2562
2605
|
});
|
|
2563
2606
|
// Handle errors
|
|
@@ -2570,7 +2613,7 @@ async function deleteLabel(projectId, labelId) {
|
|
|
2570
2613
|
* @returns {Promise<GitLabProject[]>} Array of projects in the group
|
|
2571
2614
|
*/
|
|
2572
2615
|
async function listGroupProjects(options) {
|
|
2573
|
-
const url = new URL(`${
|
|
2616
|
+
const url = new URL(`${getEffectiveApiUrl()}/groups/${encodeURIComponent(options.group_id)}/projects`);
|
|
2574
2617
|
// Add optional parameters to URL
|
|
2575
2618
|
if (options.include_subgroups)
|
|
2576
2619
|
url.searchParams.append("include_subgroups", "true");
|
|
@@ -2605,7 +2648,7 @@ async function listGroupProjects(options) {
|
|
|
2605
2648
|
if (options.with_security_reports !== undefined)
|
|
2606
2649
|
url.searchParams.append("with_security_reports", options.with_security_reports.toString());
|
|
2607
2650
|
const response = await fetch(url.toString(), {
|
|
2608
|
-
...
|
|
2651
|
+
...getFetchConfig(),
|
|
2609
2652
|
});
|
|
2610
2653
|
await handleGitLabError(response);
|
|
2611
2654
|
const projects = await response.json();
|
|
@@ -2617,7 +2660,7 @@ async function listGroupProjects(options) {
|
|
|
2617
2660
|
*/
|
|
2618
2661
|
async function listWikiPages(projectId, options = {}) {
|
|
2619
2662
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
2620
|
-
const url = new URL(`${
|
|
2663
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/wikis`);
|
|
2621
2664
|
if (options.page)
|
|
2622
2665
|
url.searchParams.append("page", options.page.toString());
|
|
2623
2666
|
if (options.per_page)
|
|
@@ -2625,7 +2668,7 @@ async function listWikiPages(projectId, options = {}) {
|
|
|
2625
2668
|
if (options.with_content)
|
|
2626
2669
|
url.searchParams.append("with_content", options.with_content.toString());
|
|
2627
2670
|
const response = await fetch(url.toString(), {
|
|
2628
|
-
...
|
|
2671
|
+
...getFetchConfig(),
|
|
2629
2672
|
});
|
|
2630
2673
|
await handleGitLabError(response);
|
|
2631
2674
|
const data = await response.json();
|
|
@@ -2636,7 +2679,7 @@ async function listWikiPages(projectId, options = {}) {
|
|
|
2636
2679
|
*/
|
|
2637
2680
|
async function getWikiPage(projectId, slug) {
|
|
2638
2681
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
2639
|
-
const response = await fetch(`${
|
|
2682
|
+
const response = await fetch(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/wikis/${encodeURIComponent(slug)}`, { ...getFetchConfig() });
|
|
2640
2683
|
await handleGitLabError(response);
|
|
2641
2684
|
const data = await response.json();
|
|
2642
2685
|
return GitLabWikiPageSchema.parse(data);
|
|
@@ -2649,8 +2692,8 @@ async function createWikiPage(projectId, title, content, format) {
|
|
|
2649
2692
|
const body = { title, content };
|
|
2650
2693
|
if (format)
|
|
2651
2694
|
body.format = format;
|
|
2652
|
-
const response = await fetch(`${
|
|
2653
|
-
...
|
|
2695
|
+
const response = await fetch(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/wikis`, {
|
|
2696
|
+
...getFetchConfig(),
|
|
2654
2697
|
method: "POST",
|
|
2655
2698
|
body: JSON.stringify(body),
|
|
2656
2699
|
});
|
|
@@ -2670,8 +2713,8 @@ async function updateWikiPage(projectId, slug, title, content, format) {
|
|
|
2670
2713
|
body.content = content;
|
|
2671
2714
|
if (format)
|
|
2672
2715
|
body.format = format;
|
|
2673
|
-
const response = await fetch(`${
|
|
2674
|
-
...
|
|
2716
|
+
const response = await fetch(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/wikis/${encodeURIComponent(slug)}`, {
|
|
2717
|
+
...getFetchConfig(),
|
|
2675
2718
|
method: "PUT",
|
|
2676
2719
|
body: JSON.stringify(body),
|
|
2677
2720
|
});
|
|
@@ -2684,8 +2727,8 @@ async function updateWikiPage(projectId, slug, title, content, format) {
|
|
|
2684
2727
|
*/
|
|
2685
2728
|
async function deleteWikiPage(projectId, slug) {
|
|
2686
2729
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
2687
|
-
const response = await fetch(`${
|
|
2688
|
-
...
|
|
2730
|
+
const response = await fetch(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/wikis/${encodeURIComponent(slug)}`, {
|
|
2731
|
+
...getFetchConfig(),
|
|
2689
2732
|
method: "DELETE",
|
|
2690
2733
|
});
|
|
2691
2734
|
await handleGitLabError(response);
|
|
@@ -2699,7 +2742,7 @@ async function deleteWikiPage(projectId, slug) {
|
|
|
2699
2742
|
*/
|
|
2700
2743
|
async function listPipelines(projectId, options = {}) {
|
|
2701
2744
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
2702
|
-
const url = new URL(`${
|
|
2745
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/pipelines`);
|
|
2703
2746
|
// Add all query parameters
|
|
2704
2747
|
Object.entries(options).forEach(([key, value]) => {
|
|
2705
2748
|
if (value !== undefined) {
|
|
@@ -2707,7 +2750,7 @@ async function listPipelines(projectId, options = {}) {
|
|
|
2707
2750
|
}
|
|
2708
2751
|
});
|
|
2709
2752
|
const response = await fetch(url.toString(), {
|
|
2710
|
-
...
|
|
2753
|
+
...getFetchConfig(),
|
|
2711
2754
|
});
|
|
2712
2755
|
await handleGitLabError(response);
|
|
2713
2756
|
const data = await response.json();
|
|
@@ -2722,9 +2765,9 @@ async function listPipelines(projectId, options = {}) {
|
|
|
2722
2765
|
*/
|
|
2723
2766
|
async function getPipeline(projectId, pipelineId) {
|
|
2724
2767
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
2725
|
-
const url = new URL(`${
|
|
2768
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/pipelines/${pipelineId}`);
|
|
2726
2769
|
const response = await fetch(url.toString(), {
|
|
2727
|
-
...
|
|
2770
|
+
...getFetchConfig(),
|
|
2728
2771
|
});
|
|
2729
2772
|
if (response.status === 404) {
|
|
2730
2773
|
throw new Error(`Pipeline not found`);
|
|
@@ -2743,7 +2786,7 @@ async function getPipeline(projectId, pipelineId) {
|
|
|
2743
2786
|
*/
|
|
2744
2787
|
async function listPipelineJobs(projectId, pipelineId, options = {}) {
|
|
2745
2788
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
2746
|
-
const url = new URL(`${
|
|
2789
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/pipelines/${pipelineId}/jobs`);
|
|
2747
2790
|
// Add all query parameters
|
|
2748
2791
|
Object.entries(options).forEach(([key, value]) => {
|
|
2749
2792
|
if (value !== undefined) {
|
|
@@ -2756,7 +2799,7 @@ async function listPipelineJobs(projectId, pipelineId, options = {}) {
|
|
|
2756
2799
|
}
|
|
2757
2800
|
});
|
|
2758
2801
|
const response = await fetch(url.toString(), {
|
|
2759
|
-
...
|
|
2802
|
+
...getFetchConfig(),
|
|
2760
2803
|
});
|
|
2761
2804
|
if (response.status === 404) {
|
|
2762
2805
|
throw new Error(`Pipeline not found`);
|
|
@@ -2775,7 +2818,7 @@ async function listPipelineJobs(projectId, pipelineId, options = {}) {
|
|
|
2775
2818
|
*/
|
|
2776
2819
|
async function listPipelineTriggerJobs(projectId, pipelineId, options = {}) {
|
|
2777
2820
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
2778
|
-
const url = new URL(`${
|
|
2821
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/pipelines/${pipelineId}/bridges`);
|
|
2779
2822
|
// Add all query parameters
|
|
2780
2823
|
Object.entries(options).forEach(([key, value]) => {
|
|
2781
2824
|
if (value !== undefined) {
|
|
@@ -2788,7 +2831,7 @@ async function listPipelineTriggerJobs(projectId, pipelineId, options = {}) {
|
|
|
2788
2831
|
}
|
|
2789
2832
|
});
|
|
2790
2833
|
const response = await fetch(url.toString(), {
|
|
2791
|
-
...
|
|
2834
|
+
...getFetchConfig(),
|
|
2792
2835
|
});
|
|
2793
2836
|
if (response.status === 404) {
|
|
2794
2837
|
throw new Error(`Pipeline not found`);
|
|
@@ -2799,9 +2842,9 @@ async function listPipelineTriggerJobs(projectId, pipelineId, options = {}) {
|
|
|
2799
2842
|
}
|
|
2800
2843
|
async function getPipelineJob(projectId, jobId) {
|
|
2801
2844
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
2802
|
-
const url = new URL(`${
|
|
2845
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/jobs/${jobId}`);
|
|
2803
2846
|
const response = await fetch(url.toString(), {
|
|
2804
|
-
...
|
|
2847
|
+
...getFetchConfig(),
|
|
2805
2848
|
});
|
|
2806
2849
|
if (response.status === 404) {
|
|
2807
2850
|
throw new Error(`Job not found`);
|
|
@@ -2821,9 +2864,9 @@ async function getPipelineJob(projectId, jobId) {
|
|
|
2821
2864
|
*/
|
|
2822
2865
|
async function getPipelineJobOutput(projectId, jobId, limit, offset) {
|
|
2823
2866
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
2824
|
-
const url = new URL(`${
|
|
2867
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/jobs/${jobId}/trace`);
|
|
2825
2868
|
const response = await fetch(url.toString(), {
|
|
2826
|
-
...
|
|
2869
|
+
...getFetchConfig(),
|
|
2827
2870
|
headers: {
|
|
2828
2871
|
...BASE_HEADERS,
|
|
2829
2872
|
...buildAuthHeaders(),
|
|
@@ -2867,7 +2910,7 @@ async function getPipelineJobOutput(projectId, jobId, limit, offset) {
|
|
|
2867
2910
|
*/
|
|
2868
2911
|
async function createPipeline(projectId, ref, variables) {
|
|
2869
2912
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
2870
|
-
const url = new URL(`${
|
|
2913
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/pipeline`);
|
|
2871
2914
|
const body = { ref };
|
|
2872
2915
|
if (variables && variables.length > 0) {
|
|
2873
2916
|
body.variables = variables;
|
|
@@ -2893,7 +2936,7 @@ async function createPipeline(projectId, ref, variables) {
|
|
|
2893
2936
|
*/
|
|
2894
2937
|
async function retryPipeline(projectId, pipelineId) {
|
|
2895
2938
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
2896
|
-
const url = new URL(`${
|
|
2939
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/pipelines/${pipelineId}/retry`);
|
|
2897
2940
|
const response = await fetch(url.toString(), {
|
|
2898
2941
|
method: "POST",
|
|
2899
2942
|
headers: {
|
|
@@ -2914,7 +2957,7 @@ async function retryPipeline(projectId, pipelineId) {
|
|
|
2914
2957
|
*/
|
|
2915
2958
|
async function cancelPipeline(projectId, pipelineId) {
|
|
2916
2959
|
projectId = decodeURIComponent(projectId); // Decode project ID
|
|
2917
|
-
const url = new URL(`${
|
|
2960
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/pipelines/${pipelineId}/cancel`);
|
|
2918
2961
|
const response = await fetch(url.toString(), {
|
|
2919
2962
|
method: "POST",
|
|
2920
2963
|
headers: {
|
|
@@ -2936,13 +2979,13 @@ async function cancelPipeline(projectId, pipelineId) {
|
|
|
2936
2979
|
*/
|
|
2937
2980
|
async function playPipelineJob(projectId, jobId, variables) {
|
|
2938
2981
|
projectId = decodeURIComponent(projectId);
|
|
2939
|
-
const url = new URL(`${
|
|
2982
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/jobs/${jobId}/play`);
|
|
2940
2983
|
const body = {};
|
|
2941
2984
|
if (variables && variables.length > 0) {
|
|
2942
2985
|
body.job_variables_attributes = variables;
|
|
2943
2986
|
}
|
|
2944
2987
|
const response = await fetch(url.toString(), {
|
|
2945
|
-
...
|
|
2988
|
+
...getFetchConfig(),
|
|
2946
2989
|
method: "POST",
|
|
2947
2990
|
body: Object.keys(body).length > 0 ? JSON.stringify(body) : undefined,
|
|
2948
2991
|
});
|
|
@@ -2959,9 +3002,9 @@ async function playPipelineJob(projectId, jobId, variables) {
|
|
|
2959
3002
|
*/
|
|
2960
3003
|
async function retryPipelineJob(projectId, jobId) {
|
|
2961
3004
|
projectId = decodeURIComponent(projectId);
|
|
2962
|
-
const url = new URL(`${
|
|
3005
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/jobs/${jobId}/retry`);
|
|
2963
3006
|
const response = await fetch(url.toString(), {
|
|
2964
|
-
...
|
|
3007
|
+
...getFetchConfig(),
|
|
2965
3008
|
method: "POST",
|
|
2966
3009
|
});
|
|
2967
3010
|
await handleGitLabError(response);
|
|
@@ -2978,12 +3021,12 @@ async function retryPipelineJob(projectId, jobId) {
|
|
|
2978
3021
|
*/
|
|
2979
3022
|
async function cancelPipelineJob(projectId, jobId, force) {
|
|
2980
3023
|
projectId = decodeURIComponent(projectId);
|
|
2981
|
-
const url = new URL(`${
|
|
3024
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/jobs/${jobId}/cancel`);
|
|
2982
3025
|
if (force !== undefined) {
|
|
2983
3026
|
url.searchParams.append('force', force.toString());
|
|
2984
3027
|
}
|
|
2985
3028
|
const response = await fetch(url.toString(), {
|
|
2986
|
-
...
|
|
3029
|
+
...getFetchConfig(),
|
|
2987
3030
|
method: "POST",
|
|
2988
3031
|
});
|
|
2989
3032
|
await handleGitLabError(response);
|
|
@@ -3015,7 +3058,7 @@ async function getRepositoryTree(options) {
|
|
|
3015
3058
|
...BASE_HEADERS,
|
|
3016
3059
|
...buildAuthHeaders(),
|
|
3017
3060
|
};
|
|
3018
|
-
const response = await fetch(`${
|
|
3061
|
+
const response = await fetch(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(options.project_id))}/repository/tree?${queryParams.toString()}`, {
|
|
3019
3062
|
headers,
|
|
3020
3063
|
});
|
|
3021
3064
|
if (response.status === 404) {
|
|
@@ -3035,7 +3078,7 @@ async function getRepositoryTree(options) {
|
|
|
3035
3078
|
*/
|
|
3036
3079
|
async function listProjectMilestones(projectId, options) {
|
|
3037
3080
|
projectId = decodeURIComponent(projectId);
|
|
3038
|
-
const url = new URL(`${
|
|
3081
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/milestones`);
|
|
3039
3082
|
Object.entries(options).forEach(([key, value]) => {
|
|
3040
3083
|
if (value !== undefined) {
|
|
3041
3084
|
if (key === "iids" && Array.isArray(value) && value.length > 0) {
|
|
@@ -3049,7 +3092,7 @@ async function listProjectMilestones(projectId, options) {
|
|
|
3049
3092
|
}
|
|
3050
3093
|
});
|
|
3051
3094
|
const response = await fetch(url.toString(), {
|
|
3052
|
-
...
|
|
3095
|
+
...getFetchConfig(),
|
|
3053
3096
|
});
|
|
3054
3097
|
await handleGitLabError(response);
|
|
3055
3098
|
const data = await response.json();
|
|
@@ -3063,9 +3106,9 @@ async function listProjectMilestones(projectId, options) {
|
|
|
3063
3106
|
*/
|
|
3064
3107
|
async function getProjectMilestone(projectId, milestoneId) {
|
|
3065
3108
|
projectId = decodeURIComponent(projectId);
|
|
3066
|
-
const url = new URL(`${
|
|
3109
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/milestones/${milestoneId}`);
|
|
3067
3110
|
const response = await fetch(url.toString(), {
|
|
3068
|
-
...
|
|
3111
|
+
...getFetchConfig(),
|
|
3069
3112
|
});
|
|
3070
3113
|
await handleGitLabError(response);
|
|
3071
3114
|
const data = await response.json();
|
|
@@ -3079,9 +3122,9 @@ async function getProjectMilestone(projectId, milestoneId) {
|
|
|
3079
3122
|
*/
|
|
3080
3123
|
async function createProjectMilestone(projectId, options) {
|
|
3081
3124
|
projectId = decodeURIComponent(projectId);
|
|
3082
|
-
const url = new URL(`${
|
|
3125
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/milestones`);
|
|
3083
3126
|
const response = await fetch(url.toString(), {
|
|
3084
|
-
...
|
|
3127
|
+
...getFetchConfig(),
|
|
3085
3128
|
method: "POST",
|
|
3086
3129
|
body: JSON.stringify(options),
|
|
3087
3130
|
});
|
|
@@ -3098,9 +3141,9 @@ async function createProjectMilestone(projectId, options) {
|
|
|
3098
3141
|
*/
|
|
3099
3142
|
async function editProjectMilestone(projectId, milestoneId, options) {
|
|
3100
3143
|
projectId = decodeURIComponent(projectId);
|
|
3101
|
-
const url = new URL(`${
|
|
3144
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/milestones/${milestoneId}`);
|
|
3102
3145
|
const response = await fetch(url.toString(), {
|
|
3103
|
-
...
|
|
3146
|
+
...getFetchConfig(),
|
|
3104
3147
|
method: "PUT",
|
|
3105
3148
|
body: JSON.stringify(options),
|
|
3106
3149
|
});
|
|
@@ -3116,9 +3159,9 @@ async function editProjectMilestone(projectId, milestoneId, options) {
|
|
|
3116
3159
|
*/
|
|
3117
3160
|
async function deleteProjectMilestone(projectId, milestoneId) {
|
|
3118
3161
|
projectId = decodeURIComponent(projectId);
|
|
3119
|
-
const url = new URL(`${
|
|
3162
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/milestones/${milestoneId}`);
|
|
3120
3163
|
const response = await fetch(url.toString(), {
|
|
3121
|
-
...
|
|
3164
|
+
...getFetchConfig(),
|
|
3122
3165
|
method: "DELETE",
|
|
3123
3166
|
});
|
|
3124
3167
|
await handleGitLabError(response);
|
|
@@ -3131,9 +3174,9 @@ async function deleteProjectMilestone(projectId, milestoneId) {
|
|
|
3131
3174
|
*/
|
|
3132
3175
|
async function getMilestoneIssues(projectId, milestoneId) {
|
|
3133
3176
|
projectId = decodeURIComponent(projectId);
|
|
3134
|
-
const url = new URL(`${
|
|
3177
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/milestones/${milestoneId}/issues`);
|
|
3135
3178
|
const response = await fetch(url.toString(), {
|
|
3136
|
-
...
|
|
3179
|
+
...getFetchConfig(),
|
|
3137
3180
|
});
|
|
3138
3181
|
await handleGitLabError(response);
|
|
3139
3182
|
const data = await response.json();
|
|
@@ -3147,9 +3190,9 @@ async function getMilestoneIssues(projectId, milestoneId) {
|
|
|
3147
3190
|
*/
|
|
3148
3191
|
async function getMilestoneMergeRequests(projectId, milestoneId) {
|
|
3149
3192
|
projectId = decodeURIComponent(projectId);
|
|
3150
|
-
const url = new URL(`${
|
|
3193
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/milestones/${milestoneId}/merge_requests`);
|
|
3151
3194
|
const response = await fetch(url.toString(), {
|
|
3152
|
-
...
|
|
3195
|
+
...getFetchConfig(),
|
|
3153
3196
|
});
|
|
3154
3197
|
await handleGitLabError(response);
|
|
3155
3198
|
const data = await response.json();
|
|
@@ -3163,9 +3206,9 @@ async function getMilestoneMergeRequests(projectId, milestoneId) {
|
|
|
3163
3206
|
*/
|
|
3164
3207
|
async function promoteProjectMilestone(projectId, milestoneId) {
|
|
3165
3208
|
projectId = decodeURIComponent(projectId);
|
|
3166
|
-
const url = new URL(`${
|
|
3209
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/milestones/${milestoneId}/promote`);
|
|
3167
3210
|
const response = await fetch(url.toString(), {
|
|
3168
|
-
...
|
|
3211
|
+
...getFetchConfig(),
|
|
3169
3212
|
method: "POST",
|
|
3170
3213
|
});
|
|
3171
3214
|
await handleGitLabError(response);
|
|
@@ -3180,9 +3223,9 @@ async function promoteProjectMilestone(projectId, milestoneId) {
|
|
|
3180
3223
|
*/
|
|
3181
3224
|
async function getMilestoneBurndownEvents(projectId, milestoneId) {
|
|
3182
3225
|
projectId = decodeURIComponent(projectId);
|
|
3183
|
-
const url = new URL(`${
|
|
3226
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/milestones/${milestoneId}/burndown_events`);
|
|
3184
3227
|
const response = await fetch(url.toString(), {
|
|
3185
|
-
...
|
|
3228
|
+
...getFetchConfig(),
|
|
3186
3229
|
});
|
|
3187
3230
|
await handleGitLabError(response);
|
|
3188
3231
|
const data = await response.json();
|
|
@@ -3196,10 +3239,10 @@ async function getMilestoneBurndownEvents(projectId, milestoneId) {
|
|
|
3196
3239
|
*/
|
|
3197
3240
|
async function getUser(username) {
|
|
3198
3241
|
try {
|
|
3199
|
-
const url = new URL(`${
|
|
3242
|
+
const url = new URL(`${getEffectiveApiUrl()}/users`);
|
|
3200
3243
|
url.searchParams.append("username", username);
|
|
3201
3244
|
const response = await fetch(url.toString(), {
|
|
3202
|
-
...
|
|
3245
|
+
...getFetchConfig(),
|
|
3203
3246
|
});
|
|
3204
3247
|
await handleGitLabError(response);
|
|
3205
3248
|
const users = await response.json();
|
|
@@ -3250,7 +3293,7 @@ async function getUsers(usernames) {
|
|
|
3250
3293
|
*/
|
|
3251
3294
|
async function listCommits(projectId, options = {}) {
|
|
3252
3295
|
projectId = decodeURIComponent(projectId);
|
|
3253
|
-
const url = new URL(`${
|
|
3296
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/repository/commits`);
|
|
3254
3297
|
// Add query parameters
|
|
3255
3298
|
if (options.ref_name)
|
|
3256
3299
|
url.searchParams.append("ref_name", options.ref_name);
|
|
@@ -3277,7 +3320,7 @@ async function listCommits(projectId, options = {}) {
|
|
|
3277
3320
|
if (options.per_page)
|
|
3278
3321
|
url.searchParams.append("per_page", options.per_page.toString());
|
|
3279
3322
|
const response = await fetch(url.toString(), {
|
|
3280
|
-
...
|
|
3323
|
+
...getFetchConfig(),
|
|
3281
3324
|
});
|
|
3282
3325
|
await handleGitLabError(response);
|
|
3283
3326
|
const data = await response.json();
|
|
@@ -3294,12 +3337,12 @@ async function listCommits(projectId, options = {}) {
|
|
|
3294
3337
|
*/
|
|
3295
3338
|
async function getCommit(projectId, sha, stats) {
|
|
3296
3339
|
projectId = decodeURIComponent(projectId);
|
|
3297
|
-
const url = new URL(`${
|
|
3340
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/repository/commits/${encodeURIComponent(sha)}`);
|
|
3298
3341
|
if (stats) {
|
|
3299
3342
|
url.searchParams.append("stats", "true");
|
|
3300
3343
|
}
|
|
3301
3344
|
const response = await fetch(url.toString(), {
|
|
3302
|
-
...
|
|
3345
|
+
...getFetchConfig(),
|
|
3303
3346
|
});
|
|
3304
3347
|
await handleGitLabError(response);
|
|
3305
3348
|
const data = await response.json();
|
|
@@ -3316,7 +3359,7 @@ async function getCommit(projectId, sha, stats) {
|
|
|
3316
3359
|
*/
|
|
3317
3360
|
async function getCommitDiff(projectId, sha, full_diff) {
|
|
3318
3361
|
projectId = decodeURIComponent(projectId);
|
|
3319
|
-
const baseUrl = `${
|
|
3362
|
+
const baseUrl = `${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/repository/commits/${encodeURIComponent(sha)}/diff`;
|
|
3320
3363
|
let allDiffs = [];
|
|
3321
3364
|
let page = 1;
|
|
3322
3365
|
while (true) {
|
|
@@ -3325,7 +3368,7 @@ async function getCommitDiff(projectId, sha, full_diff) {
|
|
|
3325
3368
|
url.searchParams.append("page", page.toString());
|
|
3326
3369
|
}
|
|
3327
3370
|
const response = await fetch(url.toString(), {
|
|
3328
|
-
...
|
|
3371
|
+
...getFetchConfig(),
|
|
3329
3372
|
});
|
|
3330
3373
|
await handleGitLabError(response);
|
|
3331
3374
|
const data = await response.json();
|
|
@@ -3348,7 +3391,7 @@ async function getCommitDiff(projectId, sha, full_diff) {
|
|
|
3348
3391
|
* @returns {Promise<GitLabUser>} The current user
|
|
3349
3392
|
*/
|
|
3350
3393
|
async function getCurrentUser() {
|
|
3351
|
-
const response = await fetch(`${
|
|
3394
|
+
const response = await fetch(`${getEffectiveApiUrl()}/user`, getFetchConfig());
|
|
3352
3395
|
await handleGitLabError(response);
|
|
3353
3396
|
const data = await response.json();
|
|
3354
3397
|
return GitLabUserSchema.parse(data);
|
|
@@ -3397,7 +3440,7 @@ async function myIssues(options = {}) {
|
|
|
3397
3440
|
async function listProjectMembers(projectId, options = {}) {
|
|
3398
3441
|
projectId = decodeURIComponent(projectId);
|
|
3399
3442
|
const effectiveProjectId = getEffectiveProjectId(projectId);
|
|
3400
|
-
const url = new URL(`${
|
|
3443
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(effectiveProjectId)}/members`);
|
|
3401
3444
|
// Add query parameters
|
|
3402
3445
|
if (options.query)
|
|
3403
3446
|
url.searchParams.append("query", options.query);
|
|
@@ -3411,7 +3454,7 @@ async function listProjectMembers(projectId, options = {}) {
|
|
|
3411
3454
|
url.searchParams.append("per_page", options.per_page.toString());
|
|
3412
3455
|
if (options.page)
|
|
3413
3456
|
url.searchParams.append("page", options.page.toString());
|
|
3414
|
-
const response = await fetch(url.toString(),
|
|
3457
|
+
const response = await fetch(url.toString(), getFetchConfig());
|
|
3415
3458
|
await handleGitLabError(response);
|
|
3416
3459
|
const data = await response.json();
|
|
3417
3460
|
return z.array(GitLabProjectMemberSchema).parse(data);
|
|
@@ -3425,7 +3468,7 @@ async function listProjectMembers(projectId, options = {}) {
|
|
|
3425
3468
|
*/
|
|
3426
3469
|
async function listGroupIterations(groupId, options = {}) {
|
|
3427
3470
|
groupId = decodeURIComponent(groupId);
|
|
3428
|
-
const url = new URL(`${
|
|
3471
|
+
const url = new URL(`${getEffectiveApiUrl()}/groups/${encodeURIComponent(groupId)}/iterations`);
|
|
3429
3472
|
// クエリパラメータの追加
|
|
3430
3473
|
if (options.state)
|
|
3431
3474
|
url.searchParams.append("state", options.state);
|
|
@@ -3445,7 +3488,7 @@ async function listGroupIterations(groupId, options = {}) {
|
|
|
3445
3488
|
url.searchParams.append("page", options.page.toString());
|
|
3446
3489
|
if (options.per_page)
|
|
3447
3490
|
url.searchParams.append("per_page", options.per_page.toString());
|
|
3448
|
-
const response = await fetch(url.toString(),
|
|
3491
|
+
const response = await fetch(url.toString(), getFetchConfig());
|
|
3449
3492
|
if (!response.ok) {
|
|
3450
3493
|
await handleGitLabError(response);
|
|
3451
3494
|
}
|
|
@@ -3476,7 +3519,7 @@ async function markdownUpload(projectId, filePath) {
|
|
|
3476
3519
|
filename: fileName,
|
|
3477
3520
|
contentType: "application/octet-stream",
|
|
3478
3521
|
});
|
|
3479
|
-
const url = new URL(`${
|
|
3522
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(effectiveProjectId)}/uploads`);
|
|
3480
3523
|
const response = await fetch(url.toString(), {
|
|
3481
3524
|
method: "POST",
|
|
3482
3525
|
headers: {
|
|
@@ -3495,7 +3538,7 @@ async function markdownUpload(projectId, filePath) {
|
|
|
3495
3538
|
}
|
|
3496
3539
|
async function downloadAttachment(projectId, secret, filename, localPath) {
|
|
3497
3540
|
const effectiveProjectId = getEffectiveProjectId(projectId);
|
|
3498
|
-
const url = new URL(`${
|
|
3541
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(effectiveProjectId)}/uploads/${secret}/${filename}`);
|
|
3499
3542
|
const response = await fetch(url.toString(), {
|
|
3500
3543
|
method: "GET",
|
|
3501
3544
|
headers: {
|
|
@@ -3520,7 +3563,7 @@ async function downloadAttachment(projectId, secret, filename, localPath) {
|
|
|
3520
3563
|
* @returns {Promise<GitLabEvent[]>} List of events
|
|
3521
3564
|
*/
|
|
3522
3565
|
async function listEvents(options = {}) {
|
|
3523
|
-
const url = new URL(`${
|
|
3566
|
+
const url = new URL(`${getEffectiveApiUrl()}/events`);
|
|
3524
3567
|
// Add all query parameters
|
|
3525
3568
|
Object.entries(options).forEach(([key, value]) => {
|
|
3526
3569
|
if (value !== undefined) {
|
|
@@ -3548,7 +3591,7 @@ async function listEvents(options = {}) {
|
|
|
3548
3591
|
*/
|
|
3549
3592
|
async function getProjectEvents(projectId, options = {}) {
|
|
3550
3593
|
const effectiveProjectId = getEffectiveProjectId(projectId);
|
|
3551
|
-
const url = new URL(`${
|
|
3594
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(effectiveProjectId)}/events`);
|
|
3552
3595
|
// Add all query parameters
|
|
3553
3596
|
Object.entries(options).forEach(([key, value]) => {
|
|
3554
3597
|
if (value !== undefined) {
|
|
@@ -3577,7 +3620,7 @@ async function getProjectEvents(projectId, options = {}) {
|
|
|
3577
3620
|
*/
|
|
3578
3621
|
async function listReleases(projectId, options = {}) {
|
|
3579
3622
|
const effectiveProjectId = getEffectiveProjectId(projectId);
|
|
3580
|
-
const url = new URL(`${
|
|
3623
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(effectiveProjectId)}/releases`);
|
|
3581
3624
|
// Add query parameters
|
|
3582
3625
|
Object.entries(options).forEach(([key, value]) => {
|
|
3583
3626
|
if (value !== undefined) {
|
|
@@ -3585,7 +3628,7 @@ async function listReleases(projectId, options = {}) {
|
|
|
3585
3628
|
}
|
|
3586
3629
|
});
|
|
3587
3630
|
const response = await fetch(url.toString(), {
|
|
3588
|
-
...
|
|
3631
|
+
...getFetchConfig(),
|
|
3589
3632
|
});
|
|
3590
3633
|
await handleGitLabError(response);
|
|
3591
3634
|
const data = await response.json();
|
|
@@ -3601,12 +3644,12 @@ async function listReleases(projectId, options = {}) {
|
|
|
3601
3644
|
*/
|
|
3602
3645
|
async function getRelease(projectId, tagName, includeHtmlDescription) {
|
|
3603
3646
|
const effectiveProjectId = getEffectiveProjectId(projectId);
|
|
3604
|
-
const url = new URL(`${
|
|
3647
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(effectiveProjectId)}/releases/${encodeURIComponent(tagName)}`);
|
|
3605
3648
|
if (includeHtmlDescription !== undefined) {
|
|
3606
3649
|
url.searchParams.append("include_html_description", includeHtmlDescription.toString());
|
|
3607
3650
|
}
|
|
3608
3651
|
const response = await fetch(url.toString(), {
|
|
3609
|
-
...
|
|
3652
|
+
...getFetchConfig(),
|
|
3610
3653
|
});
|
|
3611
3654
|
await handleGitLabError(response);
|
|
3612
3655
|
const data = await response.json();
|
|
@@ -3621,8 +3664,8 @@ async function getRelease(projectId, tagName, includeHtmlDescription) {
|
|
|
3621
3664
|
*/
|
|
3622
3665
|
async function createRelease(projectId, options) {
|
|
3623
3666
|
const effectiveProjectId = getEffectiveProjectId(projectId);
|
|
3624
|
-
const response = await fetch(`${
|
|
3625
|
-
...
|
|
3667
|
+
const response = await fetch(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(effectiveProjectId)}/releases`, {
|
|
3668
|
+
...getFetchConfig(),
|
|
3626
3669
|
method: "POST",
|
|
3627
3670
|
body: JSON.stringify(options),
|
|
3628
3671
|
});
|
|
@@ -3640,8 +3683,8 @@ async function createRelease(projectId, options) {
|
|
|
3640
3683
|
*/
|
|
3641
3684
|
async function updateRelease(projectId, tagName, options) {
|
|
3642
3685
|
const effectiveProjectId = getEffectiveProjectId(projectId);
|
|
3643
|
-
const response = await fetch(`${
|
|
3644
|
-
...
|
|
3686
|
+
const response = await fetch(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(effectiveProjectId)}/releases/${encodeURIComponent(tagName)}`, {
|
|
3687
|
+
...getFetchConfig(),
|
|
3645
3688
|
method: "PUT",
|
|
3646
3689
|
body: JSON.stringify(options),
|
|
3647
3690
|
});
|
|
@@ -3658,8 +3701,8 @@ async function updateRelease(projectId, tagName, options) {
|
|
|
3658
3701
|
*/
|
|
3659
3702
|
async function deleteRelease(projectId, tagName) {
|
|
3660
3703
|
const effectiveProjectId = getEffectiveProjectId(projectId);
|
|
3661
|
-
const response = await fetch(`${
|
|
3662
|
-
...
|
|
3704
|
+
const response = await fetch(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(effectiveProjectId)}/releases/${encodeURIComponent(tagName)}`, {
|
|
3705
|
+
...getFetchConfig(),
|
|
3663
3706
|
method: "DELETE",
|
|
3664
3707
|
});
|
|
3665
3708
|
await handleGitLabError(response);
|
|
@@ -3674,8 +3717,8 @@ async function deleteRelease(projectId, tagName) {
|
|
|
3674
3717
|
*/
|
|
3675
3718
|
async function createReleaseEvidence(projectId, tagName) {
|
|
3676
3719
|
const effectiveProjectId = getEffectiveProjectId(projectId);
|
|
3677
|
-
const response = await fetch(`${
|
|
3678
|
-
...
|
|
3720
|
+
const response = await fetch(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(effectiveProjectId)}/releases/${encodeURIComponent(tagName)}/evidence`, {
|
|
3721
|
+
...getFetchConfig(),
|
|
3679
3722
|
method: "POST",
|
|
3680
3723
|
});
|
|
3681
3724
|
await handleGitLabError(response);
|
|
@@ -3690,13 +3733,16 @@ async function createReleaseEvidence(projectId, tagName) {
|
|
|
3690
3733
|
*/
|
|
3691
3734
|
async function downloadReleaseAsset(projectId, tagName, directAssetPath) {
|
|
3692
3735
|
const effectiveProjectId = getEffectiveProjectId(projectId);
|
|
3693
|
-
const response = await fetch(`${
|
|
3694
|
-
...
|
|
3736
|
+
const response = await fetch(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(effectiveProjectId)}/releases/${encodeURIComponent(tagName)}/downloads/${directAssetPath}`, {
|
|
3737
|
+
...getFetchConfig(),
|
|
3695
3738
|
});
|
|
3696
3739
|
await handleGitLabError(response);
|
|
3697
3740
|
return await response.text();
|
|
3698
3741
|
}
|
|
3699
3742
|
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
3743
|
+
// In remote auth mode, retrieve session context from AsyncLocalStorage
|
|
3744
|
+
// This ensures the context is available even when called from SDK's async chains
|
|
3745
|
+
const sessionContext = REMOTE_AUTHORIZATION ? sessionAuthStore.getStore() : null;
|
|
3700
3746
|
// Apply read-only filter first
|
|
3701
3747
|
const tools0 = GITLAB_READ_ONLY_MODE
|
|
3702
3748
|
? allTools.filter(tool => readOnlyTools.includes(tool.name))
|
|
@@ -3733,19 +3779,38 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
3733
3779
|
};
|
|
3734
3780
|
});
|
|
3735
3781
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
3782
|
+
// Manually retrieve the session context using the session ID passed in the request.
|
|
3783
|
+
// This is a robust workaround for AsyncLocalStorage context loss.
|
|
3784
|
+
const sessionId = request.params.sessionId;
|
|
3785
|
+
if (REMOTE_AUTHORIZATION && sessionId && authBySession[sessionId]) {
|
|
3786
|
+
const authData = authBySession[sessionId];
|
|
3787
|
+
const sessionContext = {
|
|
3788
|
+
sessionId,
|
|
3789
|
+
header: authData.header,
|
|
3790
|
+
token: authData.token,
|
|
3791
|
+
lastUsed: authData.lastUsed,
|
|
3792
|
+
apiUrl: authData.apiUrl,
|
|
3793
|
+
};
|
|
3794
|
+
// Run the handler within the retrieved context
|
|
3795
|
+
return await sessionAuthStore.run(sessionContext, () => handleToolCall(request.params));
|
|
3796
|
+
}
|
|
3797
|
+
// Fallback for non-remote-auth mode or if session is not found
|
|
3798
|
+
return handleToolCall(request.params);
|
|
3799
|
+
});
|
|
3800
|
+
async function handleToolCall(params) {
|
|
3736
3801
|
try {
|
|
3737
|
-
if (!
|
|
3802
|
+
if (!params.arguments) {
|
|
3738
3803
|
throw new Error("Arguments are required");
|
|
3739
3804
|
}
|
|
3740
3805
|
// Ensure session is established for every request if cookie authentication is enabled
|
|
3741
3806
|
if (GITLAB_AUTH_COOKIE_PATH) {
|
|
3742
3807
|
await ensureSessionForRequest();
|
|
3743
3808
|
}
|
|
3744
|
-
logger.info(
|
|
3745
|
-
switch (
|
|
3809
|
+
logger.info(params.name);
|
|
3810
|
+
switch (params.name) {
|
|
3746
3811
|
case "execute_graphql": {
|
|
3747
|
-
const args = ExecuteGraphQLSchema.parse(
|
|
3748
|
-
const apiUrl = new URL(
|
|
3812
|
+
const args = ExecuteGraphQLSchema.parse(params.arguments);
|
|
3813
|
+
const apiUrl = new URL(getEffectiveApiUrl());
|
|
3749
3814
|
// Build GraphQL endpoint preserving any instance subpath (e.g. /gitlab)
|
|
3750
3815
|
const restPath = apiUrl.pathname || ""; // e.g. /api/v4 or /gitlab/api/v4
|
|
3751
3816
|
const idx = restPath.lastIndexOf("/api/v4");
|
|
@@ -3758,7 +3823,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
3758
3823
|
logger.info({ endpoint: graphqlUrl }, "execute_graphql request");
|
|
3759
3824
|
try {
|
|
3760
3825
|
const response = await fetch(graphqlUrl, {
|
|
3761
|
-
...
|
|
3826
|
+
...getFetchConfig(),
|
|
3762
3827
|
method: "POST",
|
|
3763
3828
|
headers: {
|
|
3764
3829
|
...BASE_HEADERS,
|
|
@@ -3794,7 +3859,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
3794
3859
|
if (GITLAB_PROJECT_ID) {
|
|
3795
3860
|
throw new Error("Direct project ID is set. So fork_repository is not allowed");
|
|
3796
3861
|
}
|
|
3797
|
-
const forkArgs = ForkRepositorySchema.parse(
|
|
3862
|
+
const forkArgs = ForkRepositorySchema.parse(params.arguments);
|
|
3798
3863
|
try {
|
|
3799
3864
|
const forkedProject = await forkProject(forkArgs.project_id, forkArgs.namespace);
|
|
3800
3865
|
return {
|
|
@@ -3818,7 +3883,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
3818
3883
|
}
|
|
3819
3884
|
}
|
|
3820
3885
|
case "create_branch": {
|
|
3821
|
-
const args = CreateBranchSchema.parse(
|
|
3886
|
+
const args = CreateBranchSchema.parse(params.arguments);
|
|
3822
3887
|
let ref = args.ref;
|
|
3823
3888
|
if (!ref) {
|
|
3824
3889
|
ref = await getDefaultBranchRef(args.project_id);
|
|
@@ -3832,7 +3897,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
3832
3897
|
};
|
|
3833
3898
|
}
|
|
3834
3899
|
case "get_branch_diffs": {
|
|
3835
|
-
const args = GetBranchDiffsSchema.parse(
|
|
3900
|
+
const args = GetBranchDiffsSchema.parse(params.arguments);
|
|
3836
3901
|
const diffResp = await getBranchDiffs(args.project_id, args.from, args.to, args.straight);
|
|
3837
3902
|
if (args.excluded_file_patterns?.length) {
|
|
3838
3903
|
const regexPatterns = args.excluded_file_patterns.map(pattern => new RegExp(pattern));
|
|
@@ -3850,7 +3915,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
3850
3915
|
};
|
|
3851
3916
|
}
|
|
3852
3917
|
case "search_repositories": {
|
|
3853
|
-
const args = SearchRepositoriesSchema.parse(
|
|
3918
|
+
const args = SearchRepositoriesSchema.parse(params.arguments);
|
|
3854
3919
|
const results = await searchProjects(args.search, args.page, args.per_page);
|
|
3855
3920
|
return {
|
|
3856
3921
|
content: [{ type: "text", text: JSON.stringify(results, null, 2) }],
|
|
@@ -3860,35 +3925,35 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
3860
3925
|
if (GITLAB_PROJECT_ID) {
|
|
3861
3926
|
throw new Error("Direct project ID is set. So fork_repository is not allowed");
|
|
3862
3927
|
}
|
|
3863
|
-
const args = CreateRepositorySchema.parse(
|
|
3928
|
+
const args = CreateRepositorySchema.parse(params.arguments);
|
|
3864
3929
|
const repository = await createRepository(args);
|
|
3865
3930
|
return {
|
|
3866
3931
|
content: [{ type: "text", text: JSON.stringify(repository, null, 2) }],
|
|
3867
3932
|
};
|
|
3868
3933
|
}
|
|
3869
3934
|
case "get_file_contents": {
|
|
3870
|
-
const args = GetFileContentsSchema.parse(
|
|
3935
|
+
const args = GetFileContentsSchema.parse(params.arguments);
|
|
3871
3936
|
const contents = await getFileContents(args.project_id, args.file_path, args.ref);
|
|
3872
3937
|
return {
|
|
3873
3938
|
content: [{ type: "text", text: JSON.stringify(contents, null, 2) }],
|
|
3874
3939
|
};
|
|
3875
3940
|
}
|
|
3876
3941
|
case "create_or_update_file": {
|
|
3877
|
-
const args = CreateOrUpdateFileSchema.parse(
|
|
3942
|
+
const args = CreateOrUpdateFileSchema.parse(params.arguments);
|
|
3878
3943
|
const result = await createOrUpdateFile(args.project_id, args.file_path, args.content, args.commit_message, args.branch, args.previous_path, args.last_commit_id, args.commit_id);
|
|
3879
3944
|
return {
|
|
3880
3945
|
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
3881
3946
|
};
|
|
3882
3947
|
}
|
|
3883
3948
|
case "push_files": {
|
|
3884
|
-
const args = PushFilesSchema.parse(
|
|
3949
|
+
const args = PushFilesSchema.parse(params.arguments);
|
|
3885
3950
|
const result = await createCommit(args.project_id, args.commit_message, args.branch, args.files.map(f => ({ path: f.file_path, content: f.content })));
|
|
3886
3951
|
return {
|
|
3887
3952
|
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
3888
3953
|
};
|
|
3889
3954
|
}
|
|
3890
3955
|
case "create_issue": {
|
|
3891
|
-
const args = CreateIssueSchema.parse(
|
|
3956
|
+
const args = CreateIssueSchema.parse(params.arguments);
|
|
3892
3957
|
const { project_id, ...options } = args;
|
|
3893
3958
|
const issue = await createIssue(project_id, options);
|
|
3894
3959
|
return {
|
|
@@ -3896,7 +3961,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
3896
3961
|
};
|
|
3897
3962
|
}
|
|
3898
3963
|
case "create_merge_request": {
|
|
3899
|
-
const args = CreateMergeRequestSchema.parse(
|
|
3964
|
+
const args = CreateMergeRequestSchema.parse(params.arguments);
|
|
3900
3965
|
const { project_id, ...options } = args;
|
|
3901
3966
|
const mergeRequest = await createMergeRequest(project_id, options);
|
|
3902
3967
|
return {
|
|
@@ -3904,7 +3969,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
3904
3969
|
};
|
|
3905
3970
|
}
|
|
3906
3971
|
case "delete_merge_request_discussion_note": {
|
|
3907
|
-
const args = DeleteMergeRequestDiscussionNoteSchema.parse(
|
|
3972
|
+
const args = DeleteMergeRequestDiscussionNoteSchema.parse(params.arguments);
|
|
3908
3973
|
const { project_id, merge_request_iid, discussion_id, note_id } = args;
|
|
3909
3974
|
await deleteMergeRequestDiscussionNote(project_id, merge_request_iid, discussion_id, note_id);
|
|
3910
3975
|
return {
|
|
@@ -3912,7 +3977,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
3912
3977
|
};
|
|
3913
3978
|
}
|
|
3914
3979
|
case "update_merge_request_discussion_note": {
|
|
3915
|
-
const args = UpdateMergeRequestDiscussionNoteSchema.parse(
|
|
3980
|
+
const args = UpdateMergeRequestDiscussionNoteSchema.parse(params.arguments);
|
|
3916
3981
|
const note = await updateMergeRequestDiscussionNote(args.project_id, args.merge_request_iid, args.discussion_id, args.note_id, args.body, // Now optional
|
|
3917
3982
|
args.resolved // Now one of body or resolved must be provided, not both
|
|
3918
3983
|
);
|
|
@@ -3921,84 +3986,84 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
3921
3986
|
};
|
|
3922
3987
|
}
|
|
3923
3988
|
case "create_merge_request_discussion_note": {
|
|
3924
|
-
const args = CreateMergeRequestDiscussionNoteSchema.parse(
|
|
3989
|
+
const args = CreateMergeRequestDiscussionNoteSchema.parse(params.arguments);
|
|
3925
3990
|
const note = await createMergeRequestDiscussionNote(args.project_id, args.merge_request_iid, args.discussion_id, args.body, args.created_at);
|
|
3926
3991
|
return {
|
|
3927
3992
|
content: [{ type: "text", text: JSON.stringify(note, null, 2) }],
|
|
3928
3993
|
};
|
|
3929
3994
|
}
|
|
3930
3995
|
case "create_merge_request_note": {
|
|
3931
|
-
const args = CreateMergeRequestNoteSchema.parse(
|
|
3996
|
+
const args = CreateMergeRequestNoteSchema.parse(params.arguments);
|
|
3932
3997
|
const note = await createMergeRequestNote(args.project_id, args.merge_request_iid, args.body);
|
|
3933
3998
|
return {
|
|
3934
3999
|
content: [{ type: "text", text: JSON.stringify(note, null, 2) }],
|
|
3935
4000
|
};
|
|
3936
4001
|
}
|
|
3937
4002
|
case "delete_merge_request_note": {
|
|
3938
|
-
const args = DeleteMergeRequestNoteSchema.parse(
|
|
4003
|
+
const args = DeleteMergeRequestNoteSchema.parse(params.arguments);
|
|
3939
4004
|
await deleteMergeRequestNote(args.project_id, args.merge_request_iid, args.note_id);
|
|
3940
4005
|
return {
|
|
3941
4006
|
content: [{ type: "text", text: "Merge request note deleted successfully" }],
|
|
3942
4007
|
};
|
|
3943
4008
|
}
|
|
3944
4009
|
case 'get_merge_request_note': {
|
|
3945
|
-
const args = GetMergeRequestNoteSchema.parse(
|
|
4010
|
+
const args = GetMergeRequestNoteSchema.parse(params.arguments);
|
|
3946
4011
|
const note = await getMergeRequestNote(args.project_id, args.merge_request_iid, args.note_id);
|
|
3947
4012
|
return {
|
|
3948
4013
|
content: [{ type: "text", text: JSON.stringify(note, null, 2) }],
|
|
3949
4014
|
};
|
|
3950
4015
|
}
|
|
3951
4016
|
case 'get_merge_request_notes': {
|
|
3952
|
-
const args = GetMergeRequestNotesSchema.parse(
|
|
4017
|
+
const args = GetMergeRequestNotesSchema.parse(params.arguments);
|
|
3953
4018
|
const notes = await getMergeRequestNotes(args.project_id, args.merge_request_iid, args.sort, args.order_by);
|
|
3954
4019
|
return {
|
|
3955
4020
|
content: [{ type: "text", text: JSON.stringify(notes, null, 2) }],
|
|
3956
4021
|
};
|
|
3957
4022
|
}
|
|
3958
4023
|
case 'update_merge_request_note': {
|
|
3959
|
-
const args = UpdateMergeRequestNoteSchema.parse(
|
|
4024
|
+
const args = UpdateMergeRequestNoteSchema.parse(params.arguments);
|
|
3960
4025
|
const note = await updateMergeRequestNote(args.project_id, args.merge_request_iid, args.note_id, args.body);
|
|
3961
4026
|
return {
|
|
3962
4027
|
content: [{ type: "text", text: JSON.stringify(note, null, 2) }],
|
|
3963
4028
|
};
|
|
3964
4029
|
}
|
|
3965
4030
|
case "update_issue_note": {
|
|
3966
|
-
const args = UpdateIssueNoteSchema.parse(
|
|
4031
|
+
const args = UpdateIssueNoteSchema.parse(params.arguments);
|
|
3967
4032
|
const note = await updateIssueNote(args.project_id, args.issue_iid, args.discussion_id, args.note_id, args.body);
|
|
3968
4033
|
return {
|
|
3969
4034
|
content: [{ type: "text", text: JSON.stringify(note, null, 2) }],
|
|
3970
4035
|
};
|
|
3971
4036
|
}
|
|
3972
4037
|
case "create_issue_note": {
|
|
3973
|
-
const args = CreateIssueNoteSchema.parse(
|
|
4038
|
+
const args = CreateIssueNoteSchema.parse(params.arguments);
|
|
3974
4039
|
const note = await createIssueNote(args.project_id, args.issue_iid, args.discussion_id, args.body, args.created_at);
|
|
3975
4040
|
return {
|
|
3976
4041
|
content: [{ type: "text", text: JSON.stringify(note, null, 2) }],
|
|
3977
4042
|
};
|
|
3978
4043
|
}
|
|
3979
4044
|
case "get_merge_request": {
|
|
3980
|
-
const args = GetMergeRequestSchema.parse(
|
|
4045
|
+
const args = GetMergeRequestSchema.parse(params.arguments);
|
|
3981
4046
|
const mergeRequest = await getMergeRequest(args.project_id, args.merge_request_iid, args.source_branch);
|
|
3982
4047
|
return {
|
|
3983
4048
|
content: [{ type: "text", text: JSON.stringify(mergeRequest, null, 2) }],
|
|
3984
4049
|
};
|
|
3985
4050
|
}
|
|
3986
4051
|
case "get_merge_request_diffs": {
|
|
3987
|
-
const args = GetMergeRequestDiffsSchema.parse(
|
|
4052
|
+
const args = GetMergeRequestDiffsSchema.parse(params.arguments);
|
|
3988
4053
|
const diffs = await getMergeRequestDiffs(args.project_id, args.merge_request_iid, args.source_branch, args.view);
|
|
3989
4054
|
return {
|
|
3990
4055
|
content: [{ type: "text", text: JSON.stringify(diffs, null, 2) }],
|
|
3991
4056
|
};
|
|
3992
4057
|
}
|
|
3993
4058
|
case "list_merge_request_diffs": {
|
|
3994
|
-
const args = ListMergeRequestDiffsSchema.parse(
|
|
4059
|
+
const args = ListMergeRequestDiffsSchema.parse(params.arguments);
|
|
3995
4060
|
const changes = await listMergeRequestDiffs(args.project_id, args.merge_request_iid, args.source_branch, args.page, args.per_page, args.unidiff);
|
|
3996
4061
|
return {
|
|
3997
4062
|
content: [{ type: "text", text: JSON.stringify(changes, null, 2) }],
|
|
3998
4063
|
};
|
|
3999
4064
|
}
|
|
4000
4065
|
case "update_merge_request": {
|
|
4001
|
-
const args = UpdateMergeRequestSchema.parse(
|
|
4066
|
+
const args = UpdateMergeRequestSchema.parse(params.arguments);
|
|
4002
4067
|
const { project_id, merge_request_iid, source_branch, ...options } = args;
|
|
4003
4068
|
const mergeRequest = await updateMergeRequest(project_id, options, merge_request_iid, source_branch);
|
|
4004
4069
|
return {
|
|
@@ -4006,7 +4071,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4006
4071
|
};
|
|
4007
4072
|
}
|
|
4008
4073
|
case "merge_merge_request": {
|
|
4009
|
-
const args = MergeMergeRequestSchema.parse(
|
|
4074
|
+
const args = MergeMergeRequestSchema.parse(params.arguments);
|
|
4010
4075
|
const { project_id, merge_request_iid, ...options } = args;
|
|
4011
4076
|
const mergeRequest = await mergeMergeRequest(project_id, options, merge_request_iid);
|
|
4012
4077
|
return {
|
|
@@ -4014,7 +4079,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4014
4079
|
};
|
|
4015
4080
|
}
|
|
4016
4081
|
case "mr_discussions": {
|
|
4017
|
-
const args = ListMergeRequestDiscussionsSchema.parse(
|
|
4082
|
+
const args = ListMergeRequestDiscussionsSchema.parse(params.arguments);
|
|
4018
4083
|
const { project_id, merge_request_iid, ...options } = args;
|
|
4019
4084
|
const discussions = await listMergeRequestDiscussions(project_id, merge_request_iid, options);
|
|
4020
4085
|
return {
|
|
@@ -4022,7 +4087,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4022
4087
|
};
|
|
4023
4088
|
}
|
|
4024
4089
|
case "list_namespaces": {
|
|
4025
|
-
const args = ListNamespacesSchema.parse(
|
|
4090
|
+
const args = ListNamespacesSchema.parse(params.arguments);
|
|
4026
4091
|
const url = new URL(`${GITLAB_API_URL}/namespaces`);
|
|
4027
4092
|
if (args.search) {
|
|
4028
4093
|
url.searchParams.append("search", args.search);
|
|
@@ -4037,7 +4102,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4037
4102
|
url.searchParams.append("owned", args.owned.toString());
|
|
4038
4103
|
}
|
|
4039
4104
|
const response = await fetch(url.toString(), {
|
|
4040
|
-
...
|
|
4105
|
+
...getFetchConfig(),
|
|
4041
4106
|
});
|
|
4042
4107
|
await handleGitLabError(response);
|
|
4043
4108
|
const data = await response.json();
|
|
@@ -4047,10 +4112,10 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4047
4112
|
};
|
|
4048
4113
|
}
|
|
4049
4114
|
case "get_namespace": {
|
|
4050
|
-
const args = GetNamespaceSchema.parse(
|
|
4115
|
+
const args = GetNamespaceSchema.parse(params.arguments);
|
|
4051
4116
|
const url = new URL(`${GITLAB_API_URL}/namespaces/${encodeURIComponent(args.namespace_id)}`);
|
|
4052
4117
|
const response = await fetch(url.toString(), {
|
|
4053
|
-
...
|
|
4118
|
+
...getFetchConfig(),
|
|
4054
4119
|
});
|
|
4055
4120
|
await handleGitLabError(response);
|
|
4056
4121
|
const data = await response.json();
|
|
@@ -4060,10 +4125,10 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4060
4125
|
};
|
|
4061
4126
|
}
|
|
4062
4127
|
case "verify_namespace": {
|
|
4063
|
-
const args = VerifyNamespaceSchema.parse(
|
|
4128
|
+
const args = VerifyNamespaceSchema.parse(params.arguments);
|
|
4064
4129
|
const url = new URL(`${GITLAB_API_URL}/namespaces/${encodeURIComponent(args.path)}/exists`);
|
|
4065
4130
|
const response = await fetch(url.toString(), {
|
|
4066
|
-
...
|
|
4131
|
+
...getFetchConfig(),
|
|
4067
4132
|
});
|
|
4068
4133
|
await handleGitLabError(response);
|
|
4069
4134
|
const data = await response.json();
|
|
@@ -4073,27 +4138,35 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4073
4138
|
};
|
|
4074
4139
|
}
|
|
4075
4140
|
case "get_project": {
|
|
4076
|
-
const args = GetProjectSchema.parse(
|
|
4077
|
-
const
|
|
4141
|
+
const args = GetProjectSchema.parse(params.arguments);
|
|
4142
|
+
const options = params.arguments;
|
|
4143
|
+
const effectiveProjectId = getEffectiveProjectId(args.project_id);
|
|
4144
|
+
const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(effectiveProjectId)}`);
|
|
4145
|
+
if (options.license)
|
|
4146
|
+
url.searchParams.append("license", "true");
|
|
4147
|
+
if (options.statistics)
|
|
4148
|
+
url.searchParams.append("statistics", "true");
|
|
4149
|
+
if (options.with_custom_attributes)
|
|
4150
|
+
url.searchParams.append("with_custom_attributes", "true");
|
|
4078
4151
|
const response = await fetch(url.toString(), {
|
|
4079
|
-
...
|
|
4152
|
+
...getFetchConfig(),
|
|
4080
4153
|
});
|
|
4081
4154
|
await handleGitLabError(response);
|
|
4082
4155
|
const data = await response.json();
|
|
4083
|
-
|
|
4156
|
+
// Return raw data without parsing through our schema to avoid type mismatches in tests
|
|
4084
4157
|
return {
|
|
4085
|
-
content: [{ type: "text", text: JSON.stringify(
|
|
4158
|
+
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
|
|
4086
4159
|
};
|
|
4087
4160
|
}
|
|
4088
4161
|
case "list_projects": {
|
|
4089
|
-
const args = ListProjectsSchema.parse(
|
|
4162
|
+
const args = ListProjectsSchema.parse(params.arguments);
|
|
4090
4163
|
const projects = await listProjects(args);
|
|
4091
4164
|
return {
|
|
4092
4165
|
content: [{ type: "text", text: JSON.stringify(projects, null, 2) }],
|
|
4093
4166
|
};
|
|
4094
4167
|
}
|
|
4095
4168
|
case "list_project_members": {
|
|
4096
|
-
const args = ListProjectMembersSchema.parse(
|
|
4169
|
+
const args = ListProjectMembersSchema.parse(params.arguments);
|
|
4097
4170
|
const { project_id, ...options } = args;
|
|
4098
4171
|
const members = await listProjectMembers(project_id, options);
|
|
4099
4172
|
return {
|
|
@@ -4101,14 +4174,14 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4101
4174
|
};
|
|
4102
4175
|
}
|
|
4103
4176
|
case "get_users": {
|
|
4104
|
-
const args = GetUsersSchema.parse(
|
|
4177
|
+
const args = GetUsersSchema.parse(params.arguments);
|
|
4105
4178
|
const usersMap = await getUsers(args.usernames);
|
|
4106
4179
|
return {
|
|
4107
4180
|
content: [{ type: "text", text: JSON.stringify(usersMap, null, 2) }],
|
|
4108
4181
|
};
|
|
4109
4182
|
}
|
|
4110
4183
|
case "create_note": {
|
|
4111
|
-
const args = CreateNoteSchema.parse(
|
|
4184
|
+
const args = CreateNoteSchema.parse(params.arguments);
|
|
4112
4185
|
const { project_id, noteable_type, noteable_iid, body } = args;
|
|
4113
4186
|
const note = await createNote(project_id, noteable_type, noteable_iid, body);
|
|
4114
4187
|
return {
|
|
@@ -4116,7 +4189,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4116
4189
|
};
|
|
4117
4190
|
}
|
|
4118
4191
|
case "get_draft_note": {
|
|
4119
|
-
const args = GetDraftNoteSchema.parse(
|
|
4192
|
+
const args = GetDraftNoteSchema.parse(params.arguments);
|
|
4120
4193
|
const { project_id, merge_request_iid, draft_note_id } = args;
|
|
4121
4194
|
const draftNote = await getDraftNote(project_id, merge_request_iid, draft_note_id);
|
|
4122
4195
|
return {
|
|
@@ -4124,7 +4197,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4124
4197
|
};
|
|
4125
4198
|
}
|
|
4126
4199
|
case "list_draft_notes": {
|
|
4127
|
-
const args = ListDraftNotesSchema.parse(
|
|
4200
|
+
const args = ListDraftNotesSchema.parse(params.arguments);
|
|
4128
4201
|
const { project_id, merge_request_iid } = args;
|
|
4129
4202
|
const draftNotes = await listDraftNotes(project_id, merge_request_iid);
|
|
4130
4203
|
return {
|
|
@@ -4132,7 +4205,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4132
4205
|
};
|
|
4133
4206
|
}
|
|
4134
4207
|
case "create_draft_note": {
|
|
4135
|
-
const args = CreateDraftNoteSchema.parse(
|
|
4208
|
+
const args = CreateDraftNoteSchema.parse(params.arguments);
|
|
4136
4209
|
const { project_id, merge_request_iid, body, position, resolve_discussion } = args;
|
|
4137
4210
|
const draftNote = await createDraftNote(project_id, merge_request_iid, body, position, resolve_discussion);
|
|
4138
4211
|
return {
|
|
@@ -4140,7 +4213,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4140
4213
|
};
|
|
4141
4214
|
}
|
|
4142
4215
|
case "update_draft_note": {
|
|
4143
|
-
const args = UpdateDraftNoteSchema.parse(
|
|
4216
|
+
const args = UpdateDraftNoteSchema.parse(params.arguments);
|
|
4144
4217
|
const { project_id, merge_request_iid, draft_note_id, body, position, resolve_discussion } = args;
|
|
4145
4218
|
const draftNote = await updateDraftNote(project_id, merge_request_iid, draft_note_id, body, position, resolve_discussion);
|
|
4146
4219
|
return {
|
|
@@ -4148,7 +4221,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4148
4221
|
};
|
|
4149
4222
|
}
|
|
4150
4223
|
case "delete_draft_note": {
|
|
4151
|
-
const args = DeleteDraftNoteSchema.parse(
|
|
4224
|
+
const args = DeleteDraftNoteSchema.parse(params.arguments);
|
|
4152
4225
|
const { project_id, merge_request_iid, draft_note_id } = args;
|
|
4153
4226
|
await deleteDraftNote(project_id, merge_request_iid, draft_note_id);
|
|
4154
4227
|
return {
|
|
@@ -4156,7 +4229,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4156
4229
|
};
|
|
4157
4230
|
}
|
|
4158
4231
|
case "publish_draft_note": {
|
|
4159
|
-
const args = PublishDraftNoteSchema.parse(
|
|
4232
|
+
const args = PublishDraftNoteSchema.parse(params.arguments);
|
|
4160
4233
|
const { project_id, merge_request_iid, draft_note_id } = args;
|
|
4161
4234
|
const publishedNote = await publishDraftNote(project_id, merge_request_iid, draft_note_id);
|
|
4162
4235
|
return {
|
|
@@ -4164,7 +4237,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4164
4237
|
};
|
|
4165
4238
|
}
|
|
4166
4239
|
case "bulk_publish_draft_notes": {
|
|
4167
|
-
const args = BulkPublishDraftNotesSchema.parse(
|
|
4240
|
+
const args = BulkPublishDraftNotesSchema.parse(params.arguments);
|
|
4168
4241
|
const { project_id, merge_request_iid } = args;
|
|
4169
4242
|
const publishedNotes = await bulkPublishDraftNotes(project_id, merge_request_iid);
|
|
4170
4243
|
return {
|
|
@@ -4172,7 +4245,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4172
4245
|
};
|
|
4173
4246
|
}
|
|
4174
4247
|
case "create_merge_request_thread": {
|
|
4175
|
-
const args = CreateMergeRequestThreadSchema.parse(
|
|
4248
|
+
const args = CreateMergeRequestThreadSchema.parse(params.arguments);
|
|
4176
4249
|
const { project_id, merge_request_iid, body, position, created_at } = args;
|
|
4177
4250
|
const thread = await createMergeRequestThread(project_id, merge_request_iid, body, position, created_at);
|
|
4178
4251
|
return {
|
|
@@ -4180,7 +4253,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4180
4253
|
};
|
|
4181
4254
|
}
|
|
4182
4255
|
case "resolve_merge_request_thread": {
|
|
4183
|
-
const args = ResolveMergeRequestThreadSchema.parse(
|
|
4256
|
+
const args = ResolveMergeRequestThreadSchema.parse(params.arguments);
|
|
4184
4257
|
const { project_id, merge_request_iid, discussion_id, resolved } = args;
|
|
4185
4258
|
await resolveMergeRequestThread(project_id, merge_request_iid, discussion_id, resolved);
|
|
4186
4259
|
return {
|
|
@@ -4188,7 +4261,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4188
4261
|
};
|
|
4189
4262
|
}
|
|
4190
4263
|
case "list_issues": {
|
|
4191
|
-
const args = ListIssuesSchema.parse(
|
|
4264
|
+
const args = ListIssuesSchema.parse(params.arguments);
|
|
4192
4265
|
const { project_id, ...options } = args;
|
|
4193
4266
|
const issues = await listIssues(project_id, options);
|
|
4194
4267
|
return {
|
|
@@ -4196,21 +4269,21 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4196
4269
|
};
|
|
4197
4270
|
}
|
|
4198
4271
|
case "my_issues": {
|
|
4199
|
-
const args = MyIssuesSchema.parse(
|
|
4272
|
+
const args = MyIssuesSchema.parse(params.arguments);
|
|
4200
4273
|
const issues = await myIssues(args);
|
|
4201
4274
|
return {
|
|
4202
4275
|
content: [{ type: "text", text: JSON.stringify(issues, null, 2) }],
|
|
4203
4276
|
};
|
|
4204
4277
|
}
|
|
4205
4278
|
case "get_issue": {
|
|
4206
|
-
const args = GetIssueSchema.parse(
|
|
4279
|
+
const args = GetIssueSchema.parse(params.arguments);
|
|
4207
4280
|
const issue = await getIssue(args.project_id, args.issue_iid);
|
|
4208
4281
|
return {
|
|
4209
4282
|
content: [{ type: "text", text: JSON.stringify(issue, null, 2) }],
|
|
4210
4283
|
};
|
|
4211
4284
|
}
|
|
4212
4285
|
case "update_issue": {
|
|
4213
|
-
const args = UpdateIssueSchema.parse(
|
|
4286
|
+
const args = UpdateIssueSchema.parse(params.arguments);
|
|
4214
4287
|
const { project_id, issue_iid, ...options } = args;
|
|
4215
4288
|
const issue = await updateIssue(project_id, issue_iid, options);
|
|
4216
4289
|
return {
|
|
@@ -4218,7 +4291,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4218
4291
|
};
|
|
4219
4292
|
}
|
|
4220
4293
|
case "delete_issue": {
|
|
4221
|
-
const args = DeleteIssueSchema.parse(
|
|
4294
|
+
const args = DeleteIssueSchema.parse(params.arguments);
|
|
4222
4295
|
await deleteIssue(args.project_id, args.issue_iid);
|
|
4223
4296
|
return {
|
|
4224
4297
|
content: [
|
|
@@ -4230,14 +4303,14 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4230
4303
|
};
|
|
4231
4304
|
}
|
|
4232
4305
|
case "list_issue_links": {
|
|
4233
|
-
const args = ListIssueLinksSchema.parse(
|
|
4306
|
+
const args = ListIssueLinksSchema.parse(params.arguments);
|
|
4234
4307
|
const links = await listIssueLinks(args.project_id, args.issue_iid);
|
|
4235
4308
|
return {
|
|
4236
4309
|
content: [{ type: "text", text: JSON.stringify(links, null, 2) }],
|
|
4237
4310
|
};
|
|
4238
4311
|
}
|
|
4239
4312
|
case "list_issue_discussions": {
|
|
4240
|
-
const args = ListIssueDiscussionsSchema.parse(
|
|
4313
|
+
const args = ListIssueDiscussionsSchema.parse(params.arguments);
|
|
4241
4314
|
const { project_id, issue_iid, ...options } = args;
|
|
4242
4315
|
const discussions = await listIssueDiscussions(project_id, issue_iid, options);
|
|
4243
4316
|
return {
|
|
@@ -4245,21 +4318,21 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4245
4318
|
};
|
|
4246
4319
|
}
|
|
4247
4320
|
case "get_issue_link": {
|
|
4248
|
-
const args = GetIssueLinkSchema.parse(
|
|
4321
|
+
const args = GetIssueLinkSchema.parse(params.arguments);
|
|
4249
4322
|
const link = await getIssueLink(args.project_id, args.issue_iid, args.issue_link_id);
|
|
4250
4323
|
return {
|
|
4251
4324
|
content: [{ type: "text", text: JSON.stringify(link, null, 2) }],
|
|
4252
4325
|
};
|
|
4253
4326
|
}
|
|
4254
4327
|
case "create_issue_link": {
|
|
4255
|
-
const args = CreateIssueLinkSchema.parse(
|
|
4328
|
+
const args = CreateIssueLinkSchema.parse(params.arguments);
|
|
4256
4329
|
const link = await createIssueLink(args.project_id, args.issue_iid, args.target_project_id, args.target_issue_iid, args.link_type);
|
|
4257
4330
|
return {
|
|
4258
4331
|
content: [{ type: "text", text: JSON.stringify(link, null, 2) }],
|
|
4259
4332
|
};
|
|
4260
4333
|
}
|
|
4261
4334
|
case "delete_issue_link": {
|
|
4262
|
-
const args = DeleteIssueLinkSchema.parse(
|
|
4335
|
+
const args = DeleteIssueLinkSchema.parse(params.arguments);
|
|
4263
4336
|
await deleteIssueLink(args.project_id, args.issue_iid, args.issue_link_id);
|
|
4264
4337
|
return {
|
|
4265
4338
|
content: [
|
|
@@ -4274,28 +4347,28 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4274
4347
|
};
|
|
4275
4348
|
}
|
|
4276
4349
|
case "list_labels": {
|
|
4277
|
-
const args = ListLabelsSchema.parse(
|
|
4350
|
+
const args = ListLabelsSchema.parse(params.arguments);
|
|
4278
4351
|
const labels = await listLabels(args.project_id, args);
|
|
4279
4352
|
return {
|
|
4280
4353
|
content: [{ type: "text", text: JSON.stringify(labels, null, 2) }],
|
|
4281
4354
|
};
|
|
4282
4355
|
}
|
|
4283
4356
|
case "get_label": {
|
|
4284
|
-
const args = GetLabelSchema.parse(
|
|
4357
|
+
const args = GetLabelSchema.parse(params.arguments);
|
|
4285
4358
|
const label = await getLabel(args.project_id, args.label_id, args.include_ancestor_groups);
|
|
4286
4359
|
return {
|
|
4287
4360
|
content: [{ type: "text", text: JSON.stringify(label, null, 2) }],
|
|
4288
4361
|
};
|
|
4289
4362
|
}
|
|
4290
4363
|
case "create_label": {
|
|
4291
|
-
const args = CreateLabelSchema.parse(
|
|
4364
|
+
const args = CreateLabelSchema.parse(params.arguments);
|
|
4292
4365
|
const label = await createLabel(args.project_id, args);
|
|
4293
4366
|
return {
|
|
4294
4367
|
content: [{ type: "text", text: JSON.stringify(label, null, 2) }],
|
|
4295
4368
|
};
|
|
4296
4369
|
}
|
|
4297
4370
|
case "update_label": {
|
|
4298
|
-
const args = UpdateLabelSchema.parse(
|
|
4371
|
+
const args = UpdateLabelSchema.parse(params.arguments);
|
|
4299
4372
|
const { project_id, label_id, ...options } = args;
|
|
4300
4373
|
const label = await updateLabel(project_id, label_id, options);
|
|
4301
4374
|
return {
|
|
@@ -4303,7 +4376,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4303
4376
|
};
|
|
4304
4377
|
}
|
|
4305
4378
|
case "delete_label": {
|
|
4306
|
-
const args = DeleteLabelSchema.parse(
|
|
4379
|
+
const args = DeleteLabelSchema.parse(params.arguments);
|
|
4307
4380
|
await deleteLabel(args.project_id, args.label_id);
|
|
4308
4381
|
return {
|
|
4309
4382
|
content: [
|
|
@@ -4315,14 +4388,14 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4315
4388
|
};
|
|
4316
4389
|
}
|
|
4317
4390
|
case "list_group_projects": {
|
|
4318
|
-
const args = ListGroupProjectsSchema.parse(
|
|
4391
|
+
const args = ListGroupProjectsSchema.parse(params.arguments);
|
|
4319
4392
|
const projects = await listGroupProjects(args);
|
|
4320
4393
|
return {
|
|
4321
4394
|
content: [{ type: "text", text: JSON.stringify(projects, null, 2) }],
|
|
4322
4395
|
};
|
|
4323
4396
|
}
|
|
4324
4397
|
case "list_wiki_pages": {
|
|
4325
|
-
const { project_id, page, per_page, with_content } = ListWikiPagesSchema.parse(
|
|
4398
|
+
const { project_id, page, per_page, with_content } = ListWikiPagesSchema.parse(params.arguments);
|
|
4326
4399
|
const wikiPages = await listWikiPages(project_id, {
|
|
4327
4400
|
page,
|
|
4328
4401
|
per_page,
|
|
@@ -4333,28 +4406,28 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4333
4406
|
};
|
|
4334
4407
|
}
|
|
4335
4408
|
case "get_wiki_page": {
|
|
4336
|
-
const { project_id, slug } = GetWikiPageSchema.parse(
|
|
4409
|
+
const { project_id, slug } = GetWikiPageSchema.parse(params.arguments);
|
|
4337
4410
|
const wikiPage = await getWikiPage(project_id, slug);
|
|
4338
4411
|
return {
|
|
4339
4412
|
content: [{ type: "text", text: JSON.stringify(wikiPage, null, 2) }],
|
|
4340
4413
|
};
|
|
4341
4414
|
}
|
|
4342
4415
|
case "create_wiki_page": {
|
|
4343
|
-
const { project_id, title, content, format } = CreateWikiPageSchema.parse(
|
|
4416
|
+
const { project_id, title, content, format } = CreateWikiPageSchema.parse(params.arguments);
|
|
4344
4417
|
const wikiPage = await createWikiPage(project_id, title, content, format);
|
|
4345
4418
|
return {
|
|
4346
4419
|
content: [{ type: "text", text: JSON.stringify(wikiPage, null, 2) }],
|
|
4347
4420
|
};
|
|
4348
4421
|
}
|
|
4349
4422
|
case "update_wiki_page": {
|
|
4350
|
-
const { project_id, slug, title, content, format } = UpdateWikiPageSchema.parse(
|
|
4423
|
+
const { project_id, slug, title, content, format } = UpdateWikiPageSchema.parse(params.arguments);
|
|
4351
4424
|
const wikiPage = await updateWikiPage(project_id, slug, title, content, format);
|
|
4352
4425
|
return {
|
|
4353
4426
|
content: [{ type: "text", text: JSON.stringify(wikiPage, null, 2) }],
|
|
4354
4427
|
};
|
|
4355
4428
|
}
|
|
4356
4429
|
case "delete_wiki_page": {
|
|
4357
|
-
const { project_id, slug } = DeleteWikiPageSchema.parse(
|
|
4430
|
+
const { project_id, slug } = DeleteWikiPageSchema.parse(params.arguments);
|
|
4358
4431
|
await deleteWikiPage(project_id, slug);
|
|
4359
4432
|
return {
|
|
4360
4433
|
content: [
|
|
@@ -4369,14 +4442,14 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4369
4442
|
};
|
|
4370
4443
|
}
|
|
4371
4444
|
case "get_repository_tree": {
|
|
4372
|
-
const args = GetRepositoryTreeSchema.parse(
|
|
4445
|
+
const args = GetRepositoryTreeSchema.parse(params.arguments);
|
|
4373
4446
|
const tree = await getRepositoryTree(args);
|
|
4374
4447
|
return {
|
|
4375
4448
|
content: [{ type: "text", text: JSON.stringify(tree, null, 2) }],
|
|
4376
4449
|
};
|
|
4377
4450
|
}
|
|
4378
4451
|
case "list_pipelines": {
|
|
4379
|
-
const args = ListPipelinesSchema.parse(
|
|
4452
|
+
const args = ListPipelinesSchema.parse(params.arguments);
|
|
4380
4453
|
const { project_id, ...options } = args;
|
|
4381
4454
|
const pipelines = await listPipelines(project_id, options);
|
|
4382
4455
|
return {
|
|
@@ -4384,7 +4457,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4384
4457
|
};
|
|
4385
4458
|
}
|
|
4386
4459
|
case "get_pipeline": {
|
|
4387
|
-
const { project_id, pipeline_id } = GetPipelineSchema.parse(
|
|
4460
|
+
const { project_id, pipeline_id } = GetPipelineSchema.parse(params.arguments);
|
|
4388
4461
|
const pipeline = await getPipeline(project_id, pipeline_id);
|
|
4389
4462
|
return {
|
|
4390
4463
|
content: [
|
|
@@ -4396,7 +4469,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4396
4469
|
};
|
|
4397
4470
|
}
|
|
4398
4471
|
case "list_pipeline_jobs": {
|
|
4399
|
-
const { project_id, pipeline_id, ...options } = ListPipelineJobsSchema.parse(
|
|
4472
|
+
const { project_id, pipeline_id, ...options } = ListPipelineJobsSchema.parse(params.arguments);
|
|
4400
4473
|
const jobs = await listPipelineJobs(project_id, pipeline_id, options);
|
|
4401
4474
|
return {
|
|
4402
4475
|
content: [
|
|
@@ -4408,7 +4481,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4408
4481
|
};
|
|
4409
4482
|
}
|
|
4410
4483
|
case "list_pipeline_trigger_jobs": {
|
|
4411
|
-
const { project_id, pipeline_id, ...options } = ListPipelineTriggerJobsSchema.parse(
|
|
4484
|
+
const { project_id, pipeline_id, ...options } = ListPipelineTriggerJobsSchema.parse(params.arguments);
|
|
4412
4485
|
const triggerJobs = await listPipelineTriggerJobs(project_id, pipeline_id, options);
|
|
4413
4486
|
return {
|
|
4414
4487
|
content: [
|
|
@@ -4420,7 +4493,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4420
4493
|
};
|
|
4421
4494
|
}
|
|
4422
4495
|
case "get_pipeline_job": {
|
|
4423
|
-
const { project_id, job_id } = GetPipelineJobOutputSchema.parse(
|
|
4496
|
+
const { project_id, job_id } = GetPipelineJobOutputSchema.parse(params.arguments);
|
|
4424
4497
|
const jobDetails = await getPipelineJob(project_id, job_id);
|
|
4425
4498
|
return {
|
|
4426
4499
|
content: [
|
|
@@ -4432,7 +4505,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4432
4505
|
};
|
|
4433
4506
|
}
|
|
4434
4507
|
case "get_pipeline_job_output": {
|
|
4435
|
-
const { project_id, job_id, limit, offset } = GetPipelineJobOutputSchema.parse(
|
|
4508
|
+
const { project_id, job_id, limit, offset } = GetPipelineJobOutputSchema.parse(params.arguments);
|
|
4436
4509
|
const jobOutput = await getPipelineJobOutput(project_id, job_id, limit, offset);
|
|
4437
4510
|
return {
|
|
4438
4511
|
content: [
|
|
@@ -4444,7 +4517,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4444
4517
|
};
|
|
4445
4518
|
}
|
|
4446
4519
|
case "create_pipeline": {
|
|
4447
|
-
const { project_id, ref, variables } = CreatePipelineSchema.parse(
|
|
4520
|
+
const { project_id, ref, variables } = CreatePipelineSchema.parse(params.arguments);
|
|
4448
4521
|
const pipeline = await createPipeline(project_id, ref, variables);
|
|
4449
4522
|
return {
|
|
4450
4523
|
content: [
|
|
@@ -4456,7 +4529,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4456
4529
|
};
|
|
4457
4530
|
}
|
|
4458
4531
|
case "retry_pipeline": {
|
|
4459
|
-
const { project_id, pipeline_id } = RetryPipelineSchema.parse(
|
|
4532
|
+
const { project_id, pipeline_id } = RetryPipelineSchema.parse(params.arguments);
|
|
4460
4533
|
const pipeline = await retryPipeline(project_id, pipeline_id);
|
|
4461
4534
|
return {
|
|
4462
4535
|
content: [
|
|
@@ -4468,7 +4541,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4468
4541
|
};
|
|
4469
4542
|
}
|
|
4470
4543
|
case "cancel_pipeline": {
|
|
4471
|
-
const { project_id, pipeline_id } = CancelPipelineSchema.parse(
|
|
4544
|
+
const { project_id, pipeline_id } = CancelPipelineSchema.parse(params.arguments);
|
|
4472
4545
|
const pipeline = await cancelPipeline(project_id, pipeline_id);
|
|
4473
4546
|
return {
|
|
4474
4547
|
content: [
|
|
@@ -4480,7 +4553,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4480
4553
|
};
|
|
4481
4554
|
}
|
|
4482
4555
|
case "play_pipeline_job": {
|
|
4483
|
-
const { project_id, job_id, job_variables_attributes } = PlayPipelineJobSchema.parse(
|
|
4556
|
+
const { project_id, job_id, job_variables_attributes } = PlayPipelineJobSchema.parse(params.arguments);
|
|
4484
4557
|
const job = await playPipelineJob(project_id, job_id, job_variables_attributes);
|
|
4485
4558
|
return {
|
|
4486
4559
|
content: [
|
|
@@ -4492,7 +4565,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4492
4565
|
};
|
|
4493
4566
|
}
|
|
4494
4567
|
case "retry_pipeline_job": {
|
|
4495
|
-
const { project_id, job_id } = RetryPipelineJobSchema.parse(
|
|
4568
|
+
const { project_id, job_id } = RetryPipelineJobSchema.parse(params.arguments);
|
|
4496
4569
|
const job = await retryPipelineJob(project_id, job_id);
|
|
4497
4570
|
return {
|
|
4498
4571
|
content: [
|
|
@@ -4504,7 +4577,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4504
4577
|
};
|
|
4505
4578
|
}
|
|
4506
4579
|
case "cancel_pipeline_job": {
|
|
4507
|
-
const { project_id, job_id, force } = CancelPipelineJobSchema.parse(
|
|
4580
|
+
const { project_id, job_id, force } = CancelPipelineJobSchema.parse(params.arguments);
|
|
4508
4581
|
const job = await cancelPipelineJob(project_id, job_id, force);
|
|
4509
4582
|
return {
|
|
4510
4583
|
content: [
|
|
@@ -4516,14 +4589,14 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4516
4589
|
};
|
|
4517
4590
|
}
|
|
4518
4591
|
case "list_merge_requests": {
|
|
4519
|
-
const args = ListMergeRequestsSchema.parse(
|
|
4592
|
+
const args = ListMergeRequestsSchema.parse(params.arguments);
|
|
4520
4593
|
const mergeRequests = await listMergeRequests(args.project_id, args);
|
|
4521
4594
|
return {
|
|
4522
4595
|
content: [{ type: "text", text: JSON.stringify(mergeRequests, null, 2) }],
|
|
4523
4596
|
};
|
|
4524
4597
|
}
|
|
4525
4598
|
case "list_milestones": {
|
|
4526
|
-
const { project_id, ...options } = ListProjectMilestonesSchema.parse(
|
|
4599
|
+
const { project_id, ...options } = ListProjectMilestonesSchema.parse(params.arguments);
|
|
4527
4600
|
const milestones = await listProjectMilestones(project_id, options);
|
|
4528
4601
|
return {
|
|
4529
4602
|
content: [
|
|
@@ -4535,7 +4608,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4535
4608
|
};
|
|
4536
4609
|
}
|
|
4537
4610
|
case "get_milestone": {
|
|
4538
|
-
const { project_id, milestone_id } = GetProjectMilestoneSchema.parse(
|
|
4611
|
+
const { project_id, milestone_id } = GetProjectMilestoneSchema.parse(params.arguments);
|
|
4539
4612
|
const milestone = await getProjectMilestone(project_id, milestone_id);
|
|
4540
4613
|
return {
|
|
4541
4614
|
content: [
|
|
@@ -4547,7 +4620,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4547
4620
|
};
|
|
4548
4621
|
}
|
|
4549
4622
|
case "create_milestone": {
|
|
4550
|
-
const { project_id, ...options } = CreateProjectMilestoneSchema.parse(
|
|
4623
|
+
const { project_id, ...options } = CreateProjectMilestoneSchema.parse(params.arguments);
|
|
4551
4624
|
const milestone = await createProjectMilestone(project_id, options);
|
|
4552
4625
|
return {
|
|
4553
4626
|
content: [
|
|
@@ -4559,7 +4632,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4559
4632
|
};
|
|
4560
4633
|
}
|
|
4561
4634
|
case "edit_milestone": {
|
|
4562
|
-
const { project_id, milestone_id, ...options } = EditProjectMilestoneSchema.parse(
|
|
4635
|
+
const { project_id, milestone_id, ...options } = EditProjectMilestoneSchema.parse(params.arguments);
|
|
4563
4636
|
const milestone = await editProjectMilestone(project_id, milestone_id, options);
|
|
4564
4637
|
return {
|
|
4565
4638
|
content: [
|
|
@@ -4571,7 +4644,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4571
4644
|
};
|
|
4572
4645
|
}
|
|
4573
4646
|
case "delete_milestone": {
|
|
4574
|
-
const { project_id, milestone_id } = DeleteProjectMilestoneSchema.parse(
|
|
4647
|
+
const { project_id, milestone_id } = DeleteProjectMilestoneSchema.parse(params.arguments);
|
|
4575
4648
|
await deleteProjectMilestone(project_id, milestone_id);
|
|
4576
4649
|
return {
|
|
4577
4650
|
content: [
|
|
@@ -4586,7 +4659,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4586
4659
|
};
|
|
4587
4660
|
}
|
|
4588
4661
|
case "get_milestone_issue": {
|
|
4589
|
-
const { project_id, milestone_id } = GetMilestoneIssuesSchema.parse(
|
|
4662
|
+
const { project_id, milestone_id } = GetMilestoneIssuesSchema.parse(params.arguments);
|
|
4590
4663
|
const issues = await getMilestoneIssues(project_id, milestone_id);
|
|
4591
4664
|
return {
|
|
4592
4665
|
content: [
|
|
@@ -4598,7 +4671,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4598
4671
|
};
|
|
4599
4672
|
}
|
|
4600
4673
|
case "get_milestone_merge_requests": {
|
|
4601
|
-
const { project_id, milestone_id } = GetMilestoneMergeRequestsSchema.parse(
|
|
4674
|
+
const { project_id, milestone_id } = GetMilestoneMergeRequestsSchema.parse(params.arguments);
|
|
4602
4675
|
const mergeRequests = await getMilestoneMergeRequests(project_id, milestone_id);
|
|
4603
4676
|
return {
|
|
4604
4677
|
content: [
|
|
@@ -4610,7 +4683,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4610
4683
|
};
|
|
4611
4684
|
}
|
|
4612
4685
|
case "promote_milestone": {
|
|
4613
|
-
const { project_id, milestone_id } = PromoteProjectMilestoneSchema.parse(
|
|
4686
|
+
const { project_id, milestone_id } = PromoteProjectMilestoneSchema.parse(params.arguments);
|
|
4614
4687
|
const milestone = await promoteProjectMilestone(project_id, milestone_id);
|
|
4615
4688
|
return {
|
|
4616
4689
|
content: [
|
|
@@ -4622,7 +4695,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4622
4695
|
};
|
|
4623
4696
|
}
|
|
4624
4697
|
case "get_milestone_burndown_events": {
|
|
4625
|
-
const { project_id, milestone_id } = GetMilestoneBurndownEventsSchema.parse(
|
|
4698
|
+
const { project_id, milestone_id } = GetMilestoneBurndownEventsSchema.parse(params.arguments);
|
|
4626
4699
|
const events = await getMilestoneBurndownEvents(project_id, milestone_id);
|
|
4627
4700
|
return {
|
|
4628
4701
|
content: [
|
|
@@ -4634,56 +4707,56 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4634
4707
|
};
|
|
4635
4708
|
}
|
|
4636
4709
|
case "list_commits": {
|
|
4637
|
-
const args = ListCommitsSchema.parse(
|
|
4710
|
+
const args = ListCommitsSchema.parse(params.arguments);
|
|
4638
4711
|
const commits = await listCommits(args.project_id, args);
|
|
4639
4712
|
return {
|
|
4640
4713
|
content: [{ type: "text", text: JSON.stringify(commits, null, 2) }],
|
|
4641
4714
|
};
|
|
4642
4715
|
}
|
|
4643
4716
|
case "get_commit": {
|
|
4644
|
-
const args = GetCommitSchema.parse(
|
|
4717
|
+
const args = GetCommitSchema.parse(params.arguments);
|
|
4645
4718
|
const commit = await getCommit(args.project_id, args.sha, args.stats);
|
|
4646
4719
|
return {
|
|
4647
4720
|
content: [{ type: "text", text: JSON.stringify(commit, null, 2) }],
|
|
4648
4721
|
};
|
|
4649
4722
|
}
|
|
4650
4723
|
case "get_commit_diff": {
|
|
4651
|
-
const args = GetCommitDiffSchema.parse(
|
|
4724
|
+
const args = GetCommitDiffSchema.parse(params.arguments);
|
|
4652
4725
|
const diff = await getCommitDiff(args.project_id, args.sha, args.full_diff);
|
|
4653
4726
|
return {
|
|
4654
4727
|
content: [{ type: "text", text: JSON.stringify(diff, null, 2) }],
|
|
4655
4728
|
};
|
|
4656
4729
|
}
|
|
4657
4730
|
case "list_group_iterations": {
|
|
4658
|
-
const args = ListGroupIterationsSchema.parse(
|
|
4731
|
+
const args = ListGroupIterationsSchema.parse(params.arguments);
|
|
4659
4732
|
const iterations = await listGroupIterations(args.group_id, args);
|
|
4660
4733
|
return {
|
|
4661
4734
|
content: [{ type: "text", text: JSON.stringify(iterations, null, 2) }],
|
|
4662
4735
|
};
|
|
4663
4736
|
}
|
|
4664
4737
|
case "upload_markdown": {
|
|
4665
|
-
const args = MarkdownUploadSchema.parse(
|
|
4738
|
+
const args = MarkdownUploadSchema.parse(params.arguments);
|
|
4666
4739
|
const upload = await markdownUpload(args.project_id, args.file_path);
|
|
4667
4740
|
return {
|
|
4668
4741
|
content: [{ type: "text", text: JSON.stringify(upload, null, 2) }],
|
|
4669
4742
|
};
|
|
4670
4743
|
}
|
|
4671
4744
|
case "download_attachment": {
|
|
4672
|
-
const args = DownloadAttachmentSchema.parse(
|
|
4745
|
+
const args = DownloadAttachmentSchema.parse(params.arguments);
|
|
4673
4746
|
const filePath = await downloadAttachment(args.project_id, args.secret, args.filename, args.local_path);
|
|
4674
4747
|
return {
|
|
4675
4748
|
content: [{ type: "text", text: JSON.stringify({ success: true, file_path: filePath }, null, 2) }],
|
|
4676
4749
|
};
|
|
4677
4750
|
}
|
|
4678
4751
|
case "list_events": {
|
|
4679
|
-
const args = ListEventsSchema.parse(
|
|
4752
|
+
const args = ListEventsSchema.parse(params.arguments);
|
|
4680
4753
|
const events = await listEvents(args);
|
|
4681
4754
|
return {
|
|
4682
4755
|
content: [{ type: "text", text: JSON.stringify(events, null, 2) }],
|
|
4683
4756
|
};
|
|
4684
4757
|
}
|
|
4685
4758
|
case "get_project_events": {
|
|
4686
|
-
const args = GetProjectEventsSchema.parse(
|
|
4759
|
+
const args = GetProjectEventsSchema.parse(params.arguments);
|
|
4687
4760
|
const { project_id, ...options } = args;
|
|
4688
4761
|
const events = await getProjectEvents(project_id, options);
|
|
4689
4762
|
return {
|
|
@@ -4691,7 +4764,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4691
4764
|
};
|
|
4692
4765
|
}
|
|
4693
4766
|
case "list_releases": {
|
|
4694
|
-
const args = ListReleasesSchema.parse(
|
|
4767
|
+
const args = ListReleasesSchema.parse(params.arguments);
|
|
4695
4768
|
const { project_id, ...options } = args;
|
|
4696
4769
|
const releases = await listReleases(project_id, options);
|
|
4697
4770
|
return {
|
|
@@ -4699,14 +4772,14 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4699
4772
|
};
|
|
4700
4773
|
}
|
|
4701
4774
|
case "get_release": {
|
|
4702
|
-
const args = GetReleaseSchema.parse(
|
|
4775
|
+
const args = GetReleaseSchema.parse(params.arguments);
|
|
4703
4776
|
const release = await getRelease(args.project_id, args.tag_name, args.include_html_description);
|
|
4704
4777
|
return {
|
|
4705
4778
|
content: [{ type: "text", text: JSON.stringify(release, null, 2) }],
|
|
4706
4779
|
};
|
|
4707
4780
|
}
|
|
4708
4781
|
case "create_release": {
|
|
4709
|
-
const args = CreateReleaseSchema.parse(
|
|
4782
|
+
const args = CreateReleaseSchema.parse(params.arguments);
|
|
4710
4783
|
const { project_id, ...options } = args;
|
|
4711
4784
|
const release = await createRelease(project_id, options);
|
|
4712
4785
|
return {
|
|
@@ -4714,7 +4787,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4714
4787
|
};
|
|
4715
4788
|
}
|
|
4716
4789
|
case "update_release": {
|
|
4717
|
-
const args = UpdateReleaseSchema.parse(
|
|
4790
|
+
const args = UpdateReleaseSchema.parse(params.arguments);
|
|
4718
4791
|
const { project_id, tag_name, ...options } = args;
|
|
4719
4792
|
const release = await updateRelease(project_id, tag_name, options);
|
|
4720
4793
|
return {
|
|
@@ -4722,7 +4795,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4722
4795
|
};
|
|
4723
4796
|
}
|
|
4724
4797
|
case "delete_release": {
|
|
4725
|
-
const args = DeleteReleaseSchema.parse(
|
|
4798
|
+
const args = DeleteReleaseSchema.parse(params.arguments);
|
|
4726
4799
|
const release = await deleteRelease(args.project_id, args.tag_name);
|
|
4727
4800
|
return {
|
|
4728
4801
|
content: [
|
|
@@ -4734,7 +4807,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4734
4807
|
};
|
|
4735
4808
|
}
|
|
4736
4809
|
case "create_release_evidence": {
|
|
4737
|
-
const args = CreateReleaseEvidenceSchema.parse(
|
|
4810
|
+
const args = CreateReleaseEvidenceSchema.parse(params.arguments);
|
|
4738
4811
|
await createReleaseEvidence(args.project_id, args.tag_name);
|
|
4739
4812
|
return {
|
|
4740
4813
|
content: [
|
|
@@ -4746,18 +4819,18 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4746
4819
|
};
|
|
4747
4820
|
}
|
|
4748
4821
|
case "download_release_asset": {
|
|
4749
|
-
const args = DownloadReleaseAssetSchema.parse(
|
|
4822
|
+
const args = DownloadReleaseAssetSchema.parse(params.arguments);
|
|
4750
4823
|
const assetContent = await downloadReleaseAsset(args.project_id, args.tag_name, args.direct_asset_path);
|
|
4751
4824
|
return {
|
|
4752
4825
|
content: [{ type: "text", text: assetContent }],
|
|
4753
4826
|
};
|
|
4754
4827
|
}
|
|
4755
4828
|
default:
|
|
4756
|
-
throw new Error(`Unknown tool: ${
|
|
4829
|
+
throw new Error(`Unknown tool: ${params.name}`);
|
|
4757
4830
|
}
|
|
4758
4831
|
}
|
|
4759
4832
|
catch (error) {
|
|
4760
|
-
logger.debug(
|
|
4833
|
+
logger.debug(params);
|
|
4761
4834
|
if (error instanceof z.ZodError) {
|
|
4762
4835
|
throw new Error(`Invalid arguments: ${error.errors
|
|
4763
4836
|
.map(e => `${e.path.join(".")}: ${e.message}`)
|
|
@@ -4765,7 +4838,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4765
4838
|
}
|
|
4766
4839
|
throw error;
|
|
4767
4840
|
}
|
|
4768
|
-
}
|
|
4841
|
+
}
|
|
4769
4842
|
/**
|
|
4770
4843
|
* Color constants for terminal output
|
|
4771
4844
|
*/
|
|
@@ -4842,8 +4915,6 @@ async function startSSEServer() {
|
|
|
4842
4915
|
async function startStreamableHTTPServer() {
|
|
4843
4916
|
const app = express();
|
|
4844
4917
|
const streamableTransports = {};
|
|
4845
|
-
// Session-based auth mapping for remote authorization
|
|
4846
|
-
const authBySession = {};
|
|
4847
4918
|
const authTimeouts = {};
|
|
4848
4919
|
// Configuration and limits
|
|
4849
4920
|
const MAX_SESSIONS = parseInt(process.env.MAX_SESSIONS || '1000');
|
|
@@ -4894,18 +4965,36 @@ async function startStreamableHTTPServer() {
|
|
|
4894
4965
|
const parseAuthHeaders = (req) => {
|
|
4895
4966
|
const authHeader = req.headers['authorization'] || '';
|
|
4896
4967
|
const privateToken = req.headers['private-token'] || '';
|
|
4968
|
+
const dynamicApiUrl = req.headers['x-gitlab-api-url']?.trim();
|
|
4969
|
+
let apiUrl = GITLAB_API_URL; // Default API URL
|
|
4970
|
+
// Only process dynamic URL if the feature is enabled
|
|
4971
|
+
if (ENABLE_DYNAMIC_API_URL && dynamicApiUrl) {
|
|
4972
|
+
try {
|
|
4973
|
+
new URL(dynamicApiUrl); // Ensure it's a valid URL format
|
|
4974
|
+
apiUrl = normalizeGitLabApiUrl(dynamicApiUrl);
|
|
4975
|
+
}
|
|
4976
|
+
catch (e) {
|
|
4977
|
+
logger.warn(`Invalid X-GitLab-API-URL provided: ${dynamicApiUrl}. Auth will fail.`);
|
|
4978
|
+
return null; // Reject if URL is malformed
|
|
4979
|
+
}
|
|
4980
|
+
}
|
|
4981
|
+
// Extract token
|
|
4982
|
+
let token = null;
|
|
4983
|
+
let header = null;
|
|
4897
4984
|
if (privateToken) {
|
|
4898
|
-
|
|
4899
|
-
|
|
4900
|
-
return null;
|
|
4901
|
-
return { header: 'Private-Token', token, lastUsed: Date.now() };
|
|
4985
|
+
token = privateToken.trim();
|
|
4986
|
+
header = 'Private-Token';
|
|
4902
4987
|
}
|
|
4903
|
-
if (authHeader) {
|
|
4988
|
+
else if (authHeader) {
|
|
4904
4989
|
const match = authHeader.match(/^Bearer\s+(.+)$/i);
|
|
4905
|
-
|
|
4906
|
-
|
|
4907
|
-
|
|
4908
|
-
|
|
4990
|
+
if (match) {
|
|
4991
|
+
token = match[1].trim();
|
|
4992
|
+
header = 'Authorization';
|
|
4993
|
+
}
|
|
4994
|
+
}
|
|
4995
|
+
// Validate token and return AuthData object
|
|
4996
|
+
if (token && header && validateToken(token)) {
|
|
4997
|
+
return { header, token, lastUsed: Date.now(), apiUrl };
|
|
4909
4998
|
}
|
|
4910
4999
|
return null;
|
|
4911
5000
|
};
|
|
@@ -5002,8 +5091,8 @@ async function startStreamableHTTPServer() {
|
|
|
5002
5091
|
// First request without session - will fail in initialization
|
|
5003
5092
|
}
|
|
5004
5093
|
}
|
|
5005
|
-
//
|
|
5006
|
-
const
|
|
5094
|
+
// Handle request with proper AsyncLocalStorage context
|
|
5095
|
+
const handleRequest = async () => {
|
|
5007
5096
|
try {
|
|
5008
5097
|
let transport;
|
|
5009
5098
|
if (sessionId && streamableTransports[sessionId]) {
|
|
@@ -5045,8 +5134,9 @@ async function startStreamableHTTPServer() {
|
|
|
5045
5134
|
}
|
|
5046
5135
|
}
|
|
5047
5136
|
};
|
|
5048
|
-
// Connect transport to MCP server
|
|
5137
|
+
// Connect transport to MCP server
|
|
5049
5138
|
await server.connect(transport);
|
|
5139
|
+
// Handle the request - context is already set up in the outer handleRequest wrapper
|
|
5050
5140
|
await transport.handleRequest(req, res, req.body);
|
|
5051
5141
|
}
|
|
5052
5142
|
}
|
|
@@ -5065,13 +5155,15 @@ async function startStreamableHTTPServer() {
|
|
|
5065
5155
|
sessionId,
|
|
5066
5156
|
header: authData.header,
|
|
5067
5157
|
token: authData.token,
|
|
5068
|
-
lastUsed: authData.lastUsed
|
|
5158
|
+
lastUsed: authData.lastUsed,
|
|
5159
|
+
apiUrl: authData.apiUrl
|
|
5069
5160
|
};
|
|
5070
|
-
|
|
5161
|
+
// Run the entire request handling within AsyncLocalStorage context
|
|
5162
|
+
await sessionAuthStore.run(ctx, handleRequest);
|
|
5071
5163
|
}
|
|
5072
5164
|
else {
|
|
5073
5165
|
// Standard execution (no remote auth or no session yet)
|
|
5074
|
-
await
|
|
5166
|
+
await handleRequest();
|
|
5075
5167
|
}
|
|
5076
5168
|
});
|
|
5077
5169
|
// Metrics endpoint
|
|
@@ -5219,6 +5311,8 @@ async function runServer() {
|
|
|
5219
5311
|
}
|
|
5220
5312
|
const transportMode = determineTransportMode();
|
|
5221
5313
|
await initializeServerByTransportMode(transportMode);
|
|
5314
|
+
logger.info(`Configured GitLab API URLs: ${GITLAB_API_URLS.join(", ")}`);
|
|
5315
|
+
logger.info(`Default GitLab API URL: ${GITLAB_API_URL}`);
|
|
5222
5316
|
}
|
|
5223
5317
|
catch (error) {
|
|
5224
5318
|
logger.error("Error initializing server:", error);
|