@coze-arch/rush-publish-plugin 0.0.5-alpha.8b5f6f → 0.0.5-alpha.a5f14f

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/lib/index.js CHANGED
@@ -282,6 +282,84 @@ const getCurrentOrigin = async (
282
282
  }
283
283
  };
284
284
 
285
+ /**
286
+ * 解析 Git 远程仓库 URL,提取主机和仓库路径
287
+ * 支持 HTTP/HTTPS 和 SSH 格式
288
+ * @param gitUrl Git 仓库 URL
289
+ * @returns 包含主机和仓库路径的对象,解析失败返回 null
290
+ */
291
+ const parseGitRemoteUrl = (
292
+ gitUrl,
293
+ ) => {
294
+ if (!gitUrl) {
295
+ return null;
296
+ }
297
+
298
+ const trimmedUrl = gitUrl.trim().replace(/\.git$/, '');
299
+
300
+ // 匹配 SSH 格式: git@github.com:owner/repo.git
301
+ const sshMatch = trimmedUrl.match(/^git@([^:]+):(.+)$/);
302
+ if (sshMatch) {
303
+ const host = sshMatch[1];
304
+ const path = sshMatch[2];
305
+ return {
306
+ host,
307
+ path,
308
+ fullUrl: `https://${host}/${path}`,
309
+ };
310
+ }
311
+
312
+ // 匹配 HTTP/HTTPS 格式: https://github.com/owner/repo.git
313
+ const httpMatch = trimmedUrl.match(/^https?:\/\/([^/]+)\/(.+)$/);
314
+ if (httpMatch) {
315
+ const host = httpMatch[1];
316
+ const path = httpMatch[2];
317
+ return {
318
+ host,
319
+ path,
320
+ fullUrl: `https://${host}/${path}`,
321
+ };
322
+ }
323
+
324
+ return null;
325
+ };
326
+
327
+ /**
328
+ * 根据仓库信息构建 MR/PR 创建链接
329
+ * @param repoInfo 仓库信息
330
+ * @param branchName 分支名称
331
+ * @returns MR/PR 创建链接,如果无法构建则返回 null
332
+ */
333
+ const buildMergeRequestUrl = (
334
+ repoInfo,
335
+ branchName,
336
+ ) => {
337
+ const { host, fullUrl } = repoInfo;
338
+
339
+ // GitHub
340
+ if (host.includes('github.com')) {
341
+ return `${fullUrl}/compare/${branchName}?expand=1`;
342
+ }
343
+
344
+ // GitLab
345
+ if (host.includes('gitlab')) {
346
+ return `${fullUrl}/-/merge_requests/new?merge_request[source_branch]=${branchName}`;
347
+ }
348
+
349
+ // Gitee
350
+ if (host.includes('gitee.com')) {
351
+ return `${fullUrl}/compare/${branchName}...master`;
352
+ }
353
+
354
+ // Bitbucket
355
+ if (host.includes('bitbucket')) {
356
+ return `${fullUrl}/pull-requests/new?source=${branchName}`;
357
+ }
358
+
359
+ // 无法识别的平台
360
+ return null;
361
+ };
362
+
285
363
  // Copyright (c) 2025 coze-dev
286
364
  // SPDX-License-Identifier: MIT
287
365
 
@@ -323,8 +401,7 @@ const getRushConfiguration$1 = (() => {
323
401
  };
324
402
  })();
325
403
 
326
- // Copyright (c) 2025 coze-dev
327
- // SPDX-License-Identifier: MIT
404
+ function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }// Copyright (c) 2025 coze-dev
328
405
 
329
406
 
330
407
 
@@ -355,14 +432,21 @@ const updateDependencyVersions = async (
355
432
  return Promise.resolve(packageJson);
356
433
  };
357
434
 
