Быстрые проверки, безопасный выпуск

Как разделили проверки CI и сохранили контроль перед выпуском

11 октября 2026

Полевая заметка

Вместе с командой SDET я разработал инициативу по ускорению CI: разделить проверки при работе над PR и перед слиянием, а тяжелый регрессионный набор запускать отдельно. Нужно было сократить ожидание обратной связи и сохранить проверки, которые защищают основные пользовательские сценарии.

Важное условие: команда работала по trunk-based development. Изменения сливались сразу в master, деплои происходили каждый день. Поэтому ошибки, обнаруженные асинхронными проверками после слияния, нужно было разбирать до ближайшего выпуска, а решение о деплое принимать по результатам проверок конкретного коммита.

На старте commit pipeline занимал около 40 минут и запускал примерно 3000 e2e-тестов. Значительная часть падений не была связана с изменениями в PR. Merge train повторял тот же набор: еще около 40 минут плюс ожидание очереди, с долей неуспешных прогонов около 10%.

Просто удалить тяжелые тесты было нельзя. В них накопились проверки реальных регрессий, а заменить весь набор тестами других уровней за короткое время было слишком дорого. Я предложил выделить критические сценарии, сохранить их перед слиянием и постепенно перенести остальные проверки в асинхронный процесс. Одновременно продуктовые команды должны были усилить тесты бизнес-логики backend и ключевых компонентов frontend.

Инициатива была внедрена. Ниже ее устройство: цели, разделение проверок, ответственность команд и порядок перехода.

Какую проблему решали

Проверки были долгими и давали много шума. Разработчик ждал полный e2e-прогон, затем разбирал падения, которые могли не относиться к его изменениям. Перед слиянием тот же тяжелый набор запускался снова.

Покрытие backend различалось между сервисами: от 10% до 80%. Frontend во многом зависел от e2e. Поэтому ускорение CI требовало изменений в тестировании, а не только перестановки jobs в конфигурации.

Инфраструктура CI стоила около 14 тысяч долларов в месяц, в пике с on-demand ресурсами около 22 тысяч. Эти расходы были частью исходной картины, но прямое сокращение стоимости не входило в объем инициативы. Экономию нельзя было считать подтвержденной без отдельного измерения.

Для диагностики использовались данные о стабильности и времени тестов, метрики пайплайнов, затраты инфраструктуры и разбор инфраструктурных сбоев.

Цели инициативы

Это цели, зафиксированные перед внедрением.

Разделение e2e на два набора

Критический набор

В него входят ключевые пользовательские сценарии. Он всегда запускается в merge train и блокирует слияние при падении.

На уровне commit его можно запускать вручную, но он не обязателен для каждого PR. Рабочая гипотеза на старте: критический набор составит примерно 15% существующих e2e. Это ориентир для отбора, а не квота, ради которой нужно выбрасывать необходимые проверки.

Асинхронный набор

В него входят остальные ценные e2e. Они регулярно запускаются на master и могут запускаться вручную для рискованных изменений. В merge train этот набор не входит и слияние не блокирует.

Падения продолжают разбираться. Если нестабилен тест, его исправляют, стабилизируют или заменяют. Если найдена регрессия продукта, исправляют код.

Мы сознательно принимали риск, что часть ошибок будет обнаружена после слияния в master. Его ограничивали критическим набором перед слиянием, улучшением тестов нижних уровней, регулярными асинхронными прогонами и быстрой реакцией на их результаты. Нужны были прозрачные сигналы и короткое время восстановления.

Усиление тестов backend и frontend

Backend

Основное внимание в принятой политике тестирования уделялось сервисному слою, который реализует пользовательские бизнес-сценарии.

Цель инициативы: довести покрытие этого слоя до 80%. Команды должны были проверить текущее покрытие, выбрать сервисы с важной логикой и слабой защитой тестами и начать с них. Это снижало зависимость от e2e и позволяло находить ошибки раньше.

Frontend

Компонентное тестирование через Playwright находилось на раннем этапе внедрения. Предложение для первого шага: выбрать около 15 ключевых UX-сценариев на кластер и покрыть их компонентными тестами.

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

Изменения в CI и выпуске

Commit pipeline

Остаются линтеры, backend unit/integration и frontend unit/component. Критические и асинхронные e2e доступны по запросу.

Merge train

Сохраняются проверки, необходимые перед слиянием, включая критический набор e2e. Асинхронный набор исключается.

Асинхронный pipeline

Тяжелый набор запускается отдельно на master. Его результаты должны быть видны участникам процесса и использоваться при решении о выпуске.

Решение о деплое

Перед деплоем проверяется состояние асинхронного прогона именно для коммита, который планируется выпускать.

Если прогон зеленый, деплой идет штатно. Если красный, автоматического выпуска нет: требуется явное решение продуктового кластера, чьи проверки упали. Кластер оценивает риск и разрешает или отклоняет выпуск. Без этого решения выкатывать изменения нельзя.

Для срочного исправления используется hotfix от текущего релиза. Так в срочную выкатку не попадают остальные изменения из master с неразобранными падениями.

Работа продуктовых команд

Сформировать критический набор

Каждый кластер выбирает небольшой набор сценариев, которые защищают стабильность его доменов. Тесты выделяются, стабилизируются и защищаются через CODEOWNERS. За корректность и актуальность набора отвечает кластер.

Для начала можно взять наиболее ценные существующие e2e. Затем сверить набор с продуктом и QA: какие сценарии действительно критичны, каких проверок не хватает и что нужно добавить.

Поднять покрытие сервисного слоя

Команда выбирает критичные сервисы с низким покрытием и последовательно доводит их до согласованного уровня.

Добавить компонентные тесты

Команда определяет ключевые UX-компоненты и пишет тесты, используя существующие регрессионные сценарии и собственное понимание рисков frontend.

Переход и действия при проблемах

Пока команды приводили тесты в порядок, оба набора продолжали выполняться как блокирующие проверки на commit и merge train.

После разделения предполагалось переносить e2e отдельных кластеров в асинхронный pipeline крупными блоками, но итеративно. В критическом наборе оставались только проверки, которые действительно нужны перед слиянием.

Если после переноса возникали систематические проблемы, дальнейший перенос приостанавливался. Команда стабилизировала тесты, устраняла flaky-падения или исправляла реальные ошибки. После стабилизации переход продолжался.

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

Кто разбирает падения

В последующем процессе закрепили отдельную модель ответственности.

Pipeline commander - автор коммита, после которого pipeline впервые стал красным. Он организует разбор: определяет причину, находит владельца и координирует восстановление. Он не обязан лично исправлять все найденные проблемы.

SDET отвечает за здоровье pipeline. Подхватывает разбор, если commander не подключился, исправляет проблемы тестов и инфраструктуры. Реальная регрессия передается владельцу продукта или домена; SDET не становится владельцем дефекта автоматически.

Ожидание по восстановлению - один рабочий день. Если ресурсов не хватает или ответственный не подключается, вопрос идет к дежурному кластера, затем к его руководителю.

Результат

Инициатива отмечена как внедренная. В последующем отчете зафиксировано сокращение MR-suite с 30 до 20 минут. Дальнейшая цель - 10 минут.

Эти замеры относятся к разным описаниям процесса: около 40 минут для commit pipeline на старте инициативы и 30 → 20 минут для MR-suite в последующем отчете. По ним нельзя утверждать, что один и тот же набор проверок ускорился с 40 до 20 минут.

Достижение всех целей по доле падений и покрытию, а также изменение стоимости CI требуют отдельного измерения.

Связанные материалы: trunk-based development и инженерная стратегия.