tdecollab 0.1.3 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-K5LQBRHJ.js → chunk-2IQ4QMK3.js} +391 -2
- package/dist/chunk-2IQ4QMK3.js.map +1 -0
- package/dist/chunk-T73I3OT6.js +964 -0
- package/dist/chunk-T73I3OT6.js.map +1 -0
- package/dist/cli.js +574 -3
- package/dist/cli.js.map +1 -1
- package/dist/index.js +2 -2
- package/dist/server-HS774DWY.js +9 -0
- package/package.json +1 -1
- package/dist/chunk-CNARZOBV.js +0 -308
- package/dist/chunk-CNARZOBV.js.map +0 -1
- package/dist/chunk-K5LQBRHJ.js.map +0 -1
- package/dist/server-VBNZQFGP.js +0 -9
- /package/dist/{server-VBNZQFGP.js.map → server-HS774DWY.js.map} +0 -0
package/dist/cli.js
CHANGED
|
@@ -3,11 +3,25 @@ import {
|
|
|
3
3
|
ConfluenceContentApi,
|
|
4
4
|
ConfluenceSearchApi,
|
|
5
5
|
ConfluenceSpaceApi,
|
|
6
|
+
GitlabBranchApi,
|
|
7
|
+
GitlabMergeRequestApi,
|
|
8
|
+
GitlabPipelineApi,
|
|
9
|
+
GitlabProjectApi,
|
|
10
|
+
GitlabRepositoryApi,
|
|
11
|
+
JiraCommentApi,
|
|
12
|
+
JiraIssueApi,
|
|
13
|
+
JiraProjectApi,
|
|
14
|
+
JiraSearchApi,
|
|
15
|
+
JiraTransitionApi,
|
|
6
16
|
MarkdownToStorageConverter,
|
|
7
17
|
StorageToMarkdownConverter,
|
|
8
18
|
createConfluenceClient,
|
|
9
|
-
|
|
10
|
-
|
|
19
|
+
createGitlabClient,
|
|
20
|
+
createJiraClient,
|
|
21
|
+
loadConfluenceConfig,
|
|
22
|
+
loadGitlabConfig,
|
|
23
|
+
loadJiraConfig
|
|
24
|
+
} from "./chunk-2IQ4QMK3.js";
|
|
11
25
|
import "./chunk-SJ7KPK6Q.js";
|
|
12
26
|
|
|
13
27
|
// src/cli.ts
|
|
@@ -152,14 +166,571 @@ function registerConfluenceCommands(program2) {
|
|
|
152
166
|
});
|
|
153
167
|
}
|
|
154
168
|
|
|
169
|
+
// src/jira/commands/index.ts
|
|
170
|
+
import chalk2 from "chalk";
|
|
171
|
+
import Table2 from "cli-table3";
|
|
172
|
+
function registerJiraCommands(program2) {
|
|
173
|
+
const jiraCmd = program2.command("jira").description("JIRA \uAD00\uB9AC");
|
|
174
|
+
const initClient = () => {
|
|
175
|
+
try {
|
|
176
|
+
const config = loadJiraConfig();
|
|
177
|
+
return createJiraClient(config);
|
|
178
|
+
} catch (e) {
|
|
179
|
+
console.error(chalk2.red(`\uC124\uC815 \uB85C\uB4DC \uC2E4\uD328: ${e.message}`));
|
|
180
|
+
process.exit(1);
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
const issueCmd = jiraCmd.command("issue").description("\uC774\uC288 \uAD00\uB9AC");
|
|
184
|
+
issueCmd.command("get <issueKey>").description("\uC774\uC288 \uC870\uD68C").action(async (issueKey) => {
|
|
185
|
+
const client = initClient();
|
|
186
|
+
const api = new JiraIssueApi(client);
|
|
187
|
+
try {
|
|
188
|
+
const issue = await api.getIssue(issueKey);
|
|
189
|
+
const f = issue.fields;
|
|
190
|
+
console.log(chalk2.bold(`[${issue.key}] ${f.summary}`));
|
|
191
|
+
console.log(chalk2.gray(`Status: ${f.status?.name || "N/A"}`));
|
|
192
|
+
console.log(`Type: ${f.issuetype?.name || "N/A"}`);
|
|
193
|
+
console.log(`Priority: ${f.priority?.name || "N/A"}`);
|
|
194
|
+
console.log(`Assignee: ${f.assignee?.displayName || "\uBBF8\uBC30\uC815"}`);
|
|
195
|
+
console.log(`Reporter: ${f.reporter?.displayName || "N/A"}`);
|
|
196
|
+
console.log(`Labels: ${f.labels?.join(", ") || "\uC5C6\uC74C"}`);
|
|
197
|
+
console.log(`Created: ${f.created || "N/A"}`);
|
|
198
|
+
console.log(`Updated: ${f.updated || "N/A"}`);
|
|
199
|
+
if (f.description) {
|
|
200
|
+
console.log(chalk2.dim("\n--- Description ---"));
|
|
201
|
+
console.log(f.description);
|
|
202
|
+
}
|
|
203
|
+
if (f.subtasks && f.subtasks.length > 0) {
|
|
204
|
+
console.log(chalk2.dim("\n--- Subtasks ---"));
|
|
205
|
+
f.subtasks.forEach((st) => {
|
|
206
|
+
console.log(` - [${st.key}] ${st.fields.summary} (${st.fields.status.name})`);
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
} catch (e) {
|
|
210
|
+
console.error(chalk2.red(`Error: ${e.message}`));
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
issueCmd.command("create").requiredOption("-p, --project <key>", "\uD504\uB85C\uC81D\uD2B8 \uD0A4").requiredOption("-s, --summary <summary>", "\uC774\uC288 \uC81C\uBAA9").requiredOption("-t, --type <type>", "\uC774\uC288 \uC720\uD615 (Task, Bug, Story \uB4F1)").option("-d, --description <desc>", "\uC774\uC288 \uC124\uBA85").option("-a, --assignee <name>", "\uB2F4\uB2F9\uC790").option("--priority <priority>", "\uC6B0\uC120\uC21C\uC704").option("-l, --labels <labels>", "\uB77C\uBCA8 (\uC27C\uD45C \uAD6C\uBD84)").option("--parent <key>", "\uC0C1\uC704 \uC774\uC288 \uD0A4 (Sub-task)").description("\uC774\uC288 \uC0DD\uC131").action(async (options) => {
|
|
214
|
+
const client = initClient();
|
|
215
|
+
const api = new JiraIssueApi(client);
|
|
216
|
+
try {
|
|
217
|
+
const issue = await api.createIssue({
|
|
218
|
+
projectKey: options.project,
|
|
219
|
+
summary: options.summary,
|
|
220
|
+
issueType: options.type,
|
|
221
|
+
description: options.description,
|
|
222
|
+
assignee: options.assignee,
|
|
223
|
+
priority: options.priority,
|
|
224
|
+
labels: options.labels?.split(",").map((l) => l.trim()),
|
|
225
|
+
parentKey: options.parent
|
|
226
|
+
});
|
|
227
|
+
const config = loadJiraConfig();
|
|
228
|
+
console.log(chalk2.green(`\uC774\uC288 \uC0DD\uC131 \uC644\uB8CC: ${issue.key}`));
|
|
229
|
+
console.log(`URL: ${config.baseUrl}/browse/${issue.key}`);
|
|
230
|
+
} catch (e) {
|
|
231
|
+
console.error(chalk2.red(`\uC0DD\uC131 \uC2E4\uD328: ${e.message}`));
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
issueCmd.command("update <issueKey>").option("-s, --summary <summary>", "\uC81C\uBAA9").option("-d, --description <desc>", "\uC124\uBA85").option("-a, --assignee <name>", "\uB2F4\uB2F9\uC790").option("--priority <priority>", "\uC6B0\uC120\uC21C\uC704").option("-l, --labels <labels>", "\uB77C\uBCA8 (\uC27C\uD45C \uAD6C\uBD84)").description("\uC774\uC288 \uC218\uC815").action(async (issueKey, options) => {
|
|
235
|
+
const client = initClient();
|
|
236
|
+
const api = new JiraIssueApi(client);
|
|
237
|
+
try {
|
|
238
|
+
await api.updateIssue(issueKey, {
|
|
239
|
+
summary: options.summary,
|
|
240
|
+
description: options.description,
|
|
241
|
+
assignee: options.assignee,
|
|
242
|
+
priority: options.priority,
|
|
243
|
+
labels: options.labels?.split(",").map((l) => l.trim())
|
|
244
|
+
});
|
|
245
|
+
console.log(chalk2.green(`\uC774\uC288 \uC218\uC815 \uC644\uB8CC: ${issueKey}`));
|
|
246
|
+
} catch (e) {
|
|
247
|
+
console.error(chalk2.red(`\uC218\uC815 \uC2E4\uD328: ${e.message}`));
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
issueCmd.command("transition <issueKey>").option("-l, --list", "\uAC00\uB2A5\uD55C \uD2B8\uB79C\uC9C0\uC158 \uC870\uD68C").option("-t, --transition <id>", "\uD2B8\uB79C\uC9C0\uC158 \uC2E4\uD589").description("\uC774\uC288 \uC0C1\uD0DC \uBCC0\uACBD").action(async (issueKey, options) => {
|
|
251
|
+
const client = initClient();
|
|
252
|
+
const api = new JiraTransitionApi(client);
|
|
253
|
+
try {
|
|
254
|
+
if (options.list || !options.transition) {
|
|
255
|
+
const transitions = await api.getTransitions(issueKey);
|
|
256
|
+
const table = new Table2({
|
|
257
|
+
head: ["ID", "Name", "To"],
|
|
258
|
+
style: { head: ["cyan"] }
|
|
259
|
+
});
|
|
260
|
+
transitions.forEach((t) => table.push([t.id, t.name, t.to.name]));
|
|
261
|
+
console.log(table.toString());
|
|
262
|
+
} else {
|
|
263
|
+
await api.doTransition(issueKey, options.transition);
|
|
264
|
+
console.log(chalk2.green(`\uD2B8\uB79C\uC9C0\uC158 \uC644\uB8CC: ${issueKey}`));
|
|
265
|
+
}
|
|
266
|
+
} catch (e) {
|
|
267
|
+
console.error(chalk2.red(`Error: ${e.message}`));
|
|
268
|
+
}
|
|
269
|
+
});
|
|
270
|
+
jiraCmd.command("search <jql>").option("-n, --max <number>", "\uCD5C\uB300 \uACB0\uACFC \uC218", "20").description("JQL \uAC80\uC0C9").action(async (jql, options) => {
|
|
271
|
+
const client = initClient();
|
|
272
|
+
const api = new JiraSearchApi(client);
|
|
273
|
+
try {
|
|
274
|
+
const result = await api.searchByJql(jql, 0, parseInt(options.max));
|
|
275
|
+
console.log(chalk2.bold(`\uAC80\uC0C9 \uACB0\uACFC: ${result.issues.length}\uAC74 (\uCD1D ${result.total}\uAC74)`));
|
|
276
|
+
const table = new Table2({
|
|
277
|
+
head: ["Key", "Summary", "Status", "Assignee"],
|
|
278
|
+
style: { head: ["cyan"] }
|
|
279
|
+
});
|
|
280
|
+
result.issues.forEach(
|
|
281
|
+
(i) => table.push([
|
|
282
|
+
i.key,
|
|
283
|
+
i.fields.summary.substring(0, 60),
|
|
284
|
+
i.fields.status?.name || "N/A",
|
|
285
|
+
i.fields.assignee?.displayName || "\uBBF8\uBC30\uC815"
|
|
286
|
+
])
|
|
287
|
+
);
|
|
288
|
+
console.log(table.toString());
|
|
289
|
+
} catch (e) {
|
|
290
|
+
console.error(chalk2.red(`\uAC80\uC0C9 \uC2E4\uD328: ${e.message}`));
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
const commentCmd = jiraCmd.command("comment").description("\uCF54\uBA58\uD2B8 \uAD00\uB9AC");
|
|
294
|
+
commentCmd.command("list <issueKey>").description("\uCF54\uBA58\uD2B8 \uBAA9\uB85D \uC870\uD68C").action(async (issueKey) => {
|
|
295
|
+
const client = initClient();
|
|
296
|
+
const api = new JiraCommentApi(client);
|
|
297
|
+
try {
|
|
298
|
+
const result = await api.getComments(issueKey);
|
|
299
|
+
result.comments.forEach((c) => {
|
|
300
|
+
console.log(chalk2.bold(`[${c.id}] ${c.author.displayName} (${c.created})`));
|
|
301
|
+
console.log(c.body);
|
|
302
|
+
console.log(chalk2.dim("---"));
|
|
303
|
+
});
|
|
304
|
+
} catch (e) {
|
|
305
|
+
console.error(chalk2.red(`Error: ${e.message}`));
|
|
306
|
+
}
|
|
307
|
+
});
|
|
308
|
+
commentCmd.command("add <issueKey> <body>").description("\uCF54\uBA58\uD2B8 \uCD94\uAC00").action(async (issueKey, body) => {
|
|
309
|
+
const client = initClient();
|
|
310
|
+
const api = new JiraCommentApi(client);
|
|
311
|
+
try {
|
|
312
|
+
const comment = await api.addComment(issueKey, body);
|
|
313
|
+
console.log(chalk2.green(`\uCF54\uBA58\uD2B8 \uCD94\uAC00 \uC644\uB8CC (ID: ${comment.id})`));
|
|
314
|
+
} catch (e) {
|
|
315
|
+
console.error(chalk2.red(`Error: ${e.message}`));
|
|
316
|
+
}
|
|
317
|
+
});
|
|
318
|
+
const projectCmd = jiraCmd.command("project").description("\uD504\uB85C\uC81D\uD2B8 \uAD00\uB9AC");
|
|
319
|
+
projectCmd.command("list").description("\uD504\uB85C\uC81D\uD2B8 \uBAA9\uB85D \uC870\uD68C").action(async () => {
|
|
320
|
+
const client = initClient();
|
|
321
|
+
const api = new JiraProjectApi(client);
|
|
322
|
+
try {
|
|
323
|
+
const projects = await api.getProjects();
|
|
324
|
+
const table = new Table2({
|
|
325
|
+
head: ["Key", "Name", "Lead"],
|
|
326
|
+
style: { head: ["cyan"] }
|
|
327
|
+
});
|
|
328
|
+
projects.forEach(
|
|
329
|
+
(p) => table.push([p.key, p.name, p.lead?.displayName || "N/A"])
|
|
330
|
+
);
|
|
331
|
+
console.log(table.toString());
|
|
332
|
+
} catch (e) {
|
|
333
|
+
console.error(chalk2.red(`Error: ${e.message}`));
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
projectCmd.command("get <projectKey>").description("\uD504\uB85C\uC81D\uD2B8 \uC0C1\uC138 \uC870\uD68C").action(async (projectKey) => {
|
|
337
|
+
const client = initClient();
|
|
338
|
+
const api = new JiraProjectApi(client);
|
|
339
|
+
try {
|
|
340
|
+
const project = await api.getProject(projectKey);
|
|
341
|
+
console.log(chalk2.bold(`${project.name} (${project.key})`));
|
|
342
|
+
console.log(`Lead: ${project.lead?.displayName || "N/A"}`);
|
|
343
|
+
if (project.issueTypes) {
|
|
344
|
+
console.log(
|
|
345
|
+
`Issue Types: ${project.issueTypes.map((t) => t.name).join(", ")}`
|
|
346
|
+
);
|
|
347
|
+
}
|
|
348
|
+
} catch (e) {
|
|
349
|
+
console.error(chalk2.red(`Error: ${e.message}`));
|
|
350
|
+
}
|
|
351
|
+
});
|
|
352
|
+
const boardCmd = jiraCmd.command("board").description("Agile \uBCF4\uB4DC \uAD00\uB9AC");
|
|
353
|
+
boardCmd.command("list").option("-p, --project <key>", "\uD504\uB85C\uC81D\uD2B8 \uD0A4").description("\uBCF4\uB4DC \uBAA9\uB85D \uC870\uD68C").action(async (options) => {
|
|
354
|
+
const client = initClient();
|
|
355
|
+
const api = new JiraProjectApi(client);
|
|
356
|
+
try {
|
|
357
|
+
const result = await api.getBoards(options.project);
|
|
358
|
+
const table = new Table2({
|
|
359
|
+
head: ["ID", "Name", "Type"],
|
|
360
|
+
style: { head: ["cyan"] }
|
|
361
|
+
});
|
|
362
|
+
result.values.forEach((b) => table.push([b.id.toString(), b.name, b.type]));
|
|
363
|
+
console.log(table.toString());
|
|
364
|
+
} catch (e) {
|
|
365
|
+
console.error(chalk2.red(`Error: ${e.message}`));
|
|
366
|
+
}
|
|
367
|
+
});
|
|
368
|
+
boardCmd.command("sprints <boardId>").option("-s, --state <state>", "\uC0C1\uD0DC \uD544\uD130 (active, closed, future)").description("\uC2A4\uD504\uB9B0\uD2B8 \uBAA9\uB85D \uC870\uD68C").action(async (boardId, options) => {
|
|
369
|
+
const client = initClient();
|
|
370
|
+
const api = new JiraProjectApi(client);
|
|
371
|
+
try {
|
|
372
|
+
const result = await api.getSprints(parseInt(boardId), options.state);
|
|
373
|
+
const table = new Table2({
|
|
374
|
+
head: ["ID", "Name", "State", "Goal"],
|
|
375
|
+
style: { head: ["cyan"] }
|
|
376
|
+
});
|
|
377
|
+
result.values.forEach(
|
|
378
|
+
(s) => table.push([s.id.toString(), s.name, s.state, s.goal || ""])
|
|
379
|
+
);
|
|
380
|
+
console.log(table.toString());
|
|
381
|
+
} catch (e) {
|
|
382
|
+
console.error(chalk2.red(`Error: ${e.message}`));
|
|
383
|
+
}
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// src/gitlab/commands/index.ts
|
|
388
|
+
import chalk3 from "chalk";
|
|
389
|
+
import Table3 from "cli-table3";
|
|
390
|
+
function registerGitlabCommands(program2) {
|
|
391
|
+
const gitlabCmd = program2.command("gitlab").description("GitLab \uAD00\uB9AC");
|
|
392
|
+
const initClient = () => {
|
|
393
|
+
try {
|
|
394
|
+
const config = loadGitlabConfig();
|
|
395
|
+
return createGitlabClient(config);
|
|
396
|
+
} catch (e) {
|
|
397
|
+
console.error(chalk3.red(`\uC124\uC815 \uB85C\uB4DC \uC2E4\uD328: ${e.message}`));
|
|
398
|
+
process.exit(1);
|
|
399
|
+
}
|
|
400
|
+
};
|
|
401
|
+
const projectCmd = gitlabCmd.command("project").description("\uD504\uB85C\uC81D\uD2B8 \uAD00\uB9AC");
|
|
402
|
+
projectCmd.command("list").option("-s, --search <query>", "\uD504\uB85C\uC81D\uD2B8\uBA85 \uAC80\uC0C9").option("--owned", "\uC18C\uC720 \uD504\uB85C\uC81D\uD2B8\uB9CC").option("--membership", "\uBA64\uBC84\uC2ED \uD504\uB85C\uC81D\uD2B8\uB9CC").description("\uD504\uB85C\uC81D\uD2B8 \uBAA9\uB85D \uC870\uD68C").action(async (options) => {
|
|
403
|
+
const client = initClient();
|
|
404
|
+
const api = new GitlabProjectApi(client);
|
|
405
|
+
try {
|
|
406
|
+
const projects = await api.getProjects({
|
|
407
|
+
search: options.search,
|
|
408
|
+
owned: options.owned,
|
|
409
|
+
membership: options.membership
|
|
410
|
+
});
|
|
411
|
+
const table = new Table3({
|
|
412
|
+
head: ["ID", "Name", "Visibility", "Default Branch", "Last Activity"],
|
|
413
|
+
style: { head: ["cyan"] }
|
|
414
|
+
});
|
|
415
|
+
projects.forEach(
|
|
416
|
+
(p) => table.push([
|
|
417
|
+
p.id.toString(),
|
|
418
|
+
p.name_with_namespace,
|
|
419
|
+
p.visibility,
|
|
420
|
+
p.default_branch || "N/A",
|
|
421
|
+
p.last_activity_at?.substring(0, 10) || "N/A"
|
|
422
|
+
])
|
|
423
|
+
);
|
|
424
|
+
console.log(table.toString());
|
|
425
|
+
} catch (e) {
|
|
426
|
+
console.error(chalk3.red(`Error: ${e.message}`));
|
|
427
|
+
}
|
|
428
|
+
});
|
|
429
|
+
projectCmd.command("get <projectId>").description("\uD504\uB85C\uC81D\uD2B8 \uC0C1\uC138 \uC870\uD68C").action(async (projectId) => {
|
|
430
|
+
const client = initClient();
|
|
431
|
+
const api = new GitlabProjectApi(client);
|
|
432
|
+
try {
|
|
433
|
+
const p = await api.getProject(parseInt(projectId));
|
|
434
|
+
console.log(chalk3.bold(p.name_with_namespace));
|
|
435
|
+
console.log(`ID: ${p.id}`);
|
|
436
|
+
console.log(`Path: ${p.path_with_namespace}`);
|
|
437
|
+
console.log(`Default Branch: ${p.default_branch}`);
|
|
438
|
+
console.log(`Visibility: ${p.visibility}`);
|
|
439
|
+
console.log(`Web URL: ${p.web_url}`);
|
|
440
|
+
console.log(`SSH URL: ${p.ssh_url_to_repo}`);
|
|
441
|
+
console.log(`HTTP URL: ${p.http_url_to_repo}`);
|
|
442
|
+
console.log(`Last Activity: ${p.last_activity_at}`);
|
|
443
|
+
if (p.description) console.log(`Description: ${p.description}`);
|
|
444
|
+
} catch (e) {
|
|
445
|
+
console.error(chalk3.red(`Error: ${e.message}`));
|
|
446
|
+
}
|
|
447
|
+
});
|
|
448
|
+
const mrCmd = gitlabCmd.command("mr").description("Merge Request \uAD00\uB9AC");
|
|
449
|
+
mrCmd.command("list <projectId>").option("-s, --state <state>", "\uC0C1\uD0DC \uD544\uD130 (opened/closed/merged/all)", "opened").option("--scope <scope>", "\uBC94\uC704 (created_by_me/assigned_to_me)").description("MR \uBAA9\uB85D \uC870\uD68C").action(async (projectId, options) => {
|
|
450
|
+
const client = initClient();
|
|
451
|
+
const api = new GitlabMergeRequestApi(client);
|
|
452
|
+
try {
|
|
453
|
+
const mrs = await api.getMergeRequests(parseInt(projectId), {
|
|
454
|
+
state: options.state,
|
|
455
|
+
scope: options.scope
|
|
456
|
+
});
|
|
457
|
+
const table = new Table3({
|
|
458
|
+
head: ["IID", "Title", "State", "Source \u2192 Target", "Author"],
|
|
459
|
+
style: { head: ["cyan"] }
|
|
460
|
+
});
|
|
461
|
+
mrs.forEach(
|
|
462
|
+
(m) => table.push([
|
|
463
|
+
`!${m.iid}`,
|
|
464
|
+
m.title.substring(0, 50),
|
|
465
|
+
m.state,
|
|
466
|
+
`${m.source_branch} \u2192 ${m.target_branch}`,
|
|
467
|
+
m.author?.name || "N/A"
|
|
468
|
+
])
|
|
469
|
+
);
|
|
470
|
+
console.log(table.toString());
|
|
471
|
+
} catch (e) {
|
|
472
|
+
console.error(chalk3.red(`Error: ${e.message}`));
|
|
473
|
+
}
|
|
474
|
+
});
|
|
475
|
+
mrCmd.command("get <projectId> <mrIid>").option("-c, --changes", "\uBCC0\uACBD \uD30C\uC77C \uD3EC\uD568").description("MR \uC0C1\uC138 \uC870\uD68C").action(async (projectId, mrIid, options) => {
|
|
476
|
+
const client = initClient();
|
|
477
|
+
const api = new GitlabMergeRequestApi(client);
|
|
478
|
+
try {
|
|
479
|
+
const mr = options.changes ? await api.getMergeRequestChanges(parseInt(projectId), parseInt(mrIid)) : await api.getMergeRequest(parseInt(projectId), parseInt(mrIid));
|
|
480
|
+
console.log(chalk3.bold(`[!${mr.iid}] ${mr.title}`));
|
|
481
|
+
console.log(`State: ${mr.state}`);
|
|
482
|
+
console.log(`Source: ${mr.source_branch} \u2192 Target: ${mr.target_branch}`);
|
|
483
|
+
console.log(`Author: ${mr.author?.name || "N/A"}`);
|
|
484
|
+
console.log(`Assignee: ${mr.assignee?.name || "\uBBF8\uBC30\uC815"}`);
|
|
485
|
+
console.log(`Merge Status: ${mr.merge_status}`);
|
|
486
|
+
console.log(`Has Conflicts: ${mr.has_conflicts}`);
|
|
487
|
+
console.log(`Pipeline: ${mr.pipeline?.status || "N/A"}`);
|
|
488
|
+
console.log(`URL: ${mr.web_url}`);
|
|
489
|
+
if (mr.description) {
|
|
490
|
+
console.log(chalk3.dim("\n--- Description ---"));
|
|
491
|
+
console.log(mr.description);
|
|
492
|
+
}
|
|
493
|
+
if (mr.changes && mr.changes.length > 0) {
|
|
494
|
+
console.log(chalk3.dim(`
|
|
495
|
+
--- Changes (${mr.changes.length}\uAC1C \uD30C\uC77C) ---`));
|
|
496
|
+
mr.changes.forEach((c) => {
|
|
497
|
+
const prefix = c.new_file ? "[NEW]" : c.deleted_file ? "[DEL]" : c.renamed_file ? "[REN]" : "[MOD]";
|
|
498
|
+
console.log(` ${prefix} ${c.new_path}`);
|
|
499
|
+
});
|
|
500
|
+
}
|
|
501
|
+
} catch (e) {
|
|
502
|
+
console.error(chalk3.red(`Error: ${e.message}`));
|
|
503
|
+
}
|
|
504
|
+
});
|
|
505
|
+
mrCmd.command("create <projectId>").requiredOption("--source <branch>", "\uC18C\uC2A4 \uBE0C\uB79C\uCE58").requiredOption("--target <branch>", "\uD0C0\uAC9F \uBE0C\uB79C\uCE58").requiredOption("--title <text>", "MR \uC81C\uBAA9").option("-d, --description <text>", "MR \uC124\uBA85").description("MR \uC0DD\uC131").action(async (projectId, options) => {
|
|
506
|
+
const client = initClient();
|
|
507
|
+
const api = new GitlabMergeRequestApi(client);
|
|
508
|
+
try {
|
|
509
|
+
const mr = await api.createMergeRequest(parseInt(projectId), {
|
|
510
|
+
source_branch: options.source,
|
|
511
|
+
target_branch: options.target,
|
|
512
|
+
title: options.title,
|
|
513
|
+
description: options.description
|
|
514
|
+
});
|
|
515
|
+
console.log(chalk3.green(`MR \uC0DD\uC131 \uC644\uB8CC: !${mr.iid}`));
|
|
516
|
+
console.log(`URL: ${mr.web_url}`);
|
|
517
|
+
} catch (e) {
|
|
518
|
+
console.error(chalk3.red(`\uC0DD\uC131 \uC2E4\uD328: ${e.message}`));
|
|
519
|
+
}
|
|
520
|
+
});
|
|
521
|
+
mrCmd.command("merge <projectId> <mrIid>").option("--squash", "\uC2A4\uCFFC\uC2DC \uBA38\uC9C0").option("--remove-source-branch", "\uC18C\uC2A4 \uBE0C\uB79C\uCE58 \uC0AD\uC81C").description("MR \uBA38\uC9C0").action(async (projectId, mrIid, options) => {
|
|
522
|
+
const client = initClient();
|
|
523
|
+
const api = new GitlabMergeRequestApi(client);
|
|
524
|
+
try {
|
|
525
|
+
const mr = await api.mergeMergeRequest(parseInt(projectId), parseInt(mrIid), {
|
|
526
|
+
squash: options.squash,
|
|
527
|
+
should_remove_source_branch: options.removeSourceBranch
|
|
528
|
+
});
|
|
529
|
+
console.log(chalk3.green(`MR !${mrIid} \uBA38\uC9C0 \uC644\uB8CC`));
|
|
530
|
+
console.log(`State: ${mr.state}`);
|
|
531
|
+
} catch (e) {
|
|
532
|
+
console.error(chalk3.red(`\uBA38\uC9C0 \uC2E4\uD328: ${e.message}`));
|
|
533
|
+
}
|
|
534
|
+
});
|
|
535
|
+
mrCmd.command("close <projectId> <mrIid>").description("MR \uB2EB\uAE30").action(async (projectId, mrIid) => {
|
|
536
|
+
const client = initClient();
|
|
537
|
+
const api = new GitlabMergeRequestApi(client);
|
|
538
|
+
try {
|
|
539
|
+
await api.updateMergeRequest(parseInt(projectId), parseInt(mrIid), {
|
|
540
|
+
state_event: "close"
|
|
541
|
+
});
|
|
542
|
+
console.log(chalk3.green(`MR !${mrIid} \uB2EB\uAE30 \uC644\uB8CC`));
|
|
543
|
+
} catch (e) {
|
|
544
|
+
console.error(chalk3.red(`Error: ${e.message}`));
|
|
545
|
+
}
|
|
546
|
+
});
|
|
547
|
+
mrCmd.command("comment <projectId> <mrIid>").requiredOption("-b, --body <text>", "\uCF54\uBA58\uD2B8 \uB0B4\uC6A9").description("MR \uCF54\uBA58\uD2B8 \uCD94\uAC00").action(async (projectId, mrIid, options) => {
|
|
548
|
+
const client = initClient();
|
|
549
|
+
const api = new GitlabMergeRequestApi(client);
|
|
550
|
+
try {
|
|
551
|
+
const note = await api.addMergeRequestNote(
|
|
552
|
+
parseInt(projectId),
|
|
553
|
+
parseInt(mrIid),
|
|
554
|
+
options.body
|
|
555
|
+
);
|
|
556
|
+
console.log(chalk3.green(`\uCF54\uBA58\uD2B8 \uCD94\uAC00 \uC644\uB8CC (ID: ${note.id})`));
|
|
557
|
+
} catch (e) {
|
|
558
|
+
console.error(chalk3.red(`Error: ${e.message}`));
|
|
559
|
+
}
|
|
560
|
+
});
|
|
561
|
+
const pipelineCmd = gitlabCmd.command("pipeline").description("\uD30C\uC774\uD504\uB77C\uC778 \uAD00\uB9AC");
|
|
562
|
+
pipelineCmd.command("list <projectId>").option("-s, --status <status>", "\uC0C1\uD0DC \uD544\uD130").option("-r, --ref <branch>", "\uBE0C\uB79C\uCE58/\uD0DC\uADF8 \uD544\uD130").description("\uD30C\uC774\uD504\uB77C\uC778 \uBAA9\uB85D \uC870\uD68C").action(async (projectId, options) => {
|
|
563
|
+
const client = initClient();
|
|
564
|
+
const api = new GitlabPipelineApi(client);
|
|
565
|
+
try {
|
|
566
|
+
const pipelines = await api.getPipelines(parseInt(projectId), {
|
|
567
|
+
status: options.status,
|
|
568
|
+
ref: options.ref
|
|
569
|
+
});
|
|
570
|
+
const table = new Table3({
|
|
571
|
+
head: ["ID", "Status", "Ref", "SHA", "Created"],
|
|
572
|
+
style: { head: ["cyan"] }
|
|
573
|
+
});
|
|
574
|
+
pipelines.forEach(
|
|
575
|
+
(p) => table.push([
|
|
576
|
+
p.id.toString(),
|
|
577
|
+
p.status,
|
|
578
|
+
p.ref,
|
|
579
|
+
p.sha.substring(0, 8),
|
|
580
|
+
p.created_at?.substring(0, 10) || "N/A"
|
|
581
|
+
])
|
|
582
|
+
);
|
|
583
|
+
console.log(table.toString());
|
|
584
|
+
} catch (e) {
|
|
585
|
+
console.error(chalk3.red(`Error: ${e.message}`));
|
|
586
|
+
}
|
|
587
|
+
});
|
|
588
|
+
pipelineCmd.command("get <projectId> <pipelineId>").option("-j, --jobs", "\uC791\uC5C5 \uBAA9\uB85D \uD3EC\uD568").description("\uD30C\uC774\uD504\uB77C\uC778 \uC0C1\uC138 \uC870\uD68C").action(async (projectId, pipelineId, options) => {
|
|
589
|
+
const client = initClient();
|
|
590
|
+
const api = new GitlabPipelineApi(client);
|
|
591
|
+
try {
|
|
592
|
+
const p = await api.getPipeline(parseInt(projectId), parseInt(pipelineId));
|
|
593
|
+
console.log(chalk3.bold(`Pipeline #${p.id}`));
|
|
594
|
+
console.log(`Status: ${p.status}`);
|
|
595
|
+
console.log(`Ref: ${p.ref}`);
|
|
596
|
+
console.log(`SHA: ${p.sha}`);
|
|
597
|
+
console.log(`Duration: ${p.duration ? p.duration + "s" : "N/A"}`);
|
|
598
|
+
console.log(`URL: ${p.web_url}`);
|
|
599
|
+
if (options.jobs) {
|
|
600
|
+
const jobs = await api.getPipelineJobs(
|
|
601
|
+
parseInt(projectId),
|
|
602
|
+
parseInt(pipelineId)
|
|
603
|
+
);
|
|
604
|
+
console.log(chalk3.dim(`
|
|
605
|
+
--- Jobs (${jobs.length}\uAC1C) ---`));
|
|
606
|
+
const table = new Table3({
|
|
607
|
+
head: ["Stage", "Name", "Status", "Duration"],
|
|
608
|
+
style: { head: ["cyan"] }
|
|
609
|
+
});
|
|
610
|
+
jobs.forEach(
|
|
611
|
+
(j) => table.push([
|
|
612
|
+
j.stage,
|
|
613
|
+
j.name,
|
|
614
|
+
j.status,
|
|
615
|
+
j.duration ? j.duration + "s" : "N/A"
|
|
616
|
+
])
|
|
617
|
+
);
|
|
618
|
+
console.log(table.toString());
|
|
619
|
+
}
|
|
620
|
+
} catch (e) {
|
|
621
|
+
console.error(chalk3.red(`Error: ${e.message}`));
|
|
622
|
+
}
|
|
623
|
+
});
|
|
624
|
+
const branchCmd = gitlabCmd.command("branch").description("\uBE0C\uB79C\uCE58 \uAD00\uB9AC");
|
|
625
|
+
branchCmd.command("list <projectId>").option("-s, --search <query>", "\uAC80\uC0C9 \uD0A4\uC6CC\uB4DC").description("\uBE0C\uB79C\uCE58 \uBAA9\uB85D \uC870\uD68C").action(async (projectId, options) => {
|
|
626
|
+
const client = initClient();
|
|
627
|
+
const api = new GitlabBranchApi(client);
|
|
628
|
+
try {
|
|
629
|
+
const branches = await api.getBranches(parseInt(projectId), {
|
|
630
|
+
search: options.search
|
|
631
|
+
});
|
|
632
|
+
const table = new Table3({
|
|
633
|
+
head: ["Name", "Commit", "Message", "Protected", "Default"],
|
|
634
|
+
style: { head: ["cyan"] }
|
|
635
|
+
});
|
|
636
|
+
branches.forEach(
|
|
637
|
+
(b) => table.push([
|
|
638
|
+
b.name,
|
|
639
|
+
b.commit.short_id,
|
|
640
|
+
b.commit.message.split("\n")[0].substring(0, 40),
|
|
641
|
+
b.protected ? "Yes" : "No",
|
|
642
|
+
b.default ? "Yes" : "No"
|
|
643
|
+
])
|
|
644
|
+
);
|
|
645
|
+
console.log(table.toString());
|
|
646
|
+
} catch (e) {
|
|
647
|
+
console.error(chalk3.red(`Error: ${e.message}`));
|
|
648
|
+
}
|
|
649
|
+
});
|
|
650
|
+
branchCmd.command("get <projectId> <branchName>").description("\uBE0C\uB79C\uCE58 \uC0C1\uC138 \uC870\uD68C").action(async (projectId, branchName) => {
|
|
651
|
+
const client = initClient();
|
|
652
|
+
const api = new GitlabBranchApi(client);
|
|
653
|
+
try {
|
|
654
|
+
const b = await api.getBranch(parseInt(projectId), branchName);
|
|
655
|
+
console.log(chalk3.bold(b.name));
|
|
656
|
+
console.log(`Default: ${b.default}`);
|
|
657
|
+
console.log(`Protected: ${b.protected}`);
|
|
658
|
+
console.log(`Merged: ${b.merged}`);
|
|
659
|
+
console.log(`Commit: ${b.commit.id}`);
|
|
660
|
+
console.log(`Message: ${b.commit.message}`);
|
|
661
|
+
console.log(`Author: ${b.commit.author_name}`);
|
|
662
|
+
console.log(`Date: ${b.commit.authored_date}`);
|
|
663
|
+
} catch (e) {
|
|
664
|
+
console.error(chalk3.red(`Error: ${e.message}`));
|
|
665
|
+
}
|
|
666
|
+
});
|
|
667
|
+
branchCmd.command("create <projectId>").requiredOption("-n, --name <branch>", "\uBE0C\uB79C\uCE58 \uC774\uB984").requiredOption("-r, --ref <ref>", "\uAE30\uC900 ref").description("\uBE0C\uB79C\uCE58 \uC0DD\uC131").action(async (projectId, options) => {
|
|
668
|
+
const client = initClient();
|
|
669
|
+
const api = new GitlabBranchApi(client);
|
|
670
|
+
try {
|
|
671
|
+
const b = await api.createBranch(
|
|
672
|
+
parseInt(projectId),
|
|
673
|
+
options.name,
|
|
674
|
+
options.ref
|
|
675
|
+
);
|
|
676
|
+
console.log(chalk3.green(`\uBE0C\uB79C\uCE58 \uC0DD\uC131 \uC644\uB8CC: ${b.name}`));
|
|
677
|
+
} catch (e) {
|
|
678
|
+
console.error(chalk3.red(`\uC0DD\uC131 \uC2E4\uD328: ${e.message}`));
|
|
679
|
+
}
|
|
680
|
+
});
|
|
681
|
+
branchCmd.command("delete <projectId> <branchName>").description("\uBE0C\uB79C\uCE58 \uC0AD\uC81C").action(async (projectId, branchName) => {
|
|
682
|
+
const client = initClient();
|
|
683
|
+
const api = new GitlabBranchApi(client);
|
|
684
|
+
try {
|
|
685
|
+
await api.deleteBranch(parseInt(projectId), branchName);
|
|
686
|
+
console.log(chalk3.green(`\uBE0C\uB79C\uCE58 \uC0AD\uC81C \uC644\uB8CC: ${branchName}`));
|
|
687
|
+
} catch (e) {
|
|
688
|
+
console.error(chalk3.red(`\uC0AD\uC81C \uC2E4\uD328: ${e.message}`));
|
|
689
|
+
}
|
|
690
|
+
});
|
|
691
|
+
const fileCmd = gitlabCmd.command("file").description("\uD30C\uC77C \uAD00\uB9AC");
|
|
692
|
+
fileCmd.command("get <projectId> <filePath>").option("-r, --ref <ref>", "\uBE0C\uB79C\uCE58/\uD0DC\uADF8/\uCEE4\uBC0B").description("\uD30C\uC77C \uB0B4\uC6A9 \uC870\uD68C").action(async (projectId, filePath, options) => {
|
|
693
|
+
const client = initClient();
|
|
694
|
+
const api = new GitlabRepositoryApi(client);
|
|
695
|
+
try {
|
|
696
|
+
const file = await api.getFile(parseInt(projectId), filePath, options.ref);
|
|
697
|
+
console.log(chalk3.bold(file.file_path));
|
|
698
|
+
console.log(chalk3.gray(`Size: ${file.size} bytes | Ref: ${file.ref}`));
|
|
699
|
+
console.log(chalk3.dim("---"));
|
|
700
|
+
console.log(file.content);
|
|
701
|
+
} catch (e) {
|
|
702
|
+
console.error(chalk3.red(`Error: ${e.message}`));
|
|
703
|
+
}
|
|
704
|
+
});
|
|
705
|
+
fileCmd.command("tree <projectId>").option("-p, --path <dir>", "\uB514\uB809\uD1A0\uB9AC \uACBD\uB85C").option("-r, --ref <ref>", "\uBE0C\uB79C\uCE58/\uD0DC\uADF8").option("--recursive", "\uC7AC\uADC0 \uC870\uD68C").description("\uB514\uB809\uD1A0\uB9AC \uD2B8\uB9AC \uC870\uD68C").action(async (projectId, options) => {
|
|
706
|
+
const client = initClient();
|
|
707
|
+
const api = new GitlabRepositoryApi(client);
|
|
708
|
+
try {
|
|
709
|
+
const entries = await api.getTree(parseInt(projectId), {
|
|
710
|
+
path: options.path,
|
|
711
|
+
ref: options.ref,
|
|
712
|
+
recursive: options.recursive
|
|
713
|
+
});
|
|
714
|
+
entries.forEach((e) => {
|
|
715
|
+
const icon = e.type === "tree" ? "\u{1F4C1}" : "\u{1F4C4}";
|
|
716
|
+
console.log(`${icon} ${e.path}`);
|
|
717
|
+
});
|
|
718
|
+
} catch (e) {
|
|
719
|
+
console.error(chalk3.red(`Error: ${e.message}`));
|
|
720
|
+
}
|
|
721
|
+
});
|
|
722
|
+
}
|
|
723
|
+
|
|
155
724
|
// src/cli.ts
|
|
156
725
|
import dotenv from "dotenv";
|
|
157
726
|
dotenv.config();
|
|
158
727
|
var program = new Command();
|
|
159
728
|
program.name("tdecollab").description("TDE Collaboration CLI").version("0.1.0");
|
|
160
729
|
registerConfluenceCommands(program);
|
|
730
|
+
registerJiraCommands(program);
|
|
731
|
+
registerGitlabCommands(program);
|
|
161
732
|
program.command("mcp").description("Run MCP Server").action(async () => {
|
|
162
|
-
const { runServer } = await import("./server-
|
|
733
|
+
const { runServer } = await import("./server-HS774DWY.js");
|
|
163
734
|
await runServer();
|
|
164
735
|
});
|
|
165
736
|
program.parse(process.argv);
|