У self-hosted CI-раннеров есть одно неудобное свойство: они всё помнят. Кэши, токены, ключ деплоя, который кто-то добавил «временно» прошлой весной. Для своих веток это нормально. Проблема начинается, когда приходит пул-реквест от человека, о котором вы никогда не слышали, — или от вашего же ИИ-агента, который написал патч, который ещё никто не читал.
Чистый ответ — отдельная машина на каждый прогон. Клонировать, установить, протестировать, выбросить машину.
Как выглядит прогон
Песочница — это микро-VM Firecracker, которая стартует примерно за секунду с 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)
Токен лежит в секретах CI как EQVPS_API_KEY. Больше ничего из вашего CI — ни ключей деплоя, ни облачных кредов — в песочницу не попадает. Когда блок with заканчивается, песочница удаляется, даже если задача упала на полпути.
Сам прогон тестов — фоновая задача, потому что одна синхронная команда останавливается на 55 секундах. Фоновая задача отдаёт вывод по ходу работы и может идти до TTL песочницы — здесь это 30 минут, чтобы зависший тест не накрутил счёт.
Лимиты, в которые вы реально упрётесь
Если сказать о них честно, это сбережёт вам полдня.
Параллельность. Аккаунт может держать 20 песочниц, но одновременно выполняются только 2 команды. Для CI это две задачи, работающие по-настоящему параллельно. Десять PR, пришедших разом, встанут в очередь. Если ваш пайплайн шардит тесты на 16 воркеров, для основного пайплайна это не тот инструмент — оставьте его на своих раннерах на VPS, а песочницы используйте для недоверенной полосы.
Без контейнеров внутри. Docker в песочнице нет. Юнит- и интеграционные тесты, которым нужен контейнер Postgres, не заработают как есть; тесты против SQLite или in-memory заглушки — заработают.
Файлы. Загрузка и скачивание через API — до 5 MB на файл. Тяните код через git внутри песочницы, а не загружайте архив.
Сколько это стоит
Вы платите за vCPU и RAM тарифа посекундно, минимум 60 секунд, с предоплаченного баланса — без подписки.
| Прогон | Тариф | Примерная стоимость |
|---|---|---|
| Линтер + юнит-тесты, 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 запас над самым медленным зелёным прогоном.
Разумное разделение
Наша рекомендация: доверенные ветки оставьте на своём быстром раннере с кэшем. Всё, что писали не вы, — форки, внешние контрибьюторы, патчи от агентов — сначала пропускайте через песочницу. Если прогон в песочнице зелёный и человек посмотрел дифф, переводите его в доверенный пайплайн.
Так у вас одна полоса, где важны скорость и кэш, и другая, где важна чистая машина, и ни один инструмент не приходится заставлять быть и тем и другим.
Начните со страницы песочниц и руководства по подключению — новые аккаунты получают $1 времени песочниц, этого хватит на несколько сотен коротких прогонов. Все методы из примера — в справочнике SDK, точные правила оплаты — в разделе лимиты и оплата песочниц.
По теме: песочница для ревью кода и проверки PR и песочница для ИИ-агентов.
Комментарии
Пока нет комментариев. Будьте первым.