Всем привет! Меня зовут Женя Мельцайкин, я старший инженер-программист в компании Контур. Большую часть времени в Контуре я работал и работаю Android-разработчиком, но статья будет не про Android и даже не про мобильную разработку. А про команду Мобильной разработки в Контуре и про наши процессы разработки! Давайте же начнем разбираться, причем тут мобильные разработчики, автоматизация и бэкенд.
Про наши процессы
В Контуре на данный момент более 20 мобильных разработчиков. Но количество приложений «немного» больше – почти в 2 раза, если считать по платформам. И помимо приложений у нас есть общие модули: дизайн система, авторизация, чат и другие.
У каждого приложения своя команда, свои менеджеры проектов, свои внешние команды-интеграторы, но у всех приложений общие процессы у команды мобильной разработки. Хотя так было не всегда.
Итак, внешних команд много, а команда мобильной разработки одна. Так что в нашем процессе работы самое главное – это прозрачность. Поэтому в прошлом году мы полностью пересмотрели процесс работы с задачами и теперь кроме обычных статусов Backlog, Development, Review, Testing и Done добавились новые. Вся статусная модель выглядит так:
-
Backlog – здесь собираются задачи, без доказанной бизнес ценности
-
Submitted – сюда падают все новые задачи для дальнейшего обсуждения
-
Open – статус, где задачи с подтвержденной пользой для проекта
-
On hold – сюда попадают задачи, которые блокированные внешними факторами
-
System engineering – этап проектирования задачи. Тут проходит подготовка аналитики, дизайнов, API.
-
Ready to dev – задача готова к разработке
-
Reopened – статус, в которой находятся задачи, которые по какой-то причине были отправлены на доработку. Например, нашли новый баг, либо были критические замечания на ревью
-
Development – активная разработка задачи
-
Review – задача на ревью
-
Waiting for build – задача прошла ревью, но ожидает тестовую сборку в сервис тестирования
-
Ready for QA – сборка с задачей загружена в сервис тестирования и ожидает тестировщика
-
Testing – задача в тестировании
-
Done – задача выполнена в полном объеме и ошибок в ней не обнаружено
-
Verified – задача прошла регрессионное тестирование
-
Released – задача вышла в релиз
Решив проблему прозрачности статусов задач, мы создали себе другую проблему – стало труднее поддерживать задачи в актуальном статусе. Данная проблема особо сильно возникает на статусах, где происходит активная разработка задачи: Development, Review, Waiting for build и Ready for QA. У части нашей команды осталась привычка держать статусы по задачам в голове. Не все сходу привыкли к расширенному перечню статусов, а когда задачи не в актуальном статусе, наши тестировщики и менеджеры начинают негодовать. Самое главное, теряется прозрачность процесса.
И для решения данной проблемы, в нашем случае, к нам приходят мы же сами – мобильные разработчики.
Какие были варианты
Прежде чем решать проблему неактуальных статусов, нужно верхнеуровнево определить, что для этого нужно. В качестве трекера задач мы используем YouTrack и Gitlab для хранения и управления репозиториями Git. Так как мы решаем проблему в статусах активной разработки, то хотим, чтобы для наших статусов был один источник правды — Gitlab. И уже на основе этого источника правды, мы обновляем статусы задач, добавляем дополнительную информация к задачам и так далее.
Для построения такой интеграции мы рассматривали несколько решений:
-
Базовая интеграция Youtrack и Gitlab. Данная интеграция нам не подошла, так как в наших статусах задачах есть дополнительные поля, которые нужно заполнить перед тем, как поменять статус задачи. Сразу увидели это ограничение и стали искать дальше.
-
Решение на основе Youtrack Workflow. Тоже не подошло, так как оно работает наоборот: за счет событий Youtrack мы можем влиять на внешние сервисы. Также у данного решения есть проблемы с хранением секретных данных: токены авторизации, логины, пароли и так далее.
-
Решение на основе Gitlab Webhook и своего сервера. А вот это звучит интереснее!
Про Gitlab Webhook
Мы быстро приняли тот факт, что, скорее всего, у нас нет другого выбора, кроме как написания своего сервер автоматизации. Давайте посмотрим общую схему решения:
Gitlab с помощью Webhook отправляет нашему серверу информацию о произошедшем событии. Сервер принимает событие, обрабатывает его и отправляет на его основе необходимый Http запрос в API Youtrack’a. Такая структура позволяет добавлять неограниченное количество внешних сервисов, например мы дополнительно отправляем информацию о новых релизах общих модулей в наш корпоративный мессенджер.
Либо уведомляем разработчиков если ревью задерживается.
Так как мы мобильные разработчики, а ещё и Android-разработчики, то и стек для нашего сервера мы подбирали такой, чтобы нам с ним было удобно работать. В качестве языка программирования выбрали Kotlin, а в качестве фреймворка для сервера Ktor. И это всё, что нам нужно!
Как это работает
Давайте реализуем небольшой пример, который будет отправлять сообщение в мессенджер при совершении какого-либо действия с merge request в Gitlab.
Для начала нам нужно создать базовый проект сервера. Это можно сделать с помощью помощника генератора проектов ktor. В данном помощнике есть много плагинов, которые можно заранее выбрать для вашего проекта: логирование, документирование, авторизация, база данных и ещё много всего.
Как только вы создадите проект, то сразу сможете запустить у себя локально и проверить, что всё работает.
Чтобы Gitlab сообщал нашему серверу информацию о событии, нужно настроить Gitlab Webhook в нашем репозитории. Для этого зайдите в Gitlab Settings -> Webhooks.
Нажмите «Add new webhook». Введите путь адрес для отправки события.
Обратите внимание: чтобы Gitlab смог доставить событие на ваш сервер, нужно открыть доступ к вашему внешнему IP-адресу в настройках вашего роутера.
Далее выбираем событие, на которое нужно реагировать. В нашем случае это merge request.
Нажимаем на кнопку «Add webhook».
Теперь при любом взаимодействии с merge request Gitlab будет отправлять событие нашему серверу. Более подробно про Gitlab Webhook можно почитать в официальной документации.
Теперь напишем обработчик событий на стороне сервера. Для этого определим основные классы для работы с merge request.
Класс обертка под webhook эвент
@Serializable data class ApiMergeWebhookDto( @SerialName("object_attributes") val objectAttributes: ApiObjectAttributesDto, @SerialName("reviewers") val reviewers: List<ApiWebhookUserDto>? = null, )
Класс с общей информацией о событии
@Serializable data class ApiObjectAttributesDto( @SerialName("action") val action: ApiMergeAction? = null, @SerialName("url") val url: String, )
Класс с информацией о пользователе
@Serializable data class ApiWebhookUserDto( @SerialName("email") val email: String?, @SerialName("username") val username: String, )
Перечисление событий с merge request
@Serializable enum class ApiMergeAction { @SerialName("open") Open, @SerialName("merge") Merge, @SerialName("update") Update; }
Далее нужно написать клиент для работы с мессенджером. В качестве примера я буду выводить сообщение в консоль. Вы же можете написать интеграцию с любым мессенджером, которое предоставляет свое API: telegram, mattermost, slack, email и другие.
class LoggerMessengerClient : MessengerClient { private val logger = System.getLogger(Logger.ROOT_LOGGER_NAME) override fun sendMessage( channelId: String, message: String ) { logger.log(System.Logger.Level.INFO, "Message receive to channel $channelId.\n$message") } }
Последним шагом остается только принять эвент от gitlab на стороне нашего сервера.
fun Application.configureGitlabWebhooks() { val messengerClient: MessengerClient = LoggerMessengerClient() routing { post("gitlab/merge/webhook") { // Задаем путь для нашего запроса val request = call.receive<ApiMergeWebhookDto>() // Принимаем body запроса val message = when (request.objectAttributes.action) { // Обрабатываем действие с merge request ApiMergeAction.Open -> { val reviewers = request.reviewers?.joinToString { "@${it.username}" } ?: "Empty" "[Merge request](${request.objectAttributes.url}) was opened. Reviewers: $reviewers" } ApiMergeAction.Merge -> { "[Merge request](${request.objectAttributes.url}) was merged." } ApiMergeAction.Update -> { "[Merge request](${request.objectAttributes.url}) was updated." } null -> { return@post call.respond(HttpStatusCode.NoContent) } } messengerClient.sendMessage( channelId = "68ff6cad-c31b-461c-855e-47323341fd9c", message = message ) call.respond(HttpStatusCode.OK) } } }
Теперь если мы произведем какое-либо действие с merge request в нашем Gitlab, то отправится запрос по нашему адресу и выведется сообщение в консоль
С полным кодом можно ознакомиться по ссылке.
Заключение
Немного о результатах нашей автоматизации. Полноценно сервер автоматизации мы запустили 30 августа 2024 и постепенно добавляли новую функциональность и за это время сервер автоматизации:
-
Обновил 602 статуса
-
Дозаполнил 1424 полей в задачах
-
Проинформировал 32 раза о новых релизах
-
Напомнил 132 раза о забытых ревью
-
Запросил 15 ежедневных отчетов
-
Уменьшил количество негодования тестировщиков и менеджеров проектов 🙂
Делитесь в комментариях своим опытом автоматизации ваших процессов. Какие технологии используете и с какими трудностями сталкивались. Буду рад почитать и подискутировать с вами!
ссылка на оригинал статьи https://habr.com/ru/articles/856374/
Добавить комментарий