Привет, Хабр! Я техлид в компании ДомКлик. В основном занимаюсь backend-разработкой. Мне периодически приходится погружаться и во front-разработку, но этого не происходило уже более двух лет. Сегодня я расскажу, как мне пришлось заняться front-разработкой для создания плагина для Bitbucket, с какими сложностями я столкнулся и как их решал. Также поделюсь результатом своей работы: надеюсь, он окажется полезен кому-нибудь ещё. Эта статья не является руководством по написанию плагинов для продуктов Atlassian и не описывает всех возможностей системы плагинов.

Проблема

Некоторые наши команды используют нотацию BPMN для описания бизнес-процессов, которые мы реализуем. Недавно мой коллега рассказал, как мы пришли к применению BPMN. В качестве движка исполнения бизнес-процессов мы используем платформу Camunda, популярность которой, как мне кажется, обусловлена несколькими важными факторами:

  • Отличный инструментарий. Сюда входят инструменты для моделирования, мониторинга, анализа бизнес-процессов.
  • Отличная документация, полная и подробная.
  • Возможность тонкой настройки под свои нужды благодаря огромному количеству настроек среды исполнения.
  • Возможность расширения базовой функциональности через реализацию своих плагинов.
  • Сообщество. Разработчики Camunda организуют конференции, митапы, записывают обучающие видео, ведут тематические блоги, поддерживают диалог на форуме и, конечно, выкладывают свой код на GitHub.

И всё было бы хорошо, но есть одна существенная проблема. Нотация BPMN использует XML для описания всех шагов, связей и расположения всех элементов схемы бизнес-процесса. Существуют различные инструменты визуального проектирования схем BPMN. Одно из самых удобных — Camunda Modeler. Любое изменение визуального представления влечет за собой изменение XML-описания. Мы в командах придерживаемся практики обязательных code review, которые проводятся средствами Bitbucket в рамках пулл-реквестов. Но рецензировать изменения в большом XML-файле, который описывает визуальное представление, практически невозможно. Попробую проиллюстрировать проблему на примере стандартного сравнения текстовых файлов, которое производит Bitbucket:

В данном случае сравнение показывает нам, что всё предыдущее содержимое файла было удалено и было добавлено полностью новое содержимое. На самом же деле на схеме изменилось лишь несколько элементов, и дополнительно был отформатирован файл BPMN.

До сих пор мы вынуждены были скачивать две версии файла (старую и новую) на локальную машину, открывать их в среде визуального просмотра и сравнивать вручную. Очень неудобно. И из-за такого подхода в прод уже просачивалось несколько багов. Актуальность этой проблемы растет вместе с количеством людей и команд, которые используют BPMN.

Долгое время меня не покидала мысль, что необходимо как-то облегчить жизнь командам, вынужденным вручную сравнивать схемы. И хорошо бы иметь встроенный в Bitbucket визуальный инструмент. Я начал изучать вопрос расширения возможностей Bitbucket с помощью плагинов. Ничего подходящего я не нашел, но зато натолкнулся на такое демо возможностей JavaScript-библиотек от разработчиков Camunda. Это ведь то, что надо! На свой вопрос о планах разработки плагина для Bitbucket на форуме я получил отрицательный ответ. Поэтому пришлось собраться с мыслями и сделать плагин самому.

Разработка плагина для Bitbucket

На момент начала разработки плагина я понятия не имел о том, как это делать, поэтому, как настоящий разработчик, сначала спросил у Google: «bitbucket plugin development». Google первым же результатом выдал страницу Beginner guide to Bitbucket Server plugin development. На этой странице мы узнаём, что есть две версии продукта: Bitbucket Server и Bitbucket Cloud. Нас интересовал Bitbucket Server. Поэтому дальнейшие шаги будут относиться только к разработке для него.

Следует заметить, что у документации Atlassian есть одна особенность: информация разбросана по множеству различных страниц, слабо связанных друг с другом. Такое впечатление, что по мере развития в документацию добавляют новые разделы, но при этом не пересматривают старые. Такой подход затрудняет поиск необходимой информации. К тому же нередко встречаются битые ссылки. Я пытался писать репорты об этом, но ситуация не меняется.

В этой статье я попробую сэкономить время тем, кто впервые сталкивается с разработкой плагинов для продуктов Atlassian, направив на действительно важные страницы и поделившись существенной информацией.

Самая важная страница — это, пожалуй, страница с инструкциями по установке, ссылкой на шаблонный проект и инструкциями по его запуску: Getting started. Шаблонный проект представляет собой полноценный проект с настроенной сборкой, нужными зависимостями, примерами добавления различных расширений и т.п. Необходимо лишь кое-что переименовать по прилагаемой инструкции, и можно добавлять свои расширения.

