Skip to content

Commit c1a8b2c

Browse files
committed
fix(cli): 改进发布脚本的远程同步和分支校验逻辑
替换原有的 fetchTags 函数为 syncRemoteState,增加 checkReleaseBranchState 函数 以更安全地同步远程分支和标签,并校验当前分支与上游分支的状态,防止在 分支落后或分叉时进行发布。同时更新 pushToRemote 函数以推送当前分支。
1 parent c2fe9e5 commit c1a8b2c

1 file changed

Lines changed: 67 additions & 16 deletions

File tree

packages/cli/scripts/release.js

Lines changed: 67 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,68 @@ function checkWorkingDirectory() {
104104
console.log(chalk.green('✅ 工作目录干净'));
105105
}
106106

107+
function getCurrentBranch() {
108+
return exec('git branch --show-current', { allowInDryRun: true }) || 'HEAD';
109+
}
110+
111+
/**
112+
* 同步远程分支和 tags
113+
*/
114+
function syncRemoteState() {
115+
const branch = getCurrentBranch();
116+
117+
console.log(chalk.yellow('🔄 同步远程分支和 tags...'));
118+
try {
119+
exec(`git fetch origin ${branch} --tags`, { allowInDryRun: true });
120+
console.log(chalk.green(`✅ 已同步 origin/${branch} 和 tags`));
121+
} catch (error) {
122+
console.log(chalk.yellow('⚠️ 无法同步远程分支,回退为仅同步 tags'));
123+
exec('git fetch --tags', { allowInDryRun: true });
124+
console.log(chalk.green('✅ Tags 已同步'));
125+
}
126+
}
127+
128+
/**
129+
* 检查当前分支是否可安全发布
130+
*/
131+
function checkReleaseBranchState() {
132+
const branch = getCurrentBranch();
133+
const upstream = exec('git rev-parse --abbrev-ref --symbolic-full-name @{upstream}', {
134+
allowFailure: true,
135+
allowInDryRun: true,
136+
});
137+
138+
if (!upstream) {
139+
console.log(chalk.yellow(`⚠️ 当前分支 ${branch} 没有上游分支,跳过远端同步校验`));
140+
return;
141+
}
142+
143+
console.log(chalk.yellow(`🌿 校验分支同步状态 (${branch} vs ${upstream})...`));
144+
145+
const head = exec('git rev-parse HEAD', { allowInDryRun: true });
146+
const upstreamHead = exec(`git rev-parse ${upstream}`, { allowInDryRun: true });
147+
const mergeBase = exec(`git merge-base HEAD ${upstream}`, { allowInDryRun: true });
148+
149+
if (head === upstreamHead) {
150+
console.log(chalk.green('✅ 当前分支与上游一致'));
151+
return;
152+
}
153+
154+
if (mergeBase === head) {
155+
const message = `当前分支落后于 ${upstream}。请先执行 git pull --rebase origin ${branch},确认同步后再重新发布。`;
156+
console.log(chalk.red(`❌ ${message}`));
157+
throw new Error(message);
158+
}
159+
160+
if (mergeBase !== upstreamHead) {
161+
const message = `当前分支与 ${upstream} 已分叉。请先执行 git pull --rebase origin ${branch} 或手动整理提交后再发布。`;
162+
console.log(chalk.red(`❌ ${message}`));
163+
throw new Error(message);
164+
}
165+
166+
console.log(chalk.green('✅ 当前分支领先上游,可继续发布'));
167+
}
168+
107169
/**
108170
* 检查代码质量
109171
*/
@@ -128,19 +190,6 @@ function checkCodeQuality() {
128190
}
129191
}
130192

131-
/**
132-
* 同步远程 tags
133-
*/
134-
function fetchTags() {
135-
console.log(chalk.yellow('🔄 同步远程 tags...'));
136-
try {
137-
exec('git fetch --tags', { allowInDryRun: true });
138-
console.log(chalk.green('✅ Tags 已同步'));
139-
} catch (error) {
140-
console.log(chalk.yellow('⚠️ 无法同步远程 tags,使用本地 tags'));
141-
}
142-
}
143-
144193
/**
145194
* 获取最新的 git tags
146195
*/
@@ -490,11 +539,12 @@ function pushToRemote() {
490539
console.log(chalk.yellow('🚀 推送到远程仓库...'));
491540

492541
try {
542+
const branch = getCurrentBranch();
493543
if (config.publish?.gitConfig?.pushBranch !== false) {
494-
exec('git push', { cwd: monorepoRoot });
544+
exec(`git push origin ${branch}`, { cwd: monorepoRoot });
495545
}
496546
if (config.publish?.gitConfig?.pushTags !== false) {
497-
exec('git push --tags', { cwd: monorepoRoot });
547+
exec('git push origin --tags', { cwd: monorepoRoot });
498548
}
499549

500550
console.log(chalk.green('✅ 已推送到远程仓库'));
@@ -774,7 +824,8 @@ async function main() {
774824
try {
775825
preReleaseCheck();
776826
checkWorkingDirectory();
777-
fetchTags();
827+
syncRemoteState();
828+
checkReleaseBranchState();
778829
checkCodeQuality();
779830

780831
newVersion = await determineNewVersion();

0 commit comments

Comments
 (0)