Эффективный CI-CD: переход на trunk-based development и GitLab. argo cd.. argo cd. cicd.. argo cd. cicd. DevOps.. argo cd. cicd. DevOps. Git.. argo cd. cicd. DevOps. Git. gitflow.. argo cd. cicd. DevOps. Git. gitflow. gitlab.. argo cd. cicd. DevOps. Git. gitflow. gitlab. gitops.. argo cd. cicd. DevOps. Git. gitflow. gitlab. gitops. Java.. argo cd. cicd. DevOps. Git. gitflow. gitlab. gitops. Java. Kubernetes.. argo cd. cicd. DevOps. Git. gitflow. gitlab. gitops. Java. Kubernetes. react.js.. argo cd. cicd. DevOps. Git. gitflow. gitlab. gitops. Java. Kubernetes. react.js. spring boot.. argo cd. cicd. DevOps. Git. gitflow. gitlab. gitops. Java. Kubernetes. react.js. spring boot. trunk-based development.. argo cd. cicd. DevOps. Git. gitflow. gitlab. gitops. Java. Kubernetes. react.js. spring boot. trunk-based development. Блог компании Столото.. argo cd. cicd. DevOps. Git. gitflow. gitlab. gitops. Java. Kubernetes. react.js. spring boot. trunk-based development. Блог компании Столото. Управление проектами.. argo cd. cicd. DevOps. Git. gitflow. gitlab. gitops. Java. Kubernetes. react.js. spring boot. trunk-based development. Блог компании Столото. Управление проектами. Управление разработкой.

Меня зовут Илья Куликов, я руковожу разработкой веб-терминалов в компании «Столото». Сегодня хочу рассказать, как мы превратили ручные релизы и вечные конфликты в почти автономный CI/CD. За почти 10 лет в компании я прошёл путь от бэкенд-разработчика до руководителя направления, в «Столото» же за это время родился и вырос целый продукт — веб-терминал для агентов розничной сети. Изначально у нас был парк дорогих аппаратных терминалов, установленных у агентов. Но как расширить сеть и снизить входной порог? Возникла идея: а что, если сделать аналогичное приложение в браузере? Тогда любой желающий мог бы стать агентом — достаточно старого ноутбука и договора с нами. Так появился полноценный веб-аналог аппаратного терминала со всеми необходимыми функциями для продажи лотерей.

Но вместе с ростом продукта росла и боль: релизы занимали часы, всё постоянно ломалось на проде, а после каждого деплоя команда судорожно грепала логи в поисках причины падения. Мы поняли: без серьёзной перестройки процессов дальше — только хуже. И тогда решили кардинально пересмотреть наш подход к CI/CD. Отказались от классического GitFlow в пользу trunk-based development, полностью перестроили пайплайны в GitLab и внедрили автоматизацию на всех этапах — от сборки и тестирования до деплоя и мониторинга.

О масштабе и требованиях

«Столото» входит в топ-10 мировых лидеров по онлайн-продажам. Около 80% билетов продаётся через цифровые каналы. На платформе ежедневно проходят сотни тиражей, а выплаты — это сотни тысяч операций в день.

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

Начну с того, как выглядят наши веб-терминалы.

Веб-терминалы "Столото"

Веб-терминалы “Столото”

Технологический стек: баланс между скоростью, надёжностью и поддержкой

В основе любого современного продукта — продуманный технологический стек, и наш не исключение. Мы сознательно выбрали инструменты, которые позволяют быстро развивать функциональность, обеспечивать стабильность и при этом не упираться в узкие места инфраструктуры.

Фронтенд — на React.js. Это не просто «по привычке», а следование мировому стандарту: React используют и в Meta, и в Netflix, и в Uber. Компонентная архитектура, мощная экосистема и виртуальный DOM дают нам то, что нужно веб-терминалу — мгновенный отклик интерфейса без перезагрузки страницы. Агент не должен ждать: он продаёт билеты, оформляет выигрыши — и всё должно работать «в моменте».

БэкендJava + Spring Boot. Этот стек остаётся одним из самых популярных в корпоративной разработке — и не зря. Он отлично подходит для сложных бизнес-процессов и интеграций. Особенно выручает Spring State Machine — мы моделируем в нём сложные сценарии, вроде цепочек продаж и выплат, как конечные автоматы. Это повышает предсказуемость, а логику делает прозрачной и управляемой.

База данныхMariaDB. Она демонстрирует стабильную производительность и подходит для наших сценариев. Мы держим её за пределами Kubernetes, на выделённых виртуалках: так проще управлять репликацией и бэкапами. (В команде шутим, что Maria в переводе — «горькая отвергающая»: видимо, кластер Kubernetes ей действительно не по душе 😄).

