chore(V0.2): 统一 APK 与 OTA 版本规则 —— 同一版本号, APK 裸写 / OTA 加 -ota
Docker Build and Push / build-image (push) Successful in 10m16s
Docker Build and Push / build-image (push) Successful in 10m16s
- readme: 版本管理章节重写, 明确 APK=0.2.0 无后缀, OTA=0.2.0-ota 多一个标记 并补充 APK versionName/versionCode 的生成链路 (tauri.properties, major*1e6+minor*1e3+patch) - scripts/ci/check-version.mjs: 新增四处一致性校验 (package.json / tauri.conf.json / Cargo.toml / Cargo.lock), 并禁止 version 带 -ota - android-build.yml: 构建前也执行版本校验 (tauri.conf.json 的 version 就是 APK versionName) - 需求文档 F-OT-01a、设计文档 §10.2 同步该规则
This commit is contained in:
@@ -1,15 +1,20 @@
|
||||
#!/usr/bin/env node
|
||||
// CI 专用: 校验分支名与 package.json 版本号一致
|
||||
// CI 专用: 校验版本号四处一致 + 与分支名一致
|
||||
//
|
||||
// 背景:
|
||||
// OTA 升级包的 version 直接取自 package.json (`<version>-ota`), 而分支按版本命名
|
||||
// (dev-0.1 / dev-0.2 ...). 两者一旦错位 (例如 dev-0.2 上 package.json 还是 0.1.0),
|
||||
// 线上 OTA 就会报成上一个版本的号, 客户端判新逻辑全部失准。
|
||||
// 版本号只允许一个手工管理点 = package.json 的 version, 其余位置全部派生:
|
||||
// - APK / 桌面安装包 version = <version> (裸版本号, 无后缀)
|
||||
// - OTA 热更包 version = <version>-ota (多一个 -ota 标记)
|
||||
// - 前端运行时 APP_VERSION = <version>
|
||||
// 任何一处漏改都会让线上版本号、APK 版本、OTA 判新三者对不上, 且很难在客户端发现。
|
||||
//
|
||||
// 规则:
|
||||
// - 分支形如 dev-<major>.<minor> → package.json 的 version 必须以 <major>.<minor> 开头
|
||||
// - 分支形如 dev-<major> → version 必须以 <major>. 开头
|
||||
// - main / master 及其它分支 → 跳过校验 (生产分支不做约束, 只打印当前版本)
|
||||
// 校验分两段:
|
||||
// A. 一致性 (任何分支都查): package.json ↔ tauri.conf.json ↔ Cargo.toml ↔ Cargo.lock
|
||||
// 并要求 package.json 的 version 不含 "-ota" (裸版本, OTA 后缀由打包脚本追加)
|
||||
// B. 分支对应 (仅 dev-<版本> 分支):
|
||||
// dev-<major>.<minor> → version 必须以 <major>.<minor> 开头
|
||||
// dev-<major> → version 必须以 <major>. 开头
|
||||
// main / master / 其它 → 跳过
|
||||
//
|
||||
// 环境变量:
|
||||
// GITHUB_REF_NAME - Gitea Actions 提供的分支名 (本地运行可用 BRANCH 覆盖)
|
||||
@@ -23,27 +28,88 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
||||
const ROOT = path.resolve(__dirname, '..', '..')
|
||||
|
||||
const branch = process.env.GITHUB_REF_NAME || process.env.BRANCH || ''
|
||||
const pkg = JSON.parse(fs.readFileSync(path.join(ROOT, 'package.json'), 'utf8'))
|
||||
const version = String(pkg.version || '0.0.0')
|
||||
|
||||
function readJson(rel) {
|
||||
return JSON.parse(fs.readFileSync(path.join(ROOT, rel), 'utf8'))
|
||||
}
|
||||
|
||||
// Cargo.toml 的 [package].version 位于文件开头, 取第一个行首 version = "x"
|
||||
function readCargoTomlVersion() {
|
||||
const text = fs.readFileSync(path.join(ROOT, 'src-tauri/Cargo.toml'), 'utf8')
|
||||
const m = /^version\s*=\s*"([^"]+)"/m.exec(text)
|
||||
return m ? m[1] : null
|
||||
}
|
||||
|
||||
// Cargo.lock 里挑出 name = "iboard" 那个包的 version
|
||||
function readCargoLockVersion() {
|
||||
const text = fs.readFileSync(path.join(ROOT, 'src-tauri/Cargo.lock'), 'utf8')
|
||||
const blocks = text.split(/^\[\[package\]\]$/m)
|
||||
for (const b of blocks) {
|
||||
if (/^name\s*=\s*"iboard"$/m.test(b)) {
|
||||
const m = /^version\s*=\s*"([^"]+)"/m.exec(b)
|
||||
if (m) return m[1]
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
const sources = [
|
||||
{ file: 'package.json', version: String(readJson('package.json').version || '') },
|
||||
{ file: 'src-tauri/tauri.conf.json', version: String(readJson('src-tauri/tauri.conf.json').version || '') },
|
||||
{ file: 'src-tauri/Cargo.toml', version: readCargoTomlVersion() },
|
||||
{ file: 'src-tauri/Cargo.lock (iboard)', version: readCargoLockVersion() },
|
||||
]
|
||||
|
||||
const version = sources[0].version
|
||||
const otaVersion = version + '-ota'
|
||||
|
||||
console.log('[check-version] 分支: ', branch || '(未知)')
|
||||
console.log('[check-version] package.json version:', version)
|
||||
console.log('[check-version] OTA 包版本将是:', otaVersion)
|
||||
console.log('[check-version] 分支: ', branch || '(未知)')
|
||||
for (const s of sources) {
|
||||
console.log(`[check-version] ${s.file.padEnd(28)} ${s.version || '(缺失)'}`)
|
||||
}
|
||||
console.log('[check-version] 产物版本: APK =', version, '/ OTA =', otaVersion)
|
||||
|
||||
let failed = false
|
||||
|
||||
// ---- A. 四处一致性 + 裸版本号 ----
|
||||
if (/-ota$/i.test(version)) {
|
||||
console.error('')
|
||||
console.error(`[check-version] package.json 的 version 不能带 "-ota": ${version}`)
|
||||
console.error('[check-version] OTA 后缀由 scripts/build-ota.mjs 自动追加, 请只写裸版本号 (如 0.2.0)')
|
||||
failed = true
|
||||
}
|
||||
|
||||
const mismatched = sources.filter((s) => s.version !== version)
|
||||
if (mismatched.length) {
|
||||
console.error('')
|
||||
console.error('============================================================')
|
||||
console.error('[check-version] 版本号不一致, 构建中止')
|
||||
console.error('============================================================')
|
||||
for (const s of mismatched) {
|
||||
console.error(` ${s.file}: ${s.version || '(缺失)'} ≠ package.json: ${version}`)
|
||||
}
|
||||
console.error('')
|
||||
console.error(' 规则: APK / 桌面包版本 = 裸版本号 (无后缀);')
|
||||
console.error(' OTA 热更包版本 = 同一个版本号 + "-ota"。')
|
||||
console.error(' 改版本时四处必须一起改 (见 readme「版本管理」)。')
|
||||
failed = true
|
||||
}
|
||||
|
||||
// ---- B. 分支对应 ----
|
||||
const m = /^dev-(\d+)(?:\.(\d+))?$/.exec(branch)
|
||||
if (!m) {
|
||||
console.log('[check-version] 非 dev-<版本> 分支, 跳过一致性校验')
|
||||
process.exit(0)
|
||||
console.log('[check-version] 非 dev-<版本> 分支, 跳过分支对应校验')
|
||||
} else {
|
||||
const want = m[2] === undefined ? `${m[1]}.` : `${m[1]}.${m[2]}`
|
||||
if (!version.startsWith(want)) {
|
||||
console.error('')
|
||||
console.error(`[check-version] 版本与分支不一致: 分支 "${branch}" 要求版本以 ${want} 开头, 实际是 ${version}`)
|
||||
console.error('[check-version] 请修改 package.json 的 version, 并同步 tauri.conf.json / Cargo.toml / Cargo.lock')
|
||||
failed = true
|
||||
} else {
|
||||
console.log(`[check-version] 分支一致 (${branch} ↔ ${version})`)
|
||||
}
|
||||
}
|
||||
|
||||
const want = m[2] === undefined ? `${m[1]}.` : `${m[1]}.${m[2]}`
|
||||
if (!version.startsWith(want)) {
|
||||
console.error('')
|
||||
console.error(`[check-version] 版本与分支不一致: 分支 "${branch}" 要求版本以 ${want} 开头, 实际是 ${version}`)
|
||||
console.error('[check-version] 请修改 package.json 的 version (唯一手动管理点),')
|
||||
console.error('[check-version] 并同步 src-tauri/tauri.conf.json 与 src-tauri/Cargo.toml')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
console.log(`[check-version] 一致 (${branch} ↔ ${version})`)
|
||||
if (failed) process.exit(1)
|
||||
console.log('[check-version] 全部通过')
|
||||
|
||||
Reference in New Issue
Block a user