#!/usr/bin/env python3 """打印版本号 —— 唯一来源是仓库根的 CHANGELOG.md。 为什么是它而不是 git tag:CI 检出是 `git fetch --depth 50`,**取不到 tag**, `git describe --tags` 会失败或者给出误导性的结果。仓库里的文件则一定在。 为什么不是另放一个 `VERSION` 文件:那是第二份副本,发版要改两处,忘一处就漂移 (正本 §3.1)。CHANGELOG.md 里本来就必须写版本号,让它当源头,副本数为一。 用法: python3 scripts/version.py # 打印版本号;解析不到就以非 0 退出 python3 scripts/version.py --check # 同时跑结构自检(等价 check-changelog.py) 退出码非 0 表示"CHANGELOG 里没有已发布版本条目" —— 构建应当据此失败, 而不是回落成一个看起来正常的假版本号。 """ from __future__ import annotations import re import sys from pathlib import Path ROOT = Path(__file__).resolve().parent.parent CHANGELOG = ROOT / "CHANGELOG.md" # 已发布版本标题:`## [0.1.0] - 2026-10-10` / `## [0.1.0]`;`## [Unreleased]` 不算 RELEASE_HEADING = re.compile(r"^##\s*\[(\d+\.\d+\.\d+)\]", re.MULTILINE) def current_version(path: Path = CHANGELOG) -> str | None: """取最上面那个已发布版本号;没有就返回 None。""" if not path.is_file(): return None m = RELEASE_HEADING.search(path.read_text(encoding="utf-8")) return m.group(1) if m else None def main(argv: list[str]) -> int: v = current_version() if v is None: print( "❌ CHANGELOG.md 里找不到已发布版本条目(形如 `## [0.1.0] - 2026-10-10`)。\n" " 版本号解析不到 ⇒ 构建应当失败,而不是回落成假版本号。", file=sys.stderr, ) return 1 if "--check" in argv: sys.path.insert(0, str(Path(__file__).resolve().parent)) from check_changelog import check # type: ignore # noqa: PLC0415 problems = check() if problems: for p in problems: print(f"❌ {p}", file=sys.stderr) return 1 print(v) return 0 if __name__ == "__main__": raise SystemExit(main(sys.argv[1:]))