Preview Environments — Лаборатория DX
Mid Авторский

Preview Environments

Эфемерные окружения для каждого PR — как это меняет процесс ревью

Code review по скриншотам

Стандартный процесс code review в большинстве команд: разработчик открывает pull request, ревьюер читает diff, мысленно достраивает поведение изменений, оставляет комментарии. Через пару итераций PR мёрджится. Проблема в том, что чтение diff — анализ кода в вакууме: ревьюер видит строки, но не видит результат. Для бэкенда ещё терпимо, логику можно проверить по коду. Для фронтенда, изменений в API, миграций базы данных или интеграций между сервисами diff полной картины не даёт.

Некоторые команды пытаются решить задачу скриншотами: разработчик делает снимок нового UI и прикладывает к PR. Но скриншот неинтерактивен. На нём не видно анимацию, поведение при ресайзе окна, реакцию формы на невалидный ввод. Другие команды просят ревьюера чекаутить ветку и запускать проект локально. На это уходит время, конфигурация окружения может отличаться, и половина ревьюеров честно признаётся, что пропускает этот шаг.

Что такое preview environments

Preview environment (он же ephemeral environment, deploy preview, review app) — изолированное окружение приложения, которое CI/CD создаёт для каждого pull request. Разработчик пушит изменения в ветку и открывает PR. Пайплайн разворачивает приложение с этими изменениями на отдельном URL, например pr-142.preview.yourapp.dev, и ссылка появляется в PR.

Preview environments ускоряют онбординг: новый разработчик видит результат своего первого PR в работающем окружении, а не в diff. Жизненный цикл preview environment привязан к PR: окружение создаётся при открытии, обновляется при каждом пуше в ветку, уничтожается при мёрдже или закрытии. Эфемерная инфраструктура: денег простаивая не ест, ручного управления не требует.

Как это меняет процесс ревью

Ревьюер открывает PR, видит ссылку на preview, кликает и получает работающее приложение с изменениями автора. Для фронтенда: проверка UI на разных разрешениях, прогон пользовательских сценариев, отлов багов, невидимых в diff. Для бэкенда: реальный запрос к API, проверка миграции, формат ответа нового endpoint.

Продакты и дизайнеры получают доступ к изменениям до мёрджа. Дают фидбек по UX, ловят несоответствие макету, предлагают правки, пока код ещё свежий в голове разработчика. QA начинает тестирование параллельно с code review, а не после деплоя в staging. Обнаружение багов сдвигается влево по pipeline и сокращает цикл обратной связи с дней до часов.

Инструменты

Kubernetes: namespace per PR

Команде на Kubernetes гибкий вариант — Argo CD с Pull Request Generator из ApplicationSet controller. При появлении нового PR Argo CD создаёт Application, разворачивает код из ветки PR в отдельный namespace, а при закрытии удаляет Application и чистит ресурсы. Работает с GitHub, GitLab, Bitbucket.

Подход требует настройки, но даёт полный контроль над инфраструктурой: ограничения на тип приложения нет, данные и трафик остаются под контролем команды, внешних платформ в зависимостях нет.

Альтернативы в экосистеме Kubernetes: Okteto разворачивает per-branch окружения с namespace isolation, включая базы данных и очереди. Bunnyshell поддерживает Docker Compose и Kubernetes и создаёт полную копию окружения для каждого PR.

Docker Compose: без Kubernetes

Команде без Kubernetes подойдёт Docker Compose. CI собирает образы из ветки PR, поднимает docker compose up на сервере (или пуле серверов), пробрасывает URL через nginx reverse proxy. При закрытии PR пайплайн вызывает docker compose down и чистит volumes.

Схема простая: один сервер, docker compose с переменными окружения для номера PR, nginx-конфиг с wildcard-доменом. На практике этого хватает для команд до 20–30 разработчиков. Traefik упрощает маршрутизацию, когда нужен автоматический TLS и service discovery.

GitLab Review Apps

В России GitLab self-hosted стоит на каждом втором сервере. Review Apps в GitLab CI/CD создают preview environment для каждого merge request. Конфигурация живёт в .gitlab-ci.yml: описывается environment с динамическим именем, задаётся on_stop action для cleanup, GitLab отображает ссылку на окружение в merge request.

Работает с любым бэкендом: Kubernetes, Docker, виртуалки. GitLab Agent for Kubernetes упрощает деплой в кластер. Для простых случаев хватает shell executor и docker compose на раннере.

Managed-платформы (глобальные)

Для фронтенда и статических сайтов Vercel и Netlify дают preview deployments из коробки: Git-репозиторий подключается, каждый PR получает preview URL без настройки CI/CD. Cloudflare Pages предлагает аналогичную функциональность. Сервисы популярны за рубежом, но могут создавать проблемы с оплатой и доступом из России.

Базы данных и состояние

Управление состоянием — узкое место preview environments. Статический фронтенд развернуть в изоляции легко, но когда приложению нужна база данных с тестовыми данными, очереди сообщений и внешние зависимости, задача усложняется.

Три подхода. Первый: разделяемый staging-бэкенд. Preview environment фронтенда подключается к общему staging API. Работает для UI-изменений, не помогает при изменениях в бэкенде или базе данных. Второй: snapshot базы данных. При создании preview environment CI копирует структуру и тестовые данные из seed-файла или снапшота. Neon (serverless Postgres) создаёт ветки базы данных за секунды, каждый PR получает свою копию БД с данными из main. Третий: полная изоляция через контейнеры. Каждый preview environment включает все зависимости в Docker Compose или Kubernetes pod — максимум независимости, минус по стоимости и времени создания окружения.

Trade-offs

Стоимость инфраструктуры. Каждый preview environment — это вычислительные ресурсы. При активной разработке с десятками открытых PR счёт за инфраструктуру растёт. Что помогает: автоматическое выключение окружений, простаивающих больше часа, spot-инстансы, лимит на количество одновременных preview environments.

Время создания. Если развёртывание preview environment занимает 20 минут, разработчики ждут и теряют контекст. Цель — 2–5 минут для фронтенда, 5–10 минут для full-stack окружений. Кэширование Docker-образов, pre-built базовые образы и параллелизация шагов пайплайна помогают уложиться в эти рамки.

Безопасность данных. Production-данных в preview environments быть не должно. Только синтетические данные или анонимизированные снапшоты. Доступ к preview URL стоит ограничить аутентификацией, чтобы случайный человек со ссылкой не видел внутреннюю разработку.

С чего начать

GitLab self-hosted — начинать с Review Apps. Kubernetes — Argo CD с ApplicationSet и Pull Request Generator. Без того и другого — Docker Compose на CI-раннере с nginx reverse proxy закроет задачу за пару дней. В каждом случае первый эффект виден быстро: ревьюеры ловят баги, которые раньше доживали до staging, продакты перестают спрашивать «можно посмотреть до релиза?» — ссылка лежит в PR.