opencode-gitlab-plugin 2.6.0 → 2.6.1

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 CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
4
4
 
5
+ ## [2.6.1](https://gitlab.com/vglafirov/opencode-gitlab-plugin/compare/v2.6.0...v2.6.1) (2026-08-17)
6
+
7
+
8
+ ### 🐛 Bug Fixes
9
+
10
+ * **merge-requests:** resolve MWPS 'checking' race in smartMerge/setAutoMerge ([b9a992f](https://gitlab.com/vglafirov/opencode-gitlab-plugin/commit/b9a992f6ebec655fba271623bf5fc963cfe16f09))
11
+ * **work-items:** avoid nullability mismatch on widget inputs ([1ae3cd7](https://gitlab.com/vglafirov/opencode-gitlab-plugin/commit/1ae3cd79627c6cca88955f90af13694472939331))
12
+
5
13
  ## [2.6.0](https://gitlab.com/vglafirov/opencode-gitlab-plugin/compare/v2.5.0...v2.6.0) (2026-05-20)
6
14
 
7
15
 
package/dist/index.js CHANGED
@@ -341,7 +341,7 @@ var RESOLVE_DISCUSSION_MUTATION = `
341
341
  }
342
342
  }
343
343
  `;
344
- var MergeRequestsClient = class extends GitLabApiClient {
344
+ var MergeRequestsClient = class _MergeRequestsClient extends GitLabApiClient {
345
345
  async getMergeRequest(projectId, mrIid, includeChanges) {
346
346
  const encodedProject = this.encodeProjectId(projectId);
347
347
  let path2 = `/projects/${encodedProject}/merge_requests/${mrIid}`;
@@ -563,20 +563,48 @@ var MergeRequestsClient = class extends GitLabApiClient {
563
563
  * Set auto-merge (MWPS) on a merge request using GraphQL API
564
564
  * Uses the mergeRequestAccept mutation with a merge strategy
565
565
  */
566
- async setAutoMerge(projectId, mrIid, sha, strategy = "MERGE_WHEN_CHECKS_PASS") {
567
- const result = await this.fetchGraphQL(SET_AUTO_MERGE_MUTATION, {
568
- projectPath: projectId,
569
- iid: String(mrIid),
570
- sha,
571
- strategy
572
- });
573
- if (result.mergeRequestAccept.errors.length > 0) {
574
- throw new Error(`Failed to set auto-merge: ${result.mergeRequestAccept.errors.join(", ")}`);
575
- }
576
- if (!result.mergeRequestAccept.mergeRequest) {
577
- throw new Error("Failed to set auto-merge: No merge request returned");
566
+ async setAutoMerge(projectId, mrIid, sha, strategy = "MERGE_WHEN_CHECKS_PASS", retries = 3) {
567
+ let lastError = null;
568
+ for (let attempt = 0; attempt <= retries; attempt++) {
569
+ const result = await this.fetchGraphQL(SET_AUTO_MERGE_MUTATION, {
570
+ projectPath: projectId,
571
+ iid: String(mrIid),
572
+ sha,
573
+ strategy
574
+ });
575
+ if (result.mergeRequestAccept.errors.length > 0) {
576
+ const message = result.mergeRequestAccept.errors.join(", ");
577
+ lastError = new Error(`Failed to set auto-merge: ${message}`);
578
+ if (attempt < retries && _MergeRequestsClient.isTransientMergeError(message)) {
579
+ await _MergeRequestsClient.delay(750 * (attempt + 1));
580
+ continue;
581
+ }
582
+ throw lastError;
583
+ }
584
+ if (!result.mergeRequestAccept.mergeRequest) {
585
+ lastError = new Error("Failed to set auto-merge: No merge request returned");
586
+ if (attempt < retries) {
587
+ await _MergeRequestsClient.delay(750 * (attempt + 1));
588
+ continue;
589
+ }
590
+ throw lastError;
591
+ }
592
+ return result.mergeRequestAccept.mergeRequest;
578
593
  }
579
- return result.mergeRequestAccept.mergeRequest;
594
+ throw lastError ?? new Error("Failed to set auto-merge: exhausted retries");
595
+ }
596
+ /**
597
+ * True for GitLab merge errors that are transient because mergeability is
598
+ * still being (re)computed. Such errors clear on their own within a second
599
+ * or two, so callers should retry rather than treat them as real failures.
600
+ */
601
+ static isTransientMergeError(message) {
602
+ const m = message.toLowerCase();
603
+ return m.includes("being checked") || m.includes("being recomputed") || m.includes("cannot be merged") || m.includes("not mergeable") || m.includes("merge failed") || m.includes("try again");
604
+ }
605
+ /** Small awaitable delay helper (ms). */
606
+ static delay(ms) {
607
+ return new Promise((resolve2) => setTimeout(resolve2, ms));
580
608
  }
581
609
  /**
582
610
  * Approve a merge request
@@ -624,7 +652,13 @@ var MergeRequestsClient = class extends GitLabApiClient {
624
652
  * Returns detailed context about what happened
625
653
  */
626
654
  async smartMerge(projectId, mrIid, sha, strategy = "MERGE_WHEN_CHECKS_PASS") {
627
- const mr = await this.getMergeRequest(projectId, mrIid);
655
+ let mr = await this.getMergeRequest(projectId, mrIid);
656
+ if (mr.detailed_merge_status === "checking") {
657
+ for (let attempt = 0; attempt < 5 && mr.detailed_merge_status === "checking"; attempt++) {
658
+ await _MergeRequestsClient.delay(1e3 * (attempt + 1));
659
+ mr = await this.getMergeRequest(projectId, mrIid);
660
+ }
661
+ }
628
662
  const context = {
629
663
  state: mr.state,
630
664
  detailedMergeStatus: mr.detailed_merge_status,
@@ -663,14 +697,13 @@ var MergeRequestsClient = class extends GitLabApiClient {
663
697
  };
664
698
  }
665
699
  }
666
- const autoMergeStatuses = ["ci_still_running", "not_approved", "checking"];
700
+ const autoMergeStatuses = ["ci_still_running", "not_approved"];
667
701
  if (autoMergeStatuses.includes(mr.detailed_merge_status)) {
668
702
  try {
669
703
  const result = await this.setAutoMerge(projectId, mrIid, sha, strategy);
670
704
  const autoMergeMessages = {
671
705
  ci_still_running: "pipeline passes",
672
- not_approved: "approved",
673
- checking: "checks complete"
706
+ not_approved: "approved"
674
707
  };
675
708
  return {
676
709
  action: "auto_merge_enabled",
@@ -1029,22 +1062,8 @@ var GET_WORK_ITEM_NOTES_QUERY = `
1029
1062
  }
1030
1063
  `;
1031
1064
  var CREATE_WORK_ITEM_MUTATION = `
1032
- mutation createWorkItem(
1033
- $projectPath: ID!
1034
- $title: String!
1035
- $workItemTypeId: WorkItemsTypeID!
1036
- $description: String
1037
- $labelIds: [LabelID!]
1038
- $assigneeIds: [UserID!]
1039
- ) {
1040
- workItemCreate(input: {
1041
- projectPath: $projectPath
1042
- title: $title
1043
- workItemTypeId: $workItemTypeId
1044
- descriptionWidget: { description: $description }
1045
- labelsWidget: { labelIds: $labelIds }
1046
- assigneesWidget: { assigneeIds: $assigneeIds }
1047
- }) {
1065
+ mutation createWorkItem($input: WorkItemCreateInput!) {
1066
+ workItemCreate(input: $input) {
1048
1067
  workItem {
1049
1068
  ${WORK_ITEM_FIELDS}
1050
1069
  }
@@ -1053,22 +1072,8 @@ var CREATE_WORK_ITEM_MUTATION = `
1053
1072
  }
1054
1073
  `;
1055
1074
  var UPDATE_WORK_ITEM_MUTATION = `
1056
- mutation updateWorkItem(
1057
- $id: WorkItemID!
1058
- $title: String
1059
- $description: String
1060
- $stateEvent: WorkItemStateEvent
1061
- $labelIds: [LabelID!]
1062
- $assigneeIds: [UserID!]
1063
- ) {
1064
- workItemUpdate(input: {
1065
- id: $id
1066
- title: $title
1067
- descriptionWidget: { description: $description }
1068
- stateEvent: $stateEvent
1069
- labelsWidget: { labelIds: $labelIds }
1070
- assigneesWidget: { assigneeIds: $assigneeIds }
1071
- }) {
1075
+ mutation updateWorkItem($input: WorkItemUpdateInput!) {
1076
+ workItemUpdate(input: $input) {
1072
1077
  workItem {
1073
1078
  ${WORK_ITEM_FIELDS}
1074
1079
  }
@@ -1162,14 +1167,21 @@ var WorkItemsClient = class extends GitLabApiClient {
1162
1167
  async createWorkItem(projectId, options) {
1163
1168
  const labelIds = options.labels?.map((l) => toGid("Label", l));
1164
1169
  const assigneeIds = options.assignee_ids?.map((id) => toGid("User", id));
1165
- const result = await this.fetchGraphQL(CREATE_WORK_ITEM_MUTATION, {
1170
+ const input = {
1166
1171
  projectPath: projectId,
1167
1172
  title: options.title,
1168
- workItemTypeId: toGid("WorkItems::Type", options.work_item_type_id),
1169
- description: options.description,
1170
- labelIds: labelIds?.length ? labelIds : void 0,
1171
- assigneeIds: assigneeIds?.length ? assigneeIds : void 0
1172
- });
1173
+ workItemTypeId: toGid("WorkItems::Type", options.work_item_type_id)
1174
+ };
1175
+ if (options.description !== void 0) {
1176
+ input.descriptionWidget = { description: options.description };
1177
+ }
1178
+ if (labelIds?.length) {
1179
+ input.labelsWidget = { labelIds };
1180
+ }
1181
+ if (assigneeIds?.length) {
1182
+ input.assigneesWidget = { assigneeIds };
1183
+ }
1184
+ const result = await this.fetchGraphQL(CREATE_WORK_ITEM_MUTATION, { input });
1173
1185
  if (result.workItemCreate.errors.length > 0) {
1174
1186
  throw new Error(`Failed to create work item: ${result.workItemCreate.errors.join(", ")}`);
1175
1187
  }
@@ -1187,14 +1199,23 @@ var WorkItemsClient = class extends GitLabApiClient {
1187
1199
  const stateEvent = options.state_event ? options.state_event === "close" ? "CLOSE" : "REOPEN" : void 0;
1188
1200
  const labelIds = options.labels?.map((l) => toGid("Label", l));
1189
1201
  const assigneeIds = options.assignee_ids?.map((id) => toGid("User", id));
1190
- const result = await this.fetchGraphQL(UPDATE_WORK_ITEM_MUTATION, {
1191
- id: gid,
1192
- title: options.title,
1193
- description: options.description,
1194
- stateEvent,
1195
- labelIds: labelIds?.length ? labelIds : void 0,
1196
- assigneeIds: assigneeIds?.length ? assigneeIds : void 0
1197
- });
1202
+ const input = { id: gid };
1203
+ if (options.title !== void 0) {
1204
+ input.title = options.title;
1205
+ }
1206
+ if (options.description !== void 0) {
1207
+ input.descriptionWidget = { description: options.description };
1208
+ }
1209
+ if (stateEvent !== void 0) {
1210
+ input.stateEvent = stateEvent;
1211
+ }
1212
+ if (labelIds?.length) {
1213
+ input.labelsWidget = { addLabelIds: labelIds };
1214
+ }
1215
+ if (assigneeIds?.length) {
1216
+ input.assigneesWidget = { assigneeIds };
1217
+ }
1218
+ const result = await this.fetchGraphQL(UPDATE_WORK_ITEM_MUTATION, { input });
1198
1219
  if (result.workItemUpdate.errors.length > 0) {
1199
1220
  throw new Error(`Failed to update work item: ${result.workItemUpdate.errors.join(", ")}`);
1200
1221
  }