Всем привет, я Java-разработчик в ЮMoney. В этой статье я хочу поговорить о том, какой профит можно получить от оптимизации действующих в компании инструментов, почему это стоит делать и с чего лучше начинать. На примере стека Atlassian и Bitbucket-плагина, который мы используем в ЮMoney, я расскажу и покажу все в деталях. Поехали! Если вспомнить разработку ПО в 70-80-е годы, на ум приходят гигантские ЭВМ и машины, в которые инженеры помещали перфокарты. Там были инструкции, они исполнялись, получался какой-то результат. И конечно, в такой системе не было ни логирования, ни CI/CD, ни контейнеризации. Со временем разработка развивалась, и в начале 2000-х мы уже собирали war-файлы (если говорить про стек Java) и деплоили их так, начал зарождаться CI/CD. Современная разработка — это уже гигантский стек технологий. Сегодня существуют разные инструменты практически для всего. К примеру, есть инструменты для коммуникации между программистами, ведения документации, контейнеризации и настройки pipeline на CI/CD, мониторинга и аналитики. Все эти инструменты можно дополнять новыми возможностями. Например, для Telegram можно создавать ботов,  а для GitHub, GitLab, Bitbucket — плагины. В ЮMoney есть много инструментов, которые мы дополняем. Вот краткий список. Система Telegram-ботов, оповещения, получения информации. Например, когда у меня, бэкенд-разработчика, возникает вопрос к специалистам DevOps, я могу написать боту, который скажет, кто сегодня дежурный. Так я не буду дергать всех подряд, а сразу обращусь к нужному специалисту. Внутреннее приложение для хранения мета-информации о сотрудниках. В нем мы храним данные о том, когда сотрудник пришел в компанию, когда сменил команду, за какие компоненты он ответственный. Этот удобный инструмент и натолкнул нас на мысль  о разработке плагинов для платформы Atlassian. Набор Bitbucket-плагинов. В частности, это плагин, который помогает нам оптимизировать code review, — Bitbucket code review tools.  У нас есть и другие плагины, которые помогают связывать Bitbucket, Confluence и Jira для взаимодействия со внутренним приложением, хранящим мета-информацию о сотрудниках. Еще есть плагины для Bitbucket, зеркалирующие наши репозитории на GitHub или упрощающие работу с Git. Сама система хранения кода, как и Bitbucket, GitHub, GitLab, поддерживает надстройку, плагины и настройку собственных функциональных возможностей. Например, у Bitbucket это набор плагинов, которые можно внедрять по REST API и с помощью SDK. В GitHub есть GitHub Actions — для создания плагинов и дополнений. Так почему стоит задуматься о разработке собственных внутренних решений и надстройке для уже существующих инструментов? Например, если вы используете в компании внутреннее приложение, которое никак не работает с внешним миром, — надстройка может стать мостиком, который поможет интегрировать внешние инструменты в ваше внутреннее приложение. Подобные решения помогут повысить эффективность разных бизнес-процессов — например, если хочется выстроить хорошую кодовую базу и ускорить выкладку на продакшн. Еще один важный фактор — стоимость. Зачастую в системах хранения кода есть маркетплейсы, на которых можно найти любые плагины. Но бывает так, что нужна всего одна функция большого плагина, а оплату просят за все сразу. Это не очень удобно, и лучше эту функцию реализовать самостоятельно. Последний пункт — это согласование  со службой безопасности. У нее свои требования — например, можно использовать только плагины, которые находятся в open source или у которых большое количество скачиваний, в противном случае внедрить решение не получится. Давайте теперь поговорим про Bitbucket code review tools. Это плагин, который позволяет оптимизировать процессы, связанные с code review. Чтобы code review приносил не боль, а только пользу, его нужно оптимизировать. Для этого мы реализуем  разные функции и надстройки. Сам по себе плагин написан на Java. Мы используем Atlassian SDK — он есть только для Java. У Atlassian есть также очень мощный REST API, с помощью которого можно точно так же реализовать все подобные функции. Этот плагин — наш внутренний инструмент, большинство его функций поддерживают наши внутренние бизнес-процессы, и его не найти на маркетплейсе. Но идеи, которые в него заложены, могут быть вам интересны. Определение экспертов по проектам и репозиториям Например, для проекта или репозитория имеется определение экспертов — людей, которые лучше всех разбираются в этом проекте. Такая метрика составляется на основе действий пользователей с pull request — таких, как открытие, проверка кода, комментарии. Автоматический мердж pull request Когда вы выходите на pull request, вам оставляют комментарии, вы вносите правки, отправляете задачу на тестирование, и происходит обычный процесс проверки кода. Чтобы не проверять вручную, все ли условия соблюдены для мерджа pull request, у нас есть функция автоматического слияния pull request. Если задача пришла с тестирования, уже находится в статусе checked, для нее поставлены approve в pull request, нет открытых задач, конфликтов и веток в pull request — тогда слияние происходит автоматически. Вывод на странице pull request списка связанных pull request Также очень удобная функция, которая показывает связанные с нашим pull request другие pull request. В ходе разработки бывают случаи, когда изменения происходят в нескольких репозиториях. На странице с pull request отображаются ссылки на все pull request, связанные с этой задачей. Набор merge check Набор позволяет проверять, например, наш GitHub flow, чтобы никто не смог мерджить неправильно. Еще есть merge check для ускорения выгрузки хотфиксов и багфиксов. Когда мы делаем hotfix, он должен оказаться в мастере. Но зачастую ветка по умолчанию, которая определена в вашем репозитории, — это develop. И при создании pull request с хотфиксом можно случайно оставить таргет на develop, мерджить туда, и в итоге hotfix придется делать заново. У этого плагина есть еще более 20 функций, которые мы тоже разберем. Рекомендую посмотреть доклад моего коллеги Валерия Чуркина «Как спасти code review и не потерять в качестве». Он подробно рассказывает про эти функции и то, как они помогли нам сделать оптимизацию. Перед разработкой или доработкой внутреннего инструмента стоит заглянуть в документацию. В случае с Atlassian она очень хорошая, в ней описаны все тонкости, которые нужно учитывать при разработке. Если у вас возникают вопросы — у Atlassian есть активное комьюнити. Например, у вас проблема не только с разработкой, но и с эксплуатацией или вы хотите узнать, возможно ли вообще реализовать какое-либо решение. Вы создаете тикет с вопросами в Atlassian Developer Community — и эксперты-разработчики вам отвечают. Разработка Atlassian-плагинов Основные этапы разработки плагина выглядят так. Устанавливаем Atlassian Plugin SDK. Генерируем проект. Делаем сборку проекта. Запускаем тестовую среду. Деплоим плагин. Установка Atlassian Plugin SDK Прежде всего нужно установить Atlassian Plugin SDK. Но сначала нужно настроить рабочее окружение: Java, Maven. Для скачивания SDK есть несколько вариантов. Первый — загрузить exe-файл с официального сайта, и тогда установится самая новая версия SDK. Если вы работаете на Linux, можно просто добавить их репозиторий, и у вас всё установится. После установки можно сделать проверку. Сразу обращаю ваше внимание на первую строку — на всех слайдах это будет команда. Так, с помощью команды atlas version можно узнать, все ли установилось корректно и какие у нас настройки. Таким образом, Atlassian Plugin SDK импортируется в переменную среду окружения, и уже из терминала можно вызывать его в любой точке вашей системы.   Еще одно замечание — на шестой строке описан важный пункт, который связан с тем, что библиотеки Atlassian Plugin SDK не выкладываются в Maven central repository, у них есть собственная версия Maven, и только с ее помощью можно работать. Поэтому при сборке плагина надо указать в IDE путь к atlassian Maven, и тогда библиотеки подтянутся правильно. Кстати, можно добавлять не только библиотеки Atlassian, но и сторонние — они так же удобно импортируются в проект. Генерация maven-проекта После установки SDK, проверки его версии и настройки рабочей среды можно начинать создание плагинов. Для этого есть команда Atlassian create Bitbucket plugin (первая строчка кода). Когда мы вводим эту команду, собирается Maven-проект, в котором нужно указать параметры названий пакетов, версию проекта и т.д., после чего можно приступать к работе. Это будет шаблонный проект (весь код проекта можно найти по ссылке: https://github.com/GSkoba/bitbucket-plugin). Давайте посмотрим на его структуру. В Java Maven проекте есть pom-файл, в котором указаны все необходимые зависимости на Bitbucket Atlassian, Bitbucket Parent и есть Dependency Manager, который будет скачивать все необходимые зависимости и следить за их обновлением.  Тут же есть различные библиотеки, чтобы взаимодействовать с UI или ORM-отображением.    Также мы указываем версию Java и переменные, которые будут использоваться для определения мета-информации про наш проект. В проекте есть src, в ресурсах которых закладывается очень важный файл — Atlassian-plugin.xml. Это что-то похожее на Spring — в нем определяются все функции, которые будут работать в плагине, название, мета-информация, которая импортируется из файла pom.xml. Здесь же можно определить картинки и выбрать, например, средство локализации. Таким образом, Bitbucket — это не только про сервер, у него есть UI, и для работы с ним тоже надо определить ресурсы, картинки, файл JavaScript. Чтобы все работало хорошо, IDE увидела весь код, все зависимости и смогла их нормально проиндексировать, нужно в Maven home directory указать путь до Maven, который используется Atlassian Plugin SDK. Если этого не сделать, все будет красное — IDE вообще не поймет, что происходит. После того, как мы познакомились со структурой проекта и файлом Atlassian.xml, а еще поняли, что является корнем нашей системы, — самое время собрать плагин. Сборка плагина Она делается через вызов atlas-mvn — это будет Maven, который обращается к Maven из SDK. Разработка Atlassian-плагинов Проект собран, теперь нужно поднять рабочее окружение и все протестировать. Для этого есть несколько вариантов — например, поднять Bitbucket-сервер с помощью докера. Для запуска проекта нужно с помощью SDK вызвать команду version run standalone. Вообще, с помощью этой команды можно запустить любой продукт. Дальше откроется веб-интерфейс, через который можно установить плагины. Давайте на это посмотрим — localhost:7990/bitbucket. Учетные данные для того, чтобы зайти на него, — admin/admin. В нем уже создан тестовый проект, есть тестовый репозиторий, тестовые пользователи, с которыми можно взаимодействовать. Так как права администраторские, здесь можно добавлять новых пользователей. Чтобы установить уже существующей плагин, нужно в разделе администрирования проекта открыть вкладку manage apps. Если хотите загрузить новую версию уже имеющегося плагина, удалять старый не нужно, Bitbucket сделает это за вас. После загрузки плагина через панель администрирования он автоматически запустится и выдаст сообщение об успехе. Если что-то пойдет не так — плагин не запустится, и придется проверять логи. Возможности Bitbucket-плагина: Доработка UI. Обработка событий от Bitbucket. Pull Request Hook. Pull Request Merge Check. Сохранение данных. Доработка UI с помощью сервлетов Как вы, возможно, заметили, для доработки UI нужно понимать, как все панели в UI называются. Тем, кто занимается тестированием, например, с помощью Selenium, известно такое понятие, как локаторы. Это идентификаторы элементов на веб-страницах, которые позволяют понять, куда в панели можно вклиниться. Query Parameter   Description   web.items   Отображение локаторов для Web Item и Client Web Item    web.panels   Отображение локаторов для Web Panel и Client Web Panel   web.sections   Отображение локаторов для Web Section и Client Web Section   Тут эти параметры следует указывать в URL, и с помощью отображения debug mode можно понять, в какую панель мы хотим вклиниться. Пример: https://<your Bitbucket Server instance>/projects?web.items&web.panels&web.sections. В главной панели мы видим id-панели. Например, очень простая доработка UI — это вывести сообщение приветствия. Вообще, доработка UI заключает в себе очень большой потенциал, потому что можно создавать как кастомные вкладки, так и кастомные функции. Так, у нас есть доработанная функция, которая показывает, в каком статусе был build, первая кнопка выдает еще лог. В итоге мы видим, на каком стейдже в Jenkins завалился build. Здесь же есть ссылка на задачу в Jira с ее статусом. И последняя функция — открытие UI-окна, в котором можно увидеть все связанные pull requests. Есть два варианта доработки UI. Первый — шаблонизация на soy, но это не очень удобно. Лучше делать React-подобные компоненты. Кого-то может это смутить, но идентификатор, куда будет встраиваться компонент, следует задавать в комментарии. Когда JavaScript будет исполняться и интерпретироваться, компонент увидит в комментарии extension point — точку входа для добавления плагина. Обработка событий от Bitbucket А как вообще выстроена работа в самом Bitbucket-сервере? Такой сервер — это СОП-система, событийно ориентированная программа, в которой действия определяются событиями. При взаимодействии с пользователем UI создает в Bitbucket события, на которые можно реагировать. Для взаимодействия и прослушивания определенных событий будет достаточно сделать такой класс:  Аннотация EventListener указывает на то, что это будет endpoint для прослушки наших сообщений — почти как консьюмер, принимающий сообщения. Здесь следует указать, какие именно сообщения в качестве аргументов хочется принимать. С подобным функционалом можно сделать систему оповещения. Например, когда вам оставляют комментарии, можно через Telegram-бот отправлять пользователю оповещение — Pull Request Hook. Более продвинутый вариант обработки события — хуки. У нас имеются три варианта хуков: Interface   Description   PostRepositoryHook<T extends RepositoryHookRequest>  Хук, который вызывается после внесения изменений PreRepositoryHook<T extends RepositoryHookRequest>   Хук, который вызывается до внесения изменений  RepositoryMergeCheck  Хук, который используется для проверки условия для операции слияния Для первых двух мы указываем generic — некий триггер, с чем нужно взаимодействовать. Рассмотрим пример. Он показывает, как мы делаем более расширенное логирование. Потому что, хотя в Bitbucket есть аудит-лог, иногда хочется иметь запасную систему логирования. А вот примеры триггеров, на которые мы можем завязываться, — это создание веток и их удаление. Trigger   Corresponding request type   BRANCH_CREATE   BranchCreationHookRequest   BRANCH_DELETE   BranchDeletionHookRequest   FILE_EDIT   FileEditHookRequest   MERGE   MergeHookRequest   PULL_REQUEST_MERGE   PullRequestMergeHookRequest  REPO_PUSH   RepositoryPushHookRequest   TAG_CREATE   TagCreationHookRequest   TAG_DELETE   TagDeletionHookRequest   После добавления плагина hook хуки будут отображаться в отдельной вкладке. Pull Request Merge Check Самым интересным является частный случай проверки хуками — можно мерджить или нет. В таком случае мы (прямо как Гэндальф) говорим: you shall not pass! (вы не выполнили условие, и мы вам не позволим мерджить). Рассмотрим это на примере нашей реализации. У нас есть много мердж-чеков — например, для репозиториев и проектов проверка того, что задачу можно только мерджить, если она была протестирована. В противном случае, если попытаться сделать слияние, будет показано сообщение вроде: «Друг, послушай, ты свою задачу не протестировал, а ну-ка, сходи к тестировщику, и вы вместе решите, как ее тестировать, или, может, нужно еще что-то доделать». Второй пример — для репозиториев и проектов у нас есть система ролей. Роль для пользователей говорит о том, что эти люди являются экспертами в области Gradle-плагинов, и они не должны обязательно их ревьюить. Или, например, как изображено на картинке, можно настроить, от каких конкретных ролей обязательно нужно получить аппрувы для pull request. Теперь о реализации MergeCheck. Нам нужно наследовать интерфейс RepositoryMergeCheck, в котором опишем метод preUpdate. В нем задаем условие проверки. С помощью аргументов из метода context и request можно проверять названия веток, их Git flow, а также контролировать, правильно ли все отбранчевалось. Сохранение данных Для разработки Bitbucket-плагинов хочется, чтобы была возможность сохранять информацию на нашем Bitbucket-сервере. У таких плагинов и стека Atlassian есть собственный ORM — active objects. Чтобы начать с ним работать, достаточно объявить DTO-класс — например, Todo. После этого можно с помощью класса ActiveОbject производить операции над dto. Например, сохранять объекты, взаимодействовать с ними и удалять. В ЮMoney мы используем этот вариант для сохранения настроек плагинов — вместо того, чтобы каждый раз менять значение в коде, мы доработали UI и через него шаблонизируем настройку. Marketplace Если вы сделали интересный плагин и хотите поделиться им с людьми, можно загрузить его на маркетплейс. Для этого достаточно зарегистрироваться как vendor, то есть тот, кто будет предоставлять плагины. Стоит отметить, что у Atlassian есть строгий гайдлайн — что можно выкладывать и сколько денег за это просить. Вместо заключения Надеюсь, эта статья будет полезна для всех, кто хочет начать разрабатывать Altassian-плагины. Сказанное выше относится не только к Atlassian — попробуйте таким образом усовершенствовать собственные решения или те, которые действуют в вашей компании. Вот еще несколько полезных ссылок по разработке Atlassian: https://developer.atlassian.com/server/bitbucket/reference/api-changelog https://www.atlassian.com/software https://community.atlassian.com И еще раз — https://github.com/GSkoba/bitbucket-plugin шаблонный. Он нужен, чтобы вы могли быстро сделать в нем какую-нибудь доработку, запустить на вашем Bitbucket-сервере и посмотреть, что из этого получится. На конференции ЮMoneyDay был доклад о нашем код-ревью с точки зрения бизнес-процессов. Ссылка на доклад: https://youtu.be/lZBF1QV4ChE.   На этом всё. Если у вас будут вопросы, пишите в комментариях, разберемся. :)  Java Backend