feat: 构建系统重构 + VCHSM 架构迁移 + 右键菜单修复 + 尺寸参数统一
## 构建、打包与分发系统重构 (build/) - 构建系统收敛至 build/ 目录:build.mjs + electron-builder.js + 6 个脚本 - electron-builder 配置从 package.json 提取为 build/electron-builder.js - 新增 --edition (personal/enterprise) 和 --channel (stable/beta/alpha) 参数 - OSS 路径按渠道隔离 - 新增 pre-build-check.mjs:Git/CHANGELOG/版本/环境变量校验 - 新增 bump-version.mjs:版本号管理 + CHANGELOG 自动生成 - updater.ts 发送 channel/edition/deviceFingerprint - 新增 src/shared/utils/rollout.ts 灰度测试工具 - 新增 10 条 NPM 脚本 ## VCHSM 五层架构迁移 - 7 个业务模块 + ~500 处导入路径同步 ## 修复 - MediaCardContextMenu 改用共享 ContextMenu 组件 - ComboBox 尺寸参数显示统一 (size-format.ts) ## 文档 - UpdateA.md / build/README.md / README.md / .env.example 更新 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
153
build/scripts/bump-version.mjs
Normal file
153
build/scripts/bump-version.mjs
Normal file
@@ -0,0 +1,153 @@
|
||||
// ============================================================
|
||||
// bump-version.mjs — 版本号管理与 CHANGELOG 模板生成
|
||||
//
|
||||
// 用法:
|
||||
// node build/scripts/bump-version.mjs <major|minor|patch> [--no-changelog]
|
||||
// node build/scripts/bump-version.mjs set <x.y.z>
|
||||
// node build/scripts/bump-version.mjs pre <beta|alpha>
|
||||
//
|
||||
// 示例:
|
||||
// node build/scripts/bump-version.mjs patch # 0.0.28 → 0.0.29
|
||||
// node build/scripts/bump-version.mjs minor # 0.0.28 → 0.1.0
|
||||
// node build/scripts/bump-version.mjs set 1.0.0 # 直接设置版本
|
||||
// node build/scripts/bump-version.mjs pre beta # 0.0.29 → 0.0.29-beta.1
|
||||
// ============================================================
|
||||
|
||||
import { readFileSync, writeFileSync } from 'node:fs';
|
||||
import { join, dirname } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
const ROOT = join(__dirname, '..', '..');
|
||||
|
||||
const args = process.argv.slice(2);
|
||||
const command = args[0];
|
||||
const arg1 = args[1];
|
||||
const noChangelog = args.includes('--no-changelog');
|
||||
|
||||
if (!command) {
|
||||
console.error('用法: node build/scripts/bump-version.mjs <major|minor|patch|set|pre> [value]');
|
||||
console.error('示例: node build/scripts/bump-version.mjs patch');
|
||||
console.error(' node build/scripts/bump-version.mjs set 1.0.0');
|
||||
console.error(' node build/scripts/bump-version.mjs pre beta');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const pkgPath = join(ROOT, 'package.json');
|
||||
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
||||
const oldVersion = pkg.version;
|
||||
|
||||
// ---------- 版本计算 ----------
|
||||
|
||||
function parseSemver(v) {
|
||||
const match = v.match(/^(\d+)\.(\d+)\.(\d+)(?:-(.+))?$/);
|
||||
if (!match) throw new Error(`无效的版本号格式: ${v}`);
|
||||
return {
|
||||
major: parseInt(match[1]),
|
||||
minor: parseInt(match[2]),
|
||||
patch: parseInt(match[3]),
|
||||
pre: match[4] || null,
|
||||
};
|
||||
}
|
||||
|
||||
let newVersion;
|
||||
|
||||
switch (command) {
|
||||
case 'major':
|
||||
case 'minor':
|
||||
case 'patch': {
|
||||
const sv = parseSemver(oldVersion);
|
||||
if (command === 'major') {
|
||||
sv.major++;
|
||||
sv.minor = 0;
|
||||
sv.patch = 0;
|
||||
} else if (command === 'minor') {
|
||||
sv.minor++;
|
||||
sv.patch = 0;
|
||||
} else {
|
||||
sv.patch++;
|
||||
}
|
||||
sv.pre = null;
|
||||
newVersion = `${sv.major}.${sv.minor}.${sv.patch}`;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'set': {
|
||||
if (!arg1) {
|
||||
console.error('用法: node build/scripts/bump-version.mjs set <x.y.z>');
|
||||
process.exit(1);
|
||||
}
|
||||
// 基本格式校验
|
||||
if (!/^\d+\.\d+\.\d+(-.+)?$/.test(arg1)) {
|
||||
console.error(`无效的版本号: ${arg1}`);
|
||||
process.exit(1);
|
||||
}
|
||||
newVersion = arg1;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'pre': {
|
||||
if (!arg1 || !['beta', 'alpha'].includes(arg1)) {
|
||||
console.error('用法: node build/scripts/bump-version.mjs pre <beta|alpha>');
|
||||
process.exit(1);
|
||||
}
|
||||
const sv = parseSemver(oldVersion);
|
||||
|
||||
// 如果当前版本已有预发布后缀,递增进位号
|
||||
if (sv.pre) {
|
||||
const match = sv.pre.match(new RegExp(`^${arg1}\\.(\\d+)$`));
|
||||
if (match) {
|
||||
const num = parseInt(match[1]) + 1;
|
||||
newVersion = `${sv.major}.${sv.minor}.${sv.patch}-${arg1}.${num}`;
|
||||
} else {
|
||||
// 不同预发布类型,重新开始
|
||||
newVersion = `${sv.major}.${sv.minor}.${sv.patch}-${arg1}.1`;
|
||||
}
|
||||
} else {
|
||||
// 纯 semver → 首次预发布:自动升 patch 再加后缀
|
||||
sv.patch++;
|
||||
newVersion = `${sv.major}.${sv.minor}.${sv.patch}-${arg1}.1`;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
console.error(`未知命令: ${command}。支持: major | minor | patch | set <ver> | pre <beta|alpha>`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// ---------- 更新 package.json ----------
|
||||
|
||||
pkg.version = newVersion;
|
||||
writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n', 'utf-8');
|
||||
console.log(`✅ package.json: ${oldVersion} → ${newVersion}`);
|
||||
|
||||
// ---------- 更新 shared/constants/version.ts(由 import pkg 动态读取,无需修改) ----------
|
||||
console.log(' shared/constants/version.ts 自动读取 package.json,无需手动同步');
|
||||
|
||||
// ---------- 更新 CHANGELOG.md ----------
|
||||
|
||||
if (!noChangelog) {
|
||||
const changelogPath = join(ROOT, 'CHANGELOG.md');
|
||||
try {
|
||||
let changelog = readFileSync(changelogPath, 'utf-8');
|
||||
|
||||
const today = new Date().toISOString().slice(0, 10);
|
||||
const entry = `## ${newVersion}(${today})\n\n**更新内容待补充**\n\n---\n\n`;
|
||||
|
||||
// 在第一个 ## 之前插入新版本条目
|
||||
const firstHeaderMatch = changelog.match(/^##\s/m);
|
||||
if (firstHeaderMatch) {
|
||||
const insertAt = firstHeaderMatch.index;
|
||||
changelog = changelog.slice(0, insertAt) + entry + changelog.slice(insertAt);
|
||||
writeFileSync(changelogPath, changelog, 'utf-8');
|
||||
console.log(`✅ CHANGELOG.md: 已添加 v${newVersion} 模板条目`);
|
||||
} else {
|
||||
console.warn('⚠️ CHANGELOG.md 格式异常,未找到 ## 版本标题');
|
||||
}
|
||||
} catch {
|
||||
console.warn('⚠️ CHANGELOG.md 不存在,跳过更新');
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`\n版本已更新: ${oldVersion} → ${newVersion}`);
|
||||
Reference in New Issue
Block a user