В компаниях с большим количеством проектов часто возникает ситуация, когда при разработке пайплайнов мы начинаем повторять себя, добавляя в разные сервисы одинаковые конструкции. Это противоречит основному принципу программирования DRY (Don’t Repeat Yourself), а ещё усложняет внесение изменений в код. Справиться с описанными проблемами помогает Jenkins Shared Library. Мы пообщались с Кириллом Борисовым, Infrastructure Engineer технологического центра Deutsche Bank, и узнали, какие задачи решает Jenkins Shared Library и что её внедрение даёт компании. А ещё рассмотрели кейс разработки и тестирования с примерами кода.  Jenkins Shared Library — это библиотека для многократного использования кода, которая позволяет описать методы один раз и затем применять их во всех пайплайнах. Она решает проблемы дублирования кода и унификации. Благодаря ней нам не нужно держать в каждом пайплайне огромное количество кода и постоянно повторять его. Мы можем написать код в одном месте, а потом инклюдить и вызывать его в рамках самого пайплайна.  Как это работает? Первым делом во всех пайплайнах мы выделяем общие части, которые можем объединить. Предположим, мы заметили, что везде используем нотификацию в Telegram, и везде она реализована по-разному. Мы создаем библиотеку, в ней делаем модуль нотификации и внедряем его во все проекты.  Затем смотрим, что ещё можем унифицировать. Например, обращение к внутренней системе, которое тоже везде реализовано по-разному. Мы заносим этот кусочек кода в библиотеку и далее распространяем на каждый микросервис. Так, выделяя общие части в каждом пайплайне, мы постепенно обогащаем нашу библиотеку и имплементируем её в наш пайплайн.  Jenkins Shared Library уменьшает количество кода в пайплайне и повышает его читаемость. Для бизнеса это не столь важно, его больше заботит скорость доставки новых версий продукта до конечных пользователей. А здесь многое зависит от скорости разработки. Если каждая команда компании перестанет придумывать своё и начнёт использовать наработки других, вероятнее всего, разработка пайплайнов пойдёт быстрее. Соответственно, процесс доставки обновлений тоже ускорится.  С точки зрения самой команды, Jenkins Shared Library одновременно и усложняет, и упрощает работу. Например, проводить онбординг оказывается проще — вы показываете всё в одном месте. В то же время командам становится сложнее взаимодействовать. Сложность заключается в необходимости постоянной коммуникации. Когда решаем изменить что-то у себя в библиотеке, мы сначала должны синхронизироваться с другой командой, чтобы убедиться, что у неё ничего не сломается. Но обычно это решается регулярными синками, ревью кода и пул-реквестами. На прошлом проекте у нас было 20 микросервисов, очень похожих между собой. Они были написаны по одному скелету на Java, а ещё в каждом из них лежал Jenkins file, где был описан пайплайн сборки проектов. Всякий раз, когда нужно было что-то поменять в пайплайне (а делать это приходилось часто, так как проект динамичный и быстро развивался), мы проходились по 20 репозиториям и поправляли всё вручную. Это довольно геморройный процесс, и мы подумали: «А почему бы нам не сделать что-то общее?».  Так мы перешли на Jenkins Shared Library. У нас появился базовый пайплайн в библиотеке, и, когда требовалось что-то изменить, мы работали с ним. Добавляли какие-то правки, и они автоматически имплементировались в каждый микросервис.  Любой инструмент призван решать какую-то проблему. Jenkins Shared Library решает проблему дублирования кода и унификации. Если вам эта унификация не нужна, смысла тащить библиотеку в проект нет.   Если, скажем, у вас небольшой проект, где всего 5 микросервисов, писать для него библиотеку с нуля не стоит. Единственный вариант — переиспользовать, если она уже написана. Jenkins Shared Library — всё-таки решение для более крупных проектов с большим количеством микросервисов. Для разработки и тестирования Jenkins Shared Library нам необходимо установить на свой компьютер gradle. Вот инструкция по установке — https://gradle.org/install/. Далее в рабочем каталоге мы выполняем команду инициализации «gradle init», говорим установщику, что хотим настроить base каталог с groovy-файлами, и получаем готовый проект. Следующий шаг — создание каталогов для JSL:  var src resources test Директория src используется для Groovy классов, которые добавляются в classpath. Директория resources содержит файлы, которые мы можем загружать в пайплайн. Директория test содержит тесты для наших скриптом. Директория vars используется в скриптах, которые определяют глобальные переменные, доступные из пайплайна. Затем заполянем build.gradle, добавляя в него описание наших каталогов: И добавляем зависимости, которые понадобятся нам в работе. Полный файл можно посмотреть в репозитории: ссылка на репозиторий. Пишем простой первый класс, который увеличивает возраст на указанное значение :) Не забываем про тесты — создаем в директории test файл с именем SampleClassTest.groovy и содержимым. В секции Before описываем действия, которые необходимо выполнить перед тестом — в нашем случае это объявление класса. Далее в секции Test описываем сам тест. Объявляем age = 7 и выполняем функцию increaseAge с параметром 3. В случае правильного выполнения ожидаем получить 10.  Тест готов, запускаем командой gradle test. Результат будет такой:  Но это синтетические примеры, давайте рассмотрим реальный Каждый раз для вызова GET или POST запроса в пайплайн нам нужно вызывать класс HttpsURLConnection, передавать в него правильные параметры и проверять валидность сертификата.  Последуем главному принципу программирования DRY и подготовим класс, который позволит нам вызывать get и post запросы в пайплайне. Создаем в директории src/com/example HttpsRequest.groovy, в нём создаем два метода get и post. В параметрах методов передаём URL-запроса и в случае POST еще и body-запроса. Корневым методом нашего класса будет метод httpInternal. В нём закладываем логику, добавляем параметры к HttpsURLConnection, отлавливаем ошибку и в результате возвращаем тело ответа и ошибку: Покрываем тестами и создаем файл в директории test/HttpsRequestTest.groovy. Для примера делаем get запрос, получаем ответ и проверяем, что он соответствует нашим ожиданиям:  Запускаем тесты: Осталось дело за малым — подключить библиотеку в Jenkins. Для этого в Jenkins нужно перейти: Manage Jenkins → Configure System (Настроить Jenkins → Конфигурирование системы). В блоке Global Pipeline Libraries, добавить наш репозиторий:  Последний шаг — создаем наш пайплайн: Выполняем :) Весь код можно найти в репозитории: ссылка на репозиторий. Jenkins Shared Library — больше инструмент разработки в том плане, что нужно программировать. Чаще всего когда вы первый раз работаете с ней, если вы не разработчик, а администратор или DevOps, вы делаете это по наитию с точки зрения администратора. Это рабочий подход, но у него есть свои недостатки. Например, расширять проект дальше сложнее.   Лучше сразу начинать мыслить как разработчик: выделять классы и методы, правильно их имплементировать в пайплайн и т.д. Если вы не из мира разработки, это осознание приходит с запозданием. И чем позже оно придёт, тем больше времени и сил вы потратите на то, чтобы переписать то, что уже сделали.  6 сентября у нас стартует курс по Jenkins, автором которого выступил Кирилл Борисов, Infrastructure Engineer технологического центра Deutsche Bank. В курсе будет много кейсов и примеров из практики спикера.  Вы научитесь:  автоматизировать процесс интеграции и поставки; ускорять цикл разработки и внедрять полезные инструменты; настраивать плагины и создавать пайплайны Jenkins as a code; работать с Jenkins Shared Library. Промокод «READER» даёт скидку 10% при покупке курса. Ознакомиться с программой и записаться: https://slurm.club/3a6OEs8  Редактор в MobileUp