В какой ветке вести разработку? Из какой ветки деплоить на PROD? В какой ветке чинить багу, выявленную на IFT? Многие команды закрыли для себя этот вопрос, но для многих он остаётся открытым. Этот пост не будет содержать каких-то особых ноу-хау и киллер-фич. В нём я расскажу наиболее простую и понятную (лично мне) практику релизных циклов на основе git flow. И постараюсь объяснить каждое своё решение и каждый подход. Итак, поехали. В идеале, в дополнение к проду, хорошо иметь ещё два стенда: интеграционно‑функциональный (далее — IFT) и, конечно, DEV. Опишем каждый стенд, его задачи и назначение более подробно: DEV. Стенд для разработки. Все новые фичи и починенные баги в рамках спринта в первую очередь выкатываются на этот стенд. Активное тестирование фич и исправленных багов происходит тут. Деплоит на него в основном команда разработки. Содержит синтезированные данные. IFT. Стенд для интеграционно‑функционального тестирования. На этапе отладки фичи и исправленные баги тестируются на нём. Как правило, размещается в тестовом окружении заказчика и содержит реальные обезличенные данные. Если у Вас проект чуть сложнее CRUD, а стенда IFT у Вас нет, разрабатывать будет больно. PROD. Продуктивный стенд, с реальными посетителями. Вершина иерархии окружения. Деплоем на такие стенды занимается специальная команда внедрения. Лучше, если у разработчиков вообще не будет к нему доступа. Как управлять разработкой для этого минимума стендов, мы и поговорим в этом посте. Спринт мы поделим на две неравные части: разработка и отладка. Активная разработка — это бо́льшая часть спринта, во время которой реализуются фичи, заявленные в спринте и исправляются баги, найденные на DEV‑стенде. Отладка — это вторая часть спринта, которая наступает после реализации фич спринта, а тестирование переносится на IFT‑стенд. Итак, у нас 3 стенда. Для каждого из них лучше создать свою ветку, назвав её соответствующим образом: prod/master, ift/test, dev/develop - как угодно, главное, чтобы по названиям было понятно их назначение или они хотя бы были в понятийной среде разработки. В нашем примере, ветки будут master, test и develop. Правило первое. Каждый стенд имеет свою одну-единственную мастер-ветку. Разворачивание приложения на стенд происходит только из неё. Выглядеть это будет следующим образом: Этот контракт необходимо поддерживать всеми силами. Активная разработка ведётся только из ветки develop. Реализуете фичу - ответвляете ветку feature/XXX от develop. Исправляете баг - пожалуйста, bug/XXX. По окончании разработки, ветка вливается обратно в develop, а оттуда уже изменения попадают на DEV-стенд. Правило второе. Вся активная разработка ведётся в ветках, образованных от ветки develop, которые по окончании разработки в них вливаются обратно в develop. На DEV-стенде размещено приложение в состоянии, соответствующем текущему спринту; на IFT и PROD - предыдущему. Выглядит это так: Как видно из картинки, на IFT и PROD код ещё в версии спринта А, тогда как на DEV-стенде уже в версии спринта Б. По окончании активной разработки, весь код из ветки develop вливается в ветку test. Тестирование на DEV‑стенде прекращается и переносится на IFT‑стенд. Этот процесс можно назвать code freeze в рамках спринта. С этого момента, разработчик уже может брать задачи следующего спринта и продолжать реализовывать обычным способом, в ветках от develop, по окончании реализации которых он в обычном режиме деплоится на DEV‑стенд. Происходит разделение стендов на уровне спринтов: IFT‑стенд принадлежит текущему спринту, тогда как DEV‑стенд — будущему. С момента отладки уже можно проводить планирование следующего спринта, чтобы определить scope задач, которые разработчик уже может брать в работу. Таким образом, на этапе отладки каждый стенд находится в версии своего спринта: тогда как PROD всё ещё в версии предыдущего спринта, то IFT уже в версии нынешнего, а DEV — в версии спринта будущего. Таким образом, разработчик не простаивает на время отладки и уже может сделать часть работы, намеченной на следующий спринт. Интеграционно‑функциональный стенд имеет несколько важных отличий от стенда разработки: а) он находится в окружении заказчика, что позволяет отладить взаимодействие с этим окружением, и б) он наполнен не синтезированным мусором, а обезличенными данными с PROD. Это позволяет тестировщику провести тестирование фич на уровне, наиболее близком к продуктивному. Конечно, целью такого тестирования является обнаружение новых багов. Итак, тестировщик нашёл новый баг. Как мы помним, IFT находится в состоянии текущего спринта, а DEV — будущего. Если мы для устранения бага создадим ветку от develop, то к тому моменту в develop уже могут оказаться фичи следующего релиза, которые не были ещё протестированы и не должны попасть в текущий релиз. Тогда, после устранения бага, нам придётся черри‑пикать изменения из develop в test и держать потом эти черри‑пики в уме, но это плохой выход из ситуации (в целом, практика черри‑пиков является костылём и в разработке может применяться только от безысходности). Отсюда вытекает правило третье: Правило третье: мы помним правило Первое, согласно которому, изменения на стенд деплоятся только из своей мастер‑ветки. Стало быть, если на каком‑то конкретном стенде были найдены причины для изменения кода, то и разработка в рамках этих изменений ведётся из мастер‑ветки этого стенда. Иными словами, если на IFT был найден баг, для его устранения мы образуем ветку из test. После исправления бага, ветка вливается обратно в test, происходит деплой на IFT, баг тестируется повторно, и если всё ок, ветка test вливается в develop. При таком подходе, сохраняется следующая взаимосвязь: ветка test содержит в себе версию кода, актуальную по текущий релиз; ветка develop содержит в себе версию кода, актуальную по текущий релиз + изменения в рамках следующего релиза. Единственное назначение стенда IFT — это тестирование приложения «как бы на проде». Окружение и наполнение IFT‑стенда не должно кардинально отличаться от прода и как можно чаще обогащаться оттуда обезличенными данными. Если у Вас не так — будете тестировать на проде, что уж. После окончания этапа отладки изменения из ветки test переносятся в ветку master и деплоятся на PROD. Версионность стендов возвращается к состоянию активной разработки (в следующей итерации), начинается новый спринт, с его победами и поражениями. В соответствии с вышеописанным, полный релизный цикл будет выглядеть так: Мы приложили все усилия для того, чтобы это не произошло. Но мы точно знаем, что это произойдёт. Что делать? В первую очередь, попробуйте воспроизвести баг на стенде IFT. Если вы держите IFT в состоянии, актуальном PROD, он в очень высокой долей вероятности воспроизведётся. Если воспроизвёлся, переходим к разделу «Этап отладки: что, если был найден баг на стенде IFT?«, правилу 3 и далее вниз по посту: исправили на IFT, влились из IFT в develop, влились в master, зарелизились на PROD повторно. Если баг не воспроизвёлся на IFT, значит, это проблема чисто PROD и применяем правило 3 уже к нему: бранчуемся из master, исправляем проблему, далее переливаем изменения из master → test → develop.  backend.developer { java, kotlin } in Sber