awesome-everything EN
↑ Обратно к восхождению

Инженерная практика

Гейт зелёного trunk — это вся сделка

Суть Общий trunk: одна поломка останавливает всех, поэтому trunk-based неотделим от быстрого блокирующего CI-гейта. На масштабе наивный pre-merge гейт гонится сам с собой — применяют merge queue с проверкой против проецируемого trunk; FIFO-очередь упирается после ~20-30 инженеров.
Высота — путь к senior
НольJuniorMiddleSenior
Ты на senior-высоте — в орбите
◷ 17 min

Команда из 40 инженеров переходит на trunk-based и за месяц объявляет это провалом: trunk красный половину дня, а когда он красный, никто не может вытянуть чистую базу или слиться на зелёном, так что вся команда стопорится. Диагноз не «trunk-based не масштабируется» — а в том, что они приняли риск (все на одной ветке) без смягчения (гейт, держащий эту ветку зелёной). Trunk-based без быстрого блокирующего CI-гейта — не trunk-based; это общая ветка без тормозов.

Общий trunk концентрирует риск

Сила trunk-based development — все интегрируются в одну ветку — одновременно его единственная точка отказа. С долгоживущими ветками сломанная ветка одного человека — проблема одного человека. С общим trunk сломанный trunk — проблема всех: никто не может вытянуть чистую базу, чтобы начать работу, никто не может слиться, потому что его PR строится на красном, а «быстрый фикс» приземляется поверх поломки, делая отказ труднее в диагностике. Практика намеренно меняет изолированную отложенную боль на общий немедленный риск — и эта сделка окупается, только если trunk держат зелёным.

Так что гейт — не дополнение; это вторая половина сделки. Правило — нет зелёного, нет слияния: каждое изменение прогоняет полную сборку и набор тестов до приземления на trunk, а красный результат блокирует слияние. Вот почему trunk-based и непрерывная интеграция — одна и та же практика, описанная с двух сторон: «мёржить в trunk ежедневно» безопасно лишь потому, что одновременно держится «автоматический гейт держит trunk всегда релизуемым». Данные DORA показывают, что сила trunk-based идёт через CI; примите модель ветвления без гейта — и вы получите режим отказа красного trunk вместо выгоды.

Гейт должен быть быстрым, или его будут обходить

Эффективность гейта затухает с его задержкой. Если сборка занимает 45 минут, разработчики начинают батчить изменения, чтобы амортизировать ожидание — что удлиняет ветки, что вновь впитывает разрыв из урока 1. Они срезают углы, пропускают локальный прогон тестов или давят слить на красном «только в этот раз». Медленный гейт тихо разрушает то самое поведение, ради обеспечения которого существует. Цель — минуты: сборка достаточно быстрая, чтобы интегрироваться мало и часто было путём наименьшего сопротивления. Скорость идёт от параллелизации тестов, ярусности (быстрые юнит-тесты блокируют слияние; медленные end-to-end наборы бегут post-merge или по ночам), кэширования и беспощадной вырезки самых медленных нарушителей в наборе.

Когда trunk всё же краснеет вопреки гейту — проскочил флейки-тест, отказ только в окружении — сеньорский рефлекс — остановить линию: починка или откат trunk важнее новой работы над фичами, потому что каждая минута красного облагает налогом всю команду. git bisect делает поиск виновного коммита дешёвым через бинарный поиск по истории, а малая, часто интегрируемая история — ровно то, что делает bisect быстрым, а откат чистым.

Дизайн гейтаКогда бегут тестыМожет ли trunk сломаться?Предел масштабирования
Только post-merge CIПосле приземления на trunkДа — обнаружено поздноЛомается постоянно после пары разработчиков
Pre-merge (тест PR-ветки)До слияния, против устаревшей базыДа — два зелёных PR могут конфликтовать семантическиГоняется сам с собой при высокой частоте слияний
Merge queue (тест против проецируемого trunk)Против trunk + PR впереди в очередиНет — приземляется только зелёное против финального состоянияFIFO-бутылочное горло ~20–30 разработчиков; флейки-тесты её стопорят

В масштабе гейт гоняется сам с собой — на сцену выходят merge queue

У наивного pre-merge гейта есть тонкая дыра. Вы тестируете PR-A против trunk: зелёный. Я тестирую PR-B против того же trunk: зелёный. Мы оба мёржим. Но A и B никогда не тестировались вместе — они могут конфликтовать семантически и сломать trunk, хотя каждый прошёл. При паре слияний в день это редко; при десятках — постоянно. Лекарство — merge queue: вместо прямого слияния PR входят в очередь, и CI тестирует каждый против проецируемого состояния trunk — trunk плюс все PR впереди него в линии. PR приземляется, только если он зелёный против ровно того состояния, которое создаст. Чтобы держать пропускную способность, очереди батчат: тестируют несколько очередных PR вместе как один комбинированный кандидат и мёржат весь батч, если зелёный, откатываясь к bisect батча, если он падает.

