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:
@@ -30,6 +30,11 @@ jobs:
|
|||||||
node-version: 22
|
node-version: 22
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
|
|
||||||
|
# 版本号一致性: package.json / tauri.conf.json / Cargo.toml / Cargo.lock 必须完全相等。
|
||||||
|
# tauri.conf.json 的 version 就是 APK 的 versionName, 漏改会打出一个版本号错误的安装包。
|
||||||
|
- name: Check version consistency
|
||||||
|
run: node scripts/ci/check-version.mjs
|
||||||
|
|
||||||
- name: Setup JDK 17
|
- name: Setup JDK 17
|
||||||
uses: https://gitea.com/actions/setup-java@v4
|
uses: https://gitea.com/actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
|
|||||||
@@ -34,8 +34,10 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
node-version: 22
|
node-version: 22
|
||||||
|
|
||||||
- name: Check version matches branch
|
- name: Check version consistency & branch
|
||||||
# 防止 OTA 版本号与分支错位: OTA 包的 version 直接取自 package.json,
|
# 1) package.json / tauri.conf.json / Cargo.toml / Cargo.lock 四处版本必须完全相等且不带 -ota
|
||||||
|
# (tauri.conf.json 的 version 就是 APK 的 versionName)
|
||||||
|
# 2) 防止 OTA 版本号与分支错位: OTA 包的 version 直接取自 package.json,
|
||||||
# dev-0.2 分支上必须是 0.2.x, 否则线上 OTA 会报成上一个版本的号
|
# dev-0.2 分支上必须是 0.2.x, 否则线上 OTA 会报成上一个版本的号
|
||||||
env:
|
env:
|
||||||
GITHUB_REF_NAME: ${{ github.ref_name }}
|
GITHUB_REF_NAME: ${{ github.ref_name }}
|
||||||
|
|||||||
+17
-3
@@ -375,18 +375,32 @@ ListView()
|
|||||||
| 3 | 设计 | 打卡 Tab 移到**最左边并默认选中**;打卡页移除**特效开关**,特效永远打开 | `BottomNav.jsx`、`App.jsx`、`TabIcon.jsx`、`HabitView.jsx`、`RingProgress.jsx`、`globals.css` |
|
| 3 | 设计 | 打卡 Tab 移到**最左边并默认选中**;打卡页移除**特效开关**,特效永远打开 | `BottomNav.jsx`、`App.jsx`、`TabIcon.jsx`、`HabitView.jsx`、`RingProgress.jsx`、`globals.css` |
|
||||||
| 4 | 设计 | 取消「首页」Tab,其**报警 / 新闻**并入宏观,成为宏观的第 5、6 个子 Tab | `MacroPage.jsx`、新增 `macro/AlertsView.jsx`、`macro/NewsView.jsx`、删除 `HomePage.jsx` |
|
| 4 | 设计 | 取消「首页」Tab,其**报警 / 新闻**并入宏观,成为宏观的第 5、6 个子 Tab | `MacroPage.jsx`、新增 `macro/AlertsView.jsx`、`macro/NewsView.jsx`、删除 `HomePage.jsx` |
|
||||||
|
|
||||||
### 10.2 OTA 版本号为什么必须跟分支走
|
### 10.2 版本号为什么必须跟分支走
|
||||||
|
|
||||||
`scripts/build-ota.mjs` 里 `manifest.version = package.json.version + '-ota'`,也就是**版本号的唯一来源仍是 `package.json`**。
|
`scripts/build-ota.mjs` 里 `manifest.version = package.json.version + '-ota'`,也就是**版本号的唯一来源仍是 `package.json`**。
|
||||||
分支按版本命名(`dev-0.2`),但版本号是手工改的,一旦忘改就会出现「分支 0.2、包版本 0.1」的错位,客户端判新逻辑全部失准。
|
分支按版本命名(`dev-0.2`),但版本号是手工改的,一旦忘改就会出现「分支 0.2、包版本 0.1」的错位,客户端判新逻辑全部失准。
|
||||||
|
|
||||||
|
**同一版本号的两种产物写法**(2026-10-22 补充确认):
|
||||||
|
|
||||||
|
```
|
||||||
|
分支 dev-0.2 → 0.2.0
|
||||||
|
├─ APK / 桌面安装包 0.2.0 裸版本号,无后缀
|
||||||
|
├─ 前端运行时 0.2.0 裸版本号,无后缀
|
||||||
|
└─ OTA 热更包 0.2.0-ota 多一个 -ota 标记
|
||||||
|
```
|
||||||
|
|
||||||
|
即 APK 与 OTA 的版本主体完全一致,唯一差别是 OTA 多 `-ota` 后缀;`package.json` 只写裸版本号,后缀由打包脚本追加。
|
||||||
|
|
||||||
| 环节 | 取值 | 现状 |
|
| 环节 | 取值 | 现状 |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `package.json` `version` | `0.2.0` | 唯一手动管理点 |
|
| `package.json` `version` | `0.2.0` | 唯一手动管理点,**不得带 `-ota`** |
|
||||||
|
| `src-tauri/tauri.conf.json` `version` | `0.2.0` | 决定 **APK `versionName`**(经 `tauri android init` 写入 `tauri.properties`)与桌面包版本 |
|
||||||
|
| `src-tauri/Cargo.toml` / `Cargo.lock` | `0.2.0` | Rust 包版本,与上两者保持一致 |
|
||||||
| OTA `latest.json.version` | `0.2.0-ota` | 打包脚本自动拼 `-ota` 后缀 |
|
| OTA `latest.json.version` | `0.2.0-ota` | 打包脚本自动拼 `-ota` 后缀 |
|
||||||
| `src/version.js` `APP_VERSION` | `0.2.0` | 前端展示与版本比较的基准 |
|
| `src/version.js` `APP_VERSION` | `0.2.0` | 前端展示与版本比较的基准 |
|
||||||
|
| APK `versionCode` | `2000` | `major*1000000 + minor*1000 + patch`,必须单调递增才能覆盖安装(`0.1.0` = 1000) |
|
||||||
| OTA `latest.json.min_binary_version` | `0.1.0` | **与前端版本解耦**:前端 bundle 要求的最低原生二进制版本。现有 APK 原生层仍是 0.1.0,跟着抬会导致旧 APK 收不到更新,CI 固定传 `--min-binary 0.1.0` |
|
| OTA `latest.json.min_binary_version` | `0.1.0` | **与前端版本解耦**:前端 bundle 要求的最低原生二进制版本。现有 APK 原生层仍是 0.1.0,跟着抬会导致旧 APK 收不到更新,CI 固定传 `--min-binary 0.1.0` |
|
||||||
| CI 守卫 | `scripts/ci/check-version.mjs` | 从 `GITHUB_REF_NAME` 解析 `dev-<major>.<minor>`,要求 `version` 以该前缀开头,否则**构建直接失败**;`main`/`master` 跳过 |
|
| CI 守卫 | `scripts/ci/check-version.mjs` | ① 四处版本必须完全相等且不含 `-ota`(`main`/`master` 也查);② 从 `GITHUB_REF_NAME` 解析 `dev-<major>.<minor>`,要求 `version` 以该前缀开头;任一不满足**构建直接失败**。`docker-build.yml` 与 `android-build.yml` 都在构建前执行 |
|
||||||
|
|
||||||
### 10.3 判新口径:版本号 vs build sequence
|
### 10.3 判新口径:版本号 vs build sequence
|
||||||
|
|
||||||
|
|||||||
+3
-2
@@ -179,7 +179,8 @@
|
|||||||
| 编号 | 需求描述 | 验收要点 | 优先级 |
|
| 编号 | 需求描述 | 验收要点 | 优先级 |
|
||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| F-OT-01 | **OTA 包版本必须与分支对应**:`dev-0.2` 分支上 OTA 包版本应为 `0.2.0-ota` | `GET /api/ota/check/0` 返回 `version = 0.2.0-ota` | P0 |
|
| F-OT-01 | **OTA 包版本必须与分支对应**:`dev-0.2` 分支上 OTA 包版本应为 `0.2.0-ota` | `GET /api/ota/check/0` 返回 `version = 0.2.0-ota` | P0 |
|
||||||
| F-OT-02 | 版本号错位在 CI 阶段就拦住:分支名 `dev-x.y` 与 `package.json` 版本主次号不一致时构建失败 | CI 输出明确报错并中断 | P0 |
|
| F-OT-01a | **APK 版本与 OTA 版本同源**:APK(含桌面包)版本为裸版本号 `0.2.0`,无后缀;OTA 版本为同一版本号加 `-ota`。两者都跟代码分支保持一致 | APK 系统信息里 versionName=`0.2.0`(versionCode=2000),OTA manifest=`0.2.0-ota` | P0 |
|
||||||
|
| F-OT-02 | 版本号错位在 CI 阶段就拦住:①`package.json`/`tauri.conf.json`/`Cargo.toml`/`Cargo.lock` 四处必须完全一致且不含 `-ota`;②分支名 `dev-x.y` 与版本主次号不一致时构建失败 | CI 输出明确报错并中断 | P0 |
|
||||||
| F-OT-03 | 「我」页 OTA 组内新增**「开发版本」开关**,默认**关闭** | 关闭=按版本号比较;打开=按 build sequence 比较 | P0 |
|
| F-OT-03 | 「我」页 OTA 组内新增**「开发版本」开关**,默认**关闭** | 关闭=按版本号比较;打开=按 build sequence 比较 | P0 |
|
||||||
| F-OT-04 | 开关值**持久化在设备端**,重启 App 后保持上次选择 | 杀进程重进仍为上次状态 | P0 |
|
| F-OT-04 | 开关值**持久化在设备端**,重启 App 后保持上次选择 | 杀进程重进仍为上次状态 | P0 |
|
||||||
| F-OT-05 | 版本号比较规则:按非数字字符切成数字字段,逐段比较大小(`0.2.0 > 0.1.0`,`0.10 > 0.9`) | 单测覆盖后缀/前缀/缺位/多位段 | P0 |
|
| F-OT-05 | 版本号比较规则:按非数字字符切成数字字段,逐段比较大小(`0.2.0 > 0.1.0`,`0.10 > 0.9`) | 单测覆盖后缀/前缀/缺位/多位段 | P0 |
|
||||||
@@ -189,7 +190,7 @@
|
|||||||
|
|
||||||
## 4. 优先级汇总(本期交付范围)
|
## 4. 优先级汇总(本期交付范围)
|
||||||
|
|
||||||
- **P0(必须)**:F-CK-01~08、F-CK-11;F-CL-01~08;F-LS-01~04;F-SY-01~05;F-OT-01~05;U-01、U-02、U-04、U-05;D-01~05;N-01、N-02、N-04、N-05;E-01、E-02、E-04、E-05、E-08。
|
- **P0(必须)**:F-CK-01~08、F-CK-11;F-CL-01~08;F-LS-01~04;F-SY-01~05;F-OT-01、F-OT-01a、F-OT-02~05;U-01、U-02、U-04、U-05;D-01~05;N-01、N-02、N-04、N-05;E-01、E-02、E-04、E-05、E-08。
|
||||||
- **P1(应该)**:F-CK-09、10、12~14;F-CL-09;F-LS-05~09;F-SY-06~08;F-OT-06;U-03、U-06~08;D-06;N-03;E-03、E-06、E-07。
|
- **P1(应该)**:F-CK-09、10、12~14;F-CL-09;F-LS-05~09;F-SY-06~08;F-OT-06;U-03、U-06~08;D-06;N-03;E-03、E-06、E-07。
|
||||||
- **P2(可选/延后)**:F-CK-15~17;F-CL-10、11;F-LS-10、11;U-09。
|
- **P2(可选/延后)**:F-CK-15~17;F-CL-10、11;F-LS-10、11;U-09。
|
||||||
|
|
||||||
|
|||||||
@@ -3,21 +3,57 @@
|
|||||||
|
|
||||||
## 版本管理
|
## 版本管理
|
||||||
|
|
||||||
版本号遵循 `主版本.次版本.修订号`,**唯一手动管理点是 `package.json` 的 `version` 字段**(当前 `0.2.0`)。
|
### 一句话规则
|
||||||
版本号必须与所在分支对应:`dev-0.2` 分支上就该是 `0.2.x`(CI 有 `scripts/ci/check-version.mjs` 强校验,不一致直接失败)。
|
|
||||||
发版时只改这一处,以下位置必须保持一致(改版本时一并核对):
|
**同一个版本号,APK(原生包)裸写,OTA 热更包多一个 `-ota` 后缀。**
|
||||||
|
|
||||||
|
```
|
||||||
|
分支 dev-0.2 → 版本 0.2.0
|
||||||
|
├─ APK / 桌面安装包 versionName = 0.2.0 (无后缀)
|
||||||
|
├─ 前端运行时 APP_VERSION = 0.2.0 (无后缀)
|
||||||
|
└─ OTA 热更包 version = 0.2.0-ota (多一个 -ota)
|
||||||
|
```
|
||||||
|
|
||||||
|
版本号遵循 `主版本.次版本.修订号`,**唯一手动管理点是 `package.json` 的 `version` 字段**(当前 `0.2.0`),
|
||||||
|
该字段只写裸版本号,**不允许带 `-ota`**——`-ota` 由 `scripts/build-ota.mjs` 打包时自动追加。
|
||||||
|
|
||||||
|
版本号必须与所在分支对应:`dev-0.2` 分支上就该是 `0.2.x`。
|
||||||
|
|
||||||
|
### 改版本号时要同步的位置
|
||||||
|
|
||||||
| 文件 | 字段 | 说明 |
|
| 文件 | 字段 | 说明 |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `package.json` | `version` | **唯一源**,前端 `src/version.js` 与 OTA 打包脚本均读取此值 |
|
| `package.json` | `version` | **唯一源**,前端 `src/version.js` 与 OTA 打包脚本均读取此值 |
|
||||||
| `src-tauri/tauri.conf.json` | `version` | Tauri 应用版本(Android/桌面包版本) |
|
| `src-tauri/tauri.conf.json` | `version` | Tauri 应用版本 → **APK 的 versionName**、桌面安装包版本 |
|
||||||
| `src-tauri/Cargo.toml` | `[package].version` | Rust 包版本,需与 tauri.conf.json 一致 |
|
| `src-tauri/Cargo.toml` | `[package].version` | Rust 包版本,需与 tauri.conf.json 一致 |
|
||||||
| `src-tauri/Cargo.lock` | `name = "iboard"` 条目 | 同上,随 Cargo.toml 一起改 |
|
| `src-tauri/Cargo.lock` | `name = "iboard"` 条目 | 同上,随 Cargo.toml 一起改 |
|
||||||
|
|
||||||
说明:
|
`scripts/ci/check-version.mjs` 会在 CI 第一段就校验这四处**完全相等**且不含 `-ota`,
|
||||||
|
并校验 `dev-<major>.<minor>` 分支与版本前缀对应;任何一项不满足直接构建失败(`main`/`master` 只跳过分支校验,一致性照样查)。
|
||||||
|
|
||||||
|
### APK 版本号是怎么来的
|
||||||
|
|
||||||
|
`tauri android init` 会按 `src-tauri/tauri.conf.json` 的 `version` 生成
|
||||||
|
`src-tauri/gen/android/app/tauri.properties`(该目录被 gitignore,CI 每次 `android init` 重新生成):
|
||||||
|
|
||||||
|
```
|
||||||
|
tauri.android.versionName = 0.2.0 # 人类可见版本,与 tauri.conf.json 一致
|
||||||
|
tauri.android.versionCode = 2000 # 整数,升级判定用 = major*1000000 + minor*1000 + patch
|
||||||
|
```
|
||||||
|
|
||||||
|
注意:
|
||||||
|
- `versionCode` 必须**单调递增**才能覆盖安装,所以版本号只能往上走(`0.2.0` → 2000 > `0.1.0` → 1000)。
|
||||||
|
- 本地如果 APK 装完显示旧版本号,是 `src-tauri/gen/android` 缓存没刷新,
|
||||||
|
删掉该目录重新 `npx tauri android init` 即可。
|
||||||
|
|
||||||
|
### 其它
|
||||||
|
|
||||||
- `src/version.js` 从 `package.json` 取值,前端"我"页与 OTA 检查接口展示的即此版本,不要另写死版本号。
|
- `src/version.js` 从 `package.json` 取值,前端"我"页与 OTA 检查接口展示的即此版本,不要另写死版本号。
|
||||||
- OTA 升级包的 `version` 字段 = `<package.json version>-ota`(见 `scripts/build-ota.mjs`),
|
- OTA 升级包的 `version` = `<package.json version>-ota`(见 `scripts/build-ota.mjs`),
|
||||||
所以版本号错位会直接导致线上 OTA 判新失准。
|
所以版本号错位会直接导致线上 OTA 判新失准。
|
||||||
|
- **`min_binary_version` 与这里的版本号是两件事**:它是 OTA 包要求的最低原生二进制版本
|
||||||
|
(CI 里由 `OTA_MIN_BINARY` 显式指定,当前 `0.1.0`)。前端版本升到 0.2.0 时它不应跟着抬,
|
||||||
|
否则装了 0.1.0 APK 的设备会直接收不到热更。
|
||||||
- `BUILD_ID` 每次编译自动生成(见 `vite.config.js` 的 `__BUILD_ID__`),无需手动维护。
|
- `BUILD_ID` 每次编译自动生成(见 `vite.config.js` 的 `__BUILD_ID__`),无需手动维护。
|
||||||
- `ota-package/latest.json` 为运行时产物,不纳入版本管理。
|
- `ota-package/latest.json` 为运行时产物,不纳入版本管理。
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,20 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
// CI 专用: 校验分支名与 package.json 版本号一致
|
// CI 专用: 校验版本号四处一致 + 与分支名一致
|
||||||
//
|
//
|
||||||
// 背景:
|
// 背景:
|
||||||
// OTA 升级包的 version 直接取自 package.json (`<version>-ota`), 而分支按版本命名
|
// 版本号只允许一个手工管理点 = package.json 的 version, 其余位置全部派生:
|
||||||
// (dev-0.1 / dev-0.2 ...). 两者一旦错位 (例如 dev-0.2 上 package.json 还是 0.1.0),
|
// - APK / 桌面安装包 version = <version> (裸版本号, 无后缀)
|
||||||
// 线上 OTA 就会报成上一个版本的号, 客户端判新逻辑全部失准。
|
// - OTA 热更包 version = <version>-ota (多一个 -ota 标记)
|
||||||
|
// - 前端运行时 APP_VERSION = <version>
|
||||||
|
// 任何一处漏改都会让线上版本号、APK 版本、OTA 判新三者对不上, 且很难在客户端发现。
|
||||||
//
|
//
|
||||||
// 规则:
|
// 校验分两段:
|
||||||
// - 分支形如 dev-<major>.<minor> → package.json 的 version 必须以 <major>.<minor> 开头
|
// A. 一致性 (任何分支都查): package.json ↔ tauri.conf.json ↔ Cargo.toml ↔ Cargo.lock
|
||||||
// - 分支形如 dev-<major> → version 必须以 <major>. 开头
|
// 并要求 package.json 的 version 不含 "-ota" (裸版本, OTA 后缀由打包脚本追加)
|
||||||
// - main / master 及其它分支 → 跳过校验 (生产分支不做约束, 只打印当前版本)
|
// B. 分支对应 (仅 dev-<版本> 分支):
|
||||||
|
// dev-<major>.<minor> → version 必须以 <major>.<minor> 开头
|
||||||
|
// dev-<major> → version 必须以 <major>. 开头
|
||||||
|
// main / master / 其它 → 跳过
|
||||||
//
|
//
|
||||||
// 环境变量:
|
// 环境变量:
|
||||||
// GITHUB_REF_NAME - Gitea Actions 提供的分支名 (本地运行可用 BRANCH 覆盖)
|
// GITHUB_REF_NAME - Gitea Actions 提供的分支名 (本地运行可用 BRANCH 覆盖)
|
||||||
@@ -23,27 +28,88 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|||||||
const ROOT = path.resolve(__dirname, '..', '..')
|
const ROOT = path.resolve(__dirname, '..', '..')
|
||||||
|
|
||||||
const branch = process.env.GITHUB_REF_NAME || process.env.BRANCH || ''
|
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'
|
const otaVersion = version + '-ota'
|
||||||
|
|
||||||
console.log('[check-version] 分支: ', branch || '(未知)')
|
console.log('[check-version] 分支: ', branch || '(未知)')
|
||||||
console.log('[check-version] package.json version:', version)
|
for (const s of sources) {
|
||||||
console.log('[check-version] OTA 包版本将是:', otaVersion)
|
console.log(`[check-version] ${s.file.padEnd(28)} ${s.version || '(缺失)'}`)
|
||||||
|
}
|
||||||
|
console.log('[check-version] 产物版本: APK =', version, '/ OTA =', otaVersion)
|
||||||
|
|
||||||
const m = /^dev-(\d+)(?:\.(\d+))?$/.exec(branch)
|
let failed = false
|
||||||
if (!m) {
|
|
||||||
console.log('[check-version] 非 dev-<版本> 分支, 跳过一致性校验')
|
// ---- A. 四处一致性 + 裸版本号 ----
|
||||||
process.exit(0)
|
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-<版本> 分支, 跳过分支对应校验')
|
||||||
|
} else {
|
||||||
const want = m[2] === undefined ? `${m[1]}.` : `${m[1]}.${m[2]}`
|
const want = m[2] === undefined ? `${m[1]}.` : `${m[1]}.${m[2]}`
|
||||||
if (!version.startsWith(want)) {
|
if (!version.startsWith(want)) {
|
||||||
console.error('')
|
console.error('')
|
||||||
console.error(`[check-version] 版本与分支不一致: 分支 "${branch}" 要求版本以 ${want} 开头, 实际是 ${version}`)
|
console.error(`[check-version] 版本与分支不一致: 分支 "${branch}" 要求版本以 ${want} 开头, 实际是 ${version}`)
|
||||||
console.error('[check-version] 请修改 package.json 的 version (唯一手动管理点),')
|
console.error('[check-version] 请修改 package.json 的 version, 并同步 tauri.conf.json / Cargo.toml / Cargo.lock')
|
||||||
console.error('[check-version] 并同步 src-tauri/tauri.conf.json 与 src-tauri/Cargo.toml')
|
failed = true
|
||||||
process.exit(1)
|
} else {
|
||||||
|
console.log(`[check-version] 分支一致 (${branch} ↔ ${version})`)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`[check-version] 一致 (${branch} ↔ ${version})`)
|
if (failed) process.exit(1)
|
||||||
|
console.log('[check-version] 全部通过')
|
||||||
|
|||||||
Reference in New Issue
Block a user