Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions docs/release-governance.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@
> 其中 `desktop/package-lock.json` 在 `.gitignore` 里(不是仓库内的版本位);仓库内跟踪的 9 处
> 由 `tests/test_version_consistency.py::test_all_version_sites_agree` 逐条比对,漂一处就红
> (v2.2.2 发版前 `deploy/kubernetes/deployment.yaml` 的镜像 tag 就停在 2.2.1,红得下来)。
>
> **哪几处 release-please 会自动改、哪几处必须人改**(它只支持 `json|toml|yaml|xml|pom|generic`,
> 没有 regex):`pyproject.toml` 与 `release-please-config.json` 的 `extra-files`
> (`version.json`/`config.yaml`/`desktop/package.json`/`tauri.conf.json`/`Cargo.toml`)是自动的;
> **必须人补**的是 `desktop/src-tauri/Cargo.lock`(归 cargo 生成)、
> `scripts/installer/setup.nsi` 的 `OutFile`/`APP_VERSION`/`VIProductVersion`
> (NSIS 注释符是 `;`,用不了 `generic` 要求的 `# x-release-please-version` 标记)、
> `deploy/kubernetes/deployment.yaml` 的镜像 tag(要跟 ghcr 上真存在的标签走)。
> 所以下一条 release PR 上,红在这三处是**预期行为**,补一个 commit 即可 ——
> 失败信息里会逐条标注哪处是『RP 自动』、哪处是『手工同步』。
- 版本位:`pyproject.toml` + `config.yaml`(release-please 驱动前端缓存参数需人工补齐,见本地 AGENTS.md #9(AGENTS.md 为本地维护、不随仓库分发))+ `CHANGELOG.md`。
- 发布**目前**由人工 `git tag -a` + `gh release create` 完成:**`release-please.yml` 是结构性空转**,
不会替你发版 —— 它设了 `skip-github-pull-request: true` 而仓库从未产生过 release PR,
Expand Down
8 changes: 7 additions & 1 deletion release-please-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@
"bump-patch-for-minor-pre-major": false,
"release-type": "python",
"include-component-in-tag": false,
"extra-files": [],
"extra-files": [
{ "type": "json", "path": "version.json", "jsonpath": "$.version" },
{ "type": "json", "path": "desktop/package.json", "jsonpath": "$.version" },
{ "type": "json", "path": "desktop/src-tauri/tauri.conf.json", "jsonpath": "$.version" },
{ "type": "toml", "path": "desktop/src-tauri/Cargo.toml", "jsonpath": "$.package.version" },
{ "type": "yaml", "path": "config.yaml", "jsonpath": "$.version" }
],
"packages": {
".": {}
}
Expand Down
36 changes: 33 additions & 3 deletions tests/test_version_consistency.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,17 @@ def test_no_hardcoded_old_version():

_SEMVER = re.compile(r"\d+\.\d+\.\d+")

#: release-please 通过 `release-please-config.json` 的 extra-files 会自动抬的版本位。
#: 键与本文件 `_site_versions()` 的键一致;改 config 时同步改这里,否则失败信息会指错方向。
_RP_MANAGED = {
"pyproject.toml",
"version.json",
"config.yaml",
"desktop/package.json",
"desktop/src-tauri/tauri.conf.json",
"desktop/src-tauri/Cargo.toml",
}


def _ver_tuple(s: str) -> tuple[int, ...]:
"""x.y.z → 可比较的整数元组(避免字典序把 2.9 判成比 2.10 大)。"""
Expand Down Expand Up @@ -151,9 +162,14 @@ def test_all_version_sites_agree() -> None:
assert not bad, f"这些版本位不是 x.y.z 形态:{bad}"
distinct = set(sites.values())
assert len(distinct) == 1, (
"版本位互相矛盾(release-governance §5 的『版本位全部同步』没做到):"
+ "\n "
+ "\n ".join(f"{k} = {v}" for k, v in sorted(sites.items()))
"版本位互相矛盾(release-governance §5 的『版本位全部同步』没做到):\n "
+ "\n ".join(
f"{k} = {v}{' ← RP 自动' if k in _RP_MANAGED else ' ← 手工同步'}" for k, v in sorted(sites.items())
)
+ "\n release-please 只会改上面标『RP 自动』的那些(它只支持 json/toml/yaml/xml/pom/generic,"
"没有 regex);标『手工同步』的必须在 release PR 上补一个 commit —— "
"Cargo.lock 归 cargo 生成、setup.nsi 的注释符是 `;` 用不了 generic 的 `# x-release-please-version` 标记、"
"k8s 镜像 tag 要跟 ghcr 上真存在的标签走、安装器那份是 gitignore 的装配中间物。"
)


Expand All @@ -173,3 +189,17 @@ def test_installer_artifact_names_track_the_version_site() -> None:
# updater.rs 只在 AppVersion 结构里解析它,shell-update.json 契约里没有这个字段),
# 所以这里只钉住唯一站得住的关系:下界不得高于本次版本。
assert _ver_tuple(minimum) <= _ver_tuple(ver), f"minimum_shell_version={minimum} 高于本次版本 {ver}"


def test_rp_managed_annotation_matches_the_actual_config() -> None:
"""`_RP_MANAGED` 只是给失败信息指路用的,它自己不能漂:必须与
release-please-config.json 的 extra-files + pyproject(python release-type 自带)一致。"""
import re as _re

cfg = (PROJECT_ROOT / "release-please-config.json").read_text(encoding="utf-8")
listed = set(_re.findall(r'"path":\s*"([^"]+)"', cfg))
assert listed, "config 里一个 extra-files 都没有,那这条闸就没意义了"
assert listed | {"pyproject.toml"} == _RP_MANAGED, (
f"RP 自动位与测试里的标注不一致:config 有 {sorted(listed)},标注多/少的部分是"
f" {sorted((listed | {'pyproject.toml'}) ^ _RP_MANAGED)}"
)
Loading