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

Активное ветвление и непрерывная поставка? Судьба вашего 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. Код, тестирование, повтор

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

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

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

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

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

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

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

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

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

Профессиональный совет. Для главной ветки или любой другой ветки, используемой для выпуска релизов, вы несомненно захотите выполнять сборку после каждой операции push. Настройте для таких веток автоматический триггер сборки в Bamboo с интенсивным графиком опросов или push‑уведомление из Bitbucket.

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

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

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

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

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

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

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

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

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

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

Здесь следует отметить лишь то, что команды SaaS обычно создают функциональные ветки из главной ветки.

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

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

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

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

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

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

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

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

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

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

Некоторые команды запускают автоматическое развертывание после каждой успешной сборки главной ветки (в этом случае важную роль играют «‎флажки возможностей»), а другие команды ждут, пока в главную ветку не будет отправлена критическая масса изменений, прежде чем поставить тег релиза и запустить развертывание. Аналогичным образом некоторые команды развертывают продукт прямо в рабочей среде, а другие, прежде чем запустить продукт в эксплуатацию, продвигают сборку в раздел проиндексированных файлов для выполнения последнего цикла тестов на проверку работоспособности.

«Самого лучшего» волшебного способа поставки кода из главной ветки клиентам не существует. Но вы находитесь на верном пути, если стремитесь к максимальной автоматизации.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Напомним еще раз: основное отличие от базового процесса состоит в том, откуда создана ваша ветка. В случае новой разработки в основе вашей функциональной ветки будет лежать ветка разработки. (Не забудьте выбрать для ответвления чистый коммит!) В случае исправлений багов для уже поставленной версии в основе будет находиться ветка стабильной версии. Такой иллюстрации здесь нет, но вы наверняка это представляете. Подробную информацию о вариантах, предлагаемых Git-flow, и соответствующих структурах веток можно найти в нашем учебном руководстве. Решение Bitbucket поддерживает все варианты, а также настройку прав доступа для веток, что дает вам возможность контролировать доступ к главной ветке и веткам версий.

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

При использовании модели Git-flow релизы можно выпускать из главной ветки или из веток стабильных версий. Общее правило заключается в том, что релиз следует сделать основной веткой для сборок Bamboo (это пригодится, когда придет время развертывания). Кроме того, следует включить ветки плана, чтобы все ветки тщательно тестировались.

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

С Git-flow этап тестирования становится интереснее. Используйте ветки плана в Bamboo, чтобы проводить тестирование в функциональной ветке (как и во всех процессах непрерывной поставки). Отличие заключается в следующем: когда внедрение завершено и все ваши тесты пройдены успешно, необходимо выполнить слияние с веткой разработки, а не с главной веткой.

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

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

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

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

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

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

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

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

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

Подобно процессу SaaS, можно автоматически создавать теги на главной ветке на основе каждой успешной сборки ветки разработки и на основе этих тегов сразу же выполнять развертывание. Или же можно подождать, пока несколько возможностей не будут успешно добавлены в ветку разработки, и создать тег вручную. Это зависит только от того, какая стратегия вам ближе: непрерывное развертывание или непрерывная поставка. Решение Git-flow совместимо с обоими вариантами.

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

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

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

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

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