Gradle - загрузите зависимости, заблокируйте версии и обновите зависимости вручную

Проблема.

Управление зависимостями Gradle сделано так:

  • нет простого способа проверить наличие обновлений зависимостей (только с помощью некоторых сторонних плагинов, таких как ben -manes / gradle-versions-plugin) и скачивать обновления, заменяющие старые версии;
  • артефакты зависимостей загружаются из удаленных репозиториев, затем сохраняются в кеш-памяти Gradle и повторно используются в последующих сборках; но успешная компиляция вашего проекта не должна зависеть от наличия подключения к Интернету, наличия удаленных репозиториев и наличия определенных версий зависимостей в этих репозиториях.

Цель.

  • скачивать и хранить все артефакты зависимостей в VCS;
  • вручную проверьте обновления для этих зависимостей и загрузите их.

person mixel    schedule 27.07.2015    source источник


Ответы (2)


Мое решение работает для конфигурации Gradle с использованием плагинов java или android.

Плагин java определяет конфигурации compile и testCompile. compile предназначен для зависимостей, необходимых для компиляции производственного источника проекта. testCompile предназначен для зависимостей, необходимых для компиляции тестового источника проекта.

Давайте определим наши собственные конфигурации в build.gradle:

configurations {
    download
    testDownload
}

Далее создадим каталоги:

  • libs/compile/downloaded - это место, где будут храниться download зависимости;
  • libs/testCompile/downloaded - это место, где будут храниться testDownload зависимости.

Далее мы определяем несколько задач.

Удалите зависимости из download конфигурации:

task cleanDownloadedDependencies(type: Delete) {
    delete fileTree('libs/compile/downloaded')
}

Удалите зависимости из testDownload конфигурации:

task cleanDownloadedTestDependencies(type: Delete) {
    delete fileTree('libs/testCompile/downloaded')
}

Загрузите зависимости из download конфигурации:

task downloadDependencies(type: Copy) {
    from configurations.download
    into "libs/compile/downloaded/"
}

Загрузите зависимости из testDownload конфигурации:

task downloadTestDependencies(type: Copy) {
    from configurations.testDownload
    into "libs/testCompile/downloaded/"
}

Выполните все вышеперечисленные задачи для обновления зависимостей:

task updateDependencies {
    dependsOn cleanDownloadedDependencies, cleanDownloadedTestDependencies, downloadDependencies, downloadTestDependencies
}

Затем мы определяем наши зависимости:

dependencies {
    download(
            'com.google.code.gson:gson:+',
            'joda-time:joda-time:+',
    )
    testDownload(
            'junit:junit:+'
    )

Затем мы сообщаем, где compile и testCompile конфигурации должны принимать зависимости, используемые для компиляции.

    compile fileTree(dir: 'libs/compile', include: '**/*.jar')
    testCompile fileTree(dir: 'libs/testCompile', include: '**/*.jar')
}

Теперь вы можете скачать или обновить уже скачанные зависимости:

./gradlew updateDependencies

Если вы используете плагин android, вы также можете добавить androidTestDownload конфигурацию для зависимостей, которые необходимы для компиляции и запуска тестов на устройстве Android. Также некоторые зависимости могут быть представлены как aar артефакты.

Это пример конфигурации Gradle с использованием плагина android:

...

repositories {

    ...

    flatDir {
        dirs 'libs/compile', 'libs/compile/downloaded',
                'libs/testCompile', 'libs/testCompileDownloaded',
                'libs/androidTestCompile', 'libs/androidTestCompile/downloaded'
    }
}

configurations {
    download
    testDownload
    androidTestDownload
}

android {
    ...
}

dependencies {
    download(
            'com.android.support:support-v4:+',
            'com.android.support:appcompat-v7:+',
            'com.google.android.gms:play-services-location:+',
            'com.facebook.android:facebook-android-sdk:+',
            'com.vk:androidsdk:+',
            'com.crashlytics.sdk.android:crashlytics:+',
            'oauth.signpost:signpost-core:+',
            'oauth.signpost:signpost-commonshttp4:+',
            'org.twitter4j:twitter4j-core:+',
            'commons-io:commons-io:+',
            'com.google.code.gson:gson:+',
            'org.jdeferred:jdeferred-android-aar:+'
    )
    compile fileTree(dir: 'libs/compile', include: '**/*.jar')
    testCompile fileTree(dir: 'libs/testCompile', include: '**/*.jar')
    androidTestCompile fileTree(dir: 'libs/androidTestCompile', include: '**/*.jar')
}


