feat(version): 對外號真的不帶 v + release 掛得動成品 + 內外對應由機器產生(arcrun-rag#88)
leo 2026-08-18 當場抓到「剛剛不是說不要 v?」——實查確認不是措辭問題: 規約寫在 wiki,而**產生號碼的那條路照舊帶 v**。這輪修的是產地與載體。 ① 對外號從**產生端**就是裸的 `daemon-version.py` 是 daemon 那條線唯一的版本產生器,一路長到 產物檔名(Arcrun-<版本>.dmg)、manifest.daemon.version、/api/latest。 - 新戳的版本一律裸號;`RELEASED_RE` 加 `v?` 讀得懂歷史 - 🔴 重打同一版**沿用 changelog 上原本的寫法**:selfupdate.go 的 newerThanCurrent() 是字串不等於就提示更新 ⇒ 把 v0.18.28 改吐成 0.18.28 會讓每台已安裝的機器收到一個內容相同卻宣稱是新版的**假更新**。 規約會自己過期:頂上那段變裸號之後,重打路徑吐的也是裸號。 - 實測:真實 changelog +一段未發佈 → 產生器吐 `0.18.30`(不是 v0.18.30) ② release 掛得動真的成品(本輪的硬前置) leo:「assets 都寫 source code,這兩個附檔實際是什麼?是 dmg 還是 go?」 ——那是 Gitea/GitHub 自動產生的整包 repo 快照。實測既有 release 的 attachment 數是 **0**,坐實那兩個附檔沒有一個是成品。 - gitea/github-release.mjs 各補 uploadReleaseAsset/listReleaseAssets (兩邊 API 形狀不同是 API 本身的差別,不硬套成同一種) - release-lines.mjs 讓**每條版本線各自宣告**自己的成品(assetKeys); daemon 線明列 mac/win/msix,**排除釘在 0.15.7 的兩筆歷史遺留** ——照「有 file 欄就掛」會把舊檔掛上新版頁面,正是本輪要治的病 - ship.mjs 建完 release 後掛檔,並**回頭查證**附件真的在頁面上; 缺任何一個就擋(不留「點下去沒東西」的版本頁) ③ 內外對應由機器產生,不再是總管手寫 leo:「對應關係記在該次發佈的 release note,不靠號碼本身編碼」 - 新增 internal-version.mjs:`RAG-20260818-001-<commit7>` - 🔴 `formatInternalVersion` 收到空的 artifacts 直接丟例外 ⇒ **算不出一個沒有成品的內部號**(leo:「內部每次就要出貨 bundle 的版本」)。 ops-facts 原本記著「這件事目前靠自律,沒有機械閘」——這就是那道閘 - 序號從**既有 release 的事實**算,不養會漂的帳;tag 與內文都掃 (08-17 那兩筆內部號寫在 tag_name 上,只掃內文當天會從 1 重編、無聲撞號) 紅線遵守:既有 tag/檔名一個都沒回頭改;沒寫 GitHub(②③ 實測都在 Gitea); 沒部署、沒推 main、沒自己併分支。演練建的 release 與 tag 都已刪除複驗。 測試:installer 252 支全綠(原 233 +新 19);collector 產生器新增 6 支全綠。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -71,7 +71,31 @@ SOURCE_LOCK = HERE / ".version-source.json"
|
||||
# 因此全部改變(`collector/cmd/…` → `cmd/…`)⇒ 舊帳本是「用不同單位量出來的數字」,
|
||||
# 比對沒有意義。照既有設計改號讓它自動整本作廢重記,不要手改 JSON。
|
||||
FINGERPRINT_ALGO = 4
|
||||
RELEASED_RE = re.compile(r"^## v(\d+)\.(\d+)\.(\d+)(", re.M)
|
||||
|
||||
# 🔴 2026-08-18(inkstone/arcrun-rag#88):**對外號是三個數字,不帶 `v`**
|
||||
# (leo 2026-08-17「不要 v」,全文 InkStoneCo `system-dev/wiki/ops-facts.md` §「定案」)。
|
||||
#
|
||||
# 這裡就是那個 `v` 的產地。在此之前本檔一律吐 `v0.18.28`,而那個字串一路長到
|
||||
# 使用者眼前的每一處:
|
||||
# · `build-dmg.sh` 的 `Arcrun-${VERSION}.dmg` → 產物檔名
|
||||
# · `manifest.daemon.version` → 桌面小幫手「檢查更新」讀的欄位
|
||||
# · `install.arcrun.dev/api/latest` 的 `daemon.version` → 安裝頁讀的欄位
|
||||
# ⇒ 規約寫在 wiki 上,而**產生號碼的那條路照舊帶 v**。改任何字串常數都改不掉它,
|
||||
# 要改的是這支唯一的產生器。
|
||||
#
|
||||
# ── 過渡怎麼走:書寫形式由 changelog 那一行決定,新戳的一律裸號 ──────────
|
||||
# 紅線是「既有已發出的 tag/檔名不回頭改」。這不是潔癖,是會壞東西:
|
||||
# `selfupdate.go` 的 `newerThanCurrent()` 判斷更新用的是**字串不等於**
|
||||
# (`strings.TrimSpace(latest) != cur`,比對 `manifest.daemon.version` 與編進執行檔的字串)
|
||||
# ⇒ 若「重打同一版」時把 `v0.18.28` 改吐成 `0.18.28`,每一台已安裝的機器
|
||||
# 都會看到一個**內容一模一樣、卻宣稱是新版**的更新。那是自己製造的假更新。
|
||||
#
|
||||
# ⇒ 所以規則只有一條:**這一版怎麼寫,看 changelog 上那一行怎麼寫;
|
||||
# 而新戳出來的那一行一律裸號。** 下一次真的升版(0.18.29)就是裸的;
|
||||
# 舊的 28 一輩子維持 `v0.18.28`,兩邊都不必記得任何例外。
|
||||
# 這條規則**會自己過期**:頂上那段變成裸號之後,重打路徑吐的也是裸號,
|
||||
# `v?` 只剩「讀得懂歷史」的作用。
|
||||
RELEASED_RE = re.compile(r"^## (v?)(\d+)\.(\d+)\.(\d+)(", re.M)
|
||||
|
||||
|
||||
def die(msg):
|
||||
@@ -185,8 +209,11 @@ def main():
|
||||
text = CHANGELOG.read_text()
|
||||
top = RELEASED_RE.search(text)
|
||||
if not top:
|
||||
die("❌ changelog 裡找不到任何 `## vX.Y.Z(…)` 的版本段落")
|
||||
prev = (int(top.group(1)), int(top.group(2)), int(top.group(3)))
|
||||
die("❌ changelog 裡找不到任何 `## X.Y.Z(…)` 的版本段落(舊的 `## vX.Y.Z(…)` 也認)")
|
||||
# group(1) 是那一版**當初怎麼寫的**('v' 或空字串)——重打同一版時要原樣沿用,
|
||||
# 否則已安裝的機器會收到一個內容相同卻宣稱是新版的假更新(見 RELEASED_RE 上方)。
|
||||
prev_prefix = top.group(1)
|
||||
prev = (int(top.group(2)), int(top.group(3)), int(top.group(4)))
|
||||
|
||||
has_unreleased = UNRELEASED in text
|
||||
if has_unreleased and text.index(UNRELEASED) > top.start():
|
||||
@@ -194,7 +221,9 @@ def main():
|
||||
|
||||
if not has_unreleased:
|
||||
# 沒有待發佈內容=重打同一版。冪等,不虛增。
|
||||
version = "v%d.%d.%d" % prev
|
||||
# 🔴 沿用那一版**當初的書寫形式**:重打 `v0.18.28` 還是叫 `v0.18.28`,
|
||||
# 產物檔名與 manifest 欄位都不變 ⇒ 已安裝的機器不會看到假更新。
|
||||
version = "%s%d.%d.%d" % ((prev_prefix,) + prev)
|
||||
check_or_record(version, stamp)
|
||||
if stamp:
|
||||
print(" ℹ️ changelog 沒有「下一版(未發佈)」段,版本維持 %s(重打同一版)"
|
||||
@@ -208,7 +237,10 @@ def main():
|
||||
nxt = (major, minor, 0)
|
||||
else:
|
||||
nxt = (prev[0], prev[1], prev[2] + 1)
|
||||
version = "v%d.%d.%d" % nxt
|
||||
# 🔴 新版一律**裸號**(leo 2026-08-17「不要 v」)。這一行就是規約真的被執行的地方:
|
||||
# 往下 `heading` 寫進 changelog、`print(version)` 餵給 build-*.sh 的 `${VERSION}`,
|
||||
# 所以檔名(`Arcrun-0.18.29.dmg`)與 manifest.daemon.version 同時就跟著裸了。
|
||||
version = "%d.%d.%d" % nxt
|
||||
|
||||
if stamp:
|
||||
check_or_record(version, True)
|
||||
|
||||
Reference in New Issue
Block a user