Кэш и сессииRedis Sentinel. Он обеспечивает высокую доступность и быстрый отклик. Redis у нас хранит не только сессии, но и контексты состояний из Spring State Machine, чтобы разгрузить память приложений и ускорить восстановление после рестартов.

Всё это работает в контейнерах под управлением Kubernetes. Он стал нашей основной платформой — автоматизирует деплой, масштабирование, обновления, следит за отказоустойчивостью.

Такой стек — это не просто набор «хайповых» технологий, а осознанный выбор в духе мировых трендов: Kubernetes + React + Spring Boot + Redis — комбинация, на которой строят свои продукты Airbnb, Spotify, Alibaba. Это проверенные временем технологии, за которыми стоят большие сообщества, документация и стабильные обновления. А для нас это значит: меньше сюрпризов, больше уверенности в завтрашнем дне.

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

Что нас сподвигло уйти с GitFlow на TBD и что нам это дало

Изначально разработка веб-терминалов велась по классическому GitFlow. Это выглядело логично: master — стабильная ветка, develop — интеграционная, feature-ветки для отдельных задач. Но после нескольких месяцев активной работы мы поняли, что переборщили с GitFlow.

Причины:

  • Feature-ветки жили по 2–3 недели из-за сложной бизнес-логики (например, state machine), и за это время develop сильно продвигался вперёд.

  • При мерже возникали массивные конфликты, которые приходилось разруливать часами.

  • Время на интеграцию росло, а не падало: вместо выпуска фич мы тратили дни на согласование изменений, ручные тесты и разруливание веток.

  • Когнитивная нагрузка на команду была высокой: каждый должен был помнить, в какую ветку коммитить, когда создавать релиз, как правильно делать hotfix.

  • Обратная связь по качеству кода задерживалась: ошибки выявлялись слишком поздно, иногда уже на проде.

Итог: мерджи и конфликты при них прилично тормозили процесс разработки и начало тестирования, вылезали ошибки, а команда теряла скорость. Стало понятно, что нужна другая модель, где интеграция — норма, а не событие, и каждое изменение проверяется максимально рано.

Переход на trunk-based development (TBD)

Мы приняли TBD как единственный рабочий подход: вся команда интегрирует изменения напрямую в master, а feature-ветки существуют только несколько часов или максимум один рабочий день. Это позволило нам:

  • Сократить время интеграции и снизить риск конфликтов.

  • Обеспечить раннее выявление ошибок через непрерывные автотесты.

  • Использовать feature toggles: незавершённые фичи можно сливать в мастер, не включая их для пользователей.

Ключевые требования для успешного TBD:

  • Строгий контроль качества кода: каждый коммит должен проходить юнит- и интеграционные тесты.

  • Обязательные feature toggles, чтобы изменения могли безопасно попадать в мастер.

  • Культура мелких коммитов: проще тестировать, ревьюить и при необходимости откатывать.

TBD стал для нас не просто стратегией ветвления, а основой безопасного, предсказуемого CI/CD, где мастер всегда готов к релизу и каждый коммит проверяется автоматически.

Культура качества и «малые» коммиты

В TBD мастер — это всегда потенциальный продакшен-кандидат. Для нас это значит, что каждый коммит проходит строгий контроль качества:

  • Автоматические тесты: юнит-тесты проверяют базовую логику, интеграционные — взаимодействие с внутренними процессинговыми системами (биллинг, расчёты выигрышей, state machine), а end-to-end и headless UI-тесты проверяют пользовательский поток.

  • Feature toggles позволяют мержить изменения без риска для пользователей.

  • Малые коммиты делают процесс ревью, тестирования и откатов проще и безопаснее.

Мы стандартизировали работу с ветками и коммитами. Git-хуки, настраиваемые локально, автоматически проверяют названия веток и сообщения коммитов, чтобы они соответствовали правилам автоматизации — это снижает человеческий фактор и облегчает жизнь разработчикам.

Таким образом, CI/CD-пайплайны и стандарты работы превращают процесс интеграции в предсказуемый, безопасный и быстрый цикл, где мастер остаётся всегда «зелёным».

Почему GitLab и как мы его используем

Для успешного TBD нужна мощная автоматизация: без неё контролировать качество и стабильность мастер-ветки невозможно. Мы выбрали GitLab, развернутый внутри компании, чтобы иметь полный контроль над пайплайнами, merge request’ами и интеграцией с внутренними сервисами.

