版本指紋閘(同一版號只准一份原始碼,實測有效)+落帳封測兩病與 md 真相

This commit is contained in:
2026-08-06 16:17:40 +08:00
parent 67effe3b7f
commit 0b8bc83bd1
2 changed files with 55 additions and 0 deletions
+3
View File
@@ -0,0 +1,3 @@
{
"v0.18.9": "8be9260eb542f527"
}
+52
View File
@@ -33,6 +33,8 @@
daemon-version.py --stamp # 把「下一版(未發佈)」戳成正式版號+日期後印出
"""
import datetime
import hashlib
import json
import re
import subprocess
import sys
@@ -45,6 +47,8 @@ CHANGELOG = ROOT / "docs-site/src/content/docs/help/changelog.md"
LINE_FILE = ROOT / "DAEMON_LINE"
UNRELEASED = "## 下一版(未發佈)"
# 版本 → 當時原始碼指紋。用來擋「同一個版號、不同的執行檔」。
SOURCE_LOCK = HERE / ".version-source.json"
RELEASED_RE = re.compile(r"^## v(\d+)\.(\d+)\.(\d+)", re.M)
@@ -53,6 +57,52 @@ def die(msg):
sys.exit(1)
def source_fingerprint():
"""會被編進執行檔的原始碼指紋(已提交的樹 + 未提交的差異)。
🔴 2026-08-06 補這道閘的由來:
戳完版號後我又改了 code,再打一次包,腳本判定「沒有未發佈段=重打同一版」
⇒ **兩個內容不同的執行檔都叫 v0.18.9**(實測 sha256 前 20 碼
63ec1077a29383b31379 vs 1ca73a5aef5bf4f90bd3)。
這正是 leo 08-05 點名的「版本號手寫=說謊溫床」換個形式復發——
機械產生版本號還不夠,還要保證**同一個版號只對應一份原始碼**。
"""
def sh(*args):
return subprocess.check_output(args, cwd=ROOT, text=True).strip()
try:
tree = sh("git", "rev-parse", "HEAD:collector")
except subprocess.CalledProcessError:
return "" # 不在 git 裡就不擋(例如從 tarball 解出來 build
diff = subprocess.run(["git", "diff", "HEAD", "--", "collector"],
cwd=ROOT, text=True, capture_output=True).stdout
return hashlib.sha256((tree + diff).encode()).hexdigest()[:16]
def check_or_record(version, stamp):
"""同一個版號只准對應一份原始碼;不同就擋下並說怎麼辦。"""
fp = source_fingerprint()
if not fp:
return
lock = json.loads(SOURCE_LOCK.read_text()) if SOURCE_LOCK.exists() else {}
known = lock.get(version)
if known and known != fp:
die("""%s 這個版號已經對應過另一份原始碼了(記錄 %s,現在 %s)。
代表你在戳完版號之後又改了 code。再打一次會產生
**兩個內容不同、卻都叫 %s 的執行檔** —— 那就是「版本號說謊」。
要出新版:在 changelog 最上面加一段
## 下一版(未發佈)
- (用戶語言的更新內容)
然後重跑打包,版號會自動變成下一個。""" % (version, known, fp, version))
if stamp and not known:
lock[version] = fp
SOURCE_LOCK.write_text(json.dumps(lock, indent=1, ensure_ascii=False) + "\n")
def main():
stamp = "--stamp" in sys.argv
if not CHANGELOG.exists():
@@ -74,6 +124,7 @@ def main():
if not has_unreleased:
# 沒有待發佈內容=重打同一版。冪等,不虛增。
version = "v%d.%d.%d" % prev
check_or_record(version, stamp)
if stamp:
print(" ️ changelog 沒有「下一版(未發佈)」段,版本維持 %s(重打同一版)"
% version, file=sys.stderr)
@@ -89,6 +140,7 @@ def main():
version = "v%d.%d.%d" % nxt
if stamp:
check_or_record(version, True)
today = datetime.date.today().isoformat()
heading = "## %s%s" % (version, today)
CHANGELOG.write_text(text.replace(UNRELEASED, heading, 1))