self-hosted CI runner 有個尷尬的特點:它什麼都記得。快取、token,還有去年春天某人「臨時」加上的部署金鑰。對您自己的分支來說沒問題。但一旦有陌生人提交 pull request——或者您自己的 AI 代理寫了一個還沒人讀過的修補程式——問題就來了。
乾淨的做法是每次執行一台機器。克隆、安裝、測試,然後把機器扔掉。
一次執行是什麼樣的
沙箱是一台 Firecracker microVM,大約一秒啟動,內建 Python 3.12、Node.js 22、git 和 curl。對外網路可用,所以 git clone 和 pip install -r requirements.txt 照常工作。沒有對內埠——執行期間任何東西都無法連入測試環境。
在 CI 任務裡,整個流程就是一段短指令碼。下面是用 Python SDK 寫的版本,可從任何 CI 任務呼叫:
import os, sys
from eqvps import Sandbox
repo, ref = os.environ["REPO_URL"], os.environ["PR_SHA"]
with Sandbox.create(tariff="standard", ttl=1800) as sb:
sb.exec(f"git clone {repo} /root/app && cd /root/app && git checkout {ref}", timeout=55)
sb.exec("cd /root/app && pip install -r requirements.txt", timeout=55)
task = sb.exec("cd /root/app && python3 -m pytest -q", background=True)
result = task.wait(on_output=lambda out, err: print(out, end=""))
sys.exit(result.exit_code or 0)
token 以 EQVPS_API_KEY 的名字儲存在 CI 的金鑰裡。CI 中的其他東西——部署金鑰、雲憑據——都不會進入沙箱。with 程式碼塊結束時沙箱會被刪除,即使任務中途崩潰也一樣。
測試本身作為背景任務執行,因為單條同步指令會在 55 秒時停止。背景任務在執行時持續輸出,可以一直執行到沙箱的 TTL——這裡設為 30 分鐘,防止卡住的測試推高帳單。
您真正會碰到的限制
把這些說清楚,能幫您省下一個下午。
同時執行。 一個帳戶可以持有 20 個沙箱,但同時只執行 2 條指令。對 CI 來說,就是兩個任務真正並行。同時到達的十個 PR 會排隊。如果您的流水線把測試分到 16 個 worker 上,那麼主流水線不適合用它——把主流水線留在您自己 VPS 上的 runner 上,沙箱用於不可信的那條通道。
內部沒有容器。 沙箱不帶 Docker。需要 Postgres 容器的單元測試和整合測試無法直接執行;基於 SQLite 或記憶體模擬物件的測試則可以。
檔案。 透過 API 上傳和下載,每個檔案最大 5 MB。請在沙箱內用 git 拉取程式碼,而不是上傳壓縮包。
費用
您按秒為方案的 vCPU 和記憶體付費,最少 60 秒,從預付餘額扣除——無需訂閱。
| 執行 | 方案 | 大致費用 |
|---|---|---|
| Lint + 單元測試,1 分鐘 | small(0.5 vCPU,1 GB) | $0.0006 |
| 完整測試套件,3 分鐘 | standard(1 vCPU,2 GB) | $0.0033 |
| 建置 + 測試,10 分鐘 | plus(2 vCPU,4 GB) | $0.022 |
在這個價位上,值得關心的不是費用,而是測試能否在您設定的時間內跑完。讓 TTL 比您最慢的一次綠色執行再多留一些餘量。
合理的分工
我們的建議:可信分支留在您那台帶快取的快速 runner 上。所有不是您寫的東西——fork、外部貢獻者、代理產生的修補程式——先經過沙箱。如果沙箱執行透過,且有人看過 diff,再把它提升到可信流水線。
這樣您就有一條注重速度和快取的通道,和一條注重乾淨機器的通道,而不必強迫一個工具同時扮演兩種角色。
從沙箱概覽和連線指南開始——新帳戶可獲得 $1 的沙箱時長,足夠跑幾百次短測試。上面用到的所有方法都在 SDK 參考中,準確的計費規則見沙箱限制與計費。
相關閱讀:用於程式碼審查和 PR 檢查的沙箱和AI 代理沙箱。
評論
目前還沒有評論。歡迎成為第一位。