Переход на Enterprise Edition не произошёл сразу. Сначала мы провели пилот на Community Edition, изучили ключевые функции, оценили возможности автотестов, MR-робота и интеграции с другими системами. Только убедившись, что GitLab решает все необходимые задачи, мы перешли на EE.

Ключевые возможности GitLab, которые мы используем:

  • Единое хранилище кода и пайплайнов (.gitlab-ci.yml рядом с кодом для версионирования и аудита).

  • Автоматический запуск пайплайнов для каждого merge request, отображение статуса тестов и блокировка мержей при провале.

  • Code Owners: автоматическое назначение ревьюеров по ownership-правилам в монорепозитории.

  • Автоматическое масштабирование CI-раннеров: GitLab динамически запускает дополнительные runner’ы в кластере при пике нагрузки и освобождает ресурсы при отсутствии таковой.

MR Robot и интеграция с Atlassian системами и SonarQube

Эффективный CI-CD: переход на trunk-based development и GitLab - 2

Название MR Robot произошло не просто так — это сокращение от Merge Request, а в шутку мы зовём его «мистер робот». MR Robot управляет merge request’ами, проверяет качество кода и отправляет уведомления. Он работает в пайплайне GitLab через Docker-образ и выполняет:

  • Назначение ревьюеров на основе ownership-правил.

  • Проверку покрытия кода тестами через SonarQube и контроль статического анализа.

  • Обновление статусов в Jira и отправку уведомлений в Telegram о сбоях сборки или блокировке мержей.

  • Интеграция с Confluence позволяет автоматически генерировать документацию для текущей версии продукта: документ по API, паспорт релиза и список задач, вошедших в релиз.

Интеграция с Jira синхронизирует статус задач с кодом: при создании MR задача автоматически переходит в статус «Review», после слияния — закрывается. Это упрощает жизнь команде и ускоряет коммуникацию между менеджерами, разработчиками и QA.

Уровни покрытия кода тестами контролируются жёстко: мы постепенно повышали минимальный порог от 20–30% до 93% для бэкенда и 86% для фронтенда. Это именно покрытие функциональности модулей тестами, а не просто количество строк кода.

Часть функциональности MR Robot доступна в GitLab Enterprise Edition, но мы начинали с Community Edition и добились стабильного процесса даже без EE.

Стратификация пайплайнов

Мы построили многоуровневую систему пайплайнов, где каждый последующий тип проверки дополняет предыдущий:

  • Feature-ветки (краткосрочные) — выполняются при каждом пуше в ветку, запускают сборку и юнит-тесты. Быстро дают обратную связь о базовой работоспособности изменений.

  • Merge Request — дополняют предыдущий уровень: кроме сборки и юнит-тестов запускается статический анализ через SonarQube и интеграционные тесты. MR Robot оценивает, можно ли сливать изменения в мастер.

  • Master-ветка — каждый коммит проходит полный цикл: сборка, юнит- и интеграционные тесты, headless UI-тесты, автотесты бизнес-логики и развертывание на тестовой среде. Если пайплайн прошёл — версия готова к релизу.

  • Релизные ветки — для финальной проверки перед продакшеном дополнительно прогоняются нагрузочные тесты и интеграция со смежными системами на нагрузочном и регрессионном стендах, соответственно.

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

GitOps и Argo CD — стенды под рукой

Для безопасного и предсказуемого деплоя мы внедрили GitOps-подход с использованием Argo CD, развернутого в Kubernetes. Он стал логичным выбором на фоне уже используемого GitLab и K8s: теперь вся конфигурация кластеров хранится в Git, а Argo CD автоматически синхронизирует её с реальным состоянием. Любые ручные изменения кластера возвращаются к «каноническому» состоянию, исключая дрейф конфигураций.

Мы выстроили несколько тестовых стендов, каждый с конкретной задачей:

  • Dev — разворачивается после успешного пайплайна в MR, используется для автоматических тестов и первичной функциональной проверки.

  • TIFA (стенд интеграционного тестирования) — основной для ручного тестирования QA, где проверяются интеграция со смежными системами и регрессионные сценарии.

  • TLI (стенд нагрузочного тестирования) — имитирует характеристики продакшена, проверяет пиковые нагрузки и устойчивость системы.

Ручное тестирование остаётся обязательным этапом — автотесты помогают, но не заменяют человека. Такой подход позволяет команде мгновенно получать изолированные среды, проверять изменения и быстро получать обратную связь.

Доставка в продакшен: канареечные релизы и фич-флаги

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

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