task cleanDownloadedDependencies(type: Delete) {
    delete fileTree('libs/compile/downloaded')
}

task cleanDownloadedTestDependencies(type: Delete) {
    delete fileTree('libs/testCompile/downloaded')
}

task cleanDownloadedAndroidTestDependencies(type: Delete) {
    delete fileTree('libs/androidTestCompile/downloaded')
}

task downloadDependencies(type: Copy) {
    from configurations.download
    into 'libs/compile/downloaded/'
}

task downloadTestDependencies(type: Copy) {
    from configurations.testDownload
    into 'libs/testCompile/downloaded/'
}

task downloadAndroidTestDependencies(type: Copy) {
    from configurations.androidTestDownload
    into 'libs/androidTestCompile/downloaded/'
}

task updateDependencies {
    dependsOn cleanDownloadedDependencies, cleanDownloadedTestDependencies, cleanDownloadedAndroidTestDependencies, downloadDependencies, downloadTestDependencies, downloadAndroidTestDependencies
}

fileTree(dir: 'libs/compile', include: '**/*.aar')
        .each { File file ->
    dependencies.add("compile",
            [name: file.name.lastIndexOf('.').with { it != -1 ? file.name[0..<it] : file.name }, ext: 'aar'])
}

fileTree(dir: 'libs/testCompile', include: '**/*.aar')
        .each { File file ->
    dependencies.add("testCompile",
            [name: file.name.lastIndexOf('.').with { it != -1 ? file.name[0..<it] : file.name }, ext: 'aar'])
}

fileTree(dir: 'libs/androidTestCompile', include: '**/*.aar')
        .each { File file ->
    dependencies.add("androidTestCompile",
            [name: file.name.lastIndexOf('.').with { it != -1 ? file.name[0..<it] : file.name }, ext: 'aar'])
}
person mixel    schedule 27.07.2015
comment
Выглядит нормально, вы можете написать плагин для всех задач, который будет обрабатывать большинство задач автоматически. Несмотря на то, что я понимаю цель, я не поклонник сохранения зависимостей в VCS. В разработке под iOS (с помощью модулей) все еще идет война - сохранять зависимости под VCS или нет;) +1! - person Opal; 28.07.2015
comment
Хорошая идея о плагине! Я попробую. - person mixel; 28.07.2015
comment
Просто спросите, если возникнут проблемы. - person Opal; 28.07.2015
comment
@Opal О сохранении зависимостей в VCS. У каждого проекта есть некоторые предпосылки и требования для успешной сборки - операционная система, инструменты (например, Java, Gradle, Android SDK), подключение к Интернету, удаленные репозитории и т. Д. Я всегда уменьшаю количество этих требований до разумного минимального набора абсолютно необходимых инструментов ( ОС, Java, Gradle, Android SDK). Если я не включаю зависимости в VCS, я включаю их в проект как модули git, репозитории которых находятся на том же хосте, что и репозиторий исходного проекта. - person mixel; 28.07.2015
comment
Это может выглядеть как паранойя, но это лучше, чем отсутствие необходимых зависимостей, если они будут удалены из репозитория maven или cocoapods. - person mixel; 28.07.2015

Для блокировки версий загруженных зависимостей (от версий библиотеки / и т.д. до жестко запрограммированных версий) для обеспечения воспроизводимости сборок, теперь Gradle 4.8 и новее, у нас будет встроенная поддержка «блокировки зависимостей». Это очень поможет сделать сборки воспроизводимыми, если кто-то использует динамические версии (Mmp / i) Major.minor.patch / interimBranch и т. Д. (Например: 4. + или 3.1. +) Или диапазон версий для извлечения артефактов из инструмента двоичного репозитория ( пример: Artifactory / Nexus).

Любой пользователь Gradle, который использует Gradle версии 4.8+, должен начать использовать эту новую функцию. https://docs.gradle.org/4.8/userguide/dependency_locking.html Примечания к выпуску Gradle 4.8: https://docs.gradle.org/4.8/release-notes.html

В прошлом эта функция блокировки зависимостей была предоставлена ​​сообществу Gradle и сделана доступной через плагин FOSS, доступный для Gradle из https://github.com/nebula-plugins/gradle-dependency-lock-plugin и https://plugins.gradle.org/plugin/nebula.dependency-lock

person AKS    schedule 13.06.2018
comment
приятно, что у нас есть внутренняя встроенная часть gradle для обновления блокировок, но ... как насчет изменения состояния блокировки другими способами? (удаление, возможность игнорировать его при разработке и т. д.) - person dtc; 08.08.2019