Как силами мобильных разработчиков автоматизировать процесс разработки

от автора

Всем привет! Меня зовут Женя Мельцайкин, я старший инженер-программист в компании Контур. Большую часть времени в Контуре я работал и работаю 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. И уже на основе этого источника правды, мы обновляем статусы задач, добавляем дополнительную информация к задачам и так далее. 

Для построения такой интеграции мы рассматривали несколько решений:

  1. Базовая интеграция Youtrack и Gitlab. Данная интеграция нам не подошла, так как в наших статусах задачах есть дополнительные поля, которые нужно заполнить перед тем, как поменять статус задачи. Сразу увидели это ограничение и стали искать дальше.

  2. Решение на основе Youtrack Workflow. Тоже не подошло, так как оно работает наоборот: за счет событий Youtrack мы можем влиять на внешние сервисы. Также у данного решения есть проблемы с хранением секретных данных: токены авторизации, логины, пароли и так далее. 

  3. Решение на основе 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 и постепенно добавляли новую функциональность и за это время сервер автоматизации:

  1. Обновил 602 статуса

  2. Дозаполнил 1424 полей в задачах

  3. Проинформировал 32 раза о новых релизах

  4. Напомнил 132 раза о забытых ревью

  5. Запросил 15 ежедневных отчетов

  6. Уменьшил количество негодования тестировщиков и менеджеров проектов 🙂

Делитесь в комментариях своим опытом автоматизации ваших процессов. Какие технологии используете и с какими трудностями сталкивались. Буду рад почитать и подискутировать с вами!


ссылка на оригинал статьи https://habr.com/ru/articles/856374/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *