@coze-arch/rush-publish-plugin 0.0.4 → 0.0.5-alpha.1ae01f
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/command-line.json +35 -3
- package/lib/action/publish/confirm.d.ts +5 -1
- package/lib/action/publish/git.d.ts +1 -5
- package/lib/action/publish/packages.d.ts +1 -1
- package/lib/action/publish/push-to-remote.d.ts +1 -0
- package/lib/action/publish/types.d.ts +3 -0
- package/lib/action/publish/version.d.ts +1 -1
- package/lib/action/release/plan.d.ts +1 -1
- package/lib/action/release/types.d.ts +3 -1
- package/lib/const/index.d.ts +12 -0
- package/lib/index.js +696 -133
- package/lib/utils/ci.d.ts +86 -0
- package/lib/utils/get-plugin-config.d.ts +8 -0
- package/lib/utils/git.d.ts +27 -0
- package/package.json +6 -10
package/lib/index.js
CHANGED
|
@@ -13,6 +13,9 @@ var prompts = require('@inquirer/prompts');
|
|
|
13
13
|
var dayjs = require('dayjs');
|
|
14
14
|
var ChangeFile = require('@rushstack/rush-sdk/lib/api/ChangeFile');
|
|
15
15
|
|
|
16
|
+
// Copyright (c) 2025 coze-dev
|
|
17
|
+
// SPDX-License-Identifier: MIT
|
|
18
|
+
|
|
16
19
|
/**
|
|
17
20
|
* 日志工具
|
|
18
21
|
*
|
|
@@ -142,6 +145,34 @@ const logger = {
|
|
|
142
145
|
},
|
|
143
146
|
};
|
|
144
147
|
|
|
148
|
+
// Copyright (c) 2025 coze-dev
|
|
149
|
+
// SPDX-License-Identifier: MIT
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* 默认的 NPM registry 地址
|
|
153
|
+
*/
|
|
154
|
+
const DEFAULT_NPM_REGISTRY = 'https://registry.npmjs.org';
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* 默认的 Git 分支名前缀
|
|
158
|
+
*/
|
|
159
|
+
const DEFAULT_BRANCH_PREFIX = 'bump';
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* 默认允许发布正式版本的分支列表
|
|
163
|
+
*/
|
|
164
|
+
const DEFAULT_ALLOW_BRANCHES = ['main', 'feat/auto-publish'];
|
|
165
|
+
|
|
166
|
+
// Copyright (c) 2025 coze-dev
|
|
167
|
+
// SPDX-License-Identifier: MIT
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
|
|
145
176
|
class ExecError extends Error {
|
|
146
177
|
|
|
147
178
|
|
|
@@ -168,6 +199,10 @@ const exec = (
|
|
|
168
199
|
});
|
|
169
200
|
});
|
|
170
201
|
|
|
202
|
+
// Copyright (c) 2025 coze-dev
|
|
203
|
+
// SPDX-License-Identifier: MIT
|
|
204
|
+
|
|
205
|
+
|
|
171
206
|
const serializeFilesName = (output) =>
|
|
172
207
|
output
|
|
173
208
|
.split('\n')
|
|
@@ -197,6 +232,15 @@ const getCurrentBranchName = async () => {
|
|
|
197
232
|
return stdout.trim();
|
|
198
233
|
};
|
|
199
234
|
|
|
235
|
+
/**
|
|
236
|
+
* 获取当前 commit hash
|
|
237
|
+
* @returns commit hash
|
|
238
|
+
*/
|
|
239
|
+
const getCurrentCommitHash = async () => {
|
|
240
|
+
const { stdout } = await exec('git rev-parse HEAD');
|
|
241
|
+
return stdout.trim();
|
|
242
|
+
};
|
|
243
|
+
|
|
200
244
|
const isMainBranch = async () => {
|
|
201
245
|
const currentBranchName = await getCurrentBranchName();
|
|
202
246
|
return currentBranchName === 'main';
|
|
@@ -238,6 +282,88 @@ const getCurrentOrigin = async (
|
|
|
238
282
|
}
|
|
239
283
|
};
|
|
240
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
|
+
|
|
363
|
+
// Copyright (c) 2025 coze-dev
|
|
364
|
+
// SPDX-License-Identifier: MIT
|
|
365
|
+
|
|
366
|
+
|
|
241
367
|
const readJsonFile = async ( path) => {
|
|
242
368
|
const content = await fs.readFile(path, 'utf8');
|
|
243
369
|
return JSON.parse(content) ;
|
|
@@ -259,7 +385,11 @@ const isDirExists = async (path) =>
|
|
|
259
385
|
.then(() => true)
|
|
260
386
|
.catch(() => false);
|
|
261
387
|
|
|
262
|
-
|
|
388
|
+
// Copyright (c) 2025 coze-dev
|
|
389
|
+
// SPDX-License-Identifier: MIT
|
|
390
|
+
|
|
391
|
+
|
|
392
|
+
const getRushConfiguration$1 = (() => {
|
|
263
393
|
let rushConfiguration = null;
|
|
264
394
|
return (useCache = true) => {
|
|
265
395
|
if (!useCache) {
|
|
@@ -271,19 +401,32 @@ const getRushConfiguration = (() => {
|
|
|
271
401
|
};
|
|
272
402
|
})();
|
|
273
403
|
|
|
404
|
+
// Copyright (c) 2025 coze-dev
|
|
405
|
+
// SPDX-License-Identifier: MIT
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
|
|
274
415
|
/**
|
|
275
416
|
* 更新依赖版本
|
|
276
417
|
*/
|
|
277
418
|
const updateDependencyVersions = async (
|
|
278
419
|
packageJson,
|
|
279
420
|
) => {
|
|
280
|
-
const rushConfiguration = getRushConfiguration();
|
|
281
|
-
const
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
const
|
|
285
|
-
|
|
286
|
-
|
|
421
|
+
const rushConfiguration = getRushConfiguration$1();
|
|
422
|
+
const depTypes = ['dependencies', 'peerDependencies'];
|
|
423
|
+
for (const depType of depTypes) {
|
|
424
|
+
if (packageJson[depType]) {
|
|
425
|
+
for (const [dep, ver] of Object.entries(packageJson[depType])) {
|
|
426
|
+
const project = rushConfiguration.getProjectByName(dep);
|
|
427
|
+
if (/^workspace:/.test(ver) && project) {
|
|
428
|
+
packageJson[depType][dep] = project.packageJson.version;
|
|
429
|
+
}
|
|
287
430
|
}
|
|
288
431
|
}
|
|
289
432
|
}
|
|
@@ -331,7 +474,12 @@ const publishPackage = async (
|
|
|
331
474
|
: version.includes('beta')
|
|
332
475
|
? 'beta'
|
|
333
476
|
: 'latest';
|
|
334
|
-
const
|
|
477
|
+
const setToken = `npm config set //bnpm.byted.org/:_authToken ${token}`;
|
|
478
|
+
await exec(setToken, {
|
|
479
|
+
cwd: project.projectFolder,
|
|
480
|
+
});
|
|
481
|
+
|
|
482
|
+
const args = [`NODE_AUTH_TOKEN=${token}`, 'npm', 'publish', `--tag ${tag}`];
|
|
335
483
|
if (dryRun) {
|
|
336
484
|
args.push('--dry-run');
|
|
337
485
|
}
|
|
@@ -406,33 +554,51 @@ const calReleasePlan = (releaseManifests) => {
|
|
|
406
554
|
const checkReleasePlan = (
|
|
407
555
|
releaseManifests,
|
|
408
556
|
branchName,
|
|
557
|
+
allowBranches = ['main', 'feat/auto-publish'],
|
|
409
558
|
) => {
|
|
410
559
|
const releasePlan = calReleasePlan(releaseManifests);
|
|
411
560
|
if (
|
|
412
561
|
releasePlan === ReleaseType.LATEST &&
|
|
413
|
-
!
|
|
562
|
+
!allowBranches.includes(branchName)
|
|
414
563
|
) {
|
|
415
|
-
throw new Error(
|
|
564
|
+
throw new Error(
|
|
565
|
+
`For LATEST release, should be on one of these branches: ${allowBranches.join(', ')}. Current Branch: ${branchName}`,
|
|
566
|
+
);
|
|
416
567
|
}
|
|
417
568
|
return true;
|
|
418
569
|
};
|
|
419
570
|
|
|
571
|
+
// Copyright (c) 2025 coze-dev
|
|
572
|
+
// SPDX-License-Identifier: MIT
|
|
573
|
+
|
|
574
|
+
|
|
575
|
+
|
|
420
576
|
/**
|
|
421
577
|
* 构建发布依赖树
|
|
422
578
|
*/
|
|
423
579
|
function buildReleaseManifest(
|
|
424
580
|
packages,
|
|
425
581
|
) {
|
|
426
|
-
const rushConfiguration = getRushConfiguration();
|
|
427
|
-
return packages
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
582
|
+
const rushConfiguration = getRushConfiguration$1();
|
|
583
|
+
return packages
|
|
584
|
+
.map(pkg => {
|
|
585
|
+
const project = rushConfiguration.getProjectByName(pkg.packageName);
|
|
586
|
+
if (!project) {
|
|
587
|
+
throw new Error(`Cannot find project: ${pkg.packageName}`);
|
|
588
|
+
}
|
|
589
|
+
if (project.shouldPublish) {
|
|
590
|
+
return { project, version: project.packageJson.version };
|
|
591
|
+
}
|
|
592
|
+
return undefined;
|
|
593
|
+
})
|
|
594
|
+
.filter(Boolean) ;
|
|
434
595
|
}
|
|
435
596
|
|
|
597
|
+
// Copyright (c) 2025 coze-dev
|
|
598
|
+
// SPDX-License-Identifier: MIT
|
|
599
|
+
|
|
600
|
+
|
|
601
|
+
|
|
436
602
|
/**
|
|
437
603
|
* 从 git tag 中解析需要发布的包信息
|
|
438
604
|
*/
|
|
@@ -461,11 +627,37 @@ const getPackagesToPublish = async (
|
|
|
461
627
|
return packages;
|
|
462
628
|
};
|
|
463
629
|
|
|
630
|
+
// Copyright (c) 2025 coze-dev
|
|
631
|
+
// SPDX-License-Identifier: MIT
|
|
632
|
+
|
|
633
|
+
|
|
464
634
|
async function release(options) {
|
|
465
|
-
const {
|
|
635
|
+
const {
|
|
636
|
+
dryRun = false,
|
|
637
|
+
registry,
|
|
638
|
+
packages,
|
|
639
|
+
allowBranches = DEFAULT_ALLOW_BRANCHES,
|
|
640
|
+
} = options;
|
|
641
|
+
let { commit } = options;
|
|
642
|
+
const hasPassedCommit = !!options.commit;
|
|
466
643
|
|
|
467
644
|
// 1. 获取需要发布的包列表
|
|
468
|
-
|
|
645
|
+
let packagesToPublish;
|
|
646
|
+
if (packages) {
|
|
647
|
+
// 直接使用传入的包列表
|
|
648
|
+
packagesToPublish = packages;
|
|
649
|
+
logger.info('Using provided package list');
|
|
650
|
+
} else {
|
|
651
|
+
// 从 git tags 获取包列表
|
|
652
|
+
if (!hasPassedCommit) {
|
|
653
|
+
commit = await getCurrentCommitHash();
|
|
654
|
+
logger.info('Using current commit');
|
|
655
|
+
}
|
|
656
|
+
// 此时 commit 必定有值(要么传入了,要么刚获取了)
|
|
657
|
+
const commitHash = commit ;
|
|
658
|
+
packagesToPublish = await getPackagesToPublish(commitHash);
|
|
659
|
+
}
|
|
660
|
+
|
|
469
661
|
if (packagesToPublish.length === 0) {
|
|
470
662
|
logger.warn('No packages to publish');
|
|
471
663
|
return;
|
|
@@ -481,8 +673,16 @@ async function release(options) {
|
|
|
481
673
|
false,
|
|
482
674
|
);
|
|
483
675
|
const branchName = await getCurrentBranchName();
|
|
484
|
-
checkReleasePlan(releaseManifests, branchName);
|
|
485
|
-
|
|
676
|
+
checkReleasePlan(releaseManifests, branchName, allowBranches);
|
|
677
|
+
|
|
678
|
+
// 只有在指定了 commit 且与当前 HEAD 不同时才切换
|
|
679
|
+
if (hasPassedCommit) {
|
|
680
|
+
const currentHead = await getCurrentCommitHash();
|
|
681
|
+
if (currentHead !== commit) {
|
|
682
|
+
logger.info(`Checking out commit: ${commit}`);
|
|
683
|
+
await exec(`git checkout ${commit}`);
|
|
684
|
+
}
|
|
685
|
+
}
|
|
486
686
|
|
|
487
687
|
await releasePackages(releaseManifests, { dryRun, registry });
|
|
488
688
|
logger.success('All packages published successfully!');
|
|
@@ -498,18 +698,19 @@ const installAction$2 = (program) => {
|
|
|
498
698
|
program
|
|
499
699
|
.command('release')
|
|
500
700
|
.description('Release packages based on git tags.')
|
|
501
|
-
.
|
|
701
|
+
.option('--commit <string>', '需要执行发布的 commit id (默认使用当前 HEAD)')
|
|
502
702
|
.option('--dry-run', '是否只执行不真实发布', false)
|
|
503
703
|
.option(
|
|
504
704
|
'-r, --registry <string>',
|
|
505
|
-
|
|
506
|
-
|
|
705
|
+
`发布到的 registry (默认: ${DEFAULT_NPM_REGISTRY})`,
|
|
706
|
+
DEFAULT_NPM_REGISTRY,
|
|
707
|
+
)
|
|
708
|
+
.option(
|
|
709
|
+
'--allow-branches <branches...>',
|
|
710
|
+
`允许发布正式版本的分支列表 (默认: ${DEFAULT_ALLOW_BRANCHES.join(', ')})`,
|
|
507
711
|
)
|
|
508
712
|
.action(async (options) => {
|
|
509
713
|
try {
|
|
510
|
-
if (!options.commit) {
|
|
511
|
-
throw new Error('请提供需要发布的 commit id');
|
|
512
|
-
}
|
|
513
714
|
if (!process.env.NPM_AUTH_TOKEN) {
|
|
514
715
|
throw new Error('请设置 NPM_AUTH_TOKEN 环境变量');
|
|
515
716
|
}
|
|
@@ -522,7 +723,14 @@ const installAction$2 = (program) => {
|
|
|
522
723
|
});
|
|
523
724
|
};
|
|
524
725
|
|
|
525
|
-
|
|
726
|
+
// Copyright (c) 2025 coze-dev
|
|
727
|
+
// SPDX-License-Identifier: MIT
|
|
728
|
+
|
|
729
|
+
const GIT_REPO_URL_REGEX = /git@.+:([^\/]+)\/([^\.]+)\.git/;
|
|
730
|
+
|
|
731
|
+
// Copyright (c) 2025 coze-dev
|
|
732
|
+
// SPDX-License-Identifier: MIT
|
|
733
|
+
|
|
526
734
|
|
|
527
735
|
/**
|
|
528
736
|
* 生成指定长度的随机字符串(使用 crypto 模块)
|
|
@@ -544,6 +752,10 @@ var BumpType; (function (BumpType) {
|
|
|
544
752
|
const MAJOR = 'major'; BumpType["MAJOR"] = MAJOR;
|
|
545
753
|
})(BumpType || (BumpType = {}));
|
|
546
754
|
|
|
755
|
+
// Copyright (c) 2025 coze-dev
|
|
756
|
+
// SPDX-License-Identifier: MIT
|
|
757
|
+
|
|
758
|
+
|
|
547
759
|
/**
|
|
548
760
|
* 获取更新类型的描述
|
|
549
761
|
*/
|
|
@@ -592,6 +804,16 @@ const requestBumpType = async () => {
|
|
|
592
804
|
}
|
|
593
805
|
};
|
|
594
806
|
|
|
807
|
+
// Copyright (c) 2025 coze-dev
|
|
808
|
+
// SPDX-License-Identifier: MIT
|
|
809
|
+
|
|
810
|
+
|
|
811
|
+
|
|
812
|
+
|
|
813
|
+
|
|
814
|
+
|
|
815
|
+
|
|
816
|
+
|
|
595
817
|
/**
|
|
596
818
|
* 根据当前版本和发布类型计算新版本号
|
|
597
819
|
*/
|
|
@@ -718,28 +940,24 @@ const generatePublishManifest = async (
|
|
|
718
940
|
};
|
|
719
941
|
};
|
|
720
942
|
|
|
943
|
+
// Copyright (c) 2025 coze-dev
|
|
944
|
+
// SPDX-License-Identifier: MIT
|
|
945
|
+
|
|
946
|
+
|
|
947
|
+
|
|
948
|
+
|
|
949
|
+
|
|
950
|
+
|
|
951
|
+
|
|
721
952
|
async function commitChanges({
|
|
722
|
-
sessionId,
|
|
723
953
|
files,
|
|
724
954
|
cwd,
|
|
725
|
-
publishManifests,
|
|
726
955
|
branchName,
|
|
727
|
-
createTags,
|
|
728
956
|
}) {
|
|
729
957
|
await exec(`git add ${files.join(' ')}`, { cwd });
|
|
730
958
|
await exec(`git commit -m "chore: Publish ${branchName}" -n`, { cwd });
|
|
731
959
|
|
|
732
|
-
|
|
733
|
-
if (createTags) {
|
|
734
|
-
tags = publishManifests.map(
|
|
735
|
-
m => `v/${m.project.packageName}@${m.newVersion}`,
|
|
736
|
-
);
|
|
737
|
-
await exec(
|
|
738
|
-
tags.map(tag => `git tag -a ${tag} -m "Bump type ${tag}"`).join(' && '),
|
|
739
|
-
{ cwd },
|
|
740
|
-
);
|
|
741
|
-
}
|
|
742
|
-
return { effects: [...tags, branchName], branchName };
|
|
960
|
+
return { effects: [branchName], branchName };
|
|
743
961
|
}
|
|
744
962
|
|
|
745
963
|
|
|
@@ -754,83 +972,307 @@ async function push({ refs, cwd, repoUrl }) {
|
|
|
754
972
|
});
|
|
755
973
|
}
|
|
756
974
|
|
|
975
|
+
// Copyright (c) 2025 coze-dev
|
|
976
|
+
// SPDX-License-Identifier: MIT
|
|
977
|
+
|
|
978
|
+
|
|
979
|
+
|
|
980
|
+
|
|
981
|
+
|
|
982
|
+
|
|
983
|
+
|
|
984
|
+
|
|
985
|
+
|
|
986
|
+
|
|
987
|
+
|
|
988
|
+
|
|
989
|
+
|
|
990
|
+
|
|
991
|
+
/**
|
|
992
|
+
* 获取或创建发布分支
|
|
993
|
+
*/
|
|
994
|
+
const getOrCreateBranch = async (params
|
|
995
|
+
|
|
996
|
+
|
|
997
|
+
|
|
998
|
+
|
|
999
|
+
) => {
|
|
1000
|
+
const { bumpPolicy, sessionId, branchPrefix, cwd } = params;
|
|
1001
|
+
|
|
1002
|
+
if (bumpPolicy === BumpType.BETA) {
|
|
1003
|
+
return await getCurrentBranchName();
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
const date = dayjs().format('YYYYMMDD');
|
|
1007
|
+
const branchName = `${branchPrefix}/${date}-${sessionId}`;
|
|
1008
|
+
await exec(`git checkout -b ${branchName}`, { cwd });
|
|
1009
|
+
return branchName;
|
|
1010
|
+
};
|
|
1011
|
+
|
|
1012
|
+
/**
|
|
1013
|
+
* 处理 Beta 发布流程:询问并执行 git push
|
|
1014
|
+
*/
|
|
1015
|
+
const handleBetaPublish = async (
|
|
1016
|
+
branchName,
|
|
1017
|
+
cwd,
|
|
1018
|
+
) => {
|
|
1019
|
+
logger.success(`Changes have been committed to branch "${branchName}".`);
|
|
1020
|
+
|
|
1021
|
+
const shouldPush = await prompts.confirm({
|
|
1022
|
+
message: 'Do you want to push the changes now?',
|
|
1023
|
+
default: true,
|
|
1024
|
+
});
|
|
1025
|
+
|
|
1026
|
+
if (shouldPush) {
|
|
1027
|
+
logger.info('Pushing changes to remote...');
|
|
1028
|
+
await exec('git push', { cwd });
|
|
1029
|
+
logger.success('Changes pushed successfully!');
|
|
1030
|
+
} else {
|
|
1031
|
+
logger.info('Please run "git push" manually when you are ready.');
|
|
1032
|
+
}
|
|
1033
|
+
};
|
|
1034
|
+
|
|
1035
|
+
/**
|
|
1036
|
+
* 显示手动创建 MR 的提示消息
|
|
1037
|
+
*/
|
|
1038
|
+
const showManualMrMessage = (
|
|
1039
|
+
branchName,
|
|
1040
|
+
repositoryUrl,
|
|
1041
|
+
) => {
|
|
1042
|
+
const baseMessage = `Please create a merge request from branch "${branchName}" to the main branch`;
|
|
1043
|
+
const suffix =
|
|
1044
|
+
'The release will be triggered after the merge request is merged.';
|
|
1045
|
+
|
|
1046
|
+
if (repositoryUrl) {
|
|
1047
|
+
logger.success(
|
|
1048
|
+
`Repository: ${repositoryUrl}\n${baseMessage}.\n${suffix}`,
|
|
1049
|
+
false,
|
|
1050
|
+
);
|
|
1051
|
+
} else {
|
|
1052
|
+
logger.success(`${baseMessage} in your repository.\n${suffix}`);
|
|
1053
|
+
}
|
|
1054
|
+
};
|
|
1055
|
+
|
|
1056
|
+
/**
|
|
1057
|
+
* 显示 MR/PR 创建链接并打开浏览器
|
|
1058
|
+
*/
|
|
1059
|
+
const showMrLinkAndOpenBrowser = async (mrUrl) => {
|
|
1060
|
+
const log = [
|
|
1061
|
+
'************************************************',
|
|
1062
|
+
'*',
|
|
1063
|
+
`* Please create MR/PR: ${mrUrl}`,
|
|
1064
|
+
'*',
|
|
1065
|
+
'* The release will be triggered after the MR is merged.',
|
|
1066
|
+
'*',
|
|
1067
|
+
'************************************************',
|
|
1068
|
+
];
|
|
1069
|
+
logger.success(log.join('\n'), false);
|
|
1070
|
+
|
|
1071
|
+
const open = await import('open');
|
|
1072
|
+
await open.default(mrUrl);
|
|
1073
|
+
};
|
|
1074
|
+
|
|
1075
|
+
/**
|
|
1076
|
+
* 处理正式版本发布流程:提示创建 MR/PR
|
|
1077
|
+
*/
|
|
1078
|
+
const handleProductionPublish = async (
|
|
1079
|
+
branchName,
|
|
1080
|
+
cwd,
|
|
1081
|
+
) => {
|
|
1082
|
+
const originUrl = await getCurrentOrigin(cwd);
|
|
1083
|
+
if (!originUrl) {
|
|
1084
|
+
showManualMrMessage(branchName);
|
|
1085
|
+
return;
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
const repoInfo = parseGitRemoteUrl(originUrl);
|
|
1089
|
+
if (!repoInfo) {
|
|
1090
|
+
showManualMrMessage(branchName);
|
|
1091
|
+
return;
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
const mrUrl = buildMergeRequestUrl(repoInfo, branchName);
|
|
1095
|
+
if (!mrUrl) {
|
|
1096
|
+
showManualMrMessage(branchName, repoInfo.fullUrl);
|
|
1097
|
+
return;
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
await showMrLinkAndOpenBrowser(mrUrl);
|
|
1101
|
+
};
|
|
1102
|
+
|
|
1103
|
+
/**
|
|
1104
|
+
* 根据发布类型处理后续提示
|
|
1105
|
+
*/
|
|
1106
|
+
const handlePostPushPrompts = async (
|
|
1107
|
+
bumpPolicy,
|
|
1108
|
+
branchName,
|
|
1109
|
+
cwd,
|
|
1110
|
+
) => {
|
|
1111
|
+
const isAlphaPublish = bumpPolicy === BumpType.ALPHA;
|
|
1112
|
+
const isBetaPublish = bumpPolicy === BumpType.BETA;
|
|
1113
|
+
|
|
1114
|
+
// Alpha 发布:不需要提示(会自动触发 CI 发布)
|
|
1115
|
+
if (isAlphaPublish) {
|
|
1116
|
+
return;
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
// Beta 发布:询问用户是否立即执行 git push
|
|
1120
|
+
if (isBetaPublish) {
|
|
1121
|
+
await handleBetaPublish(branchName, cwd);
|
|
1122
|
+
return;
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
// 正式版本发布:提示创建 MR/PR
|
|
1126
|
+
await handleProductionPublish(branchName, cwd);
|
|
1127
|
+
};
|
|
1128
|
+
|
|
757
1129
|
const pushToRemote = async (options) => {
|
|
758
1130
|
const {
|
|
759
1131
|
sessionId,
|
|
760
1132
|
changedFiles,
|
|
761
1133
|
cwd,
|
|
762
|
-
publishManifests,
|
|
763
1134
|
bumpPolicy,
|
|
764
1135
|
skipCommit,
|
|
765
1136
|
skipPush,
|
|
766
1137
|
repoUrl,
|
|
1138
|
+
branchPrefix = 'release',
|
|
767
1139
|
} = options;
|
|
1140
|
+
|
|
768
1141
|
if (skipCommit) {
|
|
769
1142
|
return;
|
|
770
1143
|
}
|
|
771
1144
|
|
|
772
|
-
//
|
|
773
|
-
const
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
}
|
|
779
|
-
const date = dayjs().format('YYYYMMDD');
|
|
780
|
-
branchName = `release/${date}-${sessionId}`;
|
|
781
|
-
await exec(`git checkout -b ${branchName}`, { cwd });
|
|
782
|
-
}
|
|
783
|
-
const isTestPublish = [BumpType.ALPHA, BumpType.BETA].includes(
|
|
784
|
-
bumpPolicy ,
|
|
785
|
-
);
|
|
1145
|
+
// 1. 获取或创建发布分支
|
|
1146
|
+
const branchName = await getOrCreateBranch({
|
|
1147
|
+
bumpPolicy,
|
|
1148
|
+
sessionId,
|
|
1149
|
+
branchPrefix,
|
|
1150
|
+
cwd,
|
|
1151
|
+
});
|
|
786
1152
|
|
|
787
|
-
//
|
|
1153
|
+
// 2. 提交变更
|
|
788
1154
|
const { effects } = await commitChanges({
|
|
789
|
-
sessionId,
|
|
790
1155
|
files: changedFiles,
|
|
791
1156
|
cwd,
|
|
792
|
-
publishManifests,
|
|
793
1157
|
branchName,
|
|
794
|
-
// 只有 alpha、beta 需要创建 tag,正式发布会在 .github/workflows/common-pr-checks.yml 创建并发布tag
|
|
795
|
-
createTags: isTestPublish,
|
|
796
1158
|
});
|
|
1159
|
+
|
|
797
1160
|
if (skipPush) {
|
|
798
1161
|
return;
|
|
799
1162
|
}
|
|
1163
|
+
|
|
1164
|
+
// 3. 推送变更
|
|
800
1165
|
await push({
|
|
801
1166
|
refs: effects,
|
|
802
1167
|
cwd,
|
|
803
|
-
repoUrl
|
|
1168
|
+
repoUrl,
|
|
804
1169
|
});
|
|
805
1170
|
|
|
806
|
-
//
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
throw new Error('Invalid git repository URL');
|
|
810
|
-
}
|
|
811
|
-
const repoOwner = repoInfoMatch[1];
|
|
812
|
-
const repoName = repoInfoMatch[2];
|
|
1171
|
+
// 4. 根据发布类型显示不同提示
|
|
1172
|
+
await handlePostPushPrompts(bumpPolicy, branchName, cwd);
|
|
1173
|
+
};
|
|
813
1174
|
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
1175
|
+
// Copyright (c) 2025 coze-dev
|
|
1176
|
+
// SPDX-License-Identifier: MIT
|
|
1177
|
+
|
|
1178
|
+
|
|
1179
|
+
const getRushConfiguration = (() => {
|
|
1180
|
+
const cachedRushConfigs = new Map();
|
|
1181
|
+
return (startingFolder) => {
|
|
1182
|
+
startingFolder = startingFolder || process.cwd();
|
|
1183
|
+
const possibleRushFile = rushSdk.RushConfiguration.tryFindRushJsonLocation({
|
|
1184
|
+
startingFolder,
|
|
1185
|
+
});
|
|
1186
|
+
if (!possibleRushFile) {
|
|
1187
|
+
throw new Error(
|
|
1188
|
+
`rush.json not found from starting folder: ${startingFolder}`,
|
|
1189
|
+
);
|
|
1190
|
+
}
|
|
1191
|
+
if (cachedRushConfigs.has(possibleRushFile)) {
|
|
1192
|
+
return cachedRushConfigs.get(possibleRushFile) ;
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1195
|
+
const rushConfig =
|
|
1196
|
+
rushSdk.RushConfiguration.loadFromConfigurationFile(possibleRushFile);
|
|
1197
|
+
cachedRushConfigs.set(startingFolder, rushConfig);
|
|
1198
|
+
return rushConfig;
|
|
1199
|
+
};
|
|
1200
|
+
})();
|
|
1201
|
+
|
|
1202
|
+
const lookupTo = (to) => {
|
|
1203
|
+
const cached = new Map();
|
|
1204
|
+
const config = getRushConfiguration();
|
|
1205
|
+
const core = (pkgName) => {
|
|
1206
|
+
if (cached.has(pkgName)) {
|
|
1207
|
+
return cached.get(pkgName);
|
|
1208
|
+
}
|
|
1209
|
+
const result = [pkgName];
|
|
1210
|
+
cached.set(pkgName, result);
|
|
1211
|
+
const projects = config.projects.filter(p => p.packageName === pkgName);
|
|
1212
|
+
if (projects.length === 0) {
|
|
1213
|
+
throw new Error(`Project ${pkgName} not found`);
|
|
1214
|
+
}
|
|
1215
|
+
const project = projects[0];
|
|
1216
|
+
const deps = Array.from(project.dependencyProjects.values()).map(
|
|
1217
|
+
p => p.packageName,
|
|
817
1218
|
);
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
1219
|
+
result.push(...deps);
|
|
1220
|
+
deps.forEach(dep => {
|
|
1221
|
+
const subPkgs = core(dep);
|
|
1222
|
+
if (subPkgs) {
|
|
1223
|
+
result.push(...subPkgs);
|
|
1224
|
+
}
|
|
1225
|
+
});
|
|
1226
|
+
return result;
|
|
1227
|
+
};
|
|
1228
|
+
const result = core(to);
|
|
1229
|
+
return [...new Set(result)];
|
|
1230
|
+
};
|
|
1231
|
+
|
|
1232
|
+
const lookupFrom = (from) => {
|
|
1233
|
+
const cached = new Map();
|
|
1234
|
+
const config = getRushConfiguration();
|
|
1235
|
+
const core = (pkgName) => {
|
|
1236
|
+
if (cached.has(pkgName)) {
|
|
1237
|
+
return cached.get(pkgName);
|
|
1238
|
+
}
|
|
1239
|
+
const result = new Set();
|
|
1240
|
+
cached.set(pkgName, result);
|
|
1241
|
+
const projects = config.projects.filter(p => p.packageName === pkgName);
|
|
1242
|
+
if (projects.length === 0) {
|
|
1243
|
+
throw new Error(`Project ${pkgName} not found`);
|
|
1244
|
+
}
|
|
1245
|
+
const project = projects[0];
|
|
1246
|
+
const deps = Array.from([
|
|
1247
|
+
...project.dependencyProjects.values(),
|
|
1248
|
+
...project.consumingProjects.values(),
|
|
1249
|
+
]).map(p => p.packageName);
|
|
1250
|
+
deps.forEach(dep => {
|
|
1251
|
+
result.add(dep);
|
|
1252
|
+
const subPkgs = cached.has(dep) ? cached.get(dep) : core(dep);
|
|
1253
|
+
if (subPkgs) {
|
|
1254
|
+
subPkgs.forEach(p => {
|
|
1255
|
+
result.add(p);
|
|
1256
|
+
});
|
|
1257
|
+
}
|
|
1258
|
+
});
|
|
1259
|
+
return result;
|
|
1260
|
+
};
|
|
1261
|
+
const result = core(from);
|
|
1262
|
+
return [...new Set(result)];
|
|
1263
|
+
};
|
|
1264
|
+
|
|
1265
|
+
const lookupOnly = (packageName) => {
|
|
1266
|
+
const config = getRushConfiguration();
|
|
1267
|
+
const projects = config.projects.filter(p => p.packageName === packageName);
|
|
1268
|
+
if (projects.length === 0) {
|
|
1269
|
+
throw new Error(`Project ${packageName} not found`);
|
|
830
1270
|
}
|
|
1271
|
+
return projects[0];
|
|
831
1272
|
};
|
|
832
1273
|
|
|
833
|
-
function _optionalChain$
|
|
1274
|
+
function _optionalChain$2(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
1275
|
+
|
|
834
1276
|
|
|
835
1277
|
|
|
836
1278
|
var RetrievePattern; (function (RetrievePattern) {
|
|
@@ -843,10 +1285,9 @@ const retrievePackages = (
|
|
|
843
1285
|
pattern,
|
|
844
1286
|
packages,
|
|
845
1287
|
) => {
|
|
846
|
-
const rushConfiguration = getRushConfiguration();
|
|
847
1288
|
const matchedPackages = new Set();
|
|
848
1289
|
packages.forEach(pkg => {
|
|
849
|
-
const project =
|
|
1290
|
+
const project = lookupOnly(pkg);
|
|
850
1291
|
if (!project) {
|
|
851
1292
|
throw new Error(`Package "${pkg}" not found in rush configuration`);
|
|
852
1293
|
}
|
|
@@ -858,16 +1299,15 @@ const retrievePackages = (
|
|
|
858
1299
|
const matched = [];
|
|
859
1300
|
switch (pattern) {
|
|
860
1301
|
case 'to': {
|
|
861
|
-
matched.push(
|
|
1302
|
+
matched.push(...lookupTo(pkg));
|
|
862
1303
|
break;
|
|
863
1304
|
}
|
|
864
1305
|
case 'from': {
|
|
865
|
-
matched.push(
|
|
866
|
-
matched.push(project.dependencyProjects);
|
|
1306
|
+
matched.push(...lookupFrom(pkg));
|
|
867
1307
|
break;
|
|
868
1308
|
}
|
|
869
1309
|
case 'only': {
|
|
870
|
-
|
|
1310
|
+
matched.push(pkg);
|
|
871
1311
|
break;
|
|
872
1312
|
}
|
|
873
1313
|
default: {
|
|
@@ -875,50 +1315,81 @@ const retrievePackages = (
|
|
|
875
1315
|
}
|
|
876
1316
|
}
|
|
877
1317
|
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
matchedPackages.add(p);
|
|
882
|
-
}
|
|
883
|
-
}
|
|
884
|
-
}
|
|
885
|
-
matchedPackages.add(project);
|
|
1318
|
+
matched.forEach(pkgName => {
|
|
1319
|
+
matchedPackages.add(pkgName);
|
|
1320
|
+
});
|
|
886
1321
|
});
|
|
887
|
-
|
|
1322
|
+
|
|
1323
|
+
return [...matchedPackages];
|
|
888
1324
|
};
|
|
889
1325
|
|
|
890
1326
|
const validateAndGetPackages = (options) => {
|
|
891
1327
|
const retrievePatterns = Object.values(RetrievePattern);
|
|
892
|
-
if (retrievePatterns.every(pattern => (_optionalChain$
|
|
1328
|
+
if (retrievePatterns.every(pattern => (_optionalChain$2([options, 'access', _ => _[pattern], 'optionalAccess', _2 => _2.length]) || 0) <= 0)) {
|
|
893
1329
|
throw new Error('No packages to publish');
|
|
894
1330
|
}
|
|
895
|
-
|
|
1331
|
+
const res = retrievePatterns.reduce((acc, pattern) => {
|
|
896
1332
|
const packages = options[pattern];
|
|
897
1333
|
if (!packages || packages.length <= 0) {
|
|
898
1334
|
return acc;
|
|
899
1335
|
}
|
|
900
1336
|
const placeholders = retrievePackages(pattern , packages);
|
|
901
|
-
|
|
1337
|
+
placeholders.forEach(pkgName => {
|
|
1338
|
+
acc.add(pkgName);
|
|
1339
|
+
});
|
|
1340
|
+
return acc;
|
|
902
1341
|
}, new Set());
|
|
1342
|
+
const result = [...res]
|
|
1343
|
+
.map(pkgName => {
|
|
1344
|
+
const p = lookupOnly(pkgName);
|
|
1345
|
+
if (p && p.shouldPublish) {
|
|
1346
|
+
return p;
|
|
1347
|
+
}
|
|
1348
|
+
return undefined;
|
|
1349
|
+
})
|
|
1350
|
+
.filter(Boolean) ;
|
|
1351
|
+
return result;
|
|
903
1352
|
};
|
|
904
1353
|
|
|
1354
|
+
function _optionalChain$1(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// Copyright (c) 2025 coze-dev
|
|
1355
|
+
|
|
1356
|
+
|
|
1357
|
+
|
|
1358
|
+
|
|
1359
|
+
|
|
1360
|
+
|
|
1361
|
+
|
|
1362
|
+
|
|
905
1363
|
const confirmForPublish = async (
|
|
906
1364
|
publishManifest,
|
|
907
1365
|
dryRun,
|
|
1366
|
+
options,
|
|
908
1367
|
) => {
|
|
909
|
-
|
|
1368
|
+
logger.info(chalk.gray('Will publish the following packages:'), false);
|
|
910
1369
|
publishManifest.forEach(manifest => {
|
|
911
|
-
const
|
|
912
|
-
|
|
1370
|
+
const versionChange = `${manifest.currentVersion} -> ${chalk.bold(manifest.newVersion)}`;
|
|
1371
|
+
const msg = `${manifest.project.packageName}: ${chalk.bgGreen(versionChange)}`;
|
|
1372
|
+
logger.info(`- ${msg}`, false);
|
|
913
1373
|
});
|
|
1374
|
+
|
|
1375
|
+
// Release 模式的额外提示
|
|
1376
|
+
if (_optionalChain$1([options, 'optionalAccess', _ => _.isReleaseMode])) {
|
|
1377
|
+
logger.info('', false);
|
|
1378
|
+
logger.warn(chalk.yellow.bold('⚠️ Release Mode Enabled:'), false);
|
|
1379
|
+
const registryMsg = ` Packages will be published directly to: ${chalk.bold(options.registry || 'default registry')}`;
|
|
1380
|
+
logger.warn(chalk.yellow(registryMsg), false);
|
|
1381
|
+
}
|
|
1382
|
+
|
|
914
1383
|
if (dryRun) {
|
|
915
1384
|
return false;
|
|
916
1385
|
}
|
|
917
1386
|
|
|
918
|
-
|
|
1387
|
+
logger.info('', false);
|
|
919
1388
|
try {
|
|
920
1389
|
const result = await prompts.confirm({
|
|
921
|
-
message: '
|
|
1390
|
+
message: _optionalChain$1([options, 'optionalAccess', _2 => _2.isReleaseMode])
|
|
1391
|
+
? 'Are you sure to publish directly?'
|
|
1392
|
+
: 'Are you sure to publish?',
|
|
922
1393
|
default: true,
|
|
923
1394
|
});
|
|
924
1395
|
return result;
|
|
@@ -927,7 +1398,8 @@ const confirmForPublish = async (
|
|
|
927
1398
|
}
|
|
928
1399
|
};
|
|
929
1400
|
|
|
930
|
-
function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
1401
|
+
function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// Copyright (c) 2025 coze-dev
|
|
1402
|
+
|
|
931
1403
|
|
|
932
1404
|
|
|
933
1405
|
|
|
@@ -1132,6 +1604,11 @@ const generateChangelog$1 = ({
|
|
|
1132
1604
|
};
|
|
1133
1605
|
};
|
|
1134
1606
|
|
|
1607
|
+
// Copyright (c) 2025 coze-dev
|
|
1608
|
+
// SPDX-License-Identifier: MIT
|
|
1609
|
+
|
|
1610
|
+
|
|
1611
|
+
|
|
1135
1612
|
const deleteFiles = async (files) => {
|
|
1136
1613
|
await Promise.all(
|
|
1137
1614
|
files.map(async file => {
|
|
@@ -1187,7 +1664,7 @@ const readPreviousChangelog = async (
|
|
|
1187
1664
|
|
|
1188
1665
|
const generateChangelogForProject = async (manifest) => {
|
|
1189
1666
|
const { project, newVersion } = manifest;
|
|
1190
|
-
const rushConfiguration = getRushConfiguration();
|
|
1667
|
+
const rushConfiguration = getRushConfiguration$1();
|
|
1191
1668
|
const { changesFolder } = rushConfiguration;
|
|
1192
1669
|
const changedFolderOfPkg = path.resolve(changesFolder, project.packageName);
|
|
1193
1670
|
const changelogJsonPath = path.resolve(
|
|
@@ -1229,6 +1706,12 @@ const generateChangelog = async (
|
|
|
1229
1706
|
return modifiedFiles.flat();
|
|
1230
1707
|
};
|
|
1231
1708
|
|
|
1709
|
+
// Copyright (c) 2025 coze-dev
|
|
1710
|
+
// SPDX-License-Identifier: MIT
|
|
1711
|
+
|
|
1712
|
+
|
|
1713
|
+
|
|
1714
|
+
|
|
1232
1715
|
const updatePackageVersion = async (
|
|
1233
1716
|
project,
|
|
1234
1717
|
newVersion,
|
|
@@ -1257,6 +1740,10 @@ const applyPublishManifest = async (
|
|
|
1257
1740
|
return modifiedFiles;
|
|
1258
1741
|
};
|
|
1259
1742
|
|
|
1743
|
+
// Copyright (c) 2025 coze-dev
|
|
1744
|
+
// SPDX-License-Identifier: MIT
|
|
1745
|
+
|
|
1746
|
+
|
|
1260
1747
|
// 针对不同类型的发布,对应不同 sideEffects:
|
|
1261
1748
|
// 1. alpha: 直接创建并push 分支,触发 CI,执行发布;
|
|
1262
1749
|
// 2. beta: 本分支直接切换版本号,并发布
|
|
@@ -1264,15 +1751,18 @@ const applyPublishManifest = async (
|
|
|
1264
1751
|
|
|
1265
1752
|
const publish = async (options) => {
|
|
1266
1753
|
const sessionId = randomHash(6);
|
|
1267
|
-
const rushConfiguration = getRushConfiguration();
|
|
1754
|
+
const rushConfiguration = getRushConfiguration$1();
|
|
1268
1755
|
const rushFolder = rushConfiguration.rushJsonFolder;
|
|
1269
|
-
if (
|
|
1756
|
+
if (
|
|
1757
|
+
process.env.SKIP_UNCOMMITTED_CHECK !== 'true' &&
|
|
1758
|
+
options.release !== true
|
|
1759
|
+
) {
|
|
1270
1760
|
await ensureNotUncommittedChanges();
|
|
1271
1761
|
}
|
|
1272
1762
|
|
|
1273
1763
|
// 1. 验证并获取需要发布的包列表
|
|
1274
1764
|
const packagesToPublish = validateAndGetPackages(options);
|
|
1275
|
-
if (packagesToPublish.
|
|
1765
|
+
if (packagesToPublish.length === 0) {
|
|
1276
1766
|
logger.error(
|
|
1277
1767
|
'No packages to publish, should specify some package by `--to` or `--from` or `--only`',
|
|
1278
1768
|
);
|
|
@@ -1291,7 +1781,11 @@ const publish = async (options) => {
|
|
|
1291
1781
|
const isBetaPublish = [BumpType.BETA, BumpType.ALPHA].includes(
|
|
1292
1782
|
bumpPolicy ,
|
|
1293
1783
|
);
|
|
1294
|
-
if (
|
|
1784
|
+
if (
|
|
1785
|
+
process.env.SKIP_BRANCH_CHECK !== 'true' &&
|
|
1786
|
+
isBetaPublish === false &&
|
|
1787
|
+
(await isMainBranch()) === false
|
|
1788
|
+
) {
|
|
1295
1789
|
// 只允许在主分支发布
|
|
1296
1790
|
logger.error(
|
|
1297
1791
|
'You are not in main branch, please switch to main branch and try again.',
|
|
@@ -1302,6 +1796,10 @@ const publish = async (options) => {
|
|
|
1302
1796
|
const continuePublish = await confirmForPublish(
|
|
1303
1797
|
publishManifests,
|
|
1304
1798
|
!!options.dryRun,
|
|
1799
|
+
{
|
|
1800
|
+
isReleaseMode: !!options.release,
|
|
1801
|
+
registry: options.registry || DEFAULT_NPM_REGISTRY,
|
|
1802
|
+
},
|
|
1305
1803
|
);
|
|
1306
1804
|
|
|
1307
1805
|
if (!continuePublish) {
|
|
@@ -1317,17 +1815,46 @@ const publish = async (options) => {
|
|
|
1317
1815
|
await Promise.all(postHandles.map(handle => handle(publishManifests)))
|
|
1318
1816
|
).flat();
|
|
1319
1817
|
|
|
1320
|
-
// 4. 创建并推送发布分支
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1818
|
+
// 4. 创建并推送发布分支 或 直接发布
|
|
1819
|
+
let shouldRelease = false;
|
|
1820
|
+
if (options.release) {
|
|
1821
|
+
// 验证 release 模式的前置条件
|
|
1822
|
+
if (isBetaPublish === false) {
|
|
1823
|
+
logger.error(
|
|
1824
|
+
'Direct release (--release) is only allowed for alpha or beta versions.',
|
|
1825
|
+
);
|
|
1826
|
+
logger.error(`Current bump type is: ${bumpPolicy}`);
|
|
1827
|
+
logger.warn('Falling back to normal publish mode...');
|
|
1828
|
+
} else {
|
|
1829
|
+
shouldRelease = true;
|
|
1830
|
+
}
|
|
1831
|
+
}
|
|
1832
|
+
|
|
1833
|
+
if (shouldRelease) {
|
|
1834
|
+
// Release 模式:直接发布
|
|
1835
|
+
logger.info('Running in direct release mode...');
|
|
1836
|
+
logger.info('Starting package release...');
|
|
1837
|
+
const registry = options.registry || DEFAULT_NPM_REGISTRY;
|
|
1838
|
+
// 将 PublishManifest[] 转换为 PackageToPublish[]
|
|
1839
|
+
const packages = publishManifests.map(manifest => ({
|
|
1840
|
+
packageName: manifest.project.packageName,
|
|
1841
|
+
version: manifest.newVersion,
|
|
1842
|
+
}));
|
|
1843
|
+
await release({ dryRun: !!options.dryRun, registry, packages });
|
|
1844
|
+
} else {
|
|
1845
|
+
// 普通模式:创建并推送发布分支
|
|
1846
|
+
await pushToRemote({
|
|
1847
|
+
bumpPolicy: bumpPolicy ,
|
|
1848
|
+
sessionId,
|
|
1849
|
+
changedFiles,
|
|
1850
|
+
cwd: rushFolder,
|
|
1851
|
+
skipCommit: !!options.skipCommit,
|
|
1852
|
+
skipPush: !!options.skipPush,
|
|
1853
|
+
repoUrl: options.repoUrl,
|
|
1854
|
+
branchPrefix: options.branchPrefix,
|
|
1855
|
+
});
|
|
1856
|
+
}
|
|
1857
|
+
|
|
1331
1858
|
logger.success('Publish success.');
|
|
1332
1859
|
};
|
|
1333
1860
|
|
|
@@ -1358,6 +1885,21 @@ const installAction$1 = (program) => {
|
|
|
1358
1885
|
'Git repository URL (e.g. git@github.com:coze-dev/coze-js.git)',
|
|
1359
1886
|
undefined,
|
|
1360
1887
|
)
|
|
1888
|
+
.option(
|
|
1889
|
+
'--branch-prefix <prefix>',
|
|
1890
|
+
`Git branch name prefix (default: ${DEFAULT_BRANCH_PREFIX})`,
|
|
1891
|
+
DEFAULT_BRANCH_PREFIX,
|
|
1892
|
+
)
|
|
1893
|
+
.option(
|
|
1894
|
+
'-l, --release',
|
|
1895
|
+
'Directly publish packages (only for alpha/beta versions)',
|
|
1896
|
+
false,
|
|
1897
|
+
)
|
|
1898
|
+
.option(
|
|
1899
|
+
'--registry <url>',
|
|
1900
|
+
`NPM registry URL (default: ${DEFAULT_NPM_REGISTRY})`,
|
|
1901
|
+
DEFAULT_NPM_REGISTRY,
|
|
1902
|
+
)
|
|
1361
1903
|
.action(async (options) => {
|
|
1362
1904
|
try {
|
|
1363
1905
|
const repoUrl = options.repoUrl || (await getCurrentOrigin());
|
|
@@ -1365,8 +1907,9 @@ const installAction$1 = (program) => {
|
|
|
1365
1907
|
throw new Error('Git repository URL is required');
|
|
1366
1908
|
}
|
|
1367
1909
|
if (!GIT_REPO_URL_REGEX.test(repoUrl)) {
|
|
1910
|
+
const expectedFormat = 'git@github.com:${org}/${repo}.git';
|
|
1368
1911
|
throw new Error(
|
|
1369
|
-
`Invalid git repository URL: ${repoUrl}, it should
|
|
1912
|
+
`Invalid git repository URL: ${repoUrl}, it should follow the format: ${expectedFormat}`,
|
|
1370
1913
|
);
|
|
1371
1914
|
}
|
|
1372
1915
|
const normalizeOptions = {
|
|
@@ -1381,6 +1924,10 @@ const installAction$1 = (program) => {
|
|
|
1381
1924
|
});
|
|
1382
1925
|
};
|
|
1383
1926
|
|
|
1927
|
+
// Copyright (c) 2025 coze-dev
|
|
1928
|
+
// SPDX-License-Identifier: MIT
|
|
1929
|
+
|
|
1930
|
+
|
|
1384
1931
|
const whoAmI = async () => {
|
|
1385
1932
|
const [name, email] = await Promise.all([
|
|
1386
1933
|
exec('git config user.name', { cwd: __dirname, silent: true }),
|
|
@@ -1392,6 +1939,10 @@ const whoAmI = async () => {
|
|
|
1392
1939
|
};
|
|
1393
1940
|
};
|
|
1394
1941
|
|
|
1942
|
+
// Copyright (c) 2025 coze-dev
|
|
1943
|
+
// SPDX-License-Identifier: MIT
|
|
1944
|
+
|
|
1945
|
+
|
|
1395
1946
|
// 这两个包没有 module 导出
|
|
1396
1947
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
1397
1948
|
const { sync } = require('conventional-commits-parser');
|
|
@@ -1408,7 +1959,7 @@ const collectShouldUpdateChangesProjects = async (
|
|
|
1408
1959
|
|
|
1409
1960
|
) => {
|
|
1410
1961
|
const changedFiles = await getChangedFilesFromCached();
|
|
1411
|
-
const rushConfiguration = getRushConfiguration();
|
|
1962
|
+
const rushConfiguration = getRushConfiguration$1();
|
|
1412
1963
|
const lookup = rushConfiguration.getProjectLookupForRoot(
|
|
1413
1964
|
rushConfiguration.rushJsonFolder,
|
|
1414
1965
|
);
|
|
@@ -1520,7 +2071,7 @@ async function generateAllChangesFile(
|
|
|
1520
2071
|
comment,
|
|
1521
2072
|
patchType,
|
|
1522
2073
|
) {
|
|
1523
|
-
const rushConfiguration = getRushConfiguration();
|
|
2074
|
+
const rushConfiguration = getRushConfiguration$1();
|
|
1524
2075
|
const needUpdateProjects = await collectShouldUpdateChangesProjects();
|
|
1525
2076
|
const { email } = await whoAmI();
|
|
1526
2077
|
|
|
@@ -1544,9 +2095,13 @@ async function generateAllChangesFile(
|
|
|
1544
2095
|
}
|
|
1545
2096
|
}
|
|
1546
2097
|
|
|
2098
|
+
// Copyright (c) 2025 coze-dev
|
|
2099
|
+
// SPDX-License-Identifier: MIT
|
|
2100
|
+
|
|
2101
|
+
|
|
1547
2102
|
const amendCommit = async () => {
|
|
1548
2103
|
const changedFiles = await getChangedFilesFromCached();
|
|
1549
|
-
const rushConfiguration = getRushConfiguration();
|
|
2104
|
+
const rushConfiguration = getRushConfiguration$1();
|
|
1550
2105
|
|
|
1551
2106
|
const relativeChangesFolder = path.relative(
|
|
1552
2107
|
rushConfiguration.rushJsonFolder,
|
|
@@ -1561,6 +2116,10 @@ const amendCommit = async () => {
|
|
|
1561
2116
|
}
|
|
1562
2117
|
};
|
|
1563
2118
|
|
|
2119
|
+
// Copyright (c) 2025 coze-dev
|
|
2120
|
+
// SPDX-License-Identifier: MIT
|
|
2121
|
+
|
|
2122
|
+
|
|
1564
2123
|
const generateChangeFiles = async (options) => {
|
|
1565
2124
|
// CI 环境的提交不做处理
|
|
1566
2125
|
if (options.ci || process.env.CI === 'true') {
|
|
@@ -1573,7 +2132,7 @@ const generateChangeFiles = async (options) => {
|
|
|
1573
2132
|
try {
|
|
1574
2133
|
let { commitMsg } = options;
|
|
1575
2134
|
if (!commitMsg) {
|
|
1576
|
-
const rushConfiguration = getRushConfiguration();
|
|
2135
|
+
const rushConfiguration = getRushConfiguration$1();
|
|
1577
2136
|
commitMsg = await fs.readFile(
|
|
1578
2137
|
path.resolve(rushConfiguration.rushJsonFolder, '.git/COMMIT_EDITMSG'),
|
|
1579
2138
|
'utf-8',
|
|
@@ -1606,6 +2165,10 @@ const installAction = (program) => {
|
|
|
1606
2165
|
});
|
|
1607
2166
|
};
|
|
1608
2167
|
|
|
2168
|
+
// Copyright (c) 2025 coze-dev
|
|
2169
|
+
// SPDX-License-Identifier: MIT
|
|
2170
|
+
|
|
2171
|
+
|
|
1609
2172
|
const main = () => {
|
|
1610
2173
|
const packageJson = JSON.parse(
|
|
1611
2174
|
fs$1.readFileSync(path.resolve(__dirname, '../package.json'), 'utf8'),
|