自託管 Mac mini M4 Runner 很快,但它仍是「某個區域的電腦」:預設時區、12/24 小時制、一週起始日與排序規則都和你的筆電不同。若 CI 未宣告這些維度,測試會在午夜、夏令時切換,或把工作從香港主機搬到美西主機時突然翻紅。本文提供 兩張決策矩陣、八步推廣清單,以及可寫進 Runbook 的數值門檻,協助 XCTest、快照與伺服器端日期運算與 Runner 和解。
請搭配 不穩定測試隔離與重試、Xcode 固定與升級漂移矩陣,以及 可排程 Mac mini M4 節點 規劃多區矩陣。互動除錯請用 VNC。區域與方案請看 套餐;預設與支援流程見 說明中心。
為何時區與語系會像「硬體不穩定」
Apple Silicon 不會消去行事曆的非決定性。在帳務窗口邊緣呼叫 Date() 的測試,會在 Runner 牆鐘跨過邊界前都綠。語系改變 NumberFormatter 的分組符號,便會撕裂在不同 LANG 錄製的快照。檔名排序若沿用系統預設定序,也可能在 CI 繼承語言特定定序時與 POSIX 假設衝突。
- 午夜邊界:23:55 開跑、00:05 結束的夜間任務,若斷言使用「今天」卻未凍結時鐘,可能重複或漏算日期。
- 夏令時跳躍:春季前進當日 23:30 排程的實際分鐘數少於預期,cron 與「睡滿 3600 秒」假設容易炸開。
- 憑證視窗:TLS 與簽章驗證比對 notBefore/notAfter 與牆鐘;偏移即變間歇性失敗。
- 多區池:同一提交在新加坡與加州 Runner 上可能對「本地星期五」有不同答案,除非你把業務日集中於單一參考時區。
矩陣 A:節點區域與建議的 CI 環境合約
NodeMac 在香港、日本、韓國、新加坡與美國營運裸金屬 Mac mini M4。下表不是 OS 預設的法律保證(營運仍可客製),卻是多數無人值守 Runner 的實際起點。請把合約寫進編排器,避免「新加坡綠了」被誤讀成「全球都綠」。
| 典型 Runner 區域 | 預設牆鐘風險 | 建議 CI 基線 | 額外矩陣任務 |
|---|---|---|---|
| 香港/新加坡 | 亞洲行事曆邊界;國定假日與美國不同 | TZ=UTC,編譯階段 LC_ALL=C.UTF-8 |
每週以 TZ=Asia/Hong_Kong 跑收據類測試 |
| 日本/韓國 | 語系套件齊全;介面文案的週序編號差異 | CLI 日誌固定 LANG=C.UTF-8 |
若出貨日文 UI,快照階段加 ja_JP.UTF-8 |
| 美國 | 12 小時制預設;各州檔案的 DST 規則不一 | 測試中強制 24 小時斷言;勿在未指定語系下解析「下午 3 點」 | DST 切換週:在 XCTest 合成兩個邊界時間 |
| 跨區池 | 同一提交、「本地今天」不一致 | 業務日以 UTC 集中;僅在 UI 邊界轉換 | 加上 timezone-matrix 標籤,紅燈即擋發布 |
矩陣 B:症狀、探針、修復模式
| 症狀 | 快速探針 | 修復模式 |
|---|---|---|
| 僅在 UTC 午夜附近失敗 | 記錄 Runner TZ、系統時鐘、任務開始小時直方圖 |
以依賴注入凍結「現在」;補邊界 XCTest 案例 |
| 數值快照跨主機不一致 | 在任務開頭列印有效 LANG/LC_NUMERIC |
於 launchd plist 或 CI 包裝器設定 LC_ALL=C.UTF-8 |
| TLS 或公證「隨機」失敗 | 以 sntp 偏移對照參考時鐘 |
強制 NTP 守紀;超過門檻即快速失敗 |
| 檔名清單排序不穩 | 在 pre-job 橫幅輸出 locale |
Swift 使用顯式 POSIX 比較器,或 sort 搭配 LC_ALL=C |
可寫進政策的數值門檻
- NTP 絕對偏移:穩態誤差維持在 250 毫秒 內;若 Runner 連續三次檢查超過 2 秒,應通知值班。
- 維護凍結:任何執行客戶端日期邏輯的區域,在 DST 切換前後 72 小時暫停時區實驗。
- 逾時緩衝:操作行事曆的套件,逾時加 15% 牆鐘餘裕,因模擬時間跳躍會非線性拉長 XCTest。
稽核提示:每次上傳 junit.xml 時一併保存有效 TZ、LANG 與量測到的 NTP 偏移。無聲 OS 修補後不穩定消失時,未來的你會感謝現在的你。
八步推廣
- 盤點所有直接呼叫真實時鐘、語系感知格式化器或未指定比較器的檔案排序測試。
- 在 CI 日誌印 preflight 橫幅:時區、語系、OS 構建號、Xcode 版本——與 漂移稽核 同一列。
- 將預設寫入 launchd EnvironmentVariables,讓自託管 Runner 的無 GUI 工作階段與 SSH shell 繼承相同合約。
- 新增小型 XCTest 輔助程式,以依賴注入凍結時間;禁止在業務邏輯測試中裸用
Date()。 - 排每週矩陣,在至少兩個出貨時區重放前二十大日期測試。
- 將 NTP 偏移尖峰與 TLS 失敗關聯告警,通常比重讀封包更快。
- 文件化例外:產品刻意使用本地時間(例如 POS 印表機)時,隔離到帶標籤 Runner。
- 橫向擴展:佇列深度迫使多團隊共用「接近午夜」窗口時,為每區新增專用 Mac mini M4。
常見問題
伺服器與模擬器是否共用同一個 TZ?
否。伺服器端預設 UTC;UI 模擬器可能需要每語系獨跑。在同一個 XCTest 行程內混用且未隔離,常造成雙重失敗。
Apple Silicon 會改變 NTP 行為嗎?
本質上不會。守紀常駐程式仍關鍵。變的是編譯更快——短工作隱藏偏移,直到三十分鐘整合測試才露出來。
今天無法改遺留測試怎麼辦?
以明確標籤隔離、暫時把任務釘在單一區域,並依不穩定手冊排程重寫。正確性優於假裝地理中立。
當行事曆敏感套件需要可預測的金屬、又不想和筆電睡眠或咖啡廳 Wi‑Fi 搏鬥時,NodeMac 上的 Mac mini M4 提供 原生 macOS、SSH 與 VNC、裸金屬上較可預期的時鐘,以及遍及香港、日本、韓國、新加坡與美國的節點,讓管線更靠近使用者。Apple Silicon 以每瓦高吞吐著稱,租用專用機則避開超賣共享 VM 的鄰居噪音。若矩陣證明需要另一區主機,請先從 套餐頁 對照區域再寫 YAML,而不是憑感覺猜。