2015-02-10 4 views
16

Я работаю над внедрением системы сборки Gradle для части программного обеспечения, которая имеет части, которые разработаны в области без подключения к Интернету или возможность установки сервера Maven/Ivy (например, Nexus). Чтобы поддерживать разработку в этих средах, я собираю плагин Gradle, который позволяет создавать «автономную рабочую область».Build Gradle repository для автономного развития

Первоначально я реализовал эту функциональность, инициировав разрешение каждой конфигурации в проекте (инициируя загрузку всех зависимостей), а затем обход всего дерева зависимостей каждой конфигурации и копирование локальной кэшированной копии зависимостей в автономную рабочую область , (Задача копирования была сгенерирована для каждой операции копирования.) Эти JAR будут ссылаться на репозиторий flatDir.

Эта реализация выполнила свою работу с использованием блока afterEvaluate. Хотя это отлично работало в Gradle 2.0, оно запускает предупреждение об устаревании в Gradle 2.2.1, потому что запуск разрешения как-то рассматривается как изменение конфигурации после того, как оно уже разрешено (Attempting to change configuration ':core:runtime' after it has been included in dependency resolution. This behaviour has been deprecated and is scheduled to be removed in Gradle 3.0). В целом, этот подход кажется довольно взломанным, так как он также требует, чтобы я модифицировал файлы build.gradle, чтобы явно перечислять все транзитивные зависимости, поскольку нет доступных POM-файлов для правильного указания зависимостей.

Более элегантный подход кажется, что он построит локальный репозиторий Maven всех зависимостей (включая POM-файлы, исходные JAR-файлы, javadoc JAR и т. Д.), А затем просто используйте тип хранилища mavenLocal(). К сожалению, я не уверен, как это сделать правильно, где мне не нужно вызывать разрешение артефакта, чтобы выполнить эту операцию.

Есть ли какой-нибудь лучший способ, которым я могу добиться полной загрузки артефактов в простой способ, чем просто перевернуть весь мой каталог USER_HOME/.gradle?

ответ

9

Чтобы иметь автономную сборку, вам нужно как-то обеспечить все необходимые зависимости. Один из вариантов здесь - просто передать эти банки в управление версиями. Трудная часть - собрать все эти зависимости. Для этого можно иметь build.gradle файл, который может работать в двух режимах (онлайн и оффлайн):

buildscript { 
    repositories { 
     if ('allow' == System.properties['build.network_access']) { 
      mavenCentral() 
     } else { 
      maven { 
       url 'dependencies' 
      } 
     } 
    } 
    dependencies { 
     classpath 'com.android.tools.build:gradle:1.2.0-beta2' 
    } 
} 

Для запуска в автономном режиме типа:

gradle --offline 

И для работы в режиме реального времени :

gradle -Dbuild.network_access=allow 

и собрать все зависимости использовать этот скрипт, который будет работать Gradle в онлайн-режиме, принеси зависимости кэшировать внутри ${project_dir}/.gradle_home и скопировать артефакты местного Maven репо сайт в dependencies папка.

#!/usr/bin/python 

import sys 
import os 
import subprocess 
import glob 
import shutil 

# Place this in build.gradle: 
# repositories { 
#  if ('allow' == System.properties['build.network_access']) { 
#   mavenCentral() 
#  } else { 
#   maven { url 'dependencies' } 
#  } 
# } 
def main(argv): 
    project_dir = os.path.dirname(os.path.realpath(__file__)) 
    repo_dir = os.path.join(project_dir, "dependencies") 
    temp_home = os.path.join(project_dir, ".gradle_home") 
    if not os.path.isdir(temp_home): 
     os.makedirs(temp_home) 
    subprocess.call(["gradle", "-g", temp_home, "-Dbuild.network_access=allow"]) 
    cache_files = os.path.join(temp_home, "caches/modules-*/files-*") 
    for cache_dir in glob.glob(cache_files): 
     for cache_group_id in os.listdir(cache_dir): 
      cache_group_dir = os.path.join(cache_dir, cache_group_id) 
      repo_group_dir = os.path.join(repo_dir, cache_group_id.replace('.', '/')) 
      for cache_artifact_id in os.listdir(cache_group_dir): 
       cache_artifact_dir = os.path.join(cache_group_dir, cache_artifact_id) 
       repo_artifact_dir = os.path.join(repo_group_dir, cache_artifact_id) 
       for cache_version_id in os.listdir(cache_artifact_dir): 
        cache_version_dir = os.path.join(cache_artifact_dir, cache_version_id) 
        repo_version_dir = os.path.join(repo_artifact_dir, cache_version_id) 
        if not os.path.isdir(repo_version_dir): 
         os.makedirs(repo_version_dir) 
        cache_items = os.path.join(cache_version_dir, "*/*") 
        for cache_item in glob.glob(cache_items): 
         cache_item_name = os.path.basename(cache_item) 
         repo_item_path = os.path.join(repo_version_dir, cache_item_name) 
         print "%s:%s:%s (%s)" % (cache_group_id, cache_artifact_id, cache_version_id, cache_item_name) 
         shutil.copyfile(cache_item, repo_item_path) 
    shutil.rmtree(temp_home) 
    return 0 

if __name__ == "__main__": 
    sys.exit(main(sys.argv)) 

Таким образом, после каждого изменения зависимостей просто запустить этот скрипт и вносить изменения в dependencies папке. Затем вы можете строить офлайн с gradle --offline или просто gradle.

3

В прошлом я использовал аналогичное решение, хотя сценарий «мой» был выполнен в groovy вместо python.

Я обнаружил другой подход пару недель назад: есть ivypot plugin. Теперь вам больше не нужно использовать какой-либо «внешний» скрипт, плагин способен скопировать все зависимости в локальный каталог, который является репозиторией плюща.

Испытательный проект можно найти on github.Я могу предоставить английский README в случае, если есть спрос на него.

+1

Английский README будет в порядке – Cesar

+0

Этот плагин ivypot классный. Но это не решает мою проблему. Мне нужно кэшировать только ограниченный набор зависимостей, которые поступают из частного репозитория. Мне не нужно все кэшировать. Итак, мне нужно найти другой похожий плагин или реализовать функцию в этом коде плагина. – kinORnirvana