В предыдущей статье мы разобрались зачем вообще нужен Jenkins и автоматизация процесса разработки. В этой статье разберем, как именно делать автоматизацию сборок в Jenkins, поделюсь лучшими практиками
Воспроизводимые билды. Хорошо, когда билды воспроизводимы. Это значит, что для одних и тех же исходных данных получается одно и то же на выходе, когда бы вы не запустили. Важно, прежде всего, для исключения ситуации "вчера все работало, а сегодня нет". Например, ваше приложение использует сторонние библиотеки, которые используют тоже какие-то сторонние библиотеки, так образуется дерево зависимостей. При сборке все это дерево складывается вместе на диске для запуска. Тут надо сказать, что у каждой библиотеки может быть в природе несколько версий. И вот вы собрали приложение в котором самые актуальные версии библиотек на данный момент, проверили, все работает как надо. Достаточно чтобы вышла хотя бы одна новая версия из данного дерева, чтоб возник риск, что что-то перестанет работать. Ну мало ли какая ошибка закралась или изменилось поведение, да мало ли что. Это общее правило, из которого вытекают следующие частности:
Используйте конкретные версии зависимостей. Разные системы сборок, такие как Maven, Gradle, NPM и прочие, предлагают механизмы управления версиями зависимостей. Можно задать что-то вроде "используй последнюю версию" или задать диапазон версий, а так же можно указать конкретную версию. Легко задать конкретные версии для библиотек, от которых ваше приложение зависит напрямую, указав их в файле конфигурации вашей системы сборки. И это очень удобно, система сборки сама найдет зависимости для каждой библиотеки и для них и так на всю глубину дерева, вам не надо знать и указывать полное дерево зависимостей, что весьма удобно и экономит время. Но тут же и скрывается риск, дело в том, что каждая библиотека описывает свои зависимости так же как и ваше приложение, и мы не можем гарантировать, что все они так же указываают конкретные версии а не используют "текущую на данный момент" версию. Для того, чтобы гарантировать это, есть способ собрать и зафиксировать номера версий для каждой библиотеки в дереве, получится файл, в котором список библиотек и их конкретные версии, которые получились на данный момент. При следующих сборках можно задать использовать версии из этого файла, даже если вышли новые версии. Если вдруг появились новые зависмости, которых нет в файле, сборка просто не пройдет, пока библиотеку не добавить в файл версий. Таким образом можно повысить шанс воспроизврдимости сборки. Что еще надо зафиксировать?
Фиксируем версию системы сборок и SDK. Иногда обновление версии системы сборок может сломать билд, бывает так, что с одной версией npm и nodejs сборки проходят, а с другой уже нет. Или то, что собиралось на Oracle JDK, уже не собирвется на OpenJDK. Не всегда команда может контролировать версию системы сборок и SDK. Есть два способа использовать такие компоненты:
Так приходим к идее, что сборки внутри контейнеров повышают их воспроизводимость.
Делайте сборки внутри контейнеров. Не важно, используете вы конейнеры в продакшене и на окружениях или нет, рекомендую сборки внутри контейнеров для повышения их воспроизводимости. Когда собираете внутри контейнера, каждая сборка начинается как с чистого листа, по новому выкачиваются все файлы, собираются артефакты. Иначе, если остался мусор от предыдущей сборки, он может оказать влияние на последующие сборки, понизив их воспроизводимость. Если во время сборки открываются какие-то фиксированые сетевые порты, например 8080, то, запустив параллельно два билда на одной машине с Jenkins, вторая сборка упадет, ведь не сможет использовать уже используемый порт, но, если каждая сборка идет в контейрере, то каждая сборка может открыть один и тот же порт, ведь порты внутри контейнеров изолированы.
Сокращайте время сборки. Например вы работаете над кодом и считаете, что все готово, осталось запустить сборку и понять, ничего ли не сломалось прежде, чем влить код в основной. Вы хотите как можно быстрее знать результат, чтобы пока в голове свеж контекст быстрее починить и уже закончить с задачей, забыть про нее и, может, начать работу над следующей. Если сборка идет долго, вы, возможно, уже переключитесь на новую задачу и, если сборка упадет, снова придется переключаться обратно, частое переключение контекста занимает время и ресурсы мозга, при этом может быть малоприятным. Как ускорить сборки? Запустить как можно раньше и чтоб сборка занимала как можно меньше времени, для этого:
Запускайте сборку как можно раньше. Jenkins умеет запускать сборки периодически, скажем, раз в 30 мин, но это значит, что, в хужшем случае, вы будете ждать 30 мин пока сборка начнет собираться, и еще сколько-то времени, пока она пройдет. Есть альтернатива получше, можно настроить Jenkins так, чтобы он запускал сборку сразу, как только появился новый код в репозитории, для этого надо настроить web-хуки.
Запускайте параллельно так много, как можете. Часто процесс сборки можно разбить на отдельные независимые этапы, Jenkins позволяет запускать их параллельно, тем самым сокращая суммарное время сборки.
Спасибо, что заглянули,
добавляйтесь в
Telegram
канал и будьте в курсе новинок.
Если Вам было интересно, можете поддержать автора