Так большие команды держат единственный trunk зелёным при высоком объёме — собственная merge queue GitHub отмасштабировала монорепозиторий с примерно тысячи слияний в месяц в 2016-м до более чем тридцати тысяч к 2023-му, с сотнями инженеров, мёржащих тысячи PR в месяц, и примерно на треть ниже среднее время деплоя. Но у очереди есть пределы, которые сеньор должен планировать. Единственная FIFO-очередь становится бутылочным горлом после примерно 20–30 активных разработчиков: несвязанные изменения конкурируют за одну полосу, и медленный CI стопорит всё за ним. Хуже того, единственный флейки-тест катастрофичен в очереди — при 50+ PR в день он может застопорить линию на часы, потому что недетерминированный отказ отвергает батчи, которые на самом деле были в порядке. Вот почему карантин флейков и параллелизм очереди (независимые полосы для независимого кода) становятся первоочередными инфраструктурными заботами в масштабе, а не приятными мелочами.

Почему это работает

Заметьте: требование к качеству гейта симметрично дисциплине флагов из прошлого урока. Флейки-тест в merge queue — это версия устаревшего флага у гейта: часть системы, которая должна давать ясный сигнал, но вместо этого излучает шум, и шум нарастает в масштабе, пока не остановит всех. Trunk-based в масштабе — меньше про модель ветвления и больше про то, чтобы держать каждый сигнал в системе — гейт, очередь, флаги — заслуживающим доверия. Сигнал, которому нельзя доверять, хуже отсутствия сигнала, потому что люди его обходят.

Выбери лучший вариант

При 50 PR/день на одном trunk он ломается пару раз в неделю, хотя каждый PR был зелёным до слияния. Какое правильное лекарство?

Викторина

Почему trunk-based development неотделим от быстрого блокирующего CI-гейта?

Викторина

Два PR каждый проходят CI против текущего trunk, затем оба мёржатся — и trunk ломается. Что случилось, и что это предотвращает?

Расставь шаги по порядку

Упорядочьте, как merge queue безопасно приземляет изменение в масштабе:

  1. 1 PR проходит свой собственный CI и аппрувится
  2. 2 PR входит в merge queue, а не мёржится напрямую
  3. 3 CI тестирует его (часто батчем) против trunk + PR впереди в линии
  4. 4 Зелёный против проецируемого финального состояния → батч мёржится в trunk
  5. 5 При отказе — bisect батча, чтобы выкинуть виновный PR и перезапустить
Вспомните перед уходом
  1. 01
    Почему команда, которая «перешла на trunk-based», заканчивает с постоянно красным trunk, и какая часть отсутствует?
  2. 02
    Объясните, почему наивный pre-merge гейт гоняется сам с собой в масштабе и как merge queue это чинят, включая пределы очередей.
Итог

Общий trunk — это сила trunk-based development и его единственная точка отказа: когда все интегрируются в одну ветку, сломанный trunk блокирует всю команду от чистой базы и от слияния, так что практика неотделима от быстрого блокирующего CI-гейта — нет зелёного, нет слияния, — который держит trunk всегда релизуемым. Гейт должен бежать за минуты, потому что медленный гейт толкает разработчиков батчить изменения и вновь впитывать разрыв, ради устранения которого существует trunk-based, а когда trunk всё же краснеет, сеньорский рефлекс — остановить линию и починить или откатить до новой работы, используя git bisect на малой частой истории, чтобы быстро найти виновника. В масштабе наивный pre-merge гейт гоняется сам с собой — два PR, каждый зелёный против одной базы, всё равно могут сломать trunk при объединении — так что merge queue тестируют каждый PR против проецируемого trunk и батчат ради пропускной способности, техника, что позволила GitHub держать один монорепозиторий зелёным с тысячи до тридцати тысяч слияний в месяц. Но очереди не бесплатны: единственная FIFO-очередь становится бутылочным горлом после примерно 20–30 разработчиков, а один флейки-тест может застопорить её на часы, делая контроль флейков и параллельные полосы ключевой инфраструктурой. Сквозная мысль: trunk-based в масштабе — это дисциплина держать каждый сигнал — гейт, очередь, флаги — заслуживающим доверия, потому что сигнал, которому люди не могут доверять, обходят.

Связанные уроки
Продолжить восхождение ↑Долг флагов и дисциплина выкатки
хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources4
expand
  1. 01
  2. 02
  3. 03
  4. 04

Trademarks belong to their respective owners. Editorial reference only.