142 lines
4.5 KiB
Markdown
142 lines
4.5 KiB
Markdown
# 更新策略
|
||
|
||
一句话:
|
||
|
||
更新策略不是为了更新
|
||
|
||
而是为了让你可以几年以后</br>
|
||
依旧知道自己运行的是哪个版本
|
||
|
||
---
|
||
|
||
## 版本号格式
|
||
|
||
frpc-console 的版本号遵循以下格式:
|
||
|
||
```
|
||
<semver>-<channel>-<date>-<time>
|
||
```
|
||
|
||
**示例:** `2.5-LTS-260804-203825`
|
||
|
||
| 组成部分 | 说明 | 示例 |
|
||
|---|---|---|
|
||
| **semver** | 语义版本号(主版本.次版本) | `2.5` |
|
||
| **channel** | 发布通道 | `LTS` / `Preview` |
|
||
| **date** | 构建日期(YYMMDD) | `260804` |
|
||
| **time** | 构建时间(HHMMSS) | `203825` |
|
||
|
||
---
|
||
|
||
## 为什么没有 Patch 版本?
|
||
|
||
你可能已经注意到了:
|
||
|
||
**版本号里只有主版本和次版本(如 `2.5`),没有 patch 号。**
|
||
|
||
这不是疏忽,而是有意识的设计选择。
|
||
|
||
原因很简单:
|
||
|
||
- frpc-console 的发行逻辑是标准的滚动式发行逻辑,而非完全由版本号驱动
|
||
- 因此,frpc-console 的更新粒度是基于**构建时间戳**的,每一个不同的构建时间点,对应的可能是不一样的版本
|
||
- 每一次构建都是一个独立的版本,通过日期时间精确标识
|
||
- `2.5-LTS-260804-203825` 和 `2.5-LTS-260805-091422` 之间,不需要、也不应该用第三个数字来区分
|
||
|
||
---
|
||
|
||
## 双通道:LTS / Preview
|
||
|
||
项目采用双线开发模式,对应两个不同的分支:
|
||
|
||
### LTS(Long-Term Support)
|
||
|
||
- **分支:** `main`
|
||
- **定位:** 稳定版,生产环境推荐
|
||
- **特征:** 低更新频率,可以在不接收任何冷热更新的情况下,长时间稳定自持
|
||
- **适用场景:** 生产环境、Homelab 主节点、长期运行设备
|
||
|
||
### Preview
|
||
|
||
- **分支:** `test`
|
||
- **定位:** 技术预览版,包含最新设计和实验性功能
|
||
- **特征:** 极高更新频率,很多时候会伴随大量不稳定commit,稳定性并不佳
|
||
- **适用场景:** 开发者用测试环境、尝鲜用户、边缘节点验证
|
||
|
||
---
|
||
|
||
## 更新机制
|
||
|
||
### 部署脚本中的更新逻辑
|
||
|
||
`deploy.sh` 脚本在每次运行时,会从远程仓库读取当前分支的最新版本:
|
||
|
||
```bash
|
||
# 从远程读取 version.ini
|
||
SEMVER=$(curl -sSL https://git.whitetop.xyz/.../version.ini)
|
||
|
||
# 根据通道生成完整版本号
|
||
if [ "$channel" = "lts" ]; then
|
||
TARGET_VERSION="${SEMVER}-lts-$(date +%Y%m%d)"
|
||
else
|
||
TARGET_VERSION="${SEMVER}-preview-$(date +%Y%m%d-%H%M%S)"
|
||
fi
|
||
```
|
||
|
||
每次运行部署脚本,都会生成一个新的版本号,并写入 `data/version.ini`。
|
||
|
||
### 版本比较
|
||
|
||
部署脚本在更新前会检查当前版本和目标版本:
|
||
|
||
```bash
|
||
CURRENT_VERSION=$(cat /opt/frpc-console/data/version.ini)
|
||
CUR_SEMVER=$(echo "$CURRENT_VERSION" | sed -E 's/^([0-9]+\.[0-9]+).*$/\1/')
|
||
TGT_SEMVER=$(echo "$TARGET_VERSION" | sed -E 's/^([0-9]+\.[0-9]+).*$/\1/')
|
||
```
|
||
|
||
如果检测到**语义版本降级**(例如从 `2.6` 降到 `2.5`),脚本会:
|
||
|
||
1. 发出警告
|
||
2. 自动备份当前数据目录
|
||
3. 等待用户确认后才继续
|
||
|
||
### 通道固定原则
|
||
|
||
一旦选择了一个通道(LTS 或 Preview),后续升级时**不应切换通道**:
|
||
|
||
- LTS → LTS:允许,正常升级
|
||
- Preview → Preview:允许,正常升级
|
||
- LTS → Preview:**不推荐**,可能引入未经充分验证的变更
|
||
- Preview → LTS:**不推荐**,可能发生版本降级
|
||
|
||
如果确实需要切换通道,部署脚本会在抓取源码前,自动备份你的数据库到安全位置,但是脚本本身也存在可能的不稳定因素,此时请保证你的手中至少有一份可用的较新的toml文件,可供部署完成后恢复
|
||
|
||
---
|
||
|
||
## 镜像保留策略
|
||
|
||
Docker 部署时,脚本会自动保留最近 **3 个** 镜像:
|
||
|
||
```bash
|
||
KEEP_IMAGES=3
|
||
```
|
||
|
||
这 3 个镜像足够用于回滚,又不会占用过多存储空间(边缘节点存储有限)。
|
||
|
||
---
|
||
|
||
## 为什么这套策略是合理的?
|
||
|
||
1. **基础设施工具不需要频繁的版本号膨胀。** 一年发布一个大版本,中间用 LTS 累积修复,比每个小补丁都发一个新版本更符合长期运行环境的预期。
|
||
|
||
2. **构建日期比 patch 号更有信息量。** `2.5-LTS-260804` 一眼就能看出是 2026 年 8 月 4 日构建的 LTS 版本,不需要查 changelog。
|
||
|
||
3. **用户不需要关心 patch。** 用户只需要知道当前是 LTS 还是 Preview,以及发布日期。具体的修复内容,在更新日志里。
|
||
|
||
---
|
||
|
||
## 相关文档
|
||
|
||
- 部署脚本的更新逻辑详见:[部署指南 - Docker版](./install_docker.md) 和 [部署指南-二进制版](./install_binary.md)
|
||
- 版本号的设计背景详见:[工程设计哲学](./engineering-philosophy.md) |