fix(cli): 更新完還看得到版本號——CLI 重部署不再把版本標籤(和你的設定)洗掉 #107

Merged
Leo merged 1 commits from fix/version-label-106 into main 2026-08-12 14:05:57 +00:00
Owner

Leo/Arcrun#106:更新完 Portal 設定頁顯示「無法讀取目前版本(知識庫服務可能正在啟動)」。


① 我選了哪個解法、為什麼

兩件事一起修,而且它們的規則剛好相反——這是本題的核心判斷:

var 類別 規則 理由
設定類(PORTAL_MAIL_RELAY_BASECONSOLE_TENANT/…) 沿用實例上的值 它是使用者實例的事實。這就是 #97「已部署的 worker 上綁著什麼就是事實」那句話,原封不動套用到 plain_text var 上——#97 保住了櫃子,這次補上櫃子上的標籤。
版本標籤 ARCRUN_BUNDLE_VERSION 每趟重烙,絕不沿用 它是這份成品的屬性,不是設定。

實作位置就在 #97 已經在做的地方:planResources()GET /workers/scripts/{name}/settings 時,
同一份回應裡本來就有 plain_text binding,舊版只挑資源類、把 var 整批丟掉。現在順手帶回來——
不多打一次 API,也不新增一種「查不到」的失敗模式(讀不到綁定已經在 #97 那道門擋掉了)。

排除清單 CLI_MANAGED_VARSWORKER_SUBDOMAIN / CF_ACCOUNT_ID / MULTI_TENANT /
KBDB_BASE_URL / 版本標籤)不沿用——那些是 CLI 這趟自己算出來的,沿用等於拿舊值蓋掉正解。

刻意沒有做「toml 有宣告就以 toml 為準」:repo toml 裡的 CONSOLE_TENANT = "leo" 是官方 prod 的值,
拿它蓋掉使用者實例上的值,就是同一種病的另一面(更新一次把人家的設定洗成官方預設)。

② 更新後那個值該是什麼、依據是什麼

「變成新版本」,不是「沿用舊的」——你的直覺是對的。

沿用舊值會得到一個永遠停在安裝當天的假標籤:程式碼換了、標籤沒換。這比沒有標籤更糟,
因為它會讓你以為驗收過了(正是紅線裡「拿安裝時的舊值充數」那條)。

那新值取哪裡?依據是**「誰在定義『最新版』」:Portal 設定頁與 daemon cloudVersionStale()
都是拿 install.arcrun.dev/api/latestrelease 當最新版來比。所以標籤必須是
同一把尺量得出來的東西**,
否則就算有值也永遠顯示「較舊版本 → 有新版可以更新」(同一個自我維持迴圈,只是換個字)。

ARCRUN_BUNDLE_VERSION = 部署當下該頻道公告的 release(純 semver)。

