53b05c6d3d
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>
59 lines
2.7 KiB
TypeScript
59 lines
2.7 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
||
import { SELF } from 'cloudflare:test';
|
||
import { healthRouter } from '../src/routes/health';
|
||
import type { Bindings, ExecutionContext } from '../src/types';
|
||
|
||
describe('GET /health — bundle_version 欄位', () => {
|
||
it('無 ARCRUN_BUNDLE_VERSION 時省略該欄(老實例情境)', async () => {
|
||
// wrangler.test.toml 不設此 var → health.ts 省略 bundle_version 欄位。
|
||
// daemon 端讀不到該欄=當作空字串=判 stale,對老實例而言**這是正確行為**
|
||
//(見 health.ts 檔頭註解)。此處驗「省略」而非「回空字串」,與實作對齊。
|
||
const res = await SELF.fetch('http://localhost/health');
|
||
const data = await res.json() as { ok: boolean; bundle_version?: string };
|
||
expect(res.status).toBe(200);
|
||
expect(data.ok).toBe(true);
|
||
expect(data.bundle_version).toBeUndefined();
|
||
});
|
||
|
||
it('有 ARCRUN_BUNDLE_VERSION 時回其值(安裝器注入情境)', async () => {
|
||
const fakeEnv = { ARCRUN_BUNDLE_VERSION: '2026-07-28/6d06162' } as unknown as Bindings;
|
||
const res = await healthRouter.fetch(
|
||
new Request('http://localhost/health'),
|
||
fakeEnv,
|
||
{} as ExecutionContext,
|
||
);
|
||
const data = await res.json() as { ok: boolean; bundle_version: string };
|
||
expect(data.ok).toBe(true);
|
||
expect(data.bundle_version).toBe('2026-07-28/6d06162');
|
||
});
|
||
|
||
// Arcrun#106:CLI 更新那條路會多烙一個 commit(版號=發行頻道編號,commit=真的部了哪份碼)。
|
||
it('有 ARCRUN_BUNDLE_COMMIT 時一起回(acr update 注入情境)', async () => {
|
||
const fakeEnv = {
|
||
ARCRUN_BUNDLE_VERSION: '1.4.41',
|
||
ARCRUN_BUNDLE_COMMIT: 'f87d0e92f49690253e7c89c5badc82a08eb5d21b',
|
||
} as unknown as Bindings;
|
||
const res = await healthRouter.fetch(
|
||
new Request('http://localhost/health'),
|
||
fakeEnv,
|
||
{} as ExecutionContext,
|
||
);
|
||
const data = await res.json() as { bundle_version: string; bundle_commit: string };
|
||
expect(data.bundle_version).toBe('1.4.41');
|
||
expect(data.bundle_commit).toBe('f87d0e92f49690253e7c89c5badc82a08eb5d21b');
|
||
});
|
||
|
||
// 安裝器那條路沒有這個 var(回歸:不能因為多了新欄位就讓舊路徑多吐一個空字串出來)。
|
||
it('沒 ARCRUN_BUNDLE_COMMIT 就省略該欄(安裝器路徑不受影響)', async () => {
|
||
const fakeEnv = { ARCRUN_BUNDLE_VERSION: '1.4.41' } as unknown as Bindings;
|
||
const res = await healthRouter.fetch(
|
||
new Request('http://localhost/health'),
|
||
fakeEnv,
|
||
{} as ExecutionContext,
|
||
);
|
||
const data = await res.json() as { bundle_version: string; bundle_commit?: string };
|
||
expect(data.bundle_version).toBe('1.4.41');
|
||
expect(data.bundle_commit).toBeUndefined();
|
||
});
|
||
});
|