Files
arcrun-collector/cloud_version.go
T
Leo e516e0dbce t177 修「知識庫需要更新」永遠消不掉:semver 打爆字串比較(兩份都修)
【leo 08-04 實撞】「刷新完兩個雲端,為什麼還要我去更新?」
實測坐實**更新其實成功了**:youlin 實例 /health = 1.4.6、daemon 已 v0.15.3,
但托盤兩個帳號都掛「⚠ 知識庫需要更新(點我)」。

【真兇】版本號 08-02 由 `2026-07-31+8e83589` 改成 semver(`1.4.6`)後,
判斷式仍是 `date < "2026-07-28"` ——**字串比較**:
    "1.4.6"      < "2026-07-28" → true   ⚠️ 最新版被判過舊
    "2026-07-31" < "2026-07-28" → false  舊格式才會對
⇒ **任何 semver 都恆判過舊,更新幾次都消不掉。** 這是 wiki 事故 D,08-02 立案未修。

【修法】照事故 D 定案③「兩種格式都要認」:
semver(X.Y.Z 純數字三段)⇒ 視為新契約、不判過舊;
舊日期格式 ⇒ 維持日期比較,讓尚未更新的老實例仍被正確提示(不為修 A 而漏報 B)。

⚠️ **這 bug 有兩份**(tasks.md:2592 早就寫明),兩份都修:
  collector/cloud_version.go  的 cloudVersionStale
  cmd/arcrun-tray/main.go     的 trayCloudVersionStale

【為什麼會出貨】collector 那份**一直有測試**、tray 那份**完全沒有**
⇒ 沒有任何閘擋得住。本 commit 補上 cmd/arcrun-tray/cloudversion_test.go。

【測試證明有效,非裝飾】暫時把 semver 分支拿掉重跑 → 三個 case 立刻紅
(含「leo 08-04 實撞的那一版」);裝回去即綠。
兩模組全測試綠(collector/supervisor/tray)。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-04 09:38:19 +08:00

83 lines
2.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// cloud_version.go — t103 daemon 雲端版本偵測。
// 每輪 GET {cypher_url}/health 取 bundle_version,比對最低相容日期,
// 過舊時 status.json 記錄,托盤顯示更新入口。
package main
import (
"encoding/json"
"io"
"net/http"
"strings"
"time"
)
// minCloudBuilt 是雲端最低相容建置日期(YYYY-MM-DD)。
// 雲端契約變更(新 API/schema 上線)時手動升此常數;daemon 下一輪自動偵測並提示更新。
const minCloudBuilt = "2026-07-28"
// fetchCloudVersion 可在測試中替換為 stub,避免真實網路呼叫拖慢測試。
var fetchCloudVersion = fetchBundleVersion
// fetchBundleVersion GET {cypherURL}/health 取 bundle_version。
// 5s timeout;失敗(逾時、連不上、非 JSON)靜默回 ("", false)——呼叫端不判定過舊。
func fetchBundleVersion(cypherURL string) (version string, ok bool) {
client := &http.Client{Timeout: 5 * time.Second}
resp, err := client.Get(strings.TrimSuffix(cypherURL, "/") + "/health")
if err != nil {
return "", false
}
defer resp.Body.Close()
var payload struct {
BundleVersion string `json:"bundle_version"`
}
if err := json.NewDecoder(io.LimitReader(resp.Body, 4096)).Decode(&payload); err != nil {
return "", false
}
return payload.BundleVersion, true
}
// cloudVersionStale 判斷雲端是否需要更新。
// checkOK=false/health 不可達)回 false(靜默不判定)。
//
// 🔴 t177wiki 事故 D**這 bug 有兩份,tray 的 trayCloudVersionStale 是另一份,兩份都要修**):
// 版本號 08-02 起改 semver`1.4.6`),舊寫法 `date < "2026-07-28"` 是**字串比較**
// `"1" < "2"` 恆成立 ⇒ 任何 semver 都被判過舊、警告永遠消不掉
// (leo 08-04 實撞:「刷新完兩個雲端,為什麼還要我去更新?」,實例已 1.4.6)。
// ⇒ 照事故 D 定案③「兩種格式都要認」:semver 走版號比較、日期格式走日期比較。
func cloudVersionStale(version string, checkOK bool) bool {
if !checkOK {
return false
}
if version == "" {
return true
}
// bundle_version 格式:semver1.4.608-02 起)或 YYYY-MM-DD+<commit hash>(舊)
head := strings.SplitN(version, "+", 2)[0]
if isSemverLikeVersion(head) {
// 吐得出 semver=雲端已是新契約 ⇒ 不算過舊。
return false
}
// 舊格式:維持日期比較,讓尚未更新的老實例仍被正確提示。
return head < minCloudBuilt
}
// isSemverLikeVersion 判斷字串是否為 `X.Y.Z`(純數字三段)。
// 與 tray 的 isSemverLike 同義;collector 與 tray 不同 package,故各持一份。
func isSemverLikeVersion(s string) bool {
parts := strings.Split(s, ".")
if len(parts) != 3 {
return false
}
for _, p := range parts {
if p == "" {
return false
}
for _, r := range p {
if r < '0' || r > '9' {
return false
}
}
}
return true
}