誠實邊界(要講清楚):CLI 部的是 Leo/Arcrun@main原始碼,semver 是安裝器頻道在發的,
兩者不是同一套編號。語義是「我跟這個頻道的最新發行同源」。所以我另外把真正部署的 commit 一起烙上去

  • 新 var ARCRUN_BUNDLE_COMMIT/health 多吐 bundle_commit
  • 標籤有沒有跟成品漂掉,看 commit 就查得出來(Portal 版本行也會顯示 commit f87d0e9

查不到 release(離線/頻道掛了)→ 不猜、不掰,退成 YYYY-MM-DD+<commit7>(老實例本來就是這個格式)。
Portal 對非 semver 一律顯示「較舊版本」——那正是我們要的:寧可說不準,也不要假裝已是最新

③ 用安裝器裝的那條路有沒有被影響

沒有。 安裝器(arcrun-rag installer/oauth-prototype/worker.js)一行都沒動,它照舊注入自己的版號。
/health 只是多一個「有才吐」的欄位(bundle_commit),安裝器不注入 → 該欄省略,回應與現在一字不差
(有回歸測試看守,見下)。用安裝器裝的實例之後如果跑 acr update,標籤會被換成同一套編號的新版號——
這正是要的行為。


實測輸出

A. Portal 設定頁的版本行——跑的是 console-ui/public/portal/index.html 裡那 79 行原文

這台環境沒有任何可部署的實例(見文末「沒做到的部分」),瀏覽器 MCP 也未授權,
所以無法對「真的更新過的實例」截圖。這支是把設定頁版本檢查那段原始碼從檔案切出來
(不是我重打的)放進最小 DOM stub 跑,餵不同的 /health payload,看那一行真的畫出什麼字。

── 取自 console-ui/public/portal/index.html 的 79 行原文 ──

① 病灶(今天的 leo21c):CLI 更新後 /health 沒有 bundle_version
   版本欄:「無法讀取目前版本(知識庫服務可能正在啟動)」        ← issue 的畫面,重現成功
   「立即更新」鈕:隱藏

② 修好後:acr update 烙了 semver + commit
   版本欄:「目前版本 1.4.41 已是最新版 commit f87d0e9」
   「立即更新」鈕:隱藏                                        ← daemon/Portal 不再判 stale

③ 真的落後的實例(安裝器裝的舊版)
   版本欄:「目前版本 1.4.29 → 最新版 1.4.41 有新版可以更新。…」
   「立即更新」鈕:顯示                                        ← 真的落後時仍會提示(沒被修壞)

④ 帶 build metadata 的版號(youlin 現況 1.4.41+d61+pw66d62stage)
   版本欄:「目前版本 1.4.41+d61+pw66d62stage 已是最新版」      ← 順手修好的:舊寫法一律顯示「較舊版本」

⑤ 老格式(日期+commit)——仍誠實顯示「較舊版本」,行為不變
   版本欄:「目前版本 較舊版本 → 最新版 1.4.41 有新版可以更新。…」
   「立即更新」鈕:顯示

B. 對真實已部署 worker 的唯讀 dry-run(只有 GET,沒有部署、沒有任何寫入)

【唯讀】已部署的 arcrun-cypher-executor(帳號 51a01bfa…,subdomain leo21c)
  deployed=true 資源綁定 8 個 plain_text var 11 個
  現在有沒有版本標籤:❌ 沒有(= issue #106 的症狀)        ← 症狀在真機上核對到了

【修好後】重烙的版本標籤:
    ARCRUN_BUNDLE_VERSION = 1.4.41
    ARCRUN_BUNDLE_COMMIT  = f87d0e92f49690253e7c89c5badc82a08eb5d21b
    來源:1.4.41(發行頻道 https://install.arcrun.dev/api/latest;實際部署 commit f87d0e9)

【修好後】真的會寫進 wrangler.toml 的 [vars](值遮蔽):
    [vars]
    ARCRUN_BUNDLE_VERSION = "1.4.41"
    ARCRUN_BUNDLE_COMMIT = "f87d0e92f49690253e7c89c5badc82a08eb5d21b"
    ENVIRONMENT = "production"
    MULTI_TENANT = "false"
    CF_ACCOUNT_ID = "…(值遮蔽)"
    WORKER_SUBDOMAIN = "…(值遮蔽)"
    KBDB_BASE_URL = "…(值遮蔽)"
    CONSOLE_TENANT = "…(值遮蔽)"
    PORTAL_SESSION_TTL = "…(值遮蔽)"  PORTAL_SHOW_WORKFLOWS = "…(值遮蔽)"
    GITEA_BASE_URL / GITEA_SPRINT_REPO / GITEA_SPRINT_DIR = "…(值遮蔽)"

註:這台實例「要沿用的 var」清單是空的——因為它那 11 個 var 不是 CLI 自己算的(4 個),
就是與 repo toml 同值(其餘)。沿用那一半是用單元測試驗的(下面 ⑦,含
PORTAL_MAIL_RELAY_BASE 這種「安裝器有、repo toml 沒有」的真實情境)。

C. 兩個必要前提是實查的,不是假設

CF /settings 真的回得出 plain_text 的值:
  binding types: {"kv_namespace":7,"secret_text":10,"plain_text":11,"d1":1,"service":13}
  CF_ACCOUNT_ID → [讀得到, 32 字]   PORTAL_SESSION_TTL → [讀得到, 6 字]  …(11 個全部讀得到)
  (secret_text 不碰,CF 本來就不回值)

Gitea 用 sha 下載 archive 真的可行(改用不可變 ref 的前提):
  branch commit id: f87d0e92f49690253e7c89c5badc82a08eb5d21b
  archive-by-sha(real) HTTP 200, 10926115 bytes

D. 測試

cli:node --experimental-transform-types --import ./tests/register-ts-hooks.mjs --test
  # tests 49  # pass 49  # fail 0
  含新增的 #106 ①–⑩:病灶重現/設定 var 沿用/CLI 自算 var 不被沿用/版號重烙不沿用舊值/
  查不到版號時誠實退版(且**不掰 semver**)/模擬整趟更新/applyVars 四種狀態/
  值含 $& 不被 replace 反向參照吃掉/注入 var 不影響資源解析

cypher-executor:npx vitest run tests/health.test.ts
  ✓ tests/health.test.ts (4 tests)
  含回歸:沒有 ARCRUN_BUNDLE_COMMIT 就省略該欄(= 安裝器那條路一字不變)

tsc --noEmit:cli 全綠;cypher-executor 剩 5 個**既有**錯(portal-data.ts / portal.ts,與本次無關)。
  順手修掉 types.ts 的 `ARCRUN_BUNDLE_VERSION` 重複宣告(TS2300,就在動到的那一行旁邊)。

cypher-executor 全套 416 項中有 14 項失敗——**進本分支之前就是這樣**:
把本分支的 cypher 變更 stash 掉重跑,同樣是那 14 項(auth-dispatcher / console-library-map-page /
executor / portal-admin / portal-data),與本次無關。

E. 附帶修好的東西(都在同一條路上)

  • acr update 現在用 commit sha 下載 archive:先問 Gitea main 的 sha,再抓那個 sha 的 tarball。
    不可變 ⇒ 順手把 #13 P2「branch tarball 被中間層快取成舊的,deploy 回 ✓ 但 ship 的是舊碼」整個病根拿掉,
    而且「這趟到底部了哪個 commit」現在會印在畫面上、也烙進標籤裡。
  • cli 的測試本來在 node 22 上一支都跑不起來src/ 內部 import 寫 .jsoutDirdist
    型別剝離不會把 .js 對回 .ts;加上 parameter property 需要 --experimental-transform-types)。
    補了一個只在「預設解析失敗時」才動作的 resolve hook。#97 那份「使用者的東西還在不在」的迴歸守衛也在裡面
    ——跑不起來的守衛等於沒有守衛。

🔴 沒做到的部分(誠實標,不算通)

沒有在真實實例上跑過 acr update,也沒有真實 Portal 的截圖。 原因是環境的硬限制,不是省略:

  1. 本機 ~/.arcrun/config.yaml 指的是 leo21c(account 51a01bfa…)——紅線禁碰
  2. 那把 CF token 看得到的兩個帳號都不是 youlin(GET /accounts 實查:leo21c + 另一個無 workers subdomain 的帳號)。
    youlin 這台沒有任何憑證可用,指定的測試靶場我進不去。
  3. 這個 session 的 wrangler 一律需要人工核准(連 wrangler --version 都是),瀏覽器 MCP 同樣未授權。

⇒ CP 狀態:◐ 半通。前端這一半(給定 payload 畫什麼)與後端這一半(會寫進去什麼)
都各自有實跑證據,但**「在一台真的實例上按下更新、再打開設定頁看」這一步沒有人做過**。

接手的人只要有 youlin 憑證,驗收是三行

acr update                                            # 畫面上會印:版本標籤 = <版號>(commit <sha7>)
curl -s https://arcrun-cypher-executor.<sub>.workers.dev/health | jq '.bundle_version, .bundle_commit'
# 然後打開 Portal 設定頁看「版本」欄 → 應為「目前版本 <版號> 已是最新版 commit <sha7>」

其他待人確認的:

  • daemon cloudVersionStale() 沒被讀過(它住在 arcrun-rag,本 repo 看不到)。
    推論是「純 semver 就會判對」,因為 Portal 用的是同一支 /api/latest——但這是推論,不是實證。
  • .worker-builds/ 沒有重編(出貨路徑 A 的成品)。本次修法不需要它:CLI 是從原始碼部署的,
    bundle_commit 只有 CLI 那條路會注入,安裝器不注入。要不要順手重編是另一個 chore。
  • console-ui 的 Portal 改動走 arcrun-rag 的 UI bundle 出貨,不隨這個 PR 到使用者手上。
    主修法不依賴它(烙的是純 semver,現行 Portal 本來就看得懂)。
修 `Leo/Arcrun#106`:更新完 Portal 設定頁顯示「無法讀取目前版本(知識庫服務可能正在啟動)」。 --- ## ① 我選了哪個解法、為什麼 **兩件事一起修,而且它們的規則剛好相反**——這是本題的核心判斷: | var 類別 | 規則 | 理由 | |---|---|---| | 設定類(`PORTAL_MAIL_RELAY_BASE`/`CONSOLE_TENANT`/…) | **沿用實例上的值** | 它是**使用者實例的事實**。這就是 `#97`「已部署的 worker 上綁著什麼就是事實」那句話,原封不動套用到 plain_text var 上——`#97` 保住了櫃子,這次補上櫃子上的標籤。 | | 版本標籤 `ARCRUN_BUNDLE_VERSION` | **每趟重烙,絕不沿用** | 它是**這份成品的屬性**,不是設定。 | 實作位置就在 `#97` 已經在做的地方:`planResources()` 讀 `GET /workers/scripts/{name}/settings` 時, 同一份回應裡本來就有 `plain_text` binding,舊版只挑資源類、把 var 整批丟掉。現在順手帶回來—— **不多打一次 API,也不新增一種「查不到」的失敗模式**(讀不到綁定已經在 `#97` 那道門擋掉了)。 排除清單 `CLI_MANAGED_VARS`(`WORKER_SUBDOMAIN` / `CF_ACCOUNT_ID` / `MULTI_TENANT` / `KBDB_BASE_URL` / 版本標籤)不沿用——那些是 CLI 這趟自己算出來的,沿用等於拿舊值蓋掉正解。 刻意**沒有**做「toml 有宣告就以 toml 為準」:repo toml 裡的 `CONSOLE_TENANT = "leo"` 是官方 prod 的值, 拿它蓋掉使用者實例上的值,就是同一種病的另一面(更新一次把人家的設定洗成官方預設)。 ## ② 更新後那個值該是什麼、依據是什麼 **「變成新版本」,不是「沿用舊的」——你的直覺是對的。** 沿用舊值會得到一個**永遠停在安裝當天的假標籤**:程式碼換了、標籤沒換。這比沒有標籤更糟, 因為它會讓你以為驗收過了(正是紅線裡「拿安裝時的舊值充數」那條)。 那新值取哪裡?依據是**「誰在定義『最新版』」**:Portal 設定頁與 daemon `cloudVersionStale()` 都是拿 `install.arcrun.dev/api/latest` 的 `release` 當最新版來比。所以標籤必須是**同一把尺量得出來的東西**, 否則就算有值也永遠顯示「較舊版本 → 有新版可以更新」(同一個自我維持迴圈,只是換個字)。 ⇒ `ARCRUN_BUNDLE_VERSION` = 部署當下該頻道公告的 `release`(純 semver)。 **誠實邊界(要講清楚)**:CLI 部的是 `Leo/Arcrun@main` 的**原始碼**,semver 是**安裝器頻道**在發的, 兩者不是同一套編號。語義是「我跟這個頻道的最新發行同源」。所以我**另外把真正部署的 commit 一起烙上去**: - 新 var `ARCRUN_BUNDLE_COMMIT`,`/health` 多吐 `bundle_commit` - 標籤有沒有跟成品漂掉,看 commit 就查得出來(Portal 版本行也會顯示 `commit f87d0e9`) 查不到 release(離線/頻道掛了)→ **不猜、不掰**,退成 `YYYY-MM-DD+<commit7>`(老實例本來就是這個格式)。 Portal 對非 semver 一律顯示「較舊版本」——那正是我們要的:**寧可說不準,也不要假裝已是最新**。 ## ③ 用安裝器裝的那條路有沒有被影響 **沒有。** 安裝器(`arcrun-rag` `installer/oauth-prototype/worker.js`)一行都沒動,它照舊注入自己的版號。 `/health` 只是多一個「有才吐」的欄位(`bundle_commit`),安裝器不注入 → 該欄省略,回應與現在一字不差 (有回歸測試看守,見下)。用安裝器裝的實例之後如果跑 `acr update`,標籤會被換成同一套編號的新版號—— 這正是要的行為。 --- # 實測輸出 ## A. Portal 設定頁的版本行——**跑的是 `console-ui/public/portal/index.html` 裡那 79 行原文** > 這台環境**沒有任何可部署的實例**(見文末「沒做到的部分」),瀏覽器 MCP 也未授權, > 所以無法對「真的更新過的實例」截圖。這支是把設定頁版本檢查那段**原始碼從檔案切出來** > (不是我重打的)放進最小 DOM stub 跑,餵不同的 `/health` payload,看那一行真的畫出什麼字。 ``` ── 取自 console-ui/public/portal/index.html 的 79 行原文 ── ① 病灶(今天的 leo21c):CLI 更新後 /health 沒有 bundle_version 版本欄:「無法讀取目前版本(知識庫服務可能正在啟動)」 ← issue 的畫面,重現成功 「立即更新」鈕:隱藏 ② 修好後:acr update 烙了 semver + commit 版本欄:「目前版本 1.4.41 已是最新版 commit f87d0e9」 「立即更新」鈕:隱藏 ← daemon/Portal 不再判 stale ③ 真的落後的實例(安裝器裝的舊版) 版本欄:「目前版本 1.4.29 → 最新版 1.4.41 有新版可以更新。…」 「立即更新」鈕:顯示 ← 真的落後時仍會提示(沒被修壞) ④ 帶 build metadata 的版號(youlin 現況 1.4.41+d61+pw66d62stage) 版本欄:「目前版本 1.4.41+d61+pw66d62stage 已是最新版」 ← 順手修好的:舊寫法一律顯示「較舊版本」 ⑤ 老格式(日期+commit)——仍誠實顯示「較舊版本」,行為不變 版本欄:「目前版本 較舊版本 → 最新版 1.4.41 有新版可以更新。…」 「立即更新」鈕:顯示 ``` ## B. 對**真實已部署 worker** 的唯讀 dry-run(只有 GET,沒有部署、沒有任何寫入) ``` 【唯讀】已部署的 arcrun-cypher-executor(帳號 51a01bfa…,subdomain leo21c) deployed=true 資源綁定 8 個 plain_text var 11 個 現在有沒有版本標籤:❌ 沒有(= issue #106 的症狀) ← 症狀在真機上核對到了 【修好後】重烙的版本標籤: ARCRUN_BUNDLE_VERSION = 1.4.41 ARCRUN_BUNDLE_COMMIT = f87d0e92f49690253e7c89c5badc82a08eb5d21b 來源:1.4.41(發行頻道 https://install.arcrun.dev/api/latest;實際部署 commit f87d0e9) 【修好後】真的會寫進 wrangler.toml 的 [vars](值遮蔽): [vars] ARCRUN_BUNDLE_VERSION = "1.4.41" ARCRUN_BUNDLE_COMMIT = "f87d0e92f49690253e7c89c5badc82a08eb5d21b" ENVIRONMENT = "production" MULTI_TENANT = "false" CF_ACCOUNT_ID = "…(值遮蔽)" WORKER_SUBDOMAIN = "…(值遮蔽)" KBDB_BASE_URL = "…(值遮蔽)" CONSOLE_TENANT = "…(值遮蔽)" PORTAL_SESSION_TTL = "…(值遮蔽)" PORTAL_SHOW_WORKFLOWS = "…(值遮蔽)" GITEA_BASE_URL / GITEA_SPRINT_REPO / GITEA_SPRINT_DIR = "…(值遮蔽)" ``` 註:這台實例「要沿用的 var」清單是空的——因為它那 11 個 var 不是 CLI 自己算的(4 個), 就是與 repo toml 同值(其餘)。**沿用那一半是用單元測試驗的**(下面 ⑦,含 `PORTAL_MAIL_RELAY_BASE` 這種「安裝器有、repo toml 沒有」的真實情境)。 ## C. 兩個必要前提是實查的,不是假設 ``` CF /settings 真的回得出 plain_text 的值: binding types: {"kv_namespace":7,"secret_text":10,"plain_text":11,"d1":1,"service":13} CF_ACCOUNT_ID → [讀得到, 32 字] PORTAL_SESSION_TTL → [讀得到, 6 字] …(11 個全部讀得到) (secret_text 不碰,CF 本來就不回值) Gitea 用 sha 下載 archive 真的可行(改用不可變 ref 的前提): branch commit id: f87d0e92f49690253e7c89c5badc82a08eb5d21b archive-by-sha(real) HTTP 200, 10926115 bytes ``` ## D. 測試 ``` cli:node --experimental-transform-types --import ./tests/register-ts-hooks.mjs --test # tests 49 # pass 49 # fail 0 含新增的 #106 ①–⑩:病灶重現/設定 var 沿用/CLI 自算 var 不被沿用/版號重烙不沿用舊值/ 查不到版號時誠實退版(且**不掰 semver**)/模擬整趟更新/applyVars 四種狀態/ 值含 $& 不被 replace 反向參照吃掉/注入 var 不影響資源解析 cypher-executor:npx vitest run tests/health.test.ts ✓ tests/health.test.ts (4 tests) 含回歸:沒有 ARCRUN_BUNDLE_COMMIT 就省略該欄(= 安裝器那條路一字不變) tsc --noEmit:cli 全綠;cypher-executor 剩 5 個**既有**錯(portal-data.ts / portal.ts,與本次無關)。 順手修掉 types.ts 的 `ARCRUN_BUNDLE_VERSION` 重複宣告(TS2300,就在動到的那一行旁邊)。 cypher-executor 全套 416 項中有 14 項失敗——**進本分支之前就是這樣**: 把本分支的 cypher 變更 stash 掉重跑,同樣是那 14 項(auth-dispatcher / console-library-map-page / executor / portal-admin / portal-data),與本次無關。 ``` ## E. 附帶修好的東西(都在同一條路上) - **`acr update` 現在用 commit sha 下載 archive**:先問 Gitea `main` 的 sha,再抓那個 sha 的 tarball。 不可變 ⇒ 順手把 `#13 P2`「branch tarball 被中間層快取成舊的,deploy 回 ✓ 但 ship 的是舊碼」整個病根拿掉, 而且「這趟到底部了哪個 commit」現在會印在畫面上、也烙進標籤裡。 - **cli 的測試本來在 node 22 上一支都跑不起來**(`src/` 內部 import 寫 `.js`、`outDir` 是 `dist`, 型別剝離不會把 `.js` 對回 `.ts`;加上 parameter property 需要 `--experimental-transform-types`)。 補了一個只在「預設解析失敗時」才動作的 resolve hook。**`#97` 那份「使用者的東西還在不在」的迴歸守衛也在裡面** ——跑不起來的守衛等於沒有守衛。 --- # 🔴 沒做到的部分(誠實標,不算通) **沒有在真實實例上跑過 `acr update`,也沒有真實 Portal 的截圖。** 原因是環境的硬限制,不是省略: 1. 本機 `~/.arcrun/config.yaml` 指的是 **leo21c**(account `51a01bfa…`)——**紅線禁碰**。 2. 那把 CF token 看得到的兩個帳號都不是 youlin(`GET /accounts` 實查:leo21c + 另一個無 workers subdomain 的帳號)。 **youlin 這台沒有任何憑證可用**,指定的測試靶場我進不去。 3. 這個 session 的 `wrangler` 一律需要人工核准(連 `wrangler --version` 都是),瀏覽器 MCP 同樣未授權。 ⇒ CP 狀態:**◐ 半通**。前端這一半(給定 payload 畫什麼)與後端這一半(會寫進去什麼) 都各自有實跑證據,但**「在一台真的實例上按下更新、再打開設定頁看」這一步沒有人做過**。 **接手的人只要有 youlin 憑證,驗收是三行**: ```bash acr update # 畫面上會印:版本標籤 = <版號>(commit <sha7>) curl -s https://arcrun-cypher-executor.<sub>.workers.dev/health | jq '.bundle_version, .bundle_commit' # 然後打開 Portal 設定頁看「版本」欄 → 應為「目前版本 <版號> 已是最新版 commit <sha7>」 ``` 其他待人確認的: - **daemon `cloudVersionStale()` 沒被讀過**(它住在 `arcrun-rag`,本 repo 看不到)。 推論是「純 semver 就會判對」,因為 Portal 用的是同一支 `/api/latest`——但這是推論,不是實證。 - **`.worker-builds/` 沒有重編**(出貨路徑 A 的成品)。本次修法不需要它:CLI 是從原始碼部署的, 而 `bundle_commit` 只有 CLI 那條路會注入,安裝器不注入。要不要順手重編是另一個 chore。 - **`console-ui` 的 Portal 改動走 arcrun-rag 的 UI bundle 出貨**,不隨這個 PR 到使用者手上。 主修法不依賴它(烙的是純 semver,現行 Portal 本來就看得懂)。
Leo added 1 commit 2026-08-12 14:00:41 +00:00
leo 08-12 實撞:更新完 leo21c,Portal 設定頁的「版本」變成
「無法讀取目前版本(知識庫服務可能正在啟動)」。版本號是 leo 唯一的驗收介面,
看不到就等於他無法自己確認任何一次更新有沒有生效。

根因(Arcrun#106):`bundle_version` 來自部署時注入的 plain_text var
`ARCRUN_BUNDLE_VERSION`,而**只有安裝器會注入**。wrangler deploy 是整份覆蓋,
toml 沒寫的 var 直接消失 ⇒ CLI 更新那條路每跑一次就把標籤洗掉一次。
#97 修好了「櫃子」(KV/D1/Vectorize 沿用既有),沒修「櫃子上的標籤」。

修法(兩種 var 走相反的規則,這是本次的判斷):
· 設定類 var = 使用者實例的事實 → **沿用**(讀綁定時同一份回應就帶回來,不多打 API)
  ——把 #97「已部署的 worker 上綁著什麼就是事實」原封不動套用到 plain_text var。
· 版本標籤 = 這份成品的屬性 → **每趟重烙,絕不沿用舊值**。
  沿用舊值會得到一個永遠停在安裝當天的假標籤——比沒有標籤更糟,
  因為它會讓人以為驗收過了。
  版號取部署當下發行頻道公告的 release(Portal/daemon 就是拿它當「最新版」比),
  另外把**真正部署的 commit** 一起烙上去(/health 多吐 `bundle_commit`)→ 漂掉查得出來。
  查不到 release 就誠實退成 `YYYY-MM-DD+<commit7>`,不掰一個 semver 假裝已是最新。

順帶(都是同一條路上的東西):
· ref 先解析成 commit sha 再用 sha 下載 archive——不可變,順手解掉 branch tarball 被快取的老病
· Portal 版本行接受帶 build metadata 的 semver(`1.4.41+d61` 這種先前一律被當成「較舊版本」)
· cli 測試在 node 22 上本來一支都跑不起來(.js→.ts 解析 + parameter property),補上 resolve hook
  ——#97 那份「使用者的東西還在不在」的迴歸守衛也在其中,跑不起來的守衛等於沒有守衛
· types.ts 的 ARCRUN_BUNDLE_VERSION 重複宣告(TS2300)併回一處

驗證見 PR:cli 49/49 綠、cypher health 4/4 綠、Portal 版本行原始碼實跑五種情境、
對真實已部署 worker 的唯讀 dry-run。**未做**:真實實例上的 acr update 端到端
(本機唯一有憑證的帳號是 leo21c=紅線禁碰,youlin 無憑證)。

Refs: Leo/Arcrun#106, #97, #95

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Leo merged commit 21293568d5 into main 2026-08-12 14:05:57 +00:00
Sign in to join this conversation.