Каждый раз, добавляя новую библиотеку в проект, встаёт вопрос о том, можно ли обойтись без неё. И не удивительно, ведь нам, разработчикам, и так приходится поддерживать зоопарк библиотек в наших проектах. Каждая новая добавляет рутинной работы по поиску, обновлению и миграции библиотек на новые версии. И если миграцию на новые версии за нас никто не выполнит, то поиск обновлений можно автоматизировать. Именно об этом, Я и расскажу в этой статье.
А зачем вообще обновлять зависимости?
Мы живём в 21ом веке, веке цифровизации всего и вся. Каждый день очередная группировка хакеров взламывает информационные системы очередной компании. Это актуально особенно сейчас, когда геополитическая обстановка изменилась.
Многие попытки взломать информационную систему завершаются успехом из-за того, что создатель самой информационной системы не удосужился обновлять кодовую базу и используемые зависимости вовремя. В любом софте, любых библиотеках и фреймворках находятся уязвимости, используемые для взлома. Вспомнить хотя бы громкую находку в Apache Log4j
, которая заставила буквально всех разработчиков срочно вносить исправления в собственные системы.
Для решения проблемы использования устаревших библиотек давно созданы сервисы вроде Dependabot или Renovate. Однако, для Java разработчиков, есть способы получать информацию о имеющихся обновлениях гораздо проще и быстрее - gradle-versions-plugin
.
Gradle Versions Plugin
Информацию о проекте и инструкции можно найти на официальной странице проекта на GitHub.
Установка
Для того, чтобы начать использовать плагин в Вашем gradle проекте, достаточно добавить плагин в Ваш build.gradle
файл проекта. В секцкию plugins
нужно включить следующее объявление:
id 'com.github.ben-manes.versions' version '0.47.0'
где 0.47.0
- это наиболее актуальная версия плагина на момент написания статьи.
И это всё.
Использование
С добавлением плагина, в Вашем gradle проекте появилась новая таска - dependencyUpdates
, которая и формирует отчёт о состоянии зависимостей Вашего проекта. Чтобы воспользоваться новой таской, достаточно выполнить следующую команду:
gradle dependencyUpdates
Полный отчёт по зависимостям, используемым в проекте будет выведен в терминал.
Пример
Теперь посмотрим на живой пример того, как выглядит работа плагина. Для этого, я создал сгенерировал новый Java проект, используя команду gradle init
. Ответив на все вопросы генератора, я получил проект с небольшим количество зависимостей - самое то, для демонстрации работы плагина.
После добавления плагина в проект, мой build.gradle
файл стал выглядеть следующим образом:
plugins {
id 'application'
id 'com.github.ben-manes.versions' version '0.47.0'
}
repositories {
mavenCentral()
}
dependencies {
implementation 'com.google.guava:guava:31.1-jre'
}
testing {
suites {
test {
useJUnitJupiter('5.8.0')
}
}
}
application {
mainClass = 'ru.anverbogatov.App'
}
Выполним gradle dependencyUpdates
для получения отчёта о наличии обновлений зависимостей нашего проекта:
$ gradle dependecyUpdates
> Task :app:dependencyUpdates
------------------------------------------------------------
:app Project Dependency Updates (report to plain text file)
------------------------------------------------------------
The following dependencies are using the latest milestone version:
- com.github.ben-manes.versions:com.github.ben-manes.versions.gradle.plugin:0.47.0
- com.google.guava:guava:31.1-jre
The following dependencies have later milestone versions:
- org.junit.jupiter:junit-jupiter [5.8.0 -> 5.9.1]
https://junit.org/junit5/
Gradle release-candidate updates:
- Gradle: [7.6: UP-TO-DATE]
Generated report file build/dependencyUpdates/report.txt
Из отчёта сразу же видно, что версия JUnit, используемая в проекте, имеет обновления:
The following dependencies have later milestone versions:
org.junit.jupiter:junit-jupiter [5.8.0 -> 5.9.1]
Исправим версию JUnit в проекте на последнюю, обновив номер версии в build.gradle
файле:
...
testing {
suites {
test {
useJUnitJupiter('5.9.1')
}
}
}
...
И выполним команду gradle dependecyUpdates
ещё раз, для того, чтобы убедиться, что теперь мы используем самые свежие версии зависимостей:
$ gradle dependencyUpdates
> Task :app:dependencyUpdates
------------------------------------------------------------
:app Project Dependency Updates (report to plain text file)
------------------------------------------------------------
The following dependencies are using the latest milestone version:
- com.github.ben-manes.versions:com.github.ben-manes.versions.gradle.plugin:0.47.0
- com.google.guava:guava:31.1-jre
- org.junit.jupiter:junit-jupiter:5.9.1
Gradle release-candidate updates:
- Gradle: [7.6: UP-TO-DATE]
Generated report file build/dependencyUpdates/report.txt
Теперь, наш проект использует самые последние версии библиотек.
Заключение
gradle-versions-plugin
прекрасно работает как на небольших проектах, так и на больших multi-project gradle проектах, со множеством библиотек. Особенно удобно получать информацию о наличии новых версий в Spring Boot проектах, где количество различных зависимостей огромно.
Консольная команда и вывод отчёта в терминал, так же делают данный плагин превосходным кандидатом на включение в Ваши CI pipeline'ы.
Список материалов
Дополнительные материалы
Комментарии (6)
kochetkov-ma
21.06.2023 04:52+3У этого плагина есть особенность, что он предлагает версии
RC
,M
,ALFA
и т.п. Нужно сделать как указано в их доке, чтобы получать только релизные обновления:def isNonStable = { String version -> def stableKeyword = ['RELEASE', 'FINAL', 'GA'].any { it -> version.toUpperCase().contains(it) } def regex = /^[0-9,.v-]+(-r)?$/ return !stableKeyword && !(version ==~ regex) } tasks.named("dependencyUpdates").configure { rejectVersionIf { isNonStable(it.candidate.version) } }
NeoCode
21.06.2023 04:52А есть вообще способ заставить работать этот gradle без доступа к интернету? Даже простейший hello world для андроида - и то лезет что-то скачивать.
Chelyuk
21.06.2023 04:52Поднять локальное зеркало репозитория пакетов и прописать настройки на него.
Как никак все менеджеры пакетов должны их откуда-то скачивать.NeoCode
21.06.2023 04:52+1Я примерно так и сделал, скачал некую подборку maven offline, сделал как у них по инструкции. Но увы, все равно кто-то лезет в инет. Причем особенность там в том, что инет (там где я хочу все это поставить) есть, но специфический - пропускает запросы только с определенным user-agent. Я и с подменой заголовков играл - натыкаюсь на другие особенности, уже с https сертификатами и их подменой, версиями tls и прочим.
В общем, я к тому, что современный мир слишком завязан на инет. Исчезли те времена, когда можно было купить (или скачать) cd/dvd с полной оффлайн версией продукта (в том числе среды разработки) и спокойно пользоваться несколько лет, до выхода следующей верси. И это плохо еще тем, что вот такое самопроизвольно-непрерывное обновление всего и вся потенциально может что-то сломать в проекте. Программисты пакетов - тоже люди, и им тоже свойственно ошибаться.
ivankudryavtsev
А просто обновление по соответствию semver не работает? Или в Java нет semver?
Borz
плагин это и делает, но ещё учитывает всякие суффиксы вида "-RC", "-M" и прочие
Например, версия "1.2.1" будет считаться свежее чем версия "1.2.1-RC2"