opencode-gitlab-plugin 2.2.0 → 2.4.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/CHANGELOG.md +14 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +502 -2
- package/dist/index.js.map +1 -1
- package/dist/mcp-server.cjs +159 -2
- package/dist/mcp-server.cjs.map +1 -1
- package/package.json +1 -1
package/dist/mcp-server.cjs
CHANGED
|
@@ -29310,6 +29310,107 @@ var MergeRequestsClient = class extends GitLabApiClient {
|
|
|
29310
29310
|
`/projects/${encodedProject}/merge_requests/${mrIid}/unapprove`
|
|
29311
29311
|
);
|
|
29312
29312
|
}
|
|
29313
|
+
/**
|
|
29314
|
+
* Merge a merge request immediately
|
|
29315
|
+
* Requires the MR to be in a mergeable state (approved, pipeline passed, no conflicts)
|
|
29316
|
+
*/
|
|
29317
|
+
async mergeMergeRequest(projectId, mrIid, options) {
|
|
29318
|
+
const encodedProject = this.encodeProjectId(projectId);
|
|
29319
|
+
const body = {};
|
|
29320
|
+
if (options?.sha) body.sha = options.sha;
|
|
29321
|
+
if (options?.squash !== void 0) body.squash = options.squash;
|
|
29322
|
+
if (options?.shouldRemoveSourceBranch !== void 0) {
|
|
29323
|
+
body.should_remove_source_branch = options.shouldRemoveSourceBranch;
|
|
29324
|
+
}
|
|
29325
|
+
return this.fetch(
|
|
29326
|
+
"PUT",
|
|
29327
|
+
`/projects/${encodedProject}/merge_requests/${mrIid}/merge`,
|
|
29328
|
+
Object.keys(body).length > 0 ? body : void 0
|
|
29329
|
+
);
|
|
29330
|
+
}
|
|
29331
|
+
/**
|
|
29332
|
+
* Smart merge: merge immediately if checks pass, otherwise set auto-merge
|
|
29333
|
+
* Returns detailed context about what happened
|
|
29334
|
+
*/
|
|
29335
|
+
async smartMerge(projectId, mrIid, sha, strategy = "MERGE_WHEN_CHECKS_PASS") {
|
|
29336
|
+
const mr = await this.getMergeRequest(projectId, mrIid);
|
|
29337
|
+
const context = {
|
|
29338
|
+
state: mr.state,
|
|
29339
|
+
detailedMergeStatus: mr.detailed_merge_status,
|
|
29340
|
+
pipelineStatus: mr.head_pipeline?.status || null,
|
|
29341
|
+
hasConflicts: mr.has_conflicts,
|
|
29342
|
+
hasAnyApproval: (mr.approved_by?.length || 0) > 0
|
|
29343
|
+
};
|
|
29344
|
+
if (mr.state !== "opened") {
|
|
29345
|
+
return {
|
|
29346
|
+
action: "failed",
|
|
29347
|
+
message: `MR is not open (state: ${mr.state})`,
|
|
29348
|
+
context
|
|
29349
|
+
};
|
|
29350
|
+
}
|
|
29351
|
+
if (mr.has_conflicts) {
|
|
29352
|
+
return {
|
|
29353
|
+
action: "failed",
|
|
29354
|
+
message: "MR has merge conflicts that must be resolved",
|
|
29355
|
+
context
|
|
29356
|
+
};
|
|
29357
|
+
}
|
|
29358
|
+
if (mr.detailed_merge_status === "mergeable") {
|
|
29359
|
+
try {
|
|
29360
|
+
const result = await this.mergeMergeRequest(projectId, mrIid, { sha: mr.sha });
|
|
29361
|
+
return {
|
|
29362
|
+
action: "merged",
|
|
29363
|
+
message: "MR merged successfully",
|
|
29364
|
+
mergeRequest: result,
|
|
29365
|
+
context
|
|
29366
|
+
};
|
|
29367
|
+
} catch (error45) {
|
|
29368
|
+
return {
|
|
29369
|
+
action: "failed",
|
|
29370
|
+
message: `Direct merge failed: ${error45 instanceof Error ? error45.message : String(error45)}`,
|
|
29371
|
+
context
|
|
29372
|
+
};
|
|
29373
|
+
}
|
|
29374
|
+
}
|
|
29375
|
+
const autoMergeStatuses = ["ci_still_running", "not_approved", "checking"];
|
|
29376
|
+
if (autoMergeStatuses.includes(mr.detailed_merge_status)) {
|
|
29377
|
+
try {
|
|
29378
|
+
const result = await this.setAutoMerge(projectId, mrIid, sha, strategy);
|
|
29379
|
+
const autoMergeMessages = {
|
|
29380
|
+
ci_still_running: "pipeline passes",
|
|
29381
|
+
not_approved: "approved",
|
|
29382
|
+
checking: "checks complete"
|
|
29383
|
+
};
|
|
29384
|
+
return {
|
|
29385
|
+
action: "auto_merge_enabled",
|
|
29386
|
+
message: `Auto-merge enabled (${strategy}). MR will merge when ${autoMergeMessages[mr.detailed_merge_status]}.`,
|
|
29387
|
+
mergeRequest: result,
|
|
29388
|
+
context
|
|
29389
|
+
};
|
|
29390
|
+
} catch (error45) {
|
|
29391
|
+
return {
|
|
29392
|
+
action: "failed",
|
|
29393
|
+
message: `Failed to enable auto-merge: ${error45 instanceof Error ? error45.message : String(error45)}. MR status: ${mr.detailed_merge_status}, pipeline: ${mr.head_pipeline?.status || "none"}`,
|
|
29394
|
+
context
|
|
29395
|
+
};
|
|
29396
|
+
}
|
|
29397
|
+
}
|
|
29398
|
+
const statusHints = {
|
|
29399
|
+
discussions_not_resolved: "Resolve all open discussion threads before merging.",
|
|
29400
|
+
draft_status: "MR is in draft. Mark as ready before merging.",
|
|
29401
|
+
need_rebase: "Source branch needs to be rebased onto the target branch.",
|
|
29402
|
+
requested_changes: "A reviewer requested changes that must be addressed.",
|
|
29403
|
+
policies_denied: "Merge is blocked by a security/compliance policy.",
|
|
29404
|
+
external_status_checks: "External status checks must pass before merging.",
|
|
29405
|
+
jira_association_missing: "MR must be linked to a Jira issue.",
|
|
29406
|
+
conflict: "MR has merge conflicts that must be resolved."
|
|
29407
|
+
};
|
|
29408
|
+
return {
|
|
29409
|
+
action: "failed",
|
|
29410
|
+
message: statusHints[mr.detailed_merge_status] ?? `Cannot merge: ${mr.detailed_merge_status}`,
|
|
29411
|
+
context
|
|
29412
|
+
};
|
|
29413
|
+
}
|
|
29313
29414
|
};
|
|
29314
29415
|
|
|
29315
29416
|
// src/client/issues.ts
|
|
@@ -31480,7 +31581,7 @@ Note: You must provide the current HEAD SHA of the MR to prevent race conditions
|
|
|
31480
31581
|
"The HEAD SHA of the merge request. Get this from the MR details (diff_refs.head_sha or sha field)."
|
|
31481
31582
|
),
|
|
31482
31583
|
strategy: z.enum(["MERGE_WHEN_CHECKS_PASS", "ADD_TO_MERGE_TRAIN_WHEN_CHECKS_PASS"]).optional().describe(
|
|
31483
|
-
"
|
|
31584
|
+
"MERGE_WHEN_CHECKS_PASS (default) waits for all checks. ADD_TO_MERGE_TRAIN_WHEN_CHECKS_PASS adds to merge train."
|
|
31484
31585
|
)
|
|
31485
31586
|
},
|
|
31486
31587
|
execute: async (args, _ctx) => {
|
|
@@ -31494,6 +31595,62 @@ Note: You must provide the current HEAD SHA of the MR to prevent race conditions
|
|
|
31494
31595
|
return JSON.stringify(result, null, 2);
|
|
31495
31596
|
}
|
|
31496
31597
|
}),
|
|
31598
|
+
gitlab_smart_merge_mr: tool({
|
|
31599
|
+
description: `Smart merge: merges immediately if checks pass, otherwise enables auto-merge (MWPS).
|
|
31600
|
+
This tool automatically determines the best merge action based on MR state:
|
|
31601
|
+
- If MR is mergeable (pipeline passed, approved): merges immediately
|
|
31602
|
+
- If pipeline is running or awaiting approval: enables auto-merge
|
|
31603
|
+
- Returns detailed context about what happened and why
|
|
31604
|
+
|
|
31605
|
+
Provides actionable feedback on failures including MR state, pipeline status, and remediation hints.
|
|
31606
|
+
Note: You must provide the current HEAD SHA of the MR to prevent race conditions.`,
|
|
31607
|
+
args: {
|
|
31608
|
+
project_id: z.string().describe('The project ID or path (e.g., "gitlab-org/gitlab")'),
|
|
31609
|
+
mr_iid: z.number().describe("The internal ID of the merge request"),
|
|
31610
|
+
sha: z.string().describe(
|
|
31611
|
+
"The HEAD SHA of the merge request. Get this from the MR details (diff_refs.head_sha or sha field)."
|
|
31612
|
+
),
|
|
31613
|
+
strategy: z.enum(["MERGE_WHEN_CHECKS_PASS", "ADD_TO_MERGE_TRAIN_WHEN_CHECKS_PASS"]).optional().describe(
|
|
31614
|
+
"Auto-merge strategy when immediate merge is not possible. MERGE_WHEN_CHECKS_PASS (default) waits for all checks. ADD_TO_MERGE_TRAIN_WHEN_CHECKS_PASS adds to merge train."
|
|
31615
|
+
)
|
|
31616
|
+
},
|
|
31617
|
+
execute: async (args, _ctx) => {
|
|
31618
|
+
const client = getGitLabClient();
|
|
31619
|
+
const result = await client.smartMerge(
|
|
31620
|
+
args.project_id,
|
|
31621
|
+
args.mr_iid,
|
|
31622
|
+
args.sha,
|
|
31623
|
+
args.strategy || "MERGE_WHEN_CHECKS_PASS"
|
|
31624
|
+
);
|
|
31625
|
+
return JSON.stringify(result, null, 2);
|
|
31626
|
+
}
|
|
31627
|
+
}),
|
|
31628
|
+
gitlab_merge_mr: tool({
|
|
31629
|
+
description: `Merge a merge request immediately.
|
|
31630
|
+
Use this when you know the MR is ready to merge (pipeline passed, approved, no conflicts).
|
|
31631
|
+
For automatic handling based on MR state, use gitlab_smart_merge_mr instead.
|
|
31632
|
+
|
|
31633
|
+
WARNING: If sha is omitted, the merge may succeed against a newer commit than what was reviewed/approved.
|
|
31634
|
+
Always provide sha when you want to ensure you're merging the exact code that was reviewed.`,
|
|
31635
|
+
args: {
|
|
31636
|
+
project_id: z.string().describe('The project ID or path (e.g., "gitlab-org/gitlab")'),
|
|
31637
|
+
mr_iid: z.number().describe("The internal ID of the merge request"),
|
|
31638
|
+
sha: z.string().optional().describe(
|
|
31639
|
+
"HEAD SHA to verify before merging. Recommended to prevent merging unreviewed code if new commits were pushed."
|
|
31640
|
+
),
|
|
31641
|
+
squash: z.boolean().optional().describe("Whether to squash commits (uses project default if not specified)"),
|
|
31642
|
+
should_remove_source_branch: z.boolean().optional().describe("Whether to delete source branch after merge")
|
|
31643
|
+
},
|
|
31644
|
+
execute: async (args, _ctx) => {
|
|
31645
|
+
const client = getGitLabClient();
|
|
31646
|
+
const result = await client.mergeMergeRequest(args.project_id, args.mr_iid, {
|
|
31647
|
+
sha: args.sha,
|
|
31648
|
+
squash: args.squash,
|
|
31649
|
+
shouldRemoveSourceBranch: args.should_remove_source_branch
|
|
31650
|
+
});
|
|
31651
|
+
return JSON.stringify(result, null, 2);
|
|
31652
|
+
}
|
|
31653
|
+
}),
|
|
31497
31654
|
gitlab_approve_merge_request: tool({
|
|
31498
31655
|
description: `Approve a merge request.
|
|
31499
31656
|
Adds the current user's approval to the merge request.
|
|
@@ -33777,7 +33934,7 @@ async function main() {
|
|
|
33777
33934
|
...auditTools,
|
|
33778
33935
|
...awardEmojiTools
|
|
33779
33936
|
};
|
|
33780
|
-
const version2 = true ? "2.
|
|
33937
|
+
const version2 = true ? "2.4.0" : "0.0.0";
|
|
33781
33938
|
const server = new McpServer({ name: "gitlab", version: version2 });
|
|
33782
33939
|
adaptToolsToMcp(server, allTools);
|
|
33783
33940
|
const transport = new StdioServerTransport();
|