- PVSM.RU - https://www.pvsm.ru -
На днях вышла прекрасная, хотя и спорная статья — Please, stop using GitFlow! [1] (и еще десяток на эту же тему после нее).
Ее основными тезисами были:
Но проблема GitFlow в том, что он и с монорепозиториями тоже не дружит.
Я сам об это споткнулся в процессе дизайна пайплайнов CI: GitFlow чудовищно мешает, когда работает поверх монорепозитория с несколькими deliverables, например, когда в одном репозитории отдельно и бэкэнд, и фронтэнд — уже из-за того, что он позволяет докоммичивать в релизные ветки, могут возникнуть конфликты при обратном мердже, если в один момент времени существует больше, чем одна релизная ветка. Да даже если одна, все равно плохо — в таких условиях надо патчить в принципе релизные механизмы GitFlow, чтобы хоть как-то заработали отдельные релизы сущностей.
Автору оригинальной статьи помог trunk-based development + feature flags — почти гугловый green trunk, но не совсем. Но это совсем не значит, что этот подход нужен именно вам.
Во-первых нужно понять приоритеты.
Как выглядят ваши релизы?
Кто работает в репозитории?
Есть ли у вас автоматизированные средства для проверки качества кода? Ну, или хотите ли вы их внедрить?
Очень важно понимать, что релизный процесс и рабочий процесс — это вообще разные потоки. Тут без вариантов, любой flow поверх гита так или иначе это делает, разделяя изменения и релизы. Работа с этими двумя процессами похожа на работу с очередями вроде Apache Kafka или SQS — есть ряд источников, которые помещают обновления в очередь, и есть ряд указателей-релизов, которые смотрят на какой-то момент в прошлом, периодически поднимаясь вверх по этой очереди.
Изменения разработчиков и релизы — это абсолютно разные вещи. Релиз включает в себя пачку (от одного до бесконечности) изменений разработчиков, да, но он не обязательно должен включать в себя всю сделанную разработчиком фичу, он может забрать, допустим, пару созданных им для работы классов или функций, но не реализованную задачу, и это нормально.
Важно понимать, что если вам иногда требуется релиз, даже если изменений нет — вы что-то делаете не так. Иногда такое происходит, когда требуется обновить базовый JSON или YAML, который забирается во время сборки от внешнего поставщика — секреты, переводы, внешняя конфигурация.
Это неправильно, потому что это завязка на внешний фактор риска, и это неправильно, потому что это можно обновлять наживую во время работы с продакшном — автоматически или по кнопке, и в ситуации, когда это нужно будет сделать срочно — вы будете ждать полноценного релиза. Все, что можно вынести из релизного процесса, стоит вынести из него. Релиз — это дорогая операция, и если вы можете уменьшить их количество при той же скорости производства — стоит это делать.
В общем случае вам будет нужна единая мастер-ветка, в которую будут попадать все изменения. Очень сложно представить ситуацию, где все вместе работают над отдельными задачами, синхронизируясь друг с другом время от времени (если это не поддержка старых версий). Есть подход, в котором заводится отдельная ветка для документации или для отдельного проекта, но по сути это отдельный репозиторий в рамках общего, и к нему надо относиться точно так же, хотя это практика, которая может привести к расхождениям между кодом и документацией к нему, а так же к невозможности одновременно держать документацию, скажем, к v1 и v2 решениям.
В целом, если вы можете жить в монорепозитории, стоит это делать. Да, нужно разово все настроить, но у вас нет никаких значимых плюсов в отдельных репозиториях, кроме потенциального риска плохо настроенного и тормозящего CI, а потенциальных минусов очень много: про преимущества монорепозиториев написана не одна и не две статьи.
Если ваши релизы частые — нужно явно внедрять Continuous Delivery.
Время релизного инженера — это издержки, которые будут расти при росте количества релизов и количества deliverables. Лучше потратьте время разработчика на что-то еще, рук не хватает всем и всегда, даже если вы Google. По личной статистике — около 10% ресурсов команды -в абсолютно разных проектах — в среднем уходят на релиз-инженера, если релизы не автоматизированы.
Для автоматизации релизов надо разово вложиться в инфраструктуру. Это разовая издержка, которая включает в себя:
Хорошие автотесты
CI-автоматику для выкладки релизов
Если у вас сервера и deliverables:
Если у вас публикация пакетов или артефактов — все зависит от вашего flow, но я буду рад помочь с построением релизного механизма, пишите
Если релизы редкие, нужны backport-ы ИЛИ если в один момент времени потенциально может существовать более чем один обслуживаемый релиз — они явно будут существовать в отдельных ветках, которые не должны мерджиться обратно. После того, как вы отбранчуете эту ветку от основной рабочей (master/develop/trunk), вам может понадобиться внести в них несовместимые изменения, или просто отдельные коммиты. Для второго есть отличный механизм в git — cherry-picking. Ваши изменения должны "течь" только в одну сторону — от разработчиков в прод, из прода в основную рабочую ветку им попадать в действительности не нужно.
Если у вас больше, чем 5-6 разработчиков, или опытная команда — вам может подойти подход trunk-based development [2] для повседневной работы разработчиков (но не обязательно, что для релизов). Если счет разработчиков в одном репозитории идет на сотни — или вы хотите объединить сотни разработчиков в одном репозитории, у вас почти нет альтернативных вариантов, разве что сменить git на что-то еще. Google рапортовал в разных статьях о значительном приросте производительности после перехода на этот подход, но, к сожалению, цифры разнятся, хотя и значимы во всех источниках. Facebook не сообщает о цифрах, но известно, что они тоже пользуются этим подходом.
Несмотря на то, что Trunk-based — это просто "вливайте минимальные изменения сразу в рабочую ветку", он, в отличии от других подходов, требует вложений в инфраструктуру и настройку ее под себя. В целом, кроме обычных CI/CD, вам потребуется еще:
механика feature flags — это разовая издержка.
Для однопакетного репозитория стоимость внедрения сильно непредсказуема, но в целом должна быть не очень большой.
Для монорепозитория же она примерно пропорциональна количеству пакетов в монорепозитории. Переведите 2-3 разных и экстраполируйте, будет относительно точная, но слегка завышенная (потому что чем дальше, тем проще) оценка
В случае работы с короткоживущими ветками — merge queue, а в случае работы прямо в транке — механизм отката коммитов, не проходящих тесты.
второй вариант сделать сложнее, и он теоретически может провоцировать конфликты, так что лучше короткоживущие ветки.
В целом, эволюционный механизм для любого типичного проекта сейчас выглядит как-то так:
Но забегать вперед — не всегда лучшая идея. Иногда стоит посидеть на github-flow или отложить разгребание техдолга (или на время нанять отдельного GitOps-а — да, такая роль и профессия теперь тоже есть). Более того, ваша реализация может и скорее всего должна начать отличаться от "эталонной". Это нормально, и много разных команд работают в своих собственных парадигмах, если описывать тут их все — это вполне может выйти в отдельный цикл статей.
Поймите, на каком этапе вы, что у вас болит, и что можно сделать, чтобы не болело.
Ваш Git — это часть вашей инфраструктуры и кодовой базы, в нем точно так же копится технический долг, и его точно так же надо обслуживать. К сожалению, это не очевидно для большинства, и это зачастую спотыкается о непонимание команд и руководителей.
Если вы ощущаете, что ваш Git делает вам больно — напишите мне, я буду рад помочь.
Автор: Сева Родионов
Источник [3]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/programmirovanie/350677
Ссылки в тексте:
[1] Please, stop using GitFlow!: https://georgestocker.com/2020/03/04/please-stop-recommending-git-flow/
[2] trunk-based development: https://trunkbaseddevelopment.com/
[3] Источник: https://habr.com/ru/post/493866/?utm_source=habrahabr&utm_medium=rss&utm_campaign=493866
Нажмите здесь для печати.