## 构建、打包与分发系统重构 (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>
136 lines
5.1 KiB
JavaScript
136 lines
5.1 KiB
JavaScript
// ============================================================
|
||
// pre-build-check.mjs — 构建前校验
|
||
//
|
||
// 用法:
|
||
// node build/scripts/pre-build-check.mjs <platform> <version> <channel>
|
||
//
|
||
// 检查项:
|
||
// 1. Git 工作区是否干净(有未提交变更时警告,非阻断)
|
||
// 2. CHANGELOG.md 是否包含当前版本条目
|
||
// 3. package.json 版本号与传入版本号一致
|
||
// 4. 渠道版本号格式校验(beta/alpha 必须含预发布后缀)
|
||
// ============================================================
|
||
|
||
import { readFileSync } from 'node:fs';
|
||
import { join, dirname } from 'node:path';
|
||
import { fileURLToPath } from 'node:url';
|
||
import { execSync } from 'node:child_process';
|
||
|
||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||
const ROOT = join(__dirname, '..', '..');
|
||
|
||
const platform = process.argv[2];
|
||
const version = process.argv[3];
|
||
const channel = process.argv[4] || 'stable';
|
||
|
||
if (!platform || !version) {
|
||
console.error('用法: node build/scripts/pre-build-check.mjs <platform> <version> [channel]');
|
||
process.exit(1);
|
||
}
|
||
|
||
let hasError = false;
|
||
|
||
// ---------- 1. Git 工作区检查 ----------
|
||
|
||
console.log('▸ 检查 Git 工作区状态...');
|
||
try {
|
||
const status = execSync('git status --porcelain', { cwd: ROOT, encoding: 'utf-8' }).trim();
|
||
if (status) {
|
||
console.warn('⚠️ 警告: Git 工作区有未提交的变更:');
|
||
const lines = status.split('\n').slice(0, 10);
|
||
lines.forEach((l) => console.warn(` ${l}`));
|
||
if (status.split('\n').length > 10) {
|
||
console.warn(` ... 还有 ${status.split('\n').length - 10} 个文件`);
|
||
}
|
||
console.warn(' (不阻断构建,但建议先提交)\n');
|
||
} else {
|
||
console.log(' ✅ Git 工作区干净\n');
|
||
}
|
||
} catch {
|
||
console.warn(' ⚠️ 非 Git 环境,跳过工作区检查\n');
|
||
}
|
||
|
||
// ---------- 2. CHANGELOG 版本条目检查 ----------
|
||
|
||
console.log('▸ 检查 CHANGELOG.md 版本条目...');
|
||
const changelogPath = join(ROOT, 'CHANGELOG.md');
|
||
try {
|
||
const changelogContent = readFileSync(changelogPath, 'utf-8');
|
||
const versionPattern = new RegExp(
|
||
`^##\\s+${version.replace(/\./g, '\\.')}\\b`,
|
||
'm',
|
||
);
|
||
if (versionPattern.test(changelogContent)) {
|
||
console.log(` ✅ CHANGELOG.md 已包含 v${version} 条目\n`);
|
||
} else {
|
||
console.error(` ❌ CHANGELOG.md 中未找到 v${version} 的更新日志条目`);
|
||
console.error(` 请在 CHANGELOG.md 顶部添加: ## ${version}(日期)\n`);
|
||
hasError = true;
|
||
}
|
||
} catch {
|
||
console.warn(' ⚠️ CHANGELOG.md 不存在,跳过版本条目检查\n');
|
||
}
|
||
|
||
// ---------- 3. package.json 版本号一致性 ----------
|
||
|
||
console.log('▸ 检查 package.json 版本一致性...');
|
||
const pkg = JSON.parse(readFileSync(join(ROOT, 'package.json'), 'utf-8'));
|
||
if (pkg.version === version) {
|
||
console.log(` ✅ package.json 版本号一致: ${version}\n`);
|
||
} else {
|
||
console.error(` ❌ 版本号不一致: 传入 ${version},package.json 为 ${pkg.version}`);
|
||
console.error(' 请先执行: node build/scripts/bump-version.mjs <major|minor|patch>\n');
|
||
hasError = true;
|
||
}
|
||
|
||
// ---------- 4. 渠道版本号格式校验 ----------
|
||
|
||
console.log('▸ 检查渠道版本号格式...');
|
||
if (channel === 'stable') {
|
||
// stable 版本号必须是纯 semver(如 0.0.28)
|
||
if (/^\d+\.\d+\.\d+$/.test(version)) {
|
||
console.log(' ✅ Stable 渠道版本号格式正确\n');
|
||
} else {
|
||
console.error(` ❌ Stable 渠道版本号必须为纯 semver 格式 (x.y.z),当前: ${version}\n`);
|
||
hasError = true;
|
||
}
|
||
} else {
|
||
// beta/alpha 版本号必须含预发布后缀(如 0.0.29-beta.1)
|
||
if (/-/.test(version)) {
|
||
console.log(` ✅ ${channel} 渠道版本号含预发布后缀\n`);
|
||
} else {
|
||
console.warn(` ⚠️ ${channel} 渠道建议使用预发布版本号(如 ${version}-${channel}.1)`);
|
||
console.warn(' 当前版本号不含预发布后缀,可能覆盖 stable 版本的 OSS 文件\n');
|
||
}
|
||
}
|
||
|
||
// ---------- 5. 环境变量检查(仅 upload/publish 时有效,此处仅提示) ----------
|
||
|
||
console.log('▸ 环境变量就绪检查...');
|
||
const uploadVars = ['OSS_ENDPOINT', 'OSS_BUCKET', 'OSS_ACCESS_KEY_ID', 'OSS_ACCESS_KEY_SECRET'];
|
||
const missingUpload = uploadVars.filter((v) => !process.env[v]);
|
||
if (missingUpload.length > 0) {
|
||
console.warn(` ⚠️ OSS 相关环境变量未设置: ${missingUpload.join(', ')}`);
|
||
console.warn(' 如需上传 OSS,请配置这些环境变量(或在 .env.local 中设置)');
|
||
} else {
|
||
console.log(' ✅ OSS 环境变量已配置');
|
||
}
|
||
|
||
if (!process.env.UPDATE_API_KEY) {
|
||
console.warn(' ⚠️ UPDATE_API_KEY 未设置,发布到 API 可能失败');
|
||
} else {
|
||
console.log(' ✅ UPDATE_API_KEY 已配置');
|
||
}
|
||
console.log('');
|
||
|
||
// ---------- 结果 ----------
|
||
|
||
if (hasError) {
|
||
console.error('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
||
console.error('❌ 构建前校验未通过,请修复以上问题后重试');
|
||
console.error('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
||
process.exit(1);
|
||
}
|
||
|
||
console.log('✅ 构建前校验全部通过');
|