flowpilot 0.0.2 → 0.1.16

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/cli.js CHANGED
@@ -3866,7 +3866,15 @@ var en_default = {
3866
3866
  "createIssueFailed": "Failed to create issue",
3867
3867
  "selectHistoryOrNew": "Select history for quick execute, or create new",
3868
3868
  "historyNew": "Create new...",
3869
- "historyQuickExecute": "Quick execute"
3869
+ "historyQuickExecute": "Quick execute",
3870
+ "createMR": "Create Merge Request for this release?",
3871
+ "selectSourceBranch": "Select source branch for MR",
3872
+ "noSourceBranches": "No other branches available as MR source",
3873
+ "selectMrBranch": "Select MR branch",
3874
+ "confirmCreateMr": "Confirm Create MR",
3875
+ "creatingMrBtn": "Creating MR...",
3876
+ "mrFromTo": "MR: {{source}} → {{target}}",
3877
+ "mrCreated": "MR created"
3870
3878
  },
3871
3879
  web: {
3872
3880
  "flowpilot": "FlowPilot",
@@ -3938,8 +3946,13 @@ var en_default = {
3938
3946
  "newModalTitle": "Create Release Request",
3939
3947
  "clearSuccess": "History cleared",
3940
3948
  "cancel": "Cancel",
3949
+ "createMrCheckbox": "Create MR",
3941
3950
  "endTitle": "End",
3942
- "endDesc": "End current task: rebase, push, create MR, update Jira."
3951
+ "endDesc": "End current task: rebase, push, create MR, update Jira.",
3952
+ "createMrBtn": "Create MR",
3953
+ "creatingMrBtn": "Creating MR...",
3954
+ "confirmCreateMr": "Confirm Create MR",
3955
+ "loadingMr": "Loading branches..."
3943
3956
  },
3944
3957
  end: {
3945
3958
  "notGitRepo": "Not a git repository. Run this inside a git project.",
@@ -4093,7 +4106,15 @@ var zh_CN_default = {
4093
4106
  "createIssueFailed": "创建 issue 失败",
4094
4107
  "selectHistoryOrNew": "选择历史记录快速执行,或新建",
4095
4108
  "historyNew": "新建...",
4096
- "historyQuickExecute": "快速执行"
4109
+ "historyQuickExecute": "快速执行",
4110
+ "createMR": "为此发布创建 Merge Request?",
4111
+ "selectSourceBranch": "选择 MR 的源分支",
4112
+ "noSourceBranches": "没有其他分支可作为 MR 源分支",
4113
+ "selectMrBranch": "选择 MR 分支",
4114
+ "confirmCreateMr": "确认创建 MR",
4115
+ "creatingMrBtn": "正在创建 MR...",
4116
+ "mrFromTo": "MR: {{source}} → {{target}}",
4117
+ "mrCreated": "MR 已创建"
4097
4118
  },
4098
4119
  web: {
4099
4120
  "flowpilot": "FlowPilot",
@@ -4165,8 +4186,13 @@ var zh_CN_default = {
4165
4186
  "newModalTitle": "新建发布申请",
4166
4187
  "clearSuccess": "历史已清空",
4167
4188
  "cancel": "取消",
4189
+ "createMrCheckbox": "创建 MR",
4168
4190
  "endTitle": "End",
4169
- "endDesc": "结束当前任务:rebase、推送、创建 MR、更新 Jira。"
4191
+ "endDesc": "结束当前任务:rebase、推送、创建 MR、更新 Jira。",
4192
+ "createMrBtn": "创建 MR",
4193
+ "creatingMrBtn": "正在创建 MR...",
4194
+ "confirmCreateMr": "确认创建 MR",
4195
+ "loadingMr": "正在加载分支..."
4170
4196
  },
4171
4197
  end: {
4172
4198
  "notGitRepo": "当前不在 git 仓库中。请在 git 项目内运行。",
@@ -19719,6 +19745,7 @@ const CONTEXT_404_MAP = {
19719
19745
  gitlabFile: "error.http404File",
19720
19746
  gitlabBranch: "error.http404",
19721
19747
  gitlabGeneral: "error.http404",
19748
+ gitlabMR: "error.http404",
19722
19749
  jiraProject: "error.http404",
19723
19750
  jiraSearch: "error.http404",
19724
19751
  jiraVersion: "error.http404",
@@ -19731,6 +19758,7 @@ const CONTEXT_FALLBACK_MAP = {
19731
19758
  gitlabBranch: "error.fetchBranchesFailed",
19732
19759
  gitlabFile: "error.fetchPomFailed",
19733
19760
  gitlabGeneral: "error.gitlabApiFailed",
19761
+ gitlabMR: "error.gitlabApiFailed",
19734
19762
  jiraProject: "error.fetchJiraProjectsFailed",
19735
19763
  jiraSearch: "error.jiraSearchFailed",
19736
19764
  jiraVersion: "error.jiraVersionFailed",
@@ -20242,6 +20270,35 @@ function cleanVersion(v) {
20242
20270
  //#region src/commands/release/routes.tsx
20243
20271
  const releaseStore$1 = new Store("release-history.json");
20244
20272
  const dedupKey$1 = (e) => `${e.projectId}:${e.branch}:${e.jiraProjectKey}`;
20273
+ async function createMrForRelease(git, projectId, targetBranch, jiraUrl, sourceBranchOverride) {
20274
+ try {
20275
+ const sourceBranch = sourceBranchOverride ?? (await git.listBranches(projectId)).find((b) => b.default)?.name;
20276
+ if (!sourceBranch || sourceBranch === targetBranch) return void 0;
20277
+ try {
20278
+ const mr = await git.createMergeRequest(projectId, sourceBranch, targetBranch, `${sourceBranch} → ${targetBranch}`, { description: jiraUrl ? `Jira: ${jiraUrl}` : "" });
20279
+ return {
20280
+ mrUrl: mr.webUrl ?? mr.web_url,
20281
+ sourceBranch,
20282
+ targetBranch
20283
+ };
20284
+ } catch (mrErr) {
20285
+ if ((mrErr instanceof Error ? mrErr.message : String(mrErr)).includes("already exists")) {
20286
+ const existing = (await git.listMergeRequests({
20287
+ projectId,
20288
+ state: "opened"
20289
+ })).find((m) => m.sourceBranch === sourceBranch && m.targetBranch === targetBranch);
20290
+ if (existing) return {
20291
+ mrUrl: existing.webUrl ?? existing.web_url ?? "",
20292
+ sourceBranch,
20293
+ targetBranch
20294
+ };
20295
+ }
20296
+ return;
20297
+ }
20298
+ } catch {
20299
+ return;
20300
+ }
20301
+ }
20245
20302
  const REQUIRED_KEYS$1 = [
20246
20303
  "jiraHost",
20247
20304
  "jiraName",
@@ -20281,11 +20338,14 @@ router.delete("/api/history", (c) => {
20281
20338
  });
20282
20339
  router.post("/api/history/:id/execute", async (c) => {
20283
20340
  const id = c.req.param("id");
20341
+ const createMr = (await c.req.json().catch(() => ({ createMr: false }))).createMr ?? false;
20284
20342
  const entry = releaseStore$1.getAll().find((h) => h.id === id);
20285
20343
  if (!entry) return c.json({ error: t("error.http404") }, 404);
20286
20344
  const git = new GitlabController();
20287
20345
  const jira = new JiraController();
20288
20346
  const config = new ConfigJson().getConfig();
20347
+ let mrResult;
20348
+ if (createMr) mrResult = await createMrForRelease(git, entry.projectId, entry.branch, "", entry.mrSourceBranch);
20289
20349
  let pomInfo;
20290
20350
  try {
20291
20351
  const file = await git.getFile(entry.projectId, "pom.xml", entry.branch);
@@ -20302,15 +20362,15 @@ router.post("/api/history/:id/execute", async (c) => {
20302
20362
  if (searchResult.total > 0 && searchResult.issues?.[0]) {
20303
20363
  const existingKey = searchResult.issues[0].key;
20304
20364
  const jiraUrl = config.jiraHost ? `${config.jiraHost}/browse/${existingKey}` : "";
20305
- releaseStore$1.add({
20306
- ...entry,
20307
- createdAt: (/* @__PURE__ */ new Date()).toISOString()
20308
- }, dedupKey$1);
20309
20365
  return c.json({
20310
20366
  issueKey: existingKey,
20311
20367
  issueUrl: jiraUrl,
20312
20368
  version: displayVersion,
20313
- versionCreated: false
20369
+ versionCreated: false,
20370
+ issueCreated: false,
20371
+ mrUrl: mrResult?.mrUrl,
20372
+ mrSourceBranch: mrResult?.sourceBranch,
20373
+ mrTargetBranch: mrResult?.targetBranch
20314
20374
  });
20315
20375
  }
20316
20376
  } catch {}
@@ -20336,15 +20396,14 @@ router.post("/api/history/:id/execute", async (c) => {
20336
20396
  customfield_13341: [{ name: "licheng.li" }]
20337
20397
  });
20338
20398
  const jiraUrl = config.jiraHost ? `${config.jiraHost}/browse/${issue.key}` : "";
20339
- releaseStore$1.add({
20340
- ...entry,
20341
- createdAt: (/* @__PURE__ */ new Date()).toISOString()
20342
- }, dedupKey$1);
20343
20399
  return c.json({
20344
20400
  issueKey: issue.key,
20345
20401
  issueUrl: jiraUrl,
20346
20402
  version: displayVersion,
20347
- versionCreated
20403
+ versionCreated,
20404
+ mrUrl: mrResult?.mrUrl,
20405
+ mrSourceBranch: mrResult?.sourceBranch,
20406
+ mrTargetBranch: mrResult?.targetBranch
20348
20407
  });
20349
20408
  } catch (e) {
20350
20409
  return c.json({ error: translateApiError(e, "jiraCreateIssue") }, 500);
@@ -20367,6 +20426,49 @@ router.get("/api/projects/:id/branches", async (c) => {
20367
20426
  return c.json({ error: translateApiError(e, "gitlabBranch") }, 500);
20368
20427
  }
20369
20428
  });
20429
+ router.post("/api/create-mr", async (c) => {
20430
+ let mrUrl = "";
20431
+ let sourceBranch = "";
20432
+ let targetBranch = "";
20433
+ let projectId = 0;
20434
+ try {
20435
+ const body = await c.req.json();
20436
+ projectId = Number(body.projectId);
20437
+ targetBranch = body.targetBranch;
20438
+ sourceBranch = body.sourceBranch;
20439
+ const jiraUrl = body.jiraUrl ?? "";
20440
+ const git = new GitlabController();
20441
+ try {
20442
+ const mr = await git.createMergeRequest(projectId, sourceBranch, targetBranch, `${sourceBranch} → ${targetBranch}`, { description: jiraUrl ? `Jira: ${jiraUrl}` : "" });
20443
+ mrUrl = mr.webUrl ?? mr.web_url;
20444
+ } catch (mrErr) {
20445
+ if ((mrErr instanceof Error ? mrErr.message : String(mrErr)).includes("already exists")) try {
20446
+ const existing = (await git.listMergeRequests({
20447
+ projectId,
20448
+ state: "opened"
20449
+ })).find((m) => m.sourceBranch === sourceBranch && m.targetBranch === targetBranch);
20450
+ if (existing) mrUrl = existing.webUrl ?? existing.web_url ?? "";
20451
+ } catch {}
20452
+ if (!mrUrl) return c.json({ error: translateApiError(mrErr, "gitlabMR") }, 500);
20453
+ }
20454
+ } catch (e) {
20455
+ return c.json({ error: translateApiError(e, "gitlabMR") }, 500);
20456
+ }
20457
+ if (mrUrl && projectId) try {
20458
+ const match = releaseStore$1.getAll().find((e) => Number(e.projectId) === projectId && e.branch === targetBranch);
20459
+ if (match) releaseStore$1.add({
20460
+ ...match,
20461
+ mrUrl,
20462
+ mrSourceBranch: sourceBranch,
20463
+ mrTargetBranch: targetBranch
20464
+ }, dedupKey$1);
20465
+ } catch {}
20466
+ return c.json({
20467
+ mrUrl,
20468
+ sourceBranch,
20469
+ targetBranch
20470
+ });
20471
+ });
20370
20472
  router.get("/api/projects/:id/pom-version", async (c) => {
20371
20473
  try {
20372
20474
  const projectId = c.req.param("id");
@@ -31821,6 +31923,7 @@ const releaseAction = async (options) => {
31821
31923
  ge(import_picocolors.default.bgCyan(import_picocolors.default.black(" FlowPilot ")));
31822
31924
  const history = releaseStore.getAll();
31823
31925
  let fromHistory = false;
31926
+ let selectedEntry = null;
31824
31927
  let projectId = "";
31825
31928
  let projectName = "";
31826
31929
  let selectedBranch = "";
@@ -31828,7 +31931,7 @@ const releaseAction = async (options) => {
31828
31931
  if (history.length > 0) {
31829
31932
  const historyOptions = history.map((h) => ({
31830
31933
  value: h,
31831
- label: `${h.projectName} / ${h.branch} / ${h.jiraProjectKey} ${import_picocolors.default.dim(h.createdAt)}`
31934
+ label: `${h.projectName} / ${h.branch} / ${h.jiraProjectKey}${h.mrSourceBranch ? import_picocolors.default.dim(` MR: ${h.mrSourceBranch} → ${h.mrTargetBranch ?? h.branch}`) : ""} ${import_picocolors.default.dim(h.createdAt)}`
31832
31935
  }));
31833
31936
  historyOptions.push({
31834
31937
  value: "new",
@@ -31844,12 +31947,12 @@ const releaseAction = async (options) => {
31844
31947
  }
31845
31948
  if (pick !== "new") {
31846
31949
  fromHistory = true;
31847
- const entry = pick;
31848
- projectId = entry.projectId;
31849
- projectName = entry.projectName;
31850
- selectedBranch = entry.branch;
31851
- selectedJiraKey = entry.jiraProjectKey;
31852
- R.info(import_picocolors.default.green("✔") + ` ${t$1("release.historyQuickExecute")}: ${entry.projectName} / ${entry.branch} / ${entry.jiraProjectKey}`);
31950
+ selectedEntry = pick;
31951
+ projectId = selectedEntry.projectId;
31952
+ projectName = selectedEntry.projectName;
31953
+ selectedBranch = selectedEntry.branch;
31954
+ selectedJiraKey = selectedEntry.jiraProjectKey;
31955
+ R.info(import_picocolors.default.green("✔") + ` ${t$1("release.historyQuickExecute")}: ${selectedEntry.projectName} / ${selectedEntry.branch} / ${selectedEntry.jiraProjectKey}`);
31853
31956
  }
31854
31957
  }
31855
31958
  if (!fromHistory) {
@@ -32063,84 +32166,208 @@ const releaseAction = async (options) => {
32063
32166
  selectedJiraKey = pick;
32064
32167
  }
32065
32168
  }
32169
+ let jiraUrl = "";
32170
+ let issueExists = false;
32066
32171
  s.start(t$1("release.checkingExisting"));
32067
32172
  try {
32068
32173
  const searchResult = await jira.search(`summary ~ "${summary}" AND project = ${selectedJiraKey}`, 1);
32069
32174
  if (searchResult.total > 0 && searchResult.issues?.[0]) {
32070
32175
  const existingKey = searchResult.issues[0].key;
32071
- const jiraUrl = config.jiraHost ? `${config.jiraHost}/browse/${existingKey}` : "";
32176
+ jiraUrl = config.jiraHost ? `${config.jiraHost}/browse/${existingKey}` : "";
32072
32177
  stopSpinner(s, import_picocolors.default.green("✔") + ` ${t$1("release.issueExists")}`);
32178
+ issueExists = true;
32073
32179
  if (jiraUrl) {
32074
32180
  await clipboard.write(jiraUrl);
32075
- R.success(`${import_picocolors.default.bold(import_picocolors.default.cyan(existingKey))} ${import_picocolors.default.blue(jiraUrl)} ${import_picocolors.default.dim("(copied to clipboard)")}`);
32181
+ R.success(`${import_picocolors.default.bold(import_picocolors.default.cyan(existingKey))} ${import_picocolors.default.blue(jiraUrl)} ${import_picocolors.default.dim(t$1("end.copied"))}`);
32076
32182
  } else R.success(import_picocolors.default.bold(import_picocolors.default.cyan(existingKey)));
32077
- releaseStore.add({
32078
- id: Date.now().toString(36),
32079
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
32080
- projectId,
32081
- projectName,
32082
- projectPath: "",
32083
- branch: selectedBranch,
32084
- jiraProjectKey: selectedJiraKey
32085
- }, dedupKey);
32086
- ye(import_picocolors.default.dim("Done"));
32087
- return;
32088
32183
  }
32089
- stopSpinner(s, import_picocolors.default.dim("No existing issue found"));
32184
+ if (!issueExists) stopSpinner(s, import_picocolors.default.dim("No existing issue found"));
32090
32185
  } catch (e) {
32091
32186
  stopSpinner(s, import_picocolors.default.yellow("⚠") + ` ${t$1("release.searchFailed")}`);
32092
32187
  R.warn(import_picocolors.default.dim(translateApiError(e, "jiraSearch")));
32093
32188
  }
32094
- s.start(t$1("release.ensuringVersion"));
32095
- let versionId;
32096
- let versionCreated = false;
32097
- try {
32098
- const existing = (await jira.getProjectVersions(selectedJiraKey)).find((v) => v.name === versionName);
32099
- if (existing) {
32100
- versionId = existing.id;
32101
- stopSpinner(s, import_picocolors.default.green("✔") + ` ${t$1("release.versionExists")}: ${versionName}`);
32102
- } else {
32103
- versionId = (await jira.createVersion(selectedJiraKey, versionName)).id;
32104
- versionCreated = true;
32105
- stopSpinner(s, import_picocolors.default.green("✔") + ` ${t$1("release.versionCreated")}: ${versionName}`);
32189
+ if (!issueExists) {
32190
+ s.start(t$1("release.ensuringVersion"));
32191
+ let versionId;
32192
+ let versionCreated = false;
32193
+ try {
32194
+ const existing = (await jira.getProjectVersions(selectedJiraKey)).find((v) => v.name === versionName);
32195
+ if (existing) {
32196
+ versionId = existing.id;
32197
+ stopSpinner(s, import_picocolors.default.green("✔") + ` ${t$1("release.versionExists")}: ${versionName}`);
32198
+ } else {
32199
+ versionId = (await jira.createVersion(selectedJiraKey, versionName)).id;
32200
+ versionCreated = true;
32201
+ stopSpinner(s, import_picocolors.default.green("✔") + ` ${t$1("release.versionCreated")}: ${versionName}`);
32202
+ }
32203
+ } catch (e) {
32204
+ stopSpinner(s, import_picocolors.default.red(`${t$1("release.ensureVersionFailed")}`));
32205
+ R.error(import_picocolors.default.dim(translateApiError(e, "jiraVersion")));
32206
+ return;
32207
+ }
32208
+ s.start(t$1("release.creatingIssue"));
32209
+ try {
32210
+ const issue = await jira.createIssue({
32211
+ project: { key: selectedJiraKey },
32212
+ summary,
32213
+ issuetype: { id: "10000" },
32214
+ customfield_15800: "无",
32215
+ customfield_13410: [{ id: versionId }],
32216
+ customfield_13341: [{ name: "licheng.li" }]
32217
+ });
32218
+ jiraUrl = config.jiraHost ? `${config.jiraHost}/browse/${issue.key}` : "";
32219
+ stopSpinner(s, import_picocolors.default.green("✔") + ` ${t$1("release.issueCreated")}`);
32220
+ if (jiraUrl) {
32221
+ await clipboard.write(jiraUrl);
32222
+ R.success(`${import_picocolors.default.bold(import_picocolors.default.cyan(issue.key))} ${import_picocolors.default.blue(jiraUrl)} ${import_picocolors.default.dim(t$1("end.copied"))}`);
32223
+ } else R.success(import_picocolors.default.bold(import_picocolors.default.cyan(issue.key)));
32224
+ if (versionCreated) R.info(import_picocolors.default.dim(t$1("release.versionAlsoCreated")));
32225
+ } catch (e) {
32226
+ stopSpinner(s, import_picocolors.default.red(`${t$1("release.createIssueFailed")}`));
32227
+ R.error(import_picocolors.default.dim(translateApiError(e, "jiraCreateIssue")));
32228
+ return;
32106
32229
  }
32107
- } catch (e) {
32108
- stopSpinner(s, import_picocolors.default.red(`${t$1("release.ensureVersionFailed")}`));
32109
- R.error(import_picocolors.default.dim(translateApiError(e, "jiraVersion")));
32110
- return;
32111
32230
  }
32112
- s.start(t$1("release.creatingIssue"));
32113
- try {
32114
- const issue = await jira.createIssue({
32115
- project: { key: selectedJiraKey },
32116
- summary,
32117
- issuetype: { id: "10000" },
32118
- customfield_15800: "无",
32119
- customfield_13410: [{ id: versionId }],
32120
- customfield_13341: [{ name: "licheng.li" }]
32121
- });
32122
- const jiraUrl = config.jiraHost ? `${config.jiraHost}/browse/${issue.key}` : "";
32123
- stopSpinner(s, import_picocolors.default.green("✔") + ` ${t$1("release.issueCreated")}`);
32124
- if (jiraUrl) {
32125
- await clipboard.write(jiraUrl);
32126
- R.success(`${import_picocolors.default.bold(import_picocolors.default.cyan(issue.key))} ${import_picocolors.default.blue(jiraUrl)} ${import_picocolors.default.dim("(copied to clipboard)")}`);
32127
- } else R.success(import_picocolors.default.bold(import_picocolors.default.cyan(issue.key)));
32128
- if (versionCreated) R.info(import_picocolors.default.dim(t$1("release.versionAlsoCreated")));
32129
- releaseStore.add({
32130
- id: Date.now().toString(36),
32131
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
32132
- projectId,
32133
- projectName,
32134
- projectPath: "",
32135
- branch: selectedBranch,
32136
- jiraProjectKey: selectedJiraKey
32137
- }, dedupKey);
32138
- } catch (e) {
32139
- stopSpinner(s, import_picocolors.default.red(`${t$1("release.createIssueFailed")}`));
32140
- R.error(import_picocolors.default.dim(translateApiError(e, "jiraCreateIssue")));
32141
- return;
32231
+ let shouldCreateMr = false;
32232
+ let mrSourceBranch = "";
32233
+ let mrTargetBranch = "";
32234
+ let mrUrl = "";
32235
+ if (fromHistory && selectedEntry?.mrSourceBranch) {
32236
+ shouldCreateMr = true;
32237
+ mrSourceBranch = selectedEntry.mrSourceBranch;
32238
+ mrTargetBranch = selectedEntry.mrTargetBranch ?? selectedEntry.branch;
32239
+ R.info(import_picocolors.default.dim(`MR: ${mrSourceBranch} ${mrTargetBranch}`));
32240
+ } else if (!fromHistory) {
32241
+ const createMr = await ue({ message: t$1("release.createMR") });
32242
+ if (q$1(createMr)) {
32243
+ ye(import_picocolors.default.dim(t$1("end.done")));
32244
+ return;
32245
+ }
32246
+ if (createMr) {
32247
+ shouldCreateMr = true;
32248
+ const mrSpinner = ft();
32249
+ mrSpinner.start(t$1("release.fetchingBranches"));
32250
+ let mrBranches;
32251
+ try {
32252
+ mrBranches = await gitlab.listBranches(projectId);
32253
+ } catch (e) {
32254
+ stopSpinner(mrSpinner, import_picocolors.default.red(`${t$1("release.fetchBranchesFailed")}`));
32255
+ R.error(import_picocolors.default.dim(translateApiError(e, "gitlabBranch")));
32256
+ ye(import_picocolors.default.dim(t$1("end.done")));
32257
+ return;
32258
+ }
32259
+ stopSpinner(mrSpinner, import_picocolors.default.green("") + ` ${mrBranches.length} branches loaded`);
32260
+ const mrBranchChoices = mrBranches.filter((b) => b.name !== selectedBranch);
32261
+ if (mrBranchChoices.length === 0) {
32262
+ R.warn(import_picocolors.default.yellow(t$1("release.noSourceBranches")));
32263
+ ye(import_picocolors.default.dim(t$1("end.done")));
32264
+ return;
32265
+ }
32266
+ if (mrBranchChoices.length <= AUTOSELECT_THRESHOLD) {
32267
+ const sourceChoices = mrBranchChoices.map((b) => ({
32268
+ value: b.name,
32269
+ label: b.name + (b.default ? import_picocolors.default.cyan(` (${t$1("release.defaultBranch")})`) : "")
32270
+ }));
32271
+ const defaultBranch = mrBranchChoices.find((b) => b.default)?.name;
32272
+ const sourceBranchPick = await xe({
32273
+ message: t$1("release.selectSourceBranch"),
32274
+ options: sourceChoices,
32275
+ initialValue: defaultBranch
32276
+ });
32277
+ if (q$1(sourceBranchPick)) {
32278
+ me(t$1("release.aborted"));
32279
+ return;
32280
+ }
32281
+ mrSourceBranch = sourceBranchPick;
32282
+ } else {
32283
+ const sourceBranchPick = await dist_default({
32284
+ message: t$1("release.selectSourceBranch"),
32285
+ source: async (term) => {
32286
+ const matched = filterByRelevance(mrBranchChoices.map((b) => ({
32287
+ name: b.name,
32288
+ path: b.name
32289
+ })), term ?? "", 30);
32290
+ if (matched.length === 0) return [{
32291
+ value: null,
32292
+ name: import_picocolors.default.dim("(no matches)"),
32293
+ disabled: true
32294
+ }];
32295
+ return matched.map((m) => {
32296
+ const branch = mrBranchChoices.find((b) => b.name === m.name);
32297
+ return {
32298
+ value: branch.name,
32299
+ name: branch.name + (branch.default ? import_picocolors.default.cyan(` (${t$1("release.defaultBranch")})`) : ""),
32300
+ description: branch.default ? "default branch" : void 0
32301
+ };
32302
+ });
32303
+ }
32304
+ });
32305
+ if (sourceBranchPick === void 0) {
32306
+ me(t$1("release.aborted"));
32307
+ return;
32308
+ }
32309
+ mrSourceBranch = sourceBranchPick;
32310
+ }
32311
+ mrTargetBranch = selectedBranch;
32312
+ }
32142
32313
  }
32143
- ye(import_picocolors.default.dim("Done"));
32314
+ if (shouldCreateMr) {
32315
+ const mrSpinner = ft();
32316
+ mrSpinner.start(t$1("end.creatingMR"));
32317
+ mrUrl = "";
32318
+ try {
32319
+ const mr = await gitlab.createMergeRequest(projectId, mrSourceBranch, mrTargetBranch, `${mrSourceBranch} → ${mrTargetBranch}`, { description: jiraUrl ? `Jira: ${jiraUrl}` : "" });
32320
+ mrUrl = mr.webUrl ?? mr.web_url;
32321
+ stopSpinner(mrSpinner, import_picocolors.default.green("✔") + ` ${t$1("release.mrCreated")}`);
32322
+ } catch (e) {
32323
+ if ((e instanceof Error ? e.message : String(e)).includes("already exists")) try {
32324
+ const existing = (await gitlab.listMergeRequests({
32325
+ projectId,
32326
+ state: "opened"
32327
+ })).find((m) => m.sourceBranch === mrSourceBranch && m.targetBranch === mrTargetBranch);
32328
+ if (existing) {
32329
+ mrUrl = existing.webUrl ?? existing.web_url ?? "";
32330
+ stopSpinner(mrSpinner, import_picocolors.default.green("✔") + ` ${t$1("release.mrCreated")} (existing)`);
32331
+ } else {
32332
+ stopSpinner(mrSpinner, import_picocolors.default.red(t$1("end.mrFailed")));
32333
+ R.error(import_picocolors.default.dim(translateApiError(e, "gitlabMR")));
32334
+ }
32335
+ } catch {
32336
+ stopSpinner(mrSpinner, import_picocolors.default.red(t$1("end.mrFailed")));
32337
+ R.error(import_picocolors.default.dim(translateApiError(e, "gitlabMR")));
32338
+ }
32339
+ else {
32340
+ stopSpinner(mrSpinner, import_picocolors.default.red(t$1("end.mrFailed")));
32341
+ R.error(import_picocolors.default.dim(translateApiError(e, "gitlabMR")));
32342
+ }
32343
+ }
32344
+ if (mrUrl) {
32345
+ await clipboard.write(mrUrl);
32346
+ R.success(`${import_picocolors.default.blue(mrUrl)} ${import_picocolors.default.dim(t$1("end.copied"))}`);
32347
+ const match = releaseStore.getAll().find((e) => e.projectId === projectId && e.branch === mrTargetBranch);
32348
+ if (match) releaseStore.add({
32349
+ ...match,
32350
+ mrUrl,
32351
+ mrSourceBranch,
32352
+ mrTargetBranch
32353
+ }, dedupKey);
32354
+ }
32355
+ }
32356
+ if (!fromHistory) releaseStore.add({
32357
+ id: `${Date.now()}`,
32358
+ createdAt: (/* @__PURE__ */ new Date()).toLocaleString(),
32359
+ projectId,
32360
+ projectName,
32361
+ projectPath: "",
32362
+ branch: selectedBranch,
32363
+ jiraProjectKey: selectedJiraKey,
32364
+ ...mrUrl ? {
32365
+ mrUrl,
32366
+ mrSourceBranch,
32367
+ mrTargetBranch
32368
+ } : {}
32369
+ }, dedupKey);
32370
+ ye(import_picocolors.default.dim(t$1("end.done")));
32144
32371
  };
32145
32372
  //#endregion
32146
32373
  //#region src/cli.ts
@@ -1,4 +1,4 @@
1
- import { a as useRef, i as useReducer, n as instance, r as useEffect, s as render, t as jsxDEV } from "./jsx-dev-runtime-DGBfem3G.js";
1
+ import { a as useRef, i as useReducer, n as instance, r as useEffect, s as render, t as jsxDEV } from "./jsx-dev-runtime-DOO7Tqjo.js";
2
2
  import { t as filterByRelevance } from "./search-cPm8k8mK.js";
3
3
  //#region src/commands/end/client.tsx
4
4
  const initPromise = typeof window !== "undefined" && window.__I18N_LOCALE__ && window.__I18N_RESOURCES__ ? instance.init({