版本指紋閘(同一版號只准一份原始碼,實測有效)+落帳封測兩病與 md 真相
This commit is contained in:
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"v0.18.9": "8be9260eb542f527"
|
||||||
|
}
|
||||||
@@ -33,6 +33,8 @@
|
|||||||
daemon-version.py --stamp # 把「下一版(未發佈)」戳成正式版號+日期後印出
|
daemon-version.py --stamp # 把「下一版(未發佈)」戳成正式版號+日期後印出
|
||||||
"""
|
"""
|
||||||
import datetime
|
import datetime
|
||||||
|
import hashlib
|
||||||
|
import json
|
||||||
import re
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
@@ -45,6 +47,8 @@ CHANGELOG = ROOT / "docs-site/src/content/docs/help/changelog.md"
|
|||||||
LINE_FILE = ROOT / "DAEMON_LINE"
|
LINE_FILE = ROOT / "DAEMON_LINE"
|
||||||
|
|
||||||
UNRELEASED = "## 下一版(未發佈)"
|
UNRELEASED = "## 下一版(未發佈)"
|
||||||
|
# 版本 → 當時原始碼指紋。用來擋「同一個版號、不同的執行檔」。
|
||||||
|
SOURCE_LOCK = HERE / ".version-source.json"
|
||||||
RELEASED_RE = re.compile(r"^## v(\d+)\.(\d+)\.(\d+)(", re.M)
|
RELEASED_RE = re.compile(r"^## v(\d+)\.(\d+)\.(\d+)(", re.M)
|
||||||
|
|
||||||
|
|
||||||
@@ -53,6 +57,52 @@ def die(msg):
|
|||||||
sys.exit(1)
|
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():
|
def main():
|
||||||
stamp = "--stamp" in sys.argv
|
stamp = "--stamp" in sys.argv
|
||||||
if not CHANGELOG.exists():
|
if not CHANGELOG.exists():
|
||||||
@@ -74,6 +124,7 @@ def main():
|
|||||||
if not has_unreleased:
|
if not has_unreleased:
|
||||||
# 沒有待發佈內容=重打同一版。冪等,不虛增。
|
# 沒有待發佈內容=重打同一版。冪等,不虛增。
|
||||||
version = "v%d.%d.%d" % prev
|
version = "v%d.%d.%d" % prev
|
||||||
|
check_or_record(version, stamp)
|
||||||
if stamp:
|
if stamp:
|
||||||
print(" ℹ️ changelog 沒有「下一版(未發佈)」段,版本維持 %s(重打同一版)"
|
print(" ℹ️ changelog 沒有「下一版(未發佈)」段,版本維持 %s(重打同一版)"
|
||||||
% version, file=sys.stderr)
|
% version, file=sys.stderr)
|
||||||
@@ -89,6 +140,7 @@ def main():
|
|||||||
version = "v%d.%d.%d" % nxt
|
version = "v%d.%d.%d" % nxt
|
||||||
|
|
||||||
if stamp:
|
if stamp:
|
||||||
|
check_or_record(version, True)
|
||||||
today = datetime.date.today().isoformat()
|
today = datetime.date.today().isoformat()
|
||||||
heading = "## %s(%s)" % (version, today)
|
heading = "## %s(%s)" % (version, today)
|
||||||
CHANGELOG.write_text(text.replace(UNRELEASED, heading, 1))
|
CHANGELOG.write_text(text.replace(UNRELEASED, heading, 1))
|
||||||
|
|||||||
Reference in New Issue
Block a user