Процессы непрерывной поставки при использовании модели «ветка на каждую задачу»

Активное ветвление и непрерывная поставка? Судьба вашего SaaS-продукта под вопросом.

Sarah Goff-Dupont Sarah Goff-Dupont

Как уже подробно объяснялось в статье Сверхмощная непрерывная поставка с Git, использование активного ветвления в процессе непрерывной поставки — это Правильно™. Это помогает поддерживать самые важные ветки в чистом и готовом к релизу состоянии, позволяет разработчикам пробовать новые вещи, не наступая на ноги своим коллегам по команде, и упрощает отслеживание проекта (если все сделано как нужно).

Мы используем процесс с отдельной веткой на каждую задачу уже в течение нескольких лет, как и многие наши клиенты. Мы также позаботились о предоставлении поддержки такого процесса в Jira Software и инструментах Atlassian для разработчиков. Таким образом, это не только рекомендовано, но еще и просто. Итак, давайте рассмотрим более подробно модель «отдельная ветка на каждую задачу» и узнаем, как она сочетается с тремя наиболее распространенными рабочими процессами непрерывной поставки: моделью SaaS, продуктами для установки на ПК и мобильные устройства, а также с Gitflow (который работает с любым типом продуктов).

Базовый процесс с отдельной веткой на каждую задачу

Название говорит само за себя: для каждой задачи, над которой вы работаете (или для каждого изменения кода, которое обязательно должно отслеживаться в Jira Software), создавайте ветку разработки. Затем проводите всю работу по реализации и тестированию в этой ветке. По завершении отправьте запрос pull, проведите слияние и выпускайте релиз, как только будете готовы.

Снимок экрана: базовый процесс | Atlassian CI/CD

Вот как можно разбить процесс на этапы с помощью инструментов Atlassian.

Шаг 0. Настройка интеграции инструментов

Интегрируйте Jira Software, Bitbucket и Bamboo в сотрудничестве с коллегой-администратором Atlassian. Обратите внимание: можно смешивать и сочетать варианты Cloud и Server. Например, несколько команд в Atlassian используют Jira Software Server, Bamboo Server и Bitbucket Cloud. Тем, кто предпочитает работать с Git через графический интерфейс, а не через командную строку, я также очень рекомендую SourceTree. Это бесплатный продукт, поэтому нет причины хотя бы не попробовать его. После установки SourceTree подключите его к своим репозиториям.

Вам также придется сделать прочие очевидные вещи, в т. ч. создать задачи для отслеживания работы, настроить парочку репозиториев, а также настроить сборки и задания по развертыванию.

Шаг 1. Создание ветки

Создайте задачу в Jira Software, назначьте ответственным за нее себя и поменяйте ее статус на In progress (В процессе), чтобы ваша команда была в курсе дела. Справа находится панель Development (Разработка). Нажмите расположенную на панели ссылку Create branch (Создать ветку). Если у вас подключено несколько менеджеров репозитория, на следующем экране необходимо будет выбрать менеджер для управления вашей веткой. В остальных случаях сразу откроется экран настройки ветки.

Снимок экрана: создание процессов на основе веток | Atlassian CI/CD

Обратите внимание, как Bitbucket подхватил ключ задачи (в этом примере MKT-15886) и использовал его в названии ветки. Это помогает реализовать множество полезных вещей, таких как отправка информации о коммите, сборке, запросе pull и развертывании обратно на панель Development (Разработка). Ключи задач инициируют всевозможные виды связывания и автоматизации на всех этапах процесса непрерывной поставки, поэтому не забудьте включать их в названия ваших веток независимо от того, работаете вы в пользовательском интерфейсе или в командной строке.

Обратите внимание на выпадающие списки, позволяющие выбрать префикс для ветки на основе ее разновидности (устранение бага, возможность, релиз и т. д.), а также на родительскую ветку или тег, на основе которых будет создана новая ветка. Если выбранная ветка собирается и тестируется в Bamboo, вы увидите индикатор, который показывает, чиста ли ветка в данный момент. Обязательно следите за этим индикатором. Меньше всего хочется сталкиваться в работе с новой веткой, которая уже неким образом испорчена.

После того, как все будет настроено в соответствии с вашими предпочтениями, нажмите Create branch (Создать ветку), и Bitbucket сделает все остальное.

Этап 2. Код, тестирование, повтор

