@zjex/git-workflow 0.0.1 → 0.1.0
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/README.md +220 -4
- package/dist/index.js +68 -35
- package/package.json +6 -3
- package/scripts/README.md +57 -0
- package/scripts/release.sh +363 -0
- package/scripts/version.js +138 -0
- package/scripts/version.sh +133 -0
- package/src/commands/branch.ts +123 -28
- package/src/commands/commit.ts +263 -0
- package/src/commands/help.ts +26 -17
- package/src/commands/init.ts +40 -0
- package/src/commands/tag.ts +66 -7
- package/src/config.ts +20 -0
- package/src/index.ts +140 -3
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
set -e
|
|
4
|
+
|
|
5
|
+
# 颜色定义
|
|
6
|
+
RED='\033[0;31m'
|
|
7
|
+
GREEN='\033[0;32m'
|
|
8
|
+
YELLOW='\033[1;33m'
|
|
9
|
+
BLUE='\033[0;34m'
|
|
10
|
+
CYAN='\033[0;36m'
|
|
11
|
+
NC='\033[0m' # No Color
|
|
12
|
+
|
|
13
|
+
# 打印带颜色的消息
|
|
14
|
+
print_info() {
|
|
15
|
+
echo -e "${BLUE}ℹ ${1}${NC}"
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
print_success() {
|
|
19
|
+
echo -e "${GREEN}✔ ${1}${NC}"
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
print_error() {
|
|
23
|
+
echo -e "${RED}✖ ${1}${NC}"
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
print_warning() {
|
|
27
|
+
echo -e "${YELLOW}⚠ ${1}${NC}"
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
print_step() {
|
|
31
|
+
echo -e "${CYAN}▶ ${1}${NC}"
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
# 错误处理
|
|
35
|
+
trap 'handle_error $? $LINENO' ERR
|
|
36
|
+
|
|
37
|
+
handle_error() {
|
|
38
|
+
print_error "发布失败 (退出码: $1, 行号: $2)"
|
|
39
|
+
|
|
40
|
+
if [[ -n "$NEW_VERSION" ]]; then
|
|
41
|
+
print_warning "正在回滚更改..."
|
|
42
|
+
|
|
43
|
+
# 回滚 package.json
|
|
44
|
+
if [[ -f "package.json.backup" ]]; then
|
|
45
|
+
mv package.json.backup package.json
|
|
46
|
+
print_info "已恢复 package.json"
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
# 删除本地 tag
|
|
50
|
+
if git tag -l "v${NEW_VERSION}" | grep -q "v${NEW_VERSION}"; then
|
|
51
|
+
git tag -d "v${NEW_VERSION}" 2>/dev/null || true
|
|
52
|
+
print_info "已删除本地 tag"
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
# 回滚 commit
|
|
56
|
+
if git log -1 --pretty=%B | grep -q "chore(release): v${NEW_VERSION}"; then
|
|
57
|
+
git reset --hard HEAD~1 2>/dev/null || true
|
|
58
|
+
print_info "已回滚 commit"
|
|
59
|
+
fi
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
exit 1
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
# 检查命令是否存在
|
|
66
|
+
check_command() {
|
|
67
|
+
if ! command -v "$1" &> /dev/null; then
|
|
68
|
+
print_error "未找到命令: $1"
|
|
69
|
+
exit 1
|
|
70
|
+
fi
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
# 检查必要的命令
|
|
74
|
+
check_command git
|
|
75
|
+
check_command node
|
|
76
|
+
check_command npm
|
|
77
|
+
|
|
78
|
+
# Dry-run 模式
|
|
79
|
+
DRY_RUN=false
|
|
80
|
+
if [[ "$1" == "--dry-run" ]]; then
|
|
81
|
+
DRY_RUN=true
|
|
82
|
+
print_warning "Dry-run 模式:仅预览,不会实际执行"
|
|
83
|
+
echo ""
|
|
84
|
+
fi
|
|
85
|
+
|
|
86
|
+
# 检查是否在 git 仓库中
|
|
87
|
+
if ! git rev-parse --git-dir > /dev/null 2>&1; then
|
|
88
|
+
print_error "当前目录不是 git 仓库"
|
|
89
|
+
exit 1
|
|
90
|
+
fi
|
|
91
|
+
|
|
92
|
+
# 检查是否有未提交的更改
|
|
93
|
+
if [[ -n $(git status --porcelain) ]]; then
|
|
94
|
+
print_error "有未提交的更改,请先提交或暂存"
|
|
95
|
+
git status --short
|
|
96
|
+
exit 1
|
|
97
|
+
fi
|
|
98
|
+
|
|
99
|
+
# 检查当前分支
|
|
100
|
+
CURRENT_BRANCH=$(git branch --show-current)
|
|
101
|
+
if [[ "$CURRENT_BRANCH" != "main" && "$CURRENT_BRANCH" != "master" ]]; then
|
|
102
|
+
print_warning "当前分支是 ${CURRENT_BRANCH},建议在 main/master 分支发布"
|
|
103
|
+
read -p "是否继续? (y/N) " -n 1 -r
|
|
104
|
+
echo
|
|
105
|
+
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
|
106
|
+
print_info "已取消"
|
|
107
|
+
exit 0
|
|
108
|
+
fi
|
|
109
|
+
fi
|
|
110
|
+
|
|
111
|
+
# 检查 npm 登录状态
|
|
112
|
+
print_step "检查 npm 登录状态..."
|
|
113
|
+
if ! npm whoami &> /dev/null; then
|
|
114
|
+
print_error "未登录 npm,请先执行: npm login"
|
|
115
|
+
exit 1
|
|
116
|
+
fi
|
|
117
|
+
NPM_USER=$(npm whoami)
|
|
118
|
+
print_success "已登录 npm (用户: ${NPM_USER})"
|
|
119
|
+
|
|
120
|
+
# 拉取最新代码
|
|
121
|
+
print_step "拉取最新代码..."
|
|
122
|
+
if [[ "$DRY_RUN" == false ]]; then
|
|
123
|
+
git pull origin "$CURRENT_BRANCH"
|
|
124
|
+
fi
|
|
125
|
+
print_success "代码已更新"
|
|
126
|
+
|
|
127
|
+
# 获取当前版本
|
|
128
|
+
CURRENT_VERSION=$(node -p "require('./package.json').version")
|
|
129
|
+
print_info "当前版本: ${CURRENT_VERSION}"
|
|
130
|
+
|
|
131
|
+
# 检查远程是否已存在该版本的 tag
|
|
132
|
+
check_tag_exists() {
|
|
133
|
+
local tag="v$1"
|
|
134
|
+
if git ls-remote --tags origin | grep -q "refs/tags/${tag}$"; then
|
|
135
|
+
return 0
|
|
136
|
+
else
|
|
137
|
+
return 1
|
|
138
|
+
fi
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
# 计算下一个版本号
|
|
142
|
+
calculate_next_version() {
|
|
143
|
+
local current=$1
|
|
144
|
+
local type=$2
|
|
145
|
+
|
|
146
|
+
IFS='.' read -r major minor patch <<< "$current"
|
|
147
|
+
|
|
148
|
+
case $type in
|
|
149
|
+
patch)
|
|
150
|
+
echo "${major}.${minor}.$((patch + 1))"
|
|
151
|
+
;;
|
|
152
|
+
minor)
|
|
153
|
+
echo "${major}.$((minor + 1)).0"
|
|
154
|
+
;;
|
|
155
|
+
major)
|
|
156
|
+
echo "$((major + 1)).0.0"
|
|
157
|
+
;;
|
|
158
|
+
esac
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
# 验证版本号格式
|
|
162
|
+
validate_version() {
|
|
163
|
+
if [[ ! $1 =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$ ]]; then
|
|
164
|
+
return 1
|
|
165
|
+
fi
|
|
166
|
+
return 0
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
# 选择版本类型
|
|
170
|
+
echo ""
|
|
171
|
+
print_step "选择新版本号"
|
|
172
|
+
echo ""
|
|
173
|
+
|
|
174
|
+
PATCH_VERSION=$(calculate_next_version "$CURRENT_VERSION" "patch")
|
|
175
|
+
MINOR_VERSION=$(calculate_next_version "$CURRENT_VERSION" "minor")
|
|
176
|
+
MAJOR_VERSION=$(calculate_next_version "$CURRENT_VERSION" "major")
|
|
177
|
+
|
|
178
|
+
echo -e " ${GREEN}1)${NC} patch ${CYAN}${CURRENT_VERSION}${NC} → ${GREEN}${PATCH_VERSION}${NC} (bug 修复)"
|
|
179
|
+
echo -e " ${GREEN}2)${NC} minor ${CYAN}${CURRENT_VERSION}${NC} → ${GREEN}${MINOR_VERSION}${NC} (新功能)"
|
|
180
|
+
echo -e " ${GREEN}3)${NC} major ${CYAN}${CURRENT_VERSION}${NC} → ${GREEN}${MAJOR_VERSION}${NC} (破坏性更新)"
|
|
181
|
+
echo -e " ${GREEN}4)${NC} custom (自定义版本号)"
|
|
182
|
+
echo -e " ${RED}5)${NC} cancel (取消发布)"
|
|
183
|
+
echo ""
|
|
184
|
+
|
|
185
|
+
while true; do
|
|
186
|
+
read -p "请选择 (1-5): " -n 1 -r VERSION_TYPE
|
|
187
|
+
echo ""
|
|
188
|
+
|
|
189
|
+
if [[ "$VERSION_TYPE" =~ ^[1-5]$ ]]; then
|
|
190
|
+
break
|
|
191
|
+
else
|
|
192
|
+
print_error "无效的选择,请输入 1-5"
|
|
193
|
+
fi
|
|
194
|
+
done
|
|
195
|
+
|
|
196
|
+
# 备份 package.json
|
|
197
|
+
cp package.json package.json.backup
|
|
198
|
+
|
|
199
|
+
case $VERSION_TYPE in
|
|
200
|
+
1)
|
|
201
|
+
NEW_VERSION=$PATCH_VERSION
|
|
202
|
+
;;
|
|
203
|
+
2)
|
|
204
|
+
NEW_VERSION=$MINOR_VERSION
|
|
205
|
+
;;
|
|
206
|
+
3)
|
|
207
|
+
NEW_VERSION=$MAJOR_VERSION
|
|
208
|
+
;;
|
|
209
|
+
4)
|
|
210
|
+
while true; do
|
|
211
|
+
read -p "请输入版本号 (如 1.0.0 或 1.0.0-beta.1): " CUSTOM_VERSION
|
|
212
|
+
|
|
213
|
+
if [[ -z "$CUSTOM_VERSION" ]]; then
|
|
214
|
+
print_error "版本号不能为空"
|
|
215
|
+
continue
|
|
216
|
+
fi
|
|
217
|
+
|
|
218
|
+
if ! validate_version "$CUSTOM_VERSION"; then
|
|
219
|
+
print_error "版本号格式无效,请使用语义化版本格式 (如 1.0.0 或 1.0.0-beta.1)"
|
|
220
|
+
continue
|
|
221
|
+
fi
|
|
222
|
+
|
|
223
|
+
NEW_VERSION=$CUSTOM_VERSION
|
|
224
|
+
break
|
|
225
|
+
done
|
|
226
|
+
;;
|
|
227
|
+
5)
|
|
228
|
+
rm package.json.backup
|
|
229
|
+
print_info "已取消发布"
|
|
230
|
+
exit 0
|
|
231
|
+
;;
|
|
232
|
+
esac
|
|
233
|
+
|
|
234
|
+
# 更新 package.json 中的版本号
|
|
235
|
+
if [[ "$DRY_RUN" == false ]]; then
|
|
236
|
+
npm version "$NEW_VERSION" --no-git-tag-version > /dev/null 2>&1 || {
|
|
237
|
+
print_error "更新版本号失败"
|
|
238
|
+
mv package.json.backup package.json
|
|
239
|
+
exit 1
|
|
240
|
+
}
|
|
241
|
+
fi
|
|
242
|
+
|
|
243
|
+
print_success "版本号已更新: ${CURRENT_VERSION} → ${NEW_VERSION}"
|
|
244
|
+
|
|
245
|
+
# 检查版本号是否已存在
|
|
246
|
+
if check_tag_exists "$NEW_VERSION"; then
|
|
247
|
+
print_error "版本 v${NEW_VERSION} 已存在于远程仓库"
|
|
248
|
+
mv package.json.backup package.json
|
|
249
|
+
exit 1
|
|
250
|
+
fi
|
|
251
|
+
|
|
252
|
+
# 运行测试(如果有)
|
|
253
|
+
if grep -q '"test"' package.json; then
|
|
254
|
+
print_step "运行测试..."
|
|
255
|
+
if [[ "$DRY_RUN" == false ]]; then
|
|
256
|
+
npm test || {
|
|
257
|
+
print_error "测试失败"
|
|
258
|
+
mv package.json.backup package.json
|
|
259
|
+
exit 1
|
|
260
|
+
}
|
|
261
|
+
fi
|
|
262
|
+
print_success "测试通过"
|
|
263
|
+
fi
|
|
264
|
+
|
|
265
|
+
# 构建项目
|
|
266
|
+
print_step "构建项目..."
|
|
267
|
+
if [[ "$DRY_RUN" == false ]]; then
|
|
268
|
+
npm run build
|
|
269
|
+
fi
|
|
270
|
+
print_success "构建完成"
|
|
271
|
+
|
|
272
|
+
# 检查构建产物
|
|
273
|
+
if [[ "$DRY_RUN" == false ]]; then
|
|
274
|
+
if [[ ! -f "dist/index.js" ]]; then
|
|
275
|
+
print_error "构建产物不存在: dist/index.js"
|
|
276
|
+
mv package.json.backup package.json
|
|
277
|
+
exit 1
|
|
278
|
+
fi
|
|
279
|
+
print_success "构建产物验证通过"
|
|
280
|
+
fi
|
|
281
|
+
|
|
282
|
+
# 生成 changelog
|
|
283
|
+
print_step "生成 CHANGELOG..."
|
|
284
|
+
if [[ "$DRY_RUN" == false ]]; then
|
|
285
|
+
npm run changelog
|
|
286
|
+
fi
|
|
287
|
+
print_success "CHANGELOG 已更新"
|
|
288
|
+
|
|
289
|
+
# 预览 changelog
|
|
290
|
+
if [[ "$DRY_RUN" == false ]]; then
|
|
291
|
+
echo ""
|
|
292
|
+
print_info "最新的 CHANGELOG 内容:"
|
|
293
|
+
echo "----------------------------------------"
|
|
294
|
+
head -n 30 CHANGELOG.md
|
|
295
|
+
echo "----------------------------------------"
|
|
296
|
+
echo ""
|
|
297
|
+
read -p "是否继续发布? (y/N) " -n 1 -r
|
|
298
|
+
echo
|
|
299
|
+
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
|
300
|
+
print_info "已取消"
|
|
301
|
+
mv package.json.backup package.json
|
|
302
|
+
exit 0
|
|
303
|
+
fi
|
|
304
|
+
fi
|
|
305
|
+
|
|
306
|
+
# 删除备份
|
|
307
|
+
rm package.json.backup
|
|
308
|
+
|
|
309
|
+
if [[ "$DRY_RUN" == true ]]; then
|
|
310
|
+
echo ""
|
|
311
|
+
print_success "Dry-run 完成!以下是将要执行的操作:"
|
|
312
|
+
echo ""
|
|
313
|
+
echo " 1. 提交更改: package.json, package-lock.json, CHANGELOG.md"
|
|
314
|
+
echo " 2. Commit 信息: 🔖 chore(release): v${NEW_VERSION}"
|
|
315
|
+
echo " 3. 创建 tag: v${NEW_VERSION}"
|
|
316
|
+
echo " 4. 推送到 GitHub: ${CURRENT_BRANCH} + v${NEW_VERSION}"
|
|
317
|
+
echo " 5. 发布到 npm: @zjex/git-workflow@${NEW_VERSION}"
|
|
318
|
+
echo ""
|
|
319
|
+
print_info "执行 'npm run release' 进行实际发布"
|
|
320
|
+
exit 0
|
|
321
|
+
fi
|
|
322
|
+
|
|
323
|
+
# 最终确认
|
|
324
|
+
echo ""
|
|
325
|
+
print_warning "即将发布版本 v${NEW_VERSION} 到 npm 和 GitHub"
|
|
326
|
+
read -p "确认发布? (y/N) " -n 1 -r
|
|
327
|
+
echo
|
|
328
|
+
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
|
329
|
+
print_info "已取消"
|
|
330
|
+
exit 0
|
|
331
|
+
fi
|
|
332
|
+
|
|
333
|
+
# 提交更改
|
|
334
|
+
print_step "提交更改..."
|
|
335
|
+
git add package.json package-lock.json CHANGELOG.md
|
|
336
|
+
git commit -m "🔖 chore(release): v${NEW_VERSION}"
|
|
337
|
+
print_success "更改已提交"
|
|
338
|
+
|
|
339
|
+
# 创建 tag
|
|
340
|
+
print_step "创建 tag: v${NEW_VERSION}..."
|
|
341
|
+
git tag -a "v${NEW_VERSION}" -m "Release v${NEW_VERSION}"
|
|
342
|
+
print_success "Tag 已创建"
|
|
343
|
+
|
|
344
|
+
# 推送到 GitHub
|
|
345
|
+
print_step "推送到 GitHub..."
|
|
346
|
+
git push origin "$CURRENT_BRANCH"
|
|
347
|
+
git push origin "v${NEW_VERSION}"
|
|
348
|
+
print_success "已推送到 GitHub"
|
|
349
|
+
|
|
350
|
+
# 发布到 npm
|
|
351
|
+
print_step "发布到 npm..."
|
|
352
|
+
npm publish
|
|
353
|
+
print_success "已发布到 npm"
|
|
354
|
+
|
|
355
|
+
echo ""
|
|
356
|
+
print_success "🎉 发布成功!"
|
|
357
|
+
echo ""
|
|
358
|
+
echo "版本: v${NEW_VERSION}"
|
|
359
|
+
echo "GitHub: https://github.com/iamzjt-front-end/git-workflow/releases/tag/v${NEW_VERSION}"
|
|
360
|
+
echo "npm: https://www.npmjs.com/package/@zjex/git-workflow/v/${NEW_VERSION}"
|
|
361
|
+
echo ""
|
|
362
|
+
print_info "提示: 可以在 GitHub 上创建 Release 并添加发布说明"
|
|
363
|
+
echo " https://github.com/iamzjt-front-end/git-workflow/releases/new?tag=v${NEW_VERSION}"
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { select, input } from "@inquirer/prompts";
|
|
4
|
+
import { readFileSync, writeFileSync } from "fs";
|
|
5
|
+
import { fileURLToPath } from "url";
|
|
6
|
+
import { dirname, join } from "path";
|
|
7
|
+
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
+
const __dirname = dirname(__filename);
|
|
10
|
+
|
|
11
|
+
// 颜色定义
|
|
12
|
+
const colors = {
|
|
13
|
+
reset: "\x1b[0m",
|
|
14
|
+
green: "\x1b[32m",
|
|
15
|
+
cyan: "\x1b[36m",
|
|
16
|
+
yellow: "\x1b[33m",
|
|
17
|
+
red: "\x1b[31m",
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const log = {
|
|
21
|
+
info: (msg) => console.log(`${colors.cyan}ℹ ${msg}${colors.reset}`),
|
|
22
|
+
success: (msg) => console.log(`${colors.green}✔ ${msg}${colors.reset}`),
|
|
23
|
+
error: (msg) => console.log(`${colors.red}✖ ${msg}${colors.reset}`),
|
|
24
|
+
warning: (msg) => console.log(`${colors.yellow}⚠ ${msg}${colors.reset}`),
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
// 读取 package.json
|
|
28
|
+
const packagePath = join(__dirname, "../package.json");
|
|
29
|
+
const packageJson = JSON.parse(readFileSync(packagePath, "utf-8"));
|
|
30
|
+
const currentVersion = packageJson.version;
|
|
31
|
+
|
|
32
|
+
// 计算下一个版本号
|
|
33
|
+
function calculateNextVersion(current, type) {
|
|
34
|
+
const [major, minor, patch] = current.split(".").map(Number);
|
|
35
|
+
|
|
36
|
+
switch (type) {
|
|
37
|
+
case "patch":
|
|
38
|
+
return `${major}.${minor}.${patch + 1}`;
|
|
39
|
+
case "minor":
|
|
40
|
+
return `${major}.${minor + 1}.0`;
|
|
41
|
+
case "major":
|
|
42
|
+
return `${major + 1}.0.0`;
|
|
43
|
+
default:
|
|
44
|
+
return current;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// 验证版本号格式
|
|
49
|
+
function validateVersion(version) {
|
|
50
|
+
const semverRegex =
|
|
51
|
+
/^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$/;
|
|
52
|
+
return semverRegex.test(version);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async function main() {
|
|
56
|
+
console.log("");
|
|
57
|
+
log.info(`当前版本: ${colors.cyan}${currentVersion}${colors.reset}`);
|
|
58
|
+
console.log("");
|
|
59
|
+
|
|
60
|
+
const patchVersion = calculateNextVersion(currentVersion, "patch");
|
|
61
|
+
const minorVersion = calculateNextVersion(currentVersion, "minor");
|
|
62
|
+
const majorVersion = calculateNextVersion(currentVersion, "major");
|
|
63
|
+
|
|
64
|
+
const choices = [
|
|
65
|
+
{
|
|
66
|
+
name: `patch ${currentVersion} → ${patchVersion} (bug 修复)`,
|
|
67
|
+
value: { type: "patch", version: patchVersion },
|
|
68
|
+
description: "向后兼容的 bug 修复",
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
name: `minor ${currentVersion} → ${minorVersion} (新功能)`,
|
|
72
|
+
value: { type: "minor", version: minorVersion },
|
|
73
|
+
description: "向后兼容的新功能",
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
name: `major ${currentVersion} → ${majorVersion} (破坏性更新)`,
|
|
77
|
+
value: { type: "major", version: majorVersion },
|
|
78
|
+
description: "不向后兼容的重大更改",
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
name: "custom (自定义版本号)",
|
|
82
|
+
value: { type: "custom", version: null },
|
|
83
|
+
description: "输入自定义版本号",
|
|
84
|
+
},
|
|
85
|
+
];
|
|
86
|
+
|
|
87
|
+
try {
|
|
88
|
+
const answer = await select({
|
|
89
|
+
message: "选择新版本号:",
|
|
90
|
+
choices,
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
let newVersion = answer.version;
|
|
94
|
+
|
|
95
|
+
// 如果选择自定义版本号
|
|
96
|
+
if (answer.type === "custom") {
|
|
97
|
+
newVersion = await input({
|
|
98
|
+
message: "请输入版本号:",
|
|
99
|
+
default: currentVersion,
|
|
100
|
+
validate: (value) => {
|
|
101
|
+
if (!value) {
|
|
102
|
+
return "版本号不能为空";
|
|
103
|
+
}
|
|
104
|
+
if (!validateVersion(value)) {
|
|
105
|
+
return "版本号格式无效,请使用语义化版本格式 (如 1.0.0 或 1.0.0-beta.1)";
|
|
106
|
+
}
|
|
107
|
+
return true;
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// 更新 package.json
|
|
113
|
+
console.log("");
|
|
114
|
+
log.info(`正在更新版本号到 ${newVersion}...`);
|
|
115
|
+
|
|
116
|
+
packageJson.version = newVersion;
|
|
117
|
+
writeFileSync(
|
|
118
|
+
packagePath,
|
|
119
|
+
JSON.stringify(packageJson, null, "\t") + "\n",
|
|
120
|
+
"utf-8"
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
log.success(`版本号已更新: ${currentVersion} → ${newVersion}`);
|
|
124
|
+
console.log("");
|
|
125
|
+
|
|
126
|
+
process.exit(0);
|
|
127
|
+
} catch (error) {
|
|
128
|
+
if (error.name === "ExitPromptError") {
|
|
129
|
+
console.log("");
|
|
130
|
+
log.info("已取消");
|
|
131
|
+
process.exit(0);
|
|
132
|
+
}
|
|
133
|
+
log.error(`发生错误: ${error.message}`);
|
|
134
|
+
process.exit(1);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
main();
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
set -e
|
|
4
|
+
|
|
5
|
+
# 颜色定义
|
|
6
|
+
RED='\033[0;31m'
|
|
7
|
+
GREEN='\033[0;32m'
|
|
8
|
+
YELLOW='\033[1;33m'
|
|
9
|
+
CYAN='\033[0;36m'
|
|
10
|
+
NC='\033[0m' # No Color
|
|
11
|
+
|
|
12
|
+
# 打印带颜色的消息
|
|
13
|
+
print_info() {
|
|
14
|
+
echo -e "${CYAN}ℹ ${1}${NC}"
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
print_success() {
|
|
18
|
+
echo -e "${GREEN}✔ ${1}${NC}"
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
print_error() {
|
|
22
|
+
echo -e "${RED}✖ ${1}${NC}"
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
# 获取当前版本
|
|
26
|
+
CURRENT_VERSION=$(node -p "require('./package.json').version")
|
|
27
|
+
|
|
28
|
+
# 计算下一个版本号
|
|
29
|
+
calculate_next_version() {
|
|
30
|
+
local current=$1
|
|
31
|
+
local type=$2
|
|
32
|
+
|
|
33
|
+
IFS='.' read -r major minor patch <<< "$current"
|
|
34
|
+
|
|
35
|
+
case $type in
|
|
36
|
+
patch)
|
|
37
|
+
echo "${major}.${minor}.$((patch + 1))"
|
|
38
|
+
;;
|
|
39
|
+
minor)
|
|
40
|
+
echo "${major}.$((minor + 1)).0"
|
|
41
|
+
;;
|
|
42
|
+
major)
|
|
43
|
+
echo "$((major + 1)).0.0"
|
|
44
|
+
;;
|
|
45
|
+
esac
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
# 验证版本号格式
|
|
49
|
+
validate_version() {
|
|
50
|
+
if [[ ! $1 =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$ ]]; then
|
|
51
|
+
return 1
|
|
52
|
+
fi
|
|
53
|
+
return 0
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
# 显示当前版本
|
|
57
|
+
echo ""
|
|
58
|
+
print_info "当前版本: ${CURRENT_VERSION}"
|
|
59
|
+
echo ""
|
|
60
|
+
|
|
61
|
+
# 计算版本选项
|
|
62
|
+
PATCH_VERSION=$(calculate_next_version "$CURRENT_VERSION" "patch")
|
|
63
|
+
MINOR_VERSION=$(calculate_next_version "$CURRENT_VERSION" "minor")
|
|
64
|
+
MAJOR_VERSION=$(calculate_next_version "$CURRENT_VERSION" "major")
|
|
65
|
+
|
|
66
|
+
# 显示选项
|
|
67
|
+
echo "选择新版本号:"
|
|
68
|
+
echo ""
|
|
69
|
+
echo -e " ${GREEN}1)${NC} patch ${CYAN}${CURRENT_VERSION}${NC} → ${GREEN}${PATCH_VERSION}${NC} (bug 修复)"
|
|
70
|
+
echo -e " ${GREEN}2)${NC} minor ${CYAN}${CURRENT_VERSION}${NC} → ${GREEN}${MINOR_VERSION}${NC} (新功能)"
|
|
71
|
+
echo -e " ${GREEN}3)${NC} major ${CYAN}${CURRENT_VERSION}${NC} → ${GREEN}${MAJOR_VERSION}${NC} (破坏性更新)"
|
|
72
|
+
echo -e " ${GREEN}4)${NC} custom (自定义版本号)"
|
|
73
|
+
echo -e " ${RED}5)${NC} cancel (取消)"
|
|
74
|
+
echo ""
|
|
75
|
+
|
|
76
|
+
# 读取用户选择
|
|
77
|
+
while true; do
|
|
78
|
+
read -p "请选择 (1-5): " -n 1 -r VERSION_TYPE
|
|
79
|
+
echo ""
|
|
80
|
+
|
|
81
|
+
if [[ "$VERSION_TYPE" =~ ^[1-5]$ ]]; then
|
|
82
|
+
break
|
|
83
|
+
else
|
|
84
|
+
print_error "无效的选择,请输入 1-5"
|
|
85
|
+
fi
|
|
86
|
+
done
|
|
87
|
+
|
|
88
|
+
# 处理选择
|
|
89
|
+
case $VERSION_TYPE in
|
|
90
|
+
1)
|
|
91
|
+
NEW_VERSION=$PATCH_VERSION
|
|
92
|
+
;;
|
|
93
|
+
2)
|
|
94
|
+
NEW_VERSION=$MINOR_VERSION
|
|
95
|
+
;;
|
|
96
|
+
3)
|
|
97
|
+
NEW_VERSION=$MAJOR_VERSION
|
|
98
|
+
;;
|
|
99
|
+
4)
|
|
100
|
+
while true; do
|
|
101
|
+
read -p "请输入版本号 (如 1.0.0 或 1.0.0-beta.1): " CUSTOM_VERSION
|
|
102
|
+
|
|
103
|
+
if [[ -z "$CUSTOM_VERSION" ]]; then
|
|
104
|
+
print_error "版本号不能为空"
|
|
105
|
+
continue
|
|
106
|
+
fi
|
|
107
|
+
|
|
108
|
+
if ! validate_version "$CUSTOM_VERSION"; then
|
|
109
|
+
print_error "版本号格式无效,请使用语义化版本格式 (如 1.0.0 或 1.0.0-beta.1)"
|
|
110
|
+
continue
|
|
111
|
+
fi
|
|
112
|
+
|
|
113
|
+
NEW_VERSION=$CUSTOM_VERSION
|
|
114
|
+
break
|
|
115
|
+
done
|
|
116
|
+
;;
|
|
117
|
+
5)
|
|
118
|
+
print_info "已取消"
|
|
119
|
+
exit 0
|
|
120
|
+
;;
|
|
121
|
+
esac
|
|
122
|
+
|
|
123
|
+
# 更新版本号
|
|
124
|
+
echo ""
|
|
125
|
+
print_info "正在更新版本号到 ${NEW_VERSION}..."
|
|
126
|
+
|
|
127
|
+
npm version "$NEW_VERSION" --no-git-tag-version > /dev/null 2>&1 || {
|
|
128
|
+
print_error "更新版本号失败"
|
|
129
|
+
exit 1
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
print_success "版本号已更新: ${CURRENT_VERSION} → ${NEW_VERSION}"
|
|
133
|
+
echo ""
|