Добавить в корзинуПозвонить
Найти в Дзене
Lyakhov Eugene

Стратегия CI/CD — Trunk-Based Development с Feature Toggles

Мы развиваем микросервисную архитектуру (Java/Spring Boot + React) в Kubernetes (Yandex Cloud) с тремя окружениями: dev, stage, prod. Нам необходимо выбрать стратегию ветвления и релизов, которая обеспечит быструю и безопасную доставку измененийc Описание: Долгоживущие ветки develop и main. Для каждого релиза создаётся ветка release/x.y, которая стабилизируется и мержится в main. Hotfix-ветки для экстренных исправлений. Плюсы: Чёткое разделение стабильного и нестабильного кода. Подходит для продуктов с жёстким релизным циклом (раз в месяц/квартал). Минусы: Сложные и болезненные мержи долгоживущих веток. Медленный feedback loop — код попадает в production через недели. Высокий overhead на поддержку нескольких веток. Плохо масштабируется для микросервисов, где каждый сервис деплоится независимо. Merge-конфликты растут экспоненциально с размером команды. Вердикт: Не подходит для микросервисной архитектуры с частыми релизами. Описание: Одна основная ветка main. Каждая фича разрабатываетс
Оглавление

Контекст

Мы развиваем микросервисную архитектуру (Java/Spring Boot + React) в Kubernetes (Yandex Cloud) с тремя окружениями: dev, stage, prod. Нам необходимо выбрать стратегию ветвления и релизов, которая обеспечит быструю и безопасную доставку измененийc

Рассмотренные варианты

1. GitFlow (Release Branches)

Описание: Долгоживущие ветки develop и main. Для каждого релиза создаётся ветка release/x.y, которая стабилизируется и мержится в main. Hotfix-ветки для экстренных исправлений.

Плюсы: Чёткое разделение стабильного и нестабильного кода. Подходит для продуктов с жёстким релизным циклом (раз в месяц/квартал).

Минусы: Сложные и болезненные мержи долгоживущих веток. Медленный feedback loop — код попадает в production через недели. Высокий overhead на поддержку нескольких веток. Плохо масштабируется для микросервисов, где каждый сервис деплоится независимо. Merge-конфликты растут экспоненциально с размером команды.

Вердикт: Не подходит для микросервисной архитектуры с частыми релизами.

2. Feature Branch Flow (GitHub Flow)

Описание: Одна основная ветка main. Каждая фича разрабатывается в отдельной ветке feature/*, проходит code review через Merge Request и вливается в main.

Плюсы: Проще GitFlow. Каждый MR — изолированное изменение. Хорошо работает с code review.

Минусы: Feature-ветки живут днями или неделями → merge-конфликты. Несколько параллельных фич конфликтуют при мерже. Нет механизма частичного включения фичи: код либо в main, либо нет. Сложно тестировать незавершённые фичи в dev/stage окружении. Интеграционные проблемы обнаруживаются поздно — только при мерже.

Вердикт: Приемлемо для небольших команд, но не оптимально для непрерывной доставки.

3. Trunk-Based Development (TBD)

Описание: Все разработчики коммитят в одну ветку main (trunk). Короткоживущие ветки (< 1-2 дня) допускаются для code review. Незавершённые фичи скрыты за feature toggles. Деплой из main в dev → stage → prod.

Плюсы: Минимальные merge-конфликты (ветки живут часы, не дни). Непрерывная интеграция — проблемы обнаруживаются мгновенно. Feature toggles позволяют деплоить код в production до готовности фичи. Быстрый rollback через выключение флага (секунды vs минуты на revert/redeploy). Простая pipeline: main → dev → stage → prod.

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

Вердикт: Оптимально для микросервисной архитектуры с частыми релизами.

4. Canary Deployment

Описание: Новая версия деплоится на небольшой процент инстансов (canary pod). Трафик распределяется между старой и новой версией. При проблемах — canary откатывается.

Плюсы: Минимальный blast radius при ошибках. Реальное тестирование на production-трафике.

Минусы: Требует сложной настройки traffic splitting (Envoy/Istio). Два разных бинарника одновременно — сложность с миграциями БД и контрактами API. Не решает задачу частичного включения фичи для конкретных пользователей. Дополнительная инфраструктура и мониторинг.

Вердикт: Дополнительная техника, не замена стратегии ветвления. Можно комбинировать с TBD в будущем.

5. A/B Testing

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

Плюсы: Data-driven решения о фичах. Измеримый impact на бизнес-метрики.

Минусы: Требует аналитической инфраструктуры (events, metrics, statistical engine). Сложность в дизайне экспериментов. Не является стратегией CI/CD — это техника поверх feature flags.

Вердикт: Будущая возможность поверх feature toggles, не базовая потребность сейчас.

6. Environment Branches (dev/staging/main)

Описание: Каждое окружение привязано к отдельной ветке. dev → dev-окружение, staging → staging, main → production. Промоушен кода через мерж между ветками.

Плюсы: Простая привязка ветка = окружение.

Минусы: Cherry-pick и мержи между ветками drift-ят и создают рассинхрон. Код в staging может отличаться от production. Сложно отследить, какой код в каком окружении. Anti-pattern по мнению большинства CI/CD-практик.

Вердикт: Антипаттерн для микросервисов. Не рассматривается.

Решение

Выбран: Trunk-Based Development с Feature Toggles на три окружения (dev, stage, prod).

Модель ветвления

main ──●──●──●──●──●──●──●──●──●──▶
│ │ │
└─MR──┘ └─MR──┘
(< 1-3 дня) (< 1-3 дня)

  • Все изменения идут в main
  • Короткоживущие ветки для code review (merge request в GitLab)
  • Ветка живёт максимум 1-3 дня
  • Незавершённые фичи скрыты за feature toggle

Pipeline

main → [GitLab CI: build + test] → dev → [auto-deploy]
stage → [manual promote]
prod → [manual promote]

  • dev: автоматический деплой при каждом коммите в main
  • stage: ручной promote из dev (или автоматический по расписанию) git tag: 1.0.0-rc
  • prod: ручной promote из stage git tag: 1.0.0-release

Один и тот же Docker-образ проходит через все три окружения. Различается только конфигурация (environment variables, feature flags).

Feature Toggles

if (featureFlags.isEnabled("new-payment-engine")) {
return newPaymentService.process(request);
} else {
return oldPaymentService.process(request);
}

  • Флаг OFF во всех окружениях при создании флаги в dev ON всегда
  • Деплоится dev → тестируется → включается в stage → тестируется → включается в prod
  • После полного включения и стабилизации —  технический лидер контролирует очистку не используемых флагов  и старый код удаляются (техдолг) раз в квартал в Jira задачи на чистку

Типы флагов

-2

Последствия

Положительные

  • Быстрая доставка: код в production за часы, не недели
  • Безопасный откат: выключение флага за секунды
  • Нет merge hell: ветки живут < 3 дней
  • Один артефакт проходит все окружения

Отрицательные

  • Требуется дисциплина по удалению старых флагов
  • Нужна инфраструктура для feature toggles
  • Код с if/else вокруг флагов может снижать читаемость при злоупотреблении

Митигация техдолга

  • Правило: каждый release toggle имеет дату удаления (максимум 30 дней после полного включения)
  • Code review проверяет: флаг добавлен → задача на удаление создана в трекере
  • Периодический аудит: список активных флагов ревьюится раз в спринт

Страховка на собеседовании

Знание есть, но стресс мешает?
Бесплатное сообщество для прокачки карьеры в IT

Подпишись на https://t.me/IT_Interview_Partner_Bot
Подпишись на
https://t.me/LyakhovEugene