# Eva-CLI 版本管理方案

日期：2026-07-14
范围：Cargo 版本、CLI 标签、Git tag、GitHub Release 与 GHCR tag

本文区分仓库代码强制执行的版本事实和操作人员政策。
`scripts/validate-version-management.ps1` 是仓库一致性检查，不是 GitHub
治理或发布成功验证器。

![Eva-CLI 发布历史与版本边界](../../../assets/release-history-boundary.zh-CN.svg)

## 当前版本状态

| 表面 | 当前状态 |
| --- | --- |
| `main` Cargo/CLI 开发线 | `1.11.5-alpha` / `V1.11.5-alpha` |
| 已存在 tag | `v1.11.5-alpha`，指向 commit `9b86adf` |
| 该 tag 的 Release | 不存在。其 Ubuntu 验证失败，因此发布 jobs 被跳过。 |
| 最新成功 GitHub Release | `v1.11.4-alpha` |

当前 `main` 在 `v1.11.5-alpha` tag 之后仍有新提交，但 Cargo 版本尚未改变。下次发布
必须先提升 SemVer；不得把已有 tag 重新指向当前 `main`。

## 版本形式

| 场景 | 格式 | 示例 |
| --- | --- | --- |
| Cargo 预发布 | `MAJOR.MINOR.PATCH-alpha[.N]` 或 `-beta[.N]` | `1.12.0-beta.1` |
| Cargo 正式版 | `MAJOR.MINOR.PATCH` | `1.12.0` |
| 人类可读预发布标签 | `V` 加 Cargo 版本 | `V1.12.0-beta.1` |
| 人类可读正式版标签 | `VMAJOR.MINOR.PATCH-release` | `V1.12.0-release` |
| Git 预发布 tag | `v` 加 Cargo 版本 | `v1.12.0-beta.1` |
| Git 正式 tag | `vMAJOR.MINOR.PATCH` | `v1.12.0` |
| GHCR 预发布 tags | 精确版本和 `sha-<7位sha>` | `1.12.0-beta.1`、`sha-abc1234` |
| GHCR 正式 tags | 精确版本、`MAJOR.MINOR`、`latest` 和 SHA | `1.12.0`、`1.12`、`latest` |

正式 Cargo/Git 形式不使用 `-release`，否则会变成 SemVer 预发布版本。当前 validator
只接受 `alpha` 和 `beta` 预发布标识。

## 版本事实来源

发布前，根 `Cargo.toml` 的 package/workspace version 决定预期 CLI 标签和 tag。
版本发布后，immutable Git tag 及其 commit SHA 是源码身份。

其他表面都是派生记录：

- CLI 嵌入 `CARGO_PKG_VERSION`，同时包含由 validator 检查的显式 release status 和标签；
- README 和文档标签必须与 Cargo 派生的人类可读版本一致；
- GitHub Release 是附着在 tag 上的可更新记录；
- GHCR tag 是工作流重跑时可能被重推的 registry reference；
- GHCR digest 才标识 image 内容；
- workflow evidence 在 tag 之后生成，并通过 `source_tag` 和 `source_sha` 绑定源码；
  它不属于 tag commit 内的文件。

## 自动化校验实际范围

CI 中不带 tag 运行：

```powershell
./scripts/validate-version-management.ps1
```

Release workflow 传入所选 tag：

```powershell
./scripts/validate-version-management.ps1 -Tag $env:RELEASE_TAG
```

脚本当前检查：

- 根 Cargo 的两处 version 声明一致；
- version 是稳定 SemVer 或仓库 regex 支持的 `alpha`/`beta` 预发布版本；
- 传入 tag 时，它必须严格等于 `v` 加 Cargo version；
- 脚本列出的 README 和 CLI 文件包含预期人类版本标签；
- CLI release status 常量与派生状态一致；
- i18n manifest 在固定路径登记版本和 package 发布文档；
- CI、release workflow、Dockerfile、`.dockerignore` 和文档包含版本校验与 GHCR
  接线所需的静态字符串。

这些只是文件内容断言。脚本不验证 tag 是否 annotated、是否为新 tag、是否来自
`main` 或是否存在于 GitHub；也不检查 branch protection、`Cargo.lock`、发布说明、
workflow 结果、GitHub Release 设置、registry digest、milestone、label 或 PR metadata。
workflow 中存在静态字符串也不证明对应 job 已成功执行。

## Tag、Release 与 Package 规则

- 仓库政策要求从已评审 release commit 创建 annotated tag；自动化当前只验证 tag 文本
  和 Cargo version。
- tag 一经推送，不得 force-push、移动、删除后重建或复用；应发布新的 prerelease
  serial 或 patch。
- release workflow 将 `alpha`/`beta` tag 标成 GitHub prerelease；稳定 tag 不标 prerelease。
- 手动 dispatch checkout 所选已有 tag，不能发布只存在于 `main` 的修复。
- workflow 可以更新已有 GitHub Release 正文，也可以重推 GHCR tags。需要不可变 package
  内容的消费者必须固定 digest。
- 稳定 GHCR release 可以更新 `MAJOR.MINOR` 和 `latest`，预发布版本不得更新它们。
- `ghcr.io/yetmos/eva-cli` 是容器分发通道，不能替代 crates.io，也不是版本事实来源。

## 仓库治理边界

截至本文日期，GitHub 仅有 `main` 分支，且未启用保护；仓库没有 milestone，也没有
`version:*` / `status:*` labels。仓库中也没有强制声明版本影响的 PR template。

因此以下内容仍是操作人员政策，不是自动化保证：

- tag 前完成评审并确认 CI 全绿；
- annotated tag 来自目标 release commit；
- 评审发布说明、迁移说明和兼容性；
- 判断 major、minor 或 patch 影响；
- 禁止直接 push 或强制 PR approvals。

不兼容公开契约或持久化格式适合提升 major；新的兼容功能面适合提升 minor；兼容修复、
诊断和发布流程修正适合提升 patch 或 prerelease serial。validator 不会推断这些决策。

## 版本发布流程

1. 选择不存在远端 tag 的新版本。
2. 更新根 Cargo package/workspace version，并重新生成 `Cargo.lock`。
3. 更新 CLI status/label、README 标签、发布说明和双语文档。
4. 运行测试、docs/i18n 校验和不带 tag 的
   `scripts/validate-version-management.ps1`。
5. 推送 commit，确认完整 CI 矩阵通过。
6. 创建并推送 annotated tag，由 tag workflow 使用 `-Tag $env:RELEASE_TAG` 校验。
7. 分别核对 workflow 结果、GitHub Release 记录、GHCR digest 和 Actions artifacts。

示例：

```powershell
git tag -a v1.12.0-alpha -m "Eva-CLI V1.12.0-alpha"
git push origin v1.12.0-alpha
```

## 修复与回滚

- tag push 前：修复 release commit 并重新运行全部检查。
- tag push 后：保持 tag 不可变并创建新版本，即使 release workflow 在创建 GitHub
  Release 前已经失败也一样。
- 后续 job 失败前若 GHCR push 已成功，记录并评审 orphaned digest；新 tag 不会自动删除它。
- 只在临时基础设施故障时重跑旧 tag workflow。重跑无法包含 tag 后提交的代码修复。
- 除可更新的 GitHub Release 正文外，还要在发布说明或 issue 中记录回滚原因、受影响
  tag/digest 和替代版本。

## 相关文档

- [项目发布方案](项目发布方案.md)
- [GitHub Packages 发布方案](软件包发布方案.md)
- [安装、升级和卸载说明](安装升级卸载说明.md)
