Три среды на бэкенде
Я уже не раз порывался написать что-то общее про бранчинг; про некогда распиаренный GitFlow, который запиаривают обратно; про trunk-based development (умеренно распиаривают), про то, как это увязать с разработкой бэкенда. И вот я затираю очередной забуксовавший черновик своей заметки с целью всё упростить и не гоняться за чрезмерным обобщением опыта. Давайте я просто поделюсь рецептом, а вы его оцените.
Обозначим ситуацию. Под небольшой апп нужно разработать небольшой бэк. Пара дизайнеров, от двух до пяти мобильщиков/фронтендеров, от двух до пяти человек на бэке, РП, аналитик, девопс, какое-нибудь начальство — средний проект на полгода-год-два, короче. Я таких повидал уже несколько, и в половине подключался на середине жизненного цикла. И может, я не самый везучий и/или не самый опытный, но с бранчингом и средами всегда была какая-то пускай не задница, но ложка дёгтя. Типа вроде всё нормально, но вот эту полную фигню мы обсуждать и исправлять не будем.
Фигнёй этой было назначение «нижних» общих сред. Если с самой верхней средой всё понятно (это святой продакшен), то с самой нижней всё очень мутно. Обзывают общие среды по-разному, но я приведу самый частый паттерн: production, staging, development. Вот, например, даже целый Микрософт этот паттерн в своём фреймворке признаёт:
И вот приходишь ты на очередной проект и спрашиваешь у ребят: как бранчуемся? Или не спрашиваешь если в репе лежит BRANCHING.md, но такой документ я лишь сам составлял. И тебе отвечают что-то в духе «у нас GitFlow, мы делаем бранчи от develop, а дальше смотри вот эту пикчу если ещё не видел». Ну и дальше ты видишь в сотый раз эту пикчу.
И конечно же выясняется, что ветка develop соответствует нижней среде, ниже которой ничего нет. Соответствует в том смысле, что попадающие туда коммиты улетают в облака и проливаются над какой-нибудь зоной типа https://api.dev.chebur.net.example/… (поэтично, да?)
Но постойте! Братцы! Если любой новый кодинг идёт от develop и это же ваша самая нижняя среда, то где вы экспериментируете? Где вы ловите баги за пределами юнит-тестов? Ах да, я надеюсь, что у вас есть юнит-тесты (naïve). И как вы поддерживаете стабильность develop? КУДА ВЫ ДЕВАЕТЕ НЕДОДЕЛАННУЮ ХРЕНЬ, ПОПАВШУЮ В develop, ЕСЛИ ВЫ ПОТОМ ОТ НЕГО ПЛЯШЕТЕ? Извините, накипело.
В ответ звучит что-нибудь про непонимание GitFlow, про заморозку кода перед релизом, про ещё какую-нибудь тропинку огородами да гаражами оправдывающую ветвление от бранча, который завязан на экспериментальную по своей природе среду. Ну или отрицание самой идеи latest-среды с недотестированными фичами.
Однажды меня осенило. Ну, в рамках своих проектов, конечно же; не претендую на открытие формулы всего: никакой ложки нижней среды на вон той диаграмме не существует, и она вообще не отвечает на вопрос долгоживущих сред. И лишь по недоразумению development-среда оказывается develop-бранчем под протухшим соусом GitFlow. Та пикча вообще не про бэкенд, который не сильно-то тяготеет к версионированию.
Оставалось признать очевидное: нужна песочница, playground, workbench — как хотите называйте — которая и станет самой нижней средой. Если запретить ветвление от неё (в неё — можно), если запретить целиком выкатывать её в staging и дальше в production, то всё встаёт на свои места. Появляется общий энв со свежайшим кодом, который разблокирует фронтендеров, который позволяет самому увидеть свой код in action (апихи живые постманом подёргать), и который никого ни к чему не обязывает. Он по определению нестабилен. Точнее, стабилен ровно настолько, насколько позволяет юнит-тестирование и насколько вообще может быть стабильна свежая фича.
Но если нельзя бранчеваться от dev|elop|ment потому что это какой-то инкубатор, то откуда и как это делать? Давайте проследим через постепенное усложнение. Допустим, у нас есть только продакшен в облаках и единственный долгоживущий бранч в репозитории — main — на который продакшен и завязан. И пропустим вариант, где мы тупо фигачим все коммиты в main не создавая веток. Итак, простейший workflow:
Нет, это не TBD
Перфекшен! Если бы все всё делали идеально, то большего не нужно. И trunk-based development как раз проповедует: никаких долгоиграющих веток! фигачим всё в ствол, понемногу и часто! любые сомнения заметаем под ковёр из фича-тогглов! Но что если мы не готовы так радикально перестраиваться? Что если у нас не всё хорошо с тестами? Что если реальность требует где-то вне продакшена проверять изменения?
Окей, добавим staging, где будем эти изменения копить и проверять. Почковаться разрешим хоть от main, хоть от staging. Типа если хочешь хотфикс сделать и проверить его на staging, то работай от main — так ты сможешь вмёрджить хотфикс в прод не утаскивая туда весь недоваренный staging. Ну, а если в staging много почти готового накопилось, а тебе поверх этого надо новую фичу пилить — бранчуйся от staging, всё равно в конце спринта это всё вместе выкатывать.
Но тут приходит фронт и говорит, что им нужна свежая апиха, над которой ты ещё работаешь, чтобы вживую всё проверить. Или приходит бэк (может даже ты сам) и говорит, что подкрутил чего-то в инфраструктурных скриптах и локально это не проверить вообще никак, надо накатить куда-то. Этим «куда-то» и становится development.
В этой диаграмме важно то, что она вообще никак не изменила предыдущую. Она просто объявила среду совместной разработки (в плане доступности свежего кода в живой среде). Общий верстак, на котором можно допиливать полуготовый код. И эта среда по умолчанию нестабильно, и двигать её целиком вверх на staging или prod нельзя, и вообще можно с неё всё смахнуть (договорившись с командой) и начать с чистого листа — ну мало ли чего там брошенного накопилось.
Бардак? Ну да, можно смотреть как на бардак. Но можно смотреть как на компромисс и реальный способ обуздать косячную реальность. Да-да, лучше сразу не косячить и всё такое. Где вы это видели? Возьмите меня туда учиться.
Идею можно развивать дальше и вместо одной песочницы объявить эфемерные среды, где можно поднять свою маленькую изолированную песочницу из любой ветки.
В теории это даже позволяет отказаться от staging, потому что проверять всё можно независимо и потом лить в продакшен тоже независимо.
Но это уже фантазии, до воплощения которых я не добирался. Предвижу, что это потребует качественного генератора тестовых данных и очень генерализованного CI/CD. Тестировщики, привыкшие к фиксированным средам, тоже спасибо не скажут. Оставим эту тему на другой раз.
Активирую режим подытоживающей интроспекции. Писать про то, как ты раз за разом сталкивался со стрёмными паттернами, неловко и обидно — что же это за работа такая грязная. Разбавлять это какими-то компромиссными решениями неловко вдвойне. Но мне норм; и даже моя команда не против описанного подхода. Признав песочницу песочницей, мы перестали спорить о её стабильности. Да, она имеет свойство засоряться, но теперь это блокирует только её саму, а не возможность выкатить обновления в прод.