Существует два способа добавления своих элементов в UI Bitbucket на стороне клиента: Client Web Fragments и Client-side Extensions (aka CSE). Второй способ появился в Bitbucket Server 7 и предполагает постепенное замещение первого способа. Пока CSE доступны только на страницах, связанных с пулл-реквестами.

В CSE входят пять типов расширений: кнопка, ссылка, модальное окно, панель, страница. Все типы описаны на соответствующих страницах с примерами использования. Чтобы определить, какие элементы страницы предполагают расширение с помощью CSE, достаточно добавить ?clientside-extensions к URL страницы. При переходе на такой URL подходящие места будут подсвечены специальной иконкой, при нажатии на которую можно узнать:

  • какие типы расширений поддерживает этот элемент,
  • идентификатор этого места (его необходимо указывать в коде вашего расширения),
  • поддерживаемые атрибуты и контекст (данные, которые будут передаваться в конструктор расширения).

Подробности можно узнать на странице, но я рекомендую просто поэкспериментировать с добавлением параметра к URL различных страниц в вашем Bitbucket.

Client Web Fragments я подробно рассматривать не буду, так как при реализации плагина этим инструментом воспользоваться не пришлось.

Помимо расширений на стороне клиента разработчику доступен механизм Plugin modules с разнообразным функционалом. Например, можно добавить свои ресурсы (CSS, JS и т.д.) и таким образом адаптировать поведение и UI под свои нужды.

Трудности

Первая трудность, с которой я столкнулся при попытке запустить шаблонный проект, заключалась в том, что расширения, реализованные в проекте, не появляются в UI Bitbucket. В логах старта обнаружилась ошибка, которая сообщала, что плагин не запускается из-за какого-то несоответствия версии библиотеки. После достаточно продолжительной медитации, гугления и исследования админки Bitbucket, причина нашлась: шаблонный проект требовал библиотеку обработки CSE версии 1.2.3. При этом на сервере оказалась установлена библиотека версии 1.0.0. Для решения этой проблемы необходимо модифицировать шаблонный проект, добавив следующий фрагмент в конфигурацию bitbucket-maven-plugin:

<plugin>
   <groupId>com.atlassian.maven.plugins</groupId>
   <artifactId>bitbucket-maven-plugin</artifactId>
    …
    <configuration>
        ....
        <pluginArtifacts>
            <pluginArtifact>
                <groupId>com.atlassian.plugins</groupId>
                <artifactId>atlassian-clientside-extensions-page-bootstrapper</artifactId>
                <version>1.2.3</version>
            </pluginArtifact>
        </pluginArtifacts>
    </configuration>
</plugin>

Трудность № 2. Мне необходимо было реализовать следующую логику на стороне клиента: получение двух версий содержимого BPMN-файла через REST API Bitbucket, построение модели BPMN, сравнение, отрисовка и раскраска схем. Отрисовка и раскраска требует возможности добавления собственного HTML-кода и подключения собственных стилей.

Единственным подходящим местом размещения управляющего элемента для переключения в режим графического сравнения схем оказалась шапка панели сравнения: она поддерживает CSE и обеспечивает отображение необходимого контекста (информации о проекте, репозитории, текущем выбранном файле для сравнения и номерах ревизий двух версий файла). Здесь поддерживается три типа расширений: кнопка, ссылка и модальное окно. Очевидным решением виделось использование модального окна: в этом случае пользователь оставался бы на той же странице и не терял бы контекст. Однако при использовании модального окна я столкнулся с двумя проблемами:

  1. У модального окна есть несколько предустановленных размеров и нельзя указать произвольный размер. В частности, нельзя нарисовать модальное окно на весь экран, что является желательным для отрисовки схем.
  2. Сейчас нет возможности привязать свои ресурсы к расширениям CSE. Либо я не обнаружил такого способа. Можно попробовать добавить JS-код и CSS-классы внутрь кода модального окна (и я даже смог это сделать и отрисовать схемы), но в результате получается совершенно неподдерживаемый кусок кода, который было бы стыдно показывать людям. К тому же это не решает первую проблему.

Далее я попробовал использовать другой тип CSE: страницу. Её использование решает первую проблему модального окна, но не решает вторую: со страницей я тоже не нашел адекватного способа подключения своих ресурсов.

Промучившись какое-то время, мне пришло в голову, что у Atlassian должна быть какая-то поддержка, форум для разработчиков. Форум быстро обнаружился и я задал в подходящем разделе свой вопрос: https://community.developer.atlassian.com/t/alternative-diff-view-plugin/43717. Однако, ответа так и не дождался. И это трудность № 3, с которой я столкнулся: низкая активность сообщества в целом и представителей Atlassian в частности. Спустя 17 дней после того, как я задал вопрос, я сам же на него и запостил ответ. Заодно ответил на вопрос другого разработчика в соседней теме, который также ждал 17 дней.

