feat(server): show whether a server runs ZeaburOS in get and list#267
Conversation
agent 拿到一個 server ID 之後無從判斷它是不是 ZeaburOS——`server get` / `server list` 都不露出這個資訊。結果 skills 只能靠反推:打一個 kubectl 指令看它會不會 `command not found`。這浪費一次 SSH round trip,而且在「要不要 在這台建專案」之前根本判斷不了。 `hasK3s` 早就在 GraphQL schema 上,純 CLI 端補齊即可,後端零改動。query 由 struct tag 反射生成,所以 model 加欄位就自動帶進 query。 - `server get` / `server list` 加 OS 欄(ZeaburOS / Ubuntu)。 - JSON 輸出除了原始 `HasK3s`,另外導出 `os` 字串——這是本次的主要目的, 讓呼叫端不必自己記三態語意,表格顯示只是附帶。 `hasK3s` 是三態,第三態是陷阱:`null` 代表 legacy server,而它**是** ZeaburOS(後端從 certificate data 推導,但 GraphQL 綁的是原始欄位,推導不會 上 wire)。所以判斷式是 `== false`,不是 `!hasK3s`——後者會把所有舊機器掃進 來、悄悄從部署目標裡消失。與 dashboard 的 `isCleanMachine()` 契約一致。 順帶修資源欄位的兩個顯示問題: - total 為 0 時印 `—` 而非 `0/0 MB`。零總量是「未測得」的契約(真實機器不可能 0 核),印 `0/0` 會讀成機器出事,而不是指標還沒收集到。乾淨 VPS 現在也會回 傳 CPU/RAM/Disk 了,這條路徑才開始有機會踩到。 - CPU 標上單位 `m`。後端回的是 millicore,4 核機器讀出來是 4000,沒有單位會 看成 4000 核。與 dashboard 的 k8s 風格顯示一致。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
📝 WalkthroughWalkthroughServer models now derive ZeaburOS or Ubuntu labels from the tri-state 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Comment |
|
LGTM ✅ — CLI-only change correctly exposes server OS via three-state hasK3s derivation with solid test coverage. What This PR DoesAdds an How It Works
Findings
What's Good (🟢)
Baseline Check
Review Metadata
🔴×0 🟡×0 🟢×5 · 💬 Comment |
get and list
Background
Renting a server provisions the base OS only — installing Zeabur services is a separate, optional step. Whether a machine runs ZeaburOS is therefore a real branch point: it determines whether the machine can host Zeabur projects at all.
Neither
server getnorserver listexposed this. Given a server ID, there was no way to tell the two apart short of running akubectlcommand over SSH and checking whether it fails withcommand not found— a wasted round trip that also cannot be done before deciding whether to create a project on that machine.hasK3shas been on theServertype in the GraphQL schema all along, so this is a CLI-side change with no backend work. Queries are generated by reflecting over struct tags, so adding the field to the model puts it in the query —pkg/api/server.gois untouched.Changes
server getandserver listgain an OS column (ZeaburOS/Ubuntu).osstring alongside the rawHasK3s. This is the main point of the change — callers should not have to rediscover the field's three-state semantics. The table column is a convenience on top.hasK3sis three-state, and the third state is a traptruefalsenullThe backend infers the legacy case from the server's certificate data, but the GraphQL field is bound to the raw column, so that inference never reaches the wire. The test is therefore
== false, never!hasK3s: the latter would sweep every legacy server in and quietly mislabel it. This mirrors the equivalent contract in the dashboard, and is pinned by unit tests.Two fixes to the resource columns, while in the area
—instead of0/0 MB. Zero total is the contract for "not measured" — a real machine cannot have zero cores. Printing0/0reads as a machine in trouble rather than one whose metrics have not been collected yet. Servers without Zeabur services only recently started reporting CPU/RAM/disk, so this path is newly reachable.m). The backend reports millicores, so a 4-core machine reads as4000; without a unit that looks like 4000 cores. Matches the k8s-style units the dashboard already uses.Verification
go build ./...andgo test ./...pass. Newpkg/model/server_test.gocovers all three states (includingnull), the—rendering, and that JSON carriesoswhile retaining the rawHasK3s.hasK3s: true; thefalseandnullstates are covered by unit tests.Out of scope
Gi.🤖 Generated with Claude Code