This part is probably familiar: clone the repo locally if you haven't already, check out your new branch, and start coding. By the time you've made your first push to the new branch, Bamboo has already detected it in your repo and configured continuous integration for it using the plan branches feature (assuming you've got automatic branch management enabled). Essentially, Bamboo listens for new branches in your repo, and applies whatever builds you've configured for main to them.

I also recommend enabling automatic merging through Bamboo. At the start of each build, Bamboo can check out any two branches, merge them, then run the build against the merged code. So for this stage of the continuous delivery workflow, you merge changes from main down to your feature branch. This way, your branch won't drift far from main, and you'll get early feedback as to whether your changes play nicely with the changes on main.

Снимок экрана: инструмент обновления веток | Atlassian CI/CD

If automatic merging isn't your thing, definitely merge main into your branch (or rebase) and fire off a build just to make sure there aren't any nasty surprises – or fix 'em if they pop up. Once implementation is complete, and all your tests are passing, you're ready for the next step.

Шаг 3. Слияние вверх

Being upstanding citizens of our teams, we never charge ahead and merge to main (or any other critical branch) without doing a pull request – the only form of code review in the known universe that does not suck.

Запросы pull можно создавать из командной строки или с помощью SourceTree, но использование интерфейса Bitbucket дает кое-какие преимущества. Прежде всего, у вас появляется возможность сравнивать вашу ветку с целевой веткой. Пробежавшись глазами по различиям, можно обнаружить пару моментов, которые сразу же захочется исправить. Затем, не покидая экран сравнения веток, достаточно нажать кнопку Create pull request (Создать запрос pull), выбрать проверяющих участников — и вперед!

Снимок экрана: запрос pull в процессах Bitbucket | Atlassian CI/CD

Bitbucket является (без преувеличения) крайне мощным инструментом, когда дело доходит до запросов pull. Помимо обычных вещей, таких как параллельное отображение различий и встроенные комментарии, здесь также можно использовать правила. Некоторые команды разработчиков в Atlassian задают правило, согласно которому слияние запросов pull возможно только после того, как их одобрят не менее двух человек. Другие команды назначают своего рода контролера: права на целевую ветку устанавливаются таким образом, что только контролер может выполнять слияние. И все без исключения команды должны включать правило, предотвращающее слияние запроса pull, если после слияния данной ветки происходит сбой какой-либо из сборок.

Pro tip: For main and whatever branch you release from, you'll definitely want to build right away after each push. Configure an automatic build trigger for them in Bamboo with an aggressive polling schedule or a push notification from Bitbucket.

Шаг 4. Переходите к поставке — и пусть все получится!

(Тут есть еще фанаты Devo? «Как только появляется новый код, надо сразу отправлять его в поставку». Нет? Ну ладно... Пожалуй, пока не буду бросать основную работу.)

Снимок экрана: развертывание сборки в процессах Bamboo | Atlassian CI/CD

Как только сборка на ветке релиза станет зеленой, вы потенциально готовы к поставке. Я говорю «потенциально», потому что решение о том, будете ли вы делать поставку прямо сейчас, зависит от вашей команды. (Сборка отвечает всем критериям приемки? Достаточно ли испытаны на прочность артефакты при нагрузочном тестировании?)

Безусловно, вы можете использовать Bamboo для автоматического развертывания сборки в промежуточную среду или сразу в рабочую среду, если вы настроены на полностью непрерывное развертывание. Но такая идея применима не для каждой команды и не для каждого продукта, что мы сейчас и обсудим.

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

Процесс непрерывной поставки для продуктов SaaS

С точки зрения веток, с которыми вы работаете, и того, как между ними перемещается код, процесс SaaS идентичен базовому процессу.

Снимок экрана: процесс SaaS | Atlassian CI/CD

Шаг 1. Создание ветки

Only thing to note here is that SaaS teams typically create their feature branches from main.

Этап 2. Код, тестирование, повтор

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

К счастью, облегченные среды становится все проще запускать и расформировывать в нужный момент благодаря таким технологиям, как Puppet, Chef, Docker и Vagrant. (Мне бы хотелось поговорить об этом подробнее, но это тема для отдельной статьи...) Bamboo также поддерживает автоматические развертывания из любой ветки. Словом, неважно, работаете вы с временными или с постоянными средами, — можно настроить развертывание всех удачных сборок вашей ветки в среде, в которой они будут проходить через последовательность автоматизированных тестов пользовательского интерфейса и/или нагрузочных тестов.

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

Скриншот среды тестирования | CI/CD Atlassian

Даже если ваша команда не мечтает о непрерывном развертывании и предпочитает самостоятельно принимать решение о том, когда делать поставку, развертывание успешных сборок веток в некой среде — хорошая идея. Это дает вам и другим участникам вашей команды возможность провести в каком-либо объеме глубокое тестирование перед окончательным слиянием.

Шаг 3. Слияние вверх

The number of pre-production environments your team uses will influence the exact point at which you move to this step. Typically, developers will run in-process tests on their branch with each build, and if those pass, deploy to a test environment for UI, load, and/or exploratory testing. Once everything is ship-shape on test, they create the pull request and merge up to whatever branch you release from (again, typically main).

Шаг 4. Поставка

At this point, you've come full circle: you've merged back up to main and verified tests are passing there. This is also a point where we see lots of variation in different teams' approach.

Some teams trigger an automatic deploy after every successful build of main (in which case, feature flags are essential), some teams wait until a critical mass of changes are on main before tagging a release and triggering a deploy. Similarly, some teams deploy straight to production, others promote the build to a staging environment for one last round of sanity-check tests before taking it live.

There's no magical "best" way to get code from main to customers. As long as you're automating as much possible, you're on the right track.

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

Главное отличие от стандартного рабочего процесса, где каждой задаче соответствует отдельная ветка, заключается в существовании веток-долгожителей, предназначенных для размещения поддерживаемых на данный момент версий. Для корпоративных B2B-продуктов, таких как продукты Atlassian, этих веток может быть полдюжины (или больше). Для мобильных приложений их будет лишь 2–3 (или даже одна).

Снимок экрана: процесс с множеством версий | Atlassian CI/CD

Шаг 1. Создание ветки

Место, откуда вы будете создавать ветку, будет зависеть от того, какие изменения вы вносите. Речь идет об устранении бага в релизе, поставку которого вы выполнили на прошлой неделе? Или о новом функционале для следующего релиза?

In the case of the latter, you'll branch off of main. If it's the former, you'll base your branch off the branch for the earliest version the change is destined for (i.e., the first version in which the bug appeared).

Этап 2. Код, тестирование, повтор

Как и в случае с SaaS-продуктами, хорошим вариантом будет развертывание успешных сборок из вашей ветки в тестовой среде, как только вы проведете все предварительные тесты. Но причины, по которым эта идея хороша, немного другие.

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

Таким образом, развертывание в тестовой среде, проводимое для тестирования пользовательского интерфейса, нагрузочного и/или глубокого тестирования, следует рассматривать как «не совсем необязательное» в этом процессе. И здесь, с учетом обстоятельств, можно сказать, что глубокое тестирование само по себе также не является необязательным. Но я отвлекаюсь...

Шаг 3. Слияние вверх (и/или вниз)

Вот тут и начинается самое интересное.

If you're working on something for an upcoming release, you do a pull request and merge your branch up to main just like in the basic workflow. But if you based your branch off a stable version branch, you'll merge back down to that branch first and make sure all your tests pass there. Then back-port to older versions that need the same update, testing each one along the way. Finally, you'll merge to main so all future versions carry the same change.

Снимок экрана: процесс с множеством версий | Atlassian CI/CD

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

Можно также использовать возможность Bamboo для автоматического слияния (описана выше), чтобы перемещать изменения между ветками стабильных версий. Однако в этом случае следует использовать Gatekeeper.

Снимок экрана: Gatekeeper | Atlassian CI/CD

Предположим, выполнив слияние, вы добавили устранение бага в ветку для версии 1.2. Перейдите к конфигурациям ветки плана для этой ветки и настройте ее на автоматическое слияние с веткой версии 1.1, и так далее.

Шаг 3,5. Создание ветки стабильной версии

Naturally, if you're working on new stuff for the next version, you'll cut a new stable version branch when you've got a critical mass of features ready. (Ready = implemented, tested, blessed, etc.) This is typically cut from main, and, like main, is configured to build and test automatically each time changes are pushed to it.

If (ok: when) you discover that more changes are needed before shipping the version out, cut feature branches off the stable version branch. Once the changes are ready, merge down to the stable version branch and test there. Assuming that goes well, cascade your change down to main, like in the diagram above.

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

Шаг 4. Поставка

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

Непрерывная поставка способом Gitflow

Instead of a single main branch, this approach uses two branches to track the history of the project. While the main branch contains tags and/or commits that record the project's official release history, a shared integration branch (usually called "develop") gives your team a place to ferret out bugs and incompatible changes.

Скриншот Gitflow | CI/CD Atlassian

Шаг 1. Создание ветки

Here again, the difference from the basic workflow is simply where you branch from. For new development work, your feature branch will be based on develop (make sure you choose a clean commit to branch from!). For bugfixes to a version you've already shipped, it'll be based on a stable version branch – not pictured above, but you get the idea. For more details on Gitflow's variations and their branching structures, check out our tutorial. Bitbucket supports all variations, as well as branch permissions that give you the option to control access main or version branches.

В каком бы месте вы ни создали ветку, используйте возможность обновления веток Bamboo (упомянута выше), чтобы путем запроса pull передавать изменения из родительской ветки в свою функциональную ветку при каждой сборке. Вы будете выявлять проблемы интеграции сразу после обновления и сможете исправить их в своей функциональной ветке. Это гораздо лучше, чем наткнуться на них уже после слияния с веткой разработки (ведь так вы успеете испортить и ее).

With the Gitflow model, it's possible to release from main, or from stable version branches. The rule of thumb is to make your release the primary branch for your Bamboo builds – this will come into play when it's time to deploy – and enable plan branches so all branches are tested thoroughly.

Этап 2. Код, тестирование, повтор

The testing step gets interesting with Gitflow. Use plan branches in Bamboo to put your feature branch under test (as in all continuous delivery workflows), but here's the difference: when implementation is complete and all your tests are passing, merge to develop instead of main.

Ветка разработки — это своего рода котел, в котором вместе варятся все изменения, вносимые вашей командой. Вам потребуется обратная связь по каждому коммиту, чтобы упростить отладку сбоев тестов (так будет меньше требующих проверки изменений между последовательными сборками). Лучший способ это гарантировать заключается в настройке ветки разработки таким образом, чтобы сборки запускались на основе push-уведомлений из Bitbucket. В случае периодического опроса репозитория иногда будут захватываться изменения из нескольких коммитов в одной сборке, потому что в ветке разработки изменения происходят очень часто. Поэтому способ с опросом лучше подходит для веток, изменения в которых более разнесены по времени или месту.

Снимок экрана: тип триггера | Atlassian CI/CD

Профессиональный совет. Еще одним преимуществом сборок, запускаемых репозиторием, с точки зрения разработки является эффективное использование ЦПУ Bamboo, как я уже говорил в статье Репозитории Git с поддержкой непрерывной интеграции. Для команд, осуществляющих непрерывную поставку в крупных масштабах, это очевидно.

Как и в случае применения стандартного рабочего процесса, убедитесь, что вы осуществляете слияние ветки разработки с функциональной веткой (или операцию rebase) и проведите тесты еще один (последний) раз перед переходом к разработке.

Шаг 3. Слияние вверх

Создание запроса pull при слиянии вашей функциональной ветки с веткой разработки является стандартным подходом. Выполнить экспертную оценку кода на данном этапе гораздо проще. Если откладывать ее до того момента, когда вы будете готовы к поставке, вам потребуется сразу проверить все изменения, внесенные после последнего релиза. Нет уж, спасибо.

Inevitably, you'll merge your feature branch to develop, only to be met with test failures there. Instead of making changes directly to develop, checkout your branch again and do the work there. (Most teams at Atlassian have "handshake" agreements never to make commits directly on main – only merge commits.)

Шаг 4. Поставка

Назначение ветки релиза в качестве основной ветки для плана сборки в Bamboo позволяет настроить довольно простой и ясный проект развертывания. Какой бы ни была ваша основная ветка для плана сборки, она автоматически станет основной веткой для задач развертывания. При этом можно настроить проект развертывания так, чтобы развертывались еще и сборки из функциональных веток.

Similar to the SaaS workflow, you can automatically create tags on main based on each successful build of develop and deploy from those tags right away. Or, you can wait until several features have been successfully been added to develop, and create the tag by hand. It simply depends on whether you're moving toward continuous deployment, or sticking with continuous delivery. Gitflow accommodates both.

Уф! Позади четыре процесса, пять диаграмм и около 3200 слов текста! (Если вы до сих пор способны это читать, мои поздравления!)

Надеюсь, вы получили базовое представление о том, как Jira Software, Bitbucket и Bamboo работают вместе, способствуя реализации в непрерывной поставке модели, где каждой задаче соответствует отдельная ветка. Если нет, свяжитесь со мной через Twitter и расскажите, как можно улучшить эту статью, — я считаю ее очень важной.

По крайней мере, мы увидели важность создания ветки для каждой задачи, над которой ведется работа. Вы перестанете наступать на ноги коллегам, а ваши самые важные ветки постоянно будут оставаться «чистыми» и пригодными для выпуска релизов. Итак, повторяйте за мной:

Использовать ветки и не допускать попадания в процесс мусора — это ПРАВИЛЬНО™.

Удачной работы с ветками!