В конце концов мне удалось решить свою задачу. Я использовал кнопку CSE на странице сравнения, которая открывает новую вкладку со страницей, где отрисовывается графическое сравнение схем. Для отдельной страницы я использовал Servlet plugin module, который поддерживает подключение статических ресурсов. А для самого подключения я применил Web Resource plugin module.

Чтобы использовать Servlet plugin module, необходимо реализовать свой сервлет, генерирующий HTML-код страницы. Очевидно, что отдавать контент сервлет должен только аутентифицированным пользователям. Но как это обеспечить? Если покопаться в примерах кода на ресурсах Atlassian, то можно обнаружить необходимый код для Jira с использованием её библиотеки, которая не подходит для Bitbucket. Но этот код наводит на мысль, что подобный API должен быть и у Bitbucket (хотя прямого описания в документации я не обнаружил). После некоторых поисков обнаружилась нужная библиотека:

<dependency>
   <groupId>com.atlassian.bitbucket.server</groupId>
   <artifactId>bitbucket-api</artifactId>
   <version>${bitbucket.api.version}</version>
   <scope>provided</scope>
</dependency>

В этой библиотеке есть класс AuthenticationContext с искомым методом isAuthenticated(). Осталось только заавтовайрить этот класс в классе сервлета.

Аналогичная проблема с библиотекой генерации HTML по шаблону (в моем случае это шаблон Velocity). Необходимо подключить библиотеку:

<dependency>
   <groupId>com.atlassian.templaterenderer</groupId>
   <artifactId>atlassian-template-renderer-api</artifactId>
   <version>${atr.version}</version>
   <scope>provided</scope>
</dependency>

И далее использовать ее в сервлете:

templateRenderer.render(TEMPLATE_PATH, params, response.getWriter());

Трудность № 4 заключалась в том, что совершенно непонятно, что за библиотеки тебе нужны для решения вполне обычных задач. В документации это либо не описано, либо находится где-то очень глубоко (поправьте меня, если я вдруг ошибаюсь).

И последний совет. Опытным frontend-разработчикам, наверное, это покажется очевидным, но я дошел до этого не сразу. Используйте режим инкогнито в браузере для тестирования своих плагинов. Это сэкономит много времени и нервов, которые были бы потрачены на поиски «странных» багов.

Результат

У меня получился плагин для Bitbucket Server версии 7. Плагин добавляет кнопку «BPMN Visual Diff» в шапку панели сравнения:

Кнопка отрисовывается только в том случае, если для сравнения выбран файл с расширением .bpmn. Таким образом, пользователи, не использующие BPMN, даже не заметят изменений.

По нажатию на кнопку открывается новая вкладка, в которой производится визуальное сравнение двух версий схемы: можно увидеть удалённые, добавленные, изменённые элементы. А для изменённых элементов дополнительно можно посмотреть, какие атрибуты этих элементов изменились и как. В результате абсолютно бесполезное сравнение текстовых файлов, приведенное в качестве примера в начале статьи, превращается вот в такое визуальное сравнение:

Исходный код проекта плагина доступен на GitHub под лицензией MIT. Пожелания, критика и пулл-реквесты приветствуются. В ближайших планах — адаптация плагина для Bitbucket Server версии 6.

Let’s block ads! (Why?)

Read More

Recent Posts

Apple возобновила переговоры с OpenAI и Google для интеграции ИИ в iPhone

Apple возобновила переговоры с OpenAI о возможности внедрения ИИ-технологий в iOS 18, на основе данной операционной системы будут работать новые…

4 часа ago

Российская «дочка» Google подготовила 23 иска к крупнейшим игрокам рекламного рынка

Конкурсный управляющий российской «дочки» Google подготовил 23 иска к участникам рекламного рынка. Общая сумма исков составляет 16 млрд рублей –…

11 часов ago

Google завершил обновление основного алгоритма March 2024 Core Update

Google завершил обновление основного алгоритма March 2024 Core Update. Раскатка обновлений была завершена 19 апреля, но сообщил об этом поисковик…

14 часов ago

Нейросети будут писать тексты объявления за продавцов на Авито

У частных продавцов на Авито появилась возможность составлять текст объявлений с помощью нейросети. Новый функционал доступен в категории «Обувь, одежда,…

15 часов ago

Объявлены победители международной премии Workspace Digital Awards-2024

24 апреля 2024 года в Москве состоялась церемония вручения наград международного конкурса Workspace Digital Awards. В этом году участниками стали…

1 день ago

Яндекс проведет гик-фестиваль Young Con

27 июня Яндекс проведет гик-фестиваль Young Con для студентов и молодых специалистов, которые интересуются технологиями и хотят работать в IT.…

2 дня ago