В приступе горячей любви к автоматизации всего, что только возможно, я взял в работу задачу своих братьев‑ручных‑тестировщиков. Суть: релиз‑кандидаты (далее RC) для регрессионного тестирования на 3 стенда ставятся из GitLab CI вручную, что отнимает либо личное время дежурного тестировщика, либо время у регресс тестирования (от 1.5 опытного до 3 новичковых ощутимых часов). Такое количество часов обусловлено тем, что в нашей системе много сервисов, работа над ними ведется командами параллельно. А как известно, разработчики хотят видеть свой код в продуктиве регулярно. Из чего мы и получаем охапку веточек RC, которые нужно вылить на тестовые стенды. Надо автоматизировать. Но чтобы автоматизировать, нужно узнать, каков алгоритм накатки сейчас.  Создание ветки от RC. Создание pipeline от ветки с указанием номера стенда. Прожатие (тут и далее — последовательное нажатие) кнопок. Причем: кнопки не связаны друг с другом — нельзя зажать 1 и успокоиться, нужно прожать самостоятельно некоторое количество; количество кнопок от сервиса к сервису отличается; деплой на стенд уже существующего там сервиса и деплой отсутствующего — два разных мероприятия; существуют особые конфигурации кнопок (в одном случае используется один набор кнопок, в другом —отличный вне зависимости от того, находится ли сервис на стенде). Исследовав GitLab API, я понял, что общение с репозиторием устроено дружелюбно и даже мило: генерируешь токен в настройках — все двери открываются (при условии, что на учетке, от которой создан токен, есть нужные разрешения). Я наскреб нужных методов в ладошку по алгоритму выше: создание ветки от RC; создание pipeline от ветки с указанием номера стенда; прожатие кнопок: получение списка джобов (кнопок) для получения по названию ID; прожатие кнопки по ID. Важно отметить, что все действия требуют branch-ID (project-ID)/pipeline-ID/job-ID. В самом начале идея была такая: в корпоративный мессенджер пишется информация о том, что надо накатить и куда; информация попадает через роут на сервис; сервис внутри себя генерирует магию. Итог: указанная веточка с кодом от разработчика доставлена на стенд. Вещи, которые я реализовывал ранее для коллег, прокидывал через мессенджер (бота). Поэтому для данной задачи я решил, что хорошая идея тут тоже его использовать (спойлер: не особо). Я начал с данных. GitLab понимает обращения к репозиториям (и всему остальному) по ID, а ручные тестировщики знают только их названия, поэтому я создал JSON файл для мапы одного с другим для удобства использования. То есть на вход мы подаем имя репы — на выходе имеем ID для работы с ним. Вышел файл вида: Далее я определился с общим набором данных для запуска: имя ветки; название репозитория; стенд для накатки; ник юзера в мессенджере (для обратного оповещения о результатах). Чтобы упростить для себя (как я тогда думал) мешанину кнопок, я разделил сервисы на группы по количеству кнопок — микросервисы/backend/frontend. Для каждого создал свой роут. * И так для каждой конфигурации сервиса и разных типов сервисов. Реализовать очень хотелось как можно скорее, не привлекая дополнительно DevOps‑инженеров для решения здорового человека (о нем позднее). Из‑за этого возник другой интересный момент: кнопки в CI между собой не связаны — нужно знать, когда job кнопки прошел, чтобы инициировать запуск следующего. Это подтолкнуло меня на реализацию бесконечного ожидания ответа от запущенного job: Позже коллега показал мне, что можно вместо опроса логов написать через опрос статуса job, но это было сделано во втором приближении. В части бота решение выглядело как расщепление строки входа по разделителям на цикл запусков API‑вызовов для всех переданных веточек, что имитировало параллельно ставящиеся сборки. Я отдал эту красоту на «потрогать» ручникам, и оказалось, что решение не настолько жизнеспособное, как мне представлялось: Выплевывание на каждый чих ссылок с созданной веткой/pipeline плюс результат работы каждого job, когда поставить нужно больше, чем три сборки, делали разбор полетов и сам информационный чатик утомительными. Люди могли запутаться в обозначениях и поставить микросервис через front или наоборот, что генерировало ошибки в чат и вызывало грусть. Из‑за бесконечного ожидания ответа от job мы ловили ситуацию: три сборки поставились нормально, четвертая после создания pipeline просто не ставилась (причем выстрелить такое могло в середине цикла: сборки 1, 2, 4 отработали как надо, а третья устала на первой кнопке). Кнопки не прожимались. Все эти пункты для поставки релиза,состоящего из 10–20 и более задач, которые нужно вылить на три стенда, делали решение, мягко говоря, так себе. Далее я попытался своими силами решить те проблемы, которые было возможно, чтобы дотянуть решение до поставки целого RC на стенд.  Первое, что я сделал, — выпилил излишние обратные сообщения в мессенджер. Оставил только ссылку на pipeline и конечное сообщение об успехе или ошибке. Естественно, нужно было объединить три роута в один. Файл JSON, мапящий id и название репозитория я превратил в конфиг, который содержит в себе дополнительно наборы кнопок для разного рода накатки. Он превратился в: За счет этого роут приобрел унифицированный вид.  Проблему с поставкой пачки сервисов, состоящей больше чем из 3–4 сборок, своими силами решить без костылей (а куда уж дальше) не удастся. Для этого нужно переделать немного логику внутри решения и продеть часть ее в.yml файлы GitLab CI репозиториев (об этом далее). Однако на время можно пойти в обход. Если ставить сборки (обновления стенда в нерегрессионную неделю и накатку RC в неделю регресса) ночью, то можно пренебречь временем и проливать их по одной. Для этого я поместил роут в крону, а в кроне организовал цикл.  Но откуда брать данные о сборках, которые нужно поставить? Их хранение я организовал в своей mongoDB. Сам объект имеет вид: Стенд Тип пачки сборки Флаг Массив сборок Я набросал роуты: простенькую логику для добавления/удаления/изменения типов сборок. Мысль такая — типов сборок может храниться несколько (в зависимости от номера стенда и цели), их можно включать с помощью флага и условно можно разделить на regress/stable/other. Для тех, кто не хочет слать запросики в Postman, я организовал тот же функционал через Jenkins pipeine: выбрал из выпадающих списков стенды/типы, передал объект сборок и нажал кнопочку. Тут я наконец‑то могу сказать, что решение бесконечного опроса от job до момента, пока я не получу ее статус — такое себе удовольствие. Я бы хотел (WIP) вот как модифицировать логику: Роут_1: приходит сигнал поставить сборку; создаем веточку; создаем pipeline; жмем первую кнопку. Не опрашиваем никого сами — забыли о сделанном действии. Роут_2: от кнопки GitLab из post секции получили обращение: ошибка — вывели ее; успех — выкачали из JSON файла конфиг репозитория; последняя кнопка — вывели сообщение об успехе; не последняя кнопка — запустили нажатие кнопки[index + 1]. Конечно, для работы такой схемы мне из GitLab нужно получать определенный список параметров. Получилось существенно сократить по времени поставку RC перед регрессионным тестированием: вместо 1,5–3 часов ребятам нужно минут 15 вечером (собрать веточки) и минут 10 утром (посмотреть, что все действительно хорошо). Потратил я на это дело примерно недели 2–2,5 (с исследованием/разговорами/написанием кода/формированием полной картинки). Порог входа для новых сотрудников/стажеров упал «в ноги». Достаточно ознакомиться раз с инструкцией по пользованию, чтобы сразу начать использовать автонакатку. Масштабируемость у текущей реализации приятная. Для добавления нового сервиса достаточно в JSON‑файл прописать параметры, о которых я уже упоминал.  Поддерживаемость по ощущениям средняя. До внесения правок в код нужно войти в контекст глубже, чем хотелось бы. Однако сейчас ведется разработка по образу идеи, описанной выше, что в том числе должно повлиять на поддерживаемость в позитивном ключе. Если у вас есть опыт решения подобной задачи с использованием, например, другой логики, или ваша задача осложняется большими вводными — мне будет интересно это обсудить.  QA инженер