Self-hosted CI-runners har en besvärlig egenskap: de minns allt. Cachar, tokens, en deploy-nyckel som någon lade till ”tillfälligt” i våras. För dina egna brancher går det bra. Det blir ett problem så fort en pull request kommer från någon du aldrig hört talas om – eller från din egen AI-agent, som skrev en patch som ingen har läst än.
Det rena svaret är en maskin per körning. Klona, installera, testa, släng maskinen.
Så ser en körning ut
En sandbox är en Firecracker-microVM som startar på ungefär en sekund med Python 3.12, Node.js 22, git och curl. Utgående internet fungerar, så git clone och pip install -r requirements.txt beter sig som vanligt. Det finns inga inkommande portar – inget kan nå testmiljön medan den körs.
Från ett CI-jobb är det hela ett kort skript. Här är det med Python-SDK:t, anropat från valfritt CI-jobb:
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 ligger i dina CI-hemligheter som EQVPS_API_KEY. Inget annat från din CI – inga deploy-nycklar, inga molnuppgifter – hamnar i sandboxen. När with-blocket slutar raderas sandboxen, även om jobbet kraschade halvvägs.
Själva testkörningen är en bakgrundsuppgift, eftersom ett enskilt synkront kommando stoppar efter 55 sekunder. En bakgrundsuppgift strömmar utdata medan den arbetar och kan fortsätta till sandboxens TTL – här satt till 30 minuter så att ett test som hänger sig inte drar upp notan.
Gränserna du faktiskt slår i
Att vara ärlig om dem sparar dig en eftermiddag.
Samtidighet. Ett konto kan ha 20 sandboxar, men bara 2 kommandon körs samtidigt. För CI är det två jobb som verkligen körs parallellt. Tio PR:er som kommer på en gång hamnar i kö. Om din pipeline delar upp testerna på 16 workers är det här fel verktyg för huvudpipelinen – behåll den på dina egna runners på en VPS och använd sandboxar för det opålitliga körfältet.
Inga containrar inuti. Docker ingår inte i sandboxen. Enhets- och integrationstester som behöver en Postgres-container fungerar inte som de är; tester mot SQLite eller en fake i minnet gör det.
Filer. Uppladdningar och nedladdningar via API:t går upp till 5 MB per fil. Hämta koden med git inuti sandboxen i stället för att ladda upp ett arkiv.
Vad det kostar
Du betalar för tariffens vCPU och RAM per sekund, minst 60 sekunder, från ett förbetalt saldo – utan abonnemang.
| Körning | Tariff | Ungefärlig kostnad |
|---|---|---|
| Lint + enhetstester, 1 min | small (0.5 vCPU, 1 GB) | $0.0006 |
| Hela sviten, 3 min | standard (1 vCPU, 2 GB) | $0.0033 |
| Bygge + tester, 10 min | plus (2 vCPU, 4 GB) | $0.022 |
Med de här priserna är den intressanta frågan inte kostnaden, utan om dina tester blir klara inom tiden du satt. Ge TTL lite marginal över din långsammaste gröna körning.
En förnuftig uppdelning
Vår rekommendation: behåll betrodda brancher på din snabba runner med cache. Skicka allt du inte skrivit själv – forkar, externa bidragsgivare, agentgenererade patchar – genom en sandbox först. Är sandboxkörningen grön och har en människa tittat på diffen, flytta upp den till den betrodda pipelinen.
Då har du ett körfält där fart och cache räknas och ett där en ren maskin räknas, utan att tvinga ett verktyg att vara båda.
Börja med översikten över sandboxar och anslutningsguiden – nya konton får $1 i sandboxtid, vilket räcker till några hundra korta testkörningar. Varje metod som används ovan finns i SDK-referensen, och de exakta debiteringsreglerna i gränser och debitering för sandboxar.
Relaterat: sandbox för kodgranskning och PR-kontroller och sandbox för AI-agenter.
Kommentarer
Inga kommentarer än. Bli först.