Для управления функциональностью мы используем Unleash — систему feature toggles. С её помощью можно мержить незавершённые функции в мастер, но держать их выключенными для пользователей до полной готовности. Unleash позволяет комбинировать разные версии приложения и разную функциональность одной и той же версии между пилотной и основной группами, что особенно ценно для сложных бизнес-процессов и экспериментов с новыми подходами.

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

Техдолг и забота о качестве

Даже самая продвинутая инфраструктура не защищает от накопления технического долга. Если его игнорировать, продукт начинает деградировать: код становится трудночитаемым, новые фичи вводятся медленно, а ошибки чаще проявляются на продакшене. Известные примеры — старые версии Facebook или Twitter в первые годы, когда масштаб и скорость роста вынуждали жертвовать качеством кода: без регулярного рефакторинга они сталкивались с падением производительности и ростом багов.

Поэтому мы сознательно выделяем 25–30% времени спринта на устранение техдолга: рефакторинг, переработку архитектуры, обновление библиотек и фреймворков до последних стабильных версий. Это позволяет нам:

  • Поддерживать код читаемым и поддерживаемым.

  • Обеспечивать совместимость и безопасность. Новые версии фреймворков и библиотек часто закрывают уязвимости и баги, а старые — наоборот создают риски.

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

Рефакторинг помогает не просто «чистить код», а улучшать архитектуру и логику взаимодействия компонентов. Например, мы перерабатываем сложные модули Spring State Machine, оптимизируем работу с Redis и пересматриваем структуру фронтенд-компонентов. Это снижает количество ошибок, ускоряет тестирование и делает систему более гибкой при изменении бизнес-требований.

Использование последних версий библиотек и фреймворков — обязательное правило для нашей команды. Оно помогает нам избегать технических ловушек прошлого и оставаться на передовой, как делают крупнейшие ИТ-компании: Spotify, Netflix и Airbnb регулярно инвестируют в обновления и рефакторинг, чтобы сохранять скорость и стабильность продукта при росте нагрузки и функциональности.

Как мы работаем с задачами

Наш день с новым подходом:

  • Продукт-менеджер формулирует задачу и создаёт её в Jira. Она сразу попадает в список для разработки.

  • Разработчик берёт задачу, создаёт feature-ветку, делает небольшие коммиты, пишет юнит-тесты и интеграционные тесты. После этого создаёт Merge Request.

  • MR Robot автоматически проверяет код: назначает ревьюеров, запускает статический анализ через SonarQube, проверяет покрытие тестами и уведомляет команду о статусе сборки.

  • Ревьюеры смотрят MR — фронтендеры проверяют интерфейс, бэкендеры — бизнес-логику и интеграцию с state machine. MR не сливается, пока все проверки и ревью не пройдены.

  • QA-инженер получает развёрнутый на стенде Dev билд, запускает ручное тестирование и проверяет сценарии, которые сложно покрыть автотестами. Автотесты здесь — помощники, ускоряющие работу, но не заменяющие человека.

  • После одобрения MR код сливается в master, где запускается полный цикл пайплайнов: сборка, все тесты, headless UI и интеграция с внутренними сервисами.

  • Технический лидер и продукт-менеджер наблюдают за результатами на стендах TIFA и TLI, проводят финальную проверку и принимают решение о релизе.

  • Деплой идёт через канареечные релизы с фич-флагами, где пилотная группа пользователей проверяет новые функции. При успехе изменения доходят до всей аудитории.

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

Заключение и советы для тех, кто на старте

Наш путь от ручных релизов и вечных конфликтов в GitFlow к стабильному, почти «невидимому» CI/CD занял время, но результат того стоил. Мы не просто ускорили доставку кода — мы изменили культуру разработки: теперь команда не боится мержить в пятницу вечером, а продакшен перестал быть «зоной риска».

Ключевые выводы в формате утверждений и вопросов к вам:

  • Автоматизация и CI/CD работают: вы можете уменьшить ручную рутину и ускорить поставку фич. А вы используете инструменты автоматизации на полную мощность в своей команде?

  • Культура качества решает всё: мелкие коммиты, тесты и фич-флаги делают мастер надёжным. А как вы поддерживаете стабильность своего кода при быстром развитии продукта?

  • Техдолг требует внимания: регулярный рефакторинг и обновление библиотек сохраняют гибкость и скорость. Вы выделяете время на системное улучшение кода или гасите пожары по мере их появления?

  • Постепенная проверка изменений снижает риски: канареечные релизы и пилотные группы позволяют аккуратно тестировать новые функции. А у вас есть безопасный способ проверять изменения перед полной выкладкой?

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

Автор: ilja_kylikov

Источник

Rambler's Top100