
В статье расскажу, как в Bercut реализовали интеграцию внутренней системы управления конфигурациями с популярной экосистемой Maven, что позволило обеспечить более удобное и стандартизированное распространение артефактов. Поделюсь проблемами, с которыми мы столкнулись при совмещении разных моделей идентификации артефактов и обеспечении корректности зависимостей, и расскажу о выбранном техническом решении на базе Jenkins, RabbitMQ и специального Consumer Service.
Кейс может быть полезен инженерам DevOps, а также разработчикам и архитекторам, которые решают похожие задачи интеграции нестандартных систем сборки и управления конфигурациями с системами на базе Maven.
Система управления конфигурациями «Автосборка»
Мы используем внутреннюю корпоративную систему управления конфигурациями «Автосборка» — промышленный конвейер для разработки, сборки, выпуска и сопровождения программного обеспечения. Она реализует единый для всей компании процесс производства ПО: централизованно управляет конфигурациями компонентов и систем (наборов компонентов), их зависимостями, версиями и статусами готовности.
Система обеспечивает целостность и гарантированную воспроизводимость сборок, однозначную идентификацию версий и полную прослеживаемость изменений на всех стадиях жизненного цикла программного обеспечения. Также «Автосборка» поддерживает компонентный подход и возможность повторного использования, позволяет надёжно пересобирать и точечно исправлять любые версии компонентов.
Система рассчитана на промышленный масштаб: ежедневный выпуск десятков релизов различных продуктов в разнородном технологическом ландшафте (с разными технологическими стеками и операционными средами). Это снижает риски выпусков и стоимость сопровождения.
Ряд продуктов нашей компании работает на единой программной платформе, написанной на Java и состоящей из нескольких платформенных систем. В основном эти продукты созданы на BPEL, однако часть из них разрабатывается на Java и зависит от платформенной системы RTSIB (Real Time Service Integration Bus).

В последние годы в Bercut наблюдается рост доли продуктов, разрабатываемых на Java: их количество увеличилось и уже достигло 25% от общего числа.
Некоторые команды стали использовать систему сборки Maven, и у нас появилась необходимость публиковать часть артефактов в Maven‑совместимый репозиторий и представлять зависимости в привычной для экосистемы Maven форме.
Так появилась задача интеграции двух систем хранения артефактов: «Автосборки» и Maven‑репозитория (в нашем случае — Sonatype Nexus).
Автоматическая загрузка артефактов в Maven-репозиторий
Первоначально мы собирались реализовать автоматическую загрузку артефактов системы RTSIB в Maven‑репозиторий. Например, для отмеченных артефактов «Автосборка» сама будет выполнять загрузку.

Однако возникли следующие проблемы:
Разные модели идентификации артефактов. Внутри «Автосборки» используются внутренние идентификаторы или наименования, а в Maven — координаты артефакта (groupId/artifactId/version). Поэтому требуется явно хранить и поддерживать маппинг между сущностями «Автосборки» и Maven‑координатами, чтобы однозначно связывать опубликованный артефакт с его источником и контекстом сборки.
Генерация информации о зависимостях артефактов в Maven‑формате. «Автосборка» может предоставить состав и граф зависимостей, но при поштучной публикации артефактов в Maven‑репозиторий нет гарантии, что на момент публикации конкретного артефакта все его зависимости уже доступны в репозитории. Это создаёт риск возникновения «битых» зависимостей при использовании. Поэтому публикацию следует трактовать как управляемый процесс (например, на уровне релиза системы), где можно проверить полноту и консистентность публикации.
«Автосборка» — критичный и нагруженный производственный контур, поэтому расширять её логикой, не относящейся напрямую к ядру сборки или выпуска, нужно осторожно. Чтобы не увеличивать связность и операционные риски, интеграционные функции (публикация во внешний формат или репозиторий, хранение маппингов, контроль консистентности публикации) разумно выносить в отдельный компонент, оставляя «Автосборку» источником истины по сборке и составу.
Поэтому мы приняли решение:
Вынести публикацию в Maven‑репозиторий в отдельный сервис.
Загрузку в Maven‑репозитории выполнять не для каждого отдельного артефакта, а для сборки платформенной системы RTSIB, как согласованного набора артефактов.
Кроме загрузки артефактов в Maven‑репозитории выполнять генерацию Parent POM‑файла (родительского файла конфигурации сборки Maven) для всех артефактов платформенной системы RTSIB.
Реализовать механизм передачи информацию о завершенной сборке от «Автосборки» в сервис публикации в Maven‑репозитории.
Конвейер Jenkins для загрузки в Maven-репозиторий
В качестве основы для такого сервиса мы выбрали Jenkins. Каналом обмена данными между «Автосборкой» и Jenkins стал RabbitMQ. Поскольку Jenkins не способен принимать сообщения по RabbitMQ, на языке Go был разработан RabbitMQ Consumer Service. На Jenkins мы создали конвейер для последовательной загрузки артефактов в Maven‑репозиторий и создания зависимостей системы для Maven‑сборки.

Конвейер работает следующим образом:
Разработчик заказывает сборку платформенной системы в «Автосборке».
«Автосборка» собирает дистрибутив платформенной системы RTSIB из артефактов, размещает его в файловом хранилище и после этого отправляет в RabbitMQ сообщение с информацией о сборке.
RabbitMQ Consumer Service преобразует сообщение из RabbitMQ в HTTP‑запрос к Jenkins.
Jenkins получает запрос и по своим настройкам определяет, что для платформенной системы RTSIB необходимо запустить загрузку артефактов в Maven‑репозиторий и генерацию Parent POM‑файла:
Загружает в Maven‑репозиторий все артефакты системы, используя имя jar файла в качестве имени артефакта.
Перебирает все артефакты в дистрибутиве системы, создаёт один Parent POM‑файл с их перечислением и загружает его в Maven‑репозиторий.
После этого разработчики продуктов используют Parent POM‑файл системы в своих проектах для сборки в Maven.
Parent POM-файл
Отдельно хочу рассказать про Parent POM‑файл.
В первых версиях системы интеграции мы публиковали платформенные артефакты в Maven‑репозитории. А разработчики продуктов сами составляли POM-файлы для своих проектов. Список зависимостей составлял полтора десятка компонентов с указанием версий. Когда мы выпускали следующий релиз платформенной системы, разработчики продуктов руками меняли номера версий в своём POM-файле. Это был трудозатратный и полный ошибок процесс.
Поскольку я сам участвовал в этом процессе ручного изменения POM-файлов, мне было понятно, что требуется системное решение. И оно нашлось — это Parent POM‑файл.
Сначала сделал генерацию Parent POM‑файла с перечнем всех артефактов платформенной системы RTSIB. И его можно было применять для сборки некоторых продуктовых артефактов. Но большинство продуктовых артефактов разрабатывалось с использованием фреймворка Spring Boot, и уже имело свой Spring Boot Parent POM. А Maven не позволяет использовать два Parent POM‑файла.
Тогда я сделал генерацию Parent POM‑файла с перечнем всех артефактов платформенной системы RTSIB, в котором был указан свой родительский Spring Boot Parent POM. Т.е. создал иерархию файлов:
Spring Boot Parent POM
|‑-→ Bercut RTSIB Parent POM
|‑-→ Продуктовый POM
В разных командах у нас используют разные версии Spring Boot, и им нужны разные версии Bercut RTSIB Parent POM. Сейчас система создаёт 4 варианта этого файла:
Для сборки без Spring Boot
Для сборки с Spring Boot 2.35
Для сборки с Spring Boot 2.45
Для сборки с Spring Boot 2.70
Создание Parent POM‑файлов оказалось спасением для разработчиков продуктов, которые получили экономию времени на обновлении зависимостей. А для разработчиков платформенной RTSIB POM‑файлы гарантируют, что в продуктах будут использованы только совместимые между собой артефакты.
Результаты использования системы
Мы уже несколько лет используем описанную систему интеграции и с её разработали использованием больше десятка продуктов. Система зарекомендовала себя как надёжное решение.
У нее есть явные преимущества:
Разработчики продуктов используют только один Parent POM‑файл вместо списка зависимостей. Он содержит всю необходимую информацию для разработки и сборки с помощью Maven.
Создаётся несколько Parent POM‑файлов — для разных видов сервисов и для нескольких версий Spring Boot.
В рамках выбранного подхода «Автосборку» не перегружали дополнительными хранилищами и сложной интеграционной логикой. Был добавлен простой механизм: отправка события (нотификации) в RabbitMQ об успешной сборке системы. Далее внешние потребители события могут выполнять синхронизацию или публикацию и хранить служебные данные, не усложняя сам производственный контур «Автосборки».
Но есть и некоторые недостатки:
Потребовалось разработать, запустить и поддерживать RabbitMQ Consumer Service.
Отдельные артефакты в Maven‑репозитории не содержат зависимостей от других артефактов.
Отсутствует хранилище информации о соответствии между сущностями «Автосборки» и Maven‑координатами. Связь «что опубликовано и чему это соответствует в исходной системе» остаётся неявной и может теряться.
В результате часть данных о сборке и публикации оказывается распределена между несколькими системами, и «Автосборка» частично теряет роль единого источника истины по выпускаемому ПО. На этапе первой реализации это было приемлемым компромиссом, позволившим быстро запустить решение и обеспечить его стабильную работу в реальных условиях.
Сейчас ставим перед собой новую цель — доработать «Автосборку», сделав ее единым источником данных для сборки и выпуска ПО. Так Maven‑репозиторий станет управляемым каналом публикации, а не обособленной внешней системой.