358
- const applyCozePublishConfig = async (
435
+ /**
436
+ * 应用发布配置
437
+ * 优先使用 botPublishConfig,如果不存在则使用 cozePublishConfig
438
+ */
439
+ const applyPublishConfigSettings = async (
359
440
  packageJson,
360
441
  ) => {
361
- const { cozePublishConfig } = packageJson;
362
- if (cozePublishConfig) {
363
- const keys = Object.keys(cozePublishConfig);
442
+ // 优先使用 botPublishConfig,如果不存在则回退到 cozePublishConfig
443
+ const publishConfig =
444
+ _nullishCoalesce(packageJson.botPublishConfig, () => ( packageJson.cozePublishConfig));
445
+
446
+ if (publishConfig) {
447
+ const keys = Object.keys(publishConfig);
364
448
  for (const key of keys) {
365
- packageJson[key] = cozePublishConfig[key];
449
+ packageJson[key] = publishConfig[key];
366
450
  }
367
451
  }
368
452
  return Promise.resolve(packageJson);
@@ -371,7 +455,7 @@ const applyCozePublishConfig = async (
371
455
  const applyPublishConfig = async (project) => {
372
456
  const jobs = [
373
457
  updateDependencyVersions,
374
- applyCozePublishConfig,
458
+ applyPublishConfigSettings,
375
459
  ];
376
460
  const packageJsonPath = path.join(project.projectFolder, 'package.json');
377
461
  let packageJson = await readJsonFile(packageJsonPath);
@@ -484,7 +568,7 @@ const checkReleasePlan = (
484
568
  !allowBranches.includes(branchName)
485
569
  ) {
486
570
  throw new Error(
487
- `For LATEST release, should be on one of these branches: ${allowBranches.join(', ')}.`,
571
+ `For LATEST release, should be on one of these branches: ${allowBranches.join(', ')}. Current Branch: ${branchName}`,
488
572
  );
489
573
  }
490
574
  return true;
@@ -910,6 +994,144 @@ async function push({ refs, cwd, repoUrl }) {
910
994
 
911
995
 
912
996
 
997
+ /**
998
+ * 获取或创建发布分支
999
+ */
1000
+ const getOrCreateBranch = async (params
1001
+
1002
+
1003
+
1004
+
1005
+ ) => {
1006
+ const { bumpPolicy, sessionId, branchPrefix, cwd } = params;
1007
+
1008
+ if (bumpPolicy === BumpType.BETA) {
1009
+ return await getCurrentBranchName();
1010
+ }
1011
+
1012
+ const date = dayjs().format('YYYYMMDD');
1013
+ const branchName = `${branchPrefix}/${date}-${sessionId}`;
1014
+ await exec(`git checkout -b ${branchName}`, { cwd });
1015
+ return branchName;
1016
+ };
1017
+
1018
+ /**
1019
+ * 处理 Beta 发布流程:询问并执行 git push
1020
+ */
1021
+ const handleBetaPublish = async (
1022
+ branchName,
1023
+ cwd,
1024
+ ) => {
1025
+ logger.success(`Changes have been committed to branch "${branchName}".`);
1026
+
1027
+ const shouldPush = await prompts.confirm({
1028
+ message: 'Do you want to push the changes now?',
1029
+ default: true,
1030
+ });
1031
+
1032
+ if (shouldPush) {
1033
+ logger.info('Pushing changes to remote...');
1034
+ await exec('git push', { cwd });
1035
+ logger.success('Changes pushed successfully!');
1036
+ } else {
1037
+ logger.info('Please run "git push" manually when you are ready.');
1038
+ }
1039
+ };
1040
+
1041
+ /**
1042
+ * 显示手动创建 MR 的提示消息
1043
+ */
1044
+ const showManualMrMessage = (
1045
+ branchName,
1046
+ repositoryUrl,
1047
+ ) => {
1048
+ const baseMessage = `Please create a merge request from branch "${branchName}" to the main branch`;
1049
+ const suffix =
1050
+ 'The release will be triggered after the merge request is merged.';
1051
+
1052
+ if (repositoryUrl) {
1053
+ logger.success(
1054
+ `Repository: ${repositoryUrl}\n${baseMessage}.\n${suffix}`,
1055
+ false,
1056
+ );
1057
+ } else {
1058
+ logger.success(`${baseMessage} in your repository.\n${suffix}`);
1059
+ }
1060
+ };
1061
+
1062
+ /**
1063
+ * 显示 MR/PR 创建链接并打开浏览器
1064
+ */
1065
+ const showMrLinkAndOpenBrowser = async (mrUrl) => {
1066
+ const log = [
1067
+ '************************************************',
1068
+ '*',
1069
+ `* Please create MR/PR: ${mrUrl}`,
1070
+ '*',
1071
+ '* The release will be triggered after the MR is merged.',
1072
+ '*',
1073
+ '************************************************',
1074
+ ];
1075
+ logger.success(log.join('\n'), false);
1076
+
1077
+ const open = await import('open');
1078
+ await open.default(mrUrl);
1079
+ };
1080
+
1081
+ /**
1082
+ * 处理正式版本发布流程:提示创建 MR/PR
1083
+ */
1084
+ const handleProductionPublish = async (
1085
+ branchName,
1086
+ cwd,
1087
+ ) => {
1088
+ const originUrl = await getCurrentOrigin(cwd);
1089
+ if (!originUrl) {
1090
+ showManualMrMessage(branchName);
1091
+ return;
1092
+ }
1093
+
1094
+ const repoInfo = parseGitRemoteUrl(originUrl);
1095
+ if (!repoInfo) {
1096
+ showManualMrMessage(branchName);
1097
+ return;
1098
+ }
1099
+
1100
+ const mrUrl = buildMergeRequestUrl(repoInfo, branchName);
1101
+ if (!mrUrl) {
1102
+ showManualMrMessage(branchName, repoInfo.fullUrl);
1103
+ return;
1104
+ }
1105
+
1106
+ await showMrLinkAndOpenBrowser(mrUrl);
1107
+ };
1108
+
1109
+ /**
1110
+ * 根据发布类型处理后续提示
1111
+ */
1112
+ const handlePostPushPrompts = async (
1113
+ bumpPolicy,
1114
+ branchName,
1115
+ cwd,
1116
+ ) => {
1117
+ const isAlphaPublish = bumpPolicy === BumpType.ALPHA;
1118
+ const isBetaPublish = bumpPolicy === BumpType.BETA;
1119
+
1120
+ // Alpha 发布:不需要提示(会自动触发 CI 发布)
1121
+ if (isAlphaPublish) {
1122
+ return;
1123
+ }
1124
+
1125
+ // Beta 发布:询问用户是否立即执行 git push
1126
+ if (isBetaPublish) {
1127
+ await handleBetaPublish(branchName, cwd);
1128
+ return;
1129
+ }
1130
+
1131
+ // 正式版本发布:提示创建 MR/PR
1132
+ await handleProductionPublish(branchName, cwd);
1133
+ };
1134
+
913
1135
  const pushToRemote = async (options) => {
914
1136
  const {
915
1137
  sessionId,
@@ -921,65 +1143,39 @@ const pushToRemote = async (options) => {
921
1143
  repoUrl,
922
1144
  branchPrefix = 'release',
923
1145
  } = options;
1146
+
924
1147
  if (skipCommit) {
925
1148
  return;
926
1149
  }
927
1150
 
928
- // 获取仓库 URL
929
- const actualRepoUrl = repoUrl;
930
-
931
- let branchName;
932
- if (bumpPolicy === BumpType.BETA) {
933
- branchName = await getCurrentBranchName();
934
- } else {
935
- const date = dayjs().format('YYYYMMDD');
936
- branchName = `${branchPrefix}/${date}-${sessionId}`;
937
- await exec(`git checkout -b ${branchName}`, { cwd });
938
- }
939
- const isTestPublish = [BumpType.ALPHA, BumpType.BETA].includes(
940
- bumpPolicy ,
941
- );
1151
+ // 1. 获取或创建发布分支
1152
+ const branchName = await getOrCreateBranch({
1153
+ bumpPolicy,
1154
+ sessionId,
1155
+ branchPrefix,
1156
+ cwd,
1157
+ });
942
1158
 
943
- // 4. 创建并推送发布分支
1159
+ // 2. 提交变更
944
1160
  const { effects } = await commitChanges({
945
1161
  files: changedFiles,
946
1162
  cwd,
947
1163
  branchName,
948
1164
  });
1165
+
949
1166
  if (skipPush) {
950
1167
  return;
951
1168
  }
1169
+
1170
+ // 3. 推送变更
952
1171
  await push({
953
1172
  refs: effects,
954
1173
  cwd,
955
- repoUrl: actualRepoUrl,
1174
+ repoUrl,
956
1175
  });
957
1176
 
958
- // git URL 提取组织和仓库名称,用于构建 GitHub 链接
959
- const repoInfoMatch = actualRepoUrl.match(GIT_REPO_URL_REGEX);
960
- if (!repoInfoMatch) {
961
- throw new Error('Invalid git repository URL');
962
- }
963
- const repoOwner = repoInfoMatch[1];
964
- const repoName = repoInfoMatch[2];
965
-
966
- if (isTestPublish) {
967
- logger.success(
968
- `Please refer to https://github.com/${repoOwner}/${repoName}/actions/workflows/release.yml for the release progress.`,
969
- );
970
- } else {
971
- const prUrl = `https://github.com/${repoOwner}/${repoName}/compare/${branchName}?expand=1`;
972
- const log = [
973
- '************************************************',
974
- '*',
975
- `* Please create PR: ${prUrl}`,
976
- '*',
977
- '************************************************',
978
- ];
979
- logger.success(log.join('\n'), false);
980
- const open = await import('open');
981
- await open.default(prUrl);
982
- }
1177
+ // 4. 根据发布类型显示不同提示
1178
+ await handlePostPushPrompts(bumpPolicy, branchName, cwd);
983
1179
  };
984
1180
 
985
1181
  // Copyright (c) 2025 coze-dev
@@ -1591,7 +1787,11 @@ const publish = async (options) => {
1591
1787
  const isBetaPublish = [BumpType.BETA, BumpType.ALPHA].includes(
1592
1788
  bumpPolicy ,
1593
1789
  );
1594
- if (isBetaPublish === false && (await isMainBranch()) === false) {
1790
+ if (
1791
+ process.env.SKIP_BRANCH_CHECK !== 'true' &&
1792
+ isBetaPublish === false &&
1793
+ (await isMainBranch()) === false
1794
+ ) {
1595
1795
  // 只允许在主分支发布
1596
1796
  logger.error(
1597
1797
  'You are not in main branch, please switch to main branch and try again.',
@@ -22,3 +22,25 @@ export declare const ensureNotUncommittedChanges: () => Promise<boolean>;
22
22
  */
23
23
  export declare const getCurrentOrigin: (cwd?: string) => Promise<string | undefined>;
24
24
  export declare const convertGitSchemaToHttp: (gitUrl: string) => string;
25
+ /**
26
+ * 解析 Git 远程仓库 URL,提取主机和仓库路径
27
+ * 支持 HTTP/HTTPS 和 SSH 格式
28
+ * @param gitUrl Git 仓库 URL
29
+ * @returns 包含主机和仓库路径的对象,解析失败返回 null
30
+ */
31
+ export declare const parseGitRemoteUrl: (gitUrl: string) => {
32
+ host: string;
33
+ path: string;
34
+ fullUrl: string;
35
+ } | null;
36
+ /**
37
+ * 根据仓库信息构建 MR/PR 创建链接
38
+ * @param repoInfo 仓库信息
39
+ * @param branchName 分支名称
40
+ * @returns MR/PR 创建链接,如果无法构建则返回 null
41
+ */
42
+ export declare const buildMergeRequestUrl: (repoInfo: {
43
+ host: string;
44
+ path: string;
45
+ fullUrl: string;
46
+ }, branchName: string) => string | null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coze-arch/rush-publish-plugin",
3
- "version": "0.0.5-alpha.8b5f6f",
3
+ "version": "0.0.5-alpha.a5f14f",
4
4
  "description": "rush plugin to generate change log and publish packages",
5
5
  "keywords": [
6
6
  "rush",