Глава 35. Публикация Ivy (новая).

Это глава описывает поддержку новой инкубационной публикации Ivy, предоставляемой плагином 'ivy-publish'. В конечном итоге, поддержка новой публикации заменит публикацию, осуществляющуюся посредством задачи Upload.

Если вы ищите документацию по изначальной поддержке публикации с использованием задачи Upload, пожалуйста, посмотрите Главу 32 Публикация артефактов.

Это глава описывает публикацию артефактов сборки в формате Apache Ivy, обычно в хранилище, которое используется другими сборка или проектами. Публикуются один или более артефактов, созданных сборкой, и описание модуля Ivy (обычно ivy.xml), которое описывает артефакты и их зависимости, если есть.

Опубликованный модуль Ivy может быть использован Gradle (смотрите Главу 25 Управление зависимостями) и другими инструментами, понимающими формат Ivy.

35.1. Плагин 'ivy-publish'.

Функция публикации в формате Ivy предоставляется плагином 'ivy-publish'.

Плагин 'publishing' создает расширение проекта с именем 'publishing' типа PublishingExtension. Это расширение предоставляет контейнер именованных публикаций и контейнер именованных хранилищ. Плагин 'ivy-publish' работает с публикациями IvyPublication и хранилищами IvyArtifactRepository.

Пример 35.1. Применение плагина 'ivy-publish'

build.gradle

apply plugin: 'ivy-publish'
	  

Применение плагина 'ivy-publish' делает следующее:

  • Применяет плагин 'publishing'.
  • Устанавливает правило автоматического создания задачи GenerateIvyDescriptor для каждой добавленной IvyPublication (смотрите Секцию 35.2 Публикации).
  • Устанавливает правило автоматического создания задачи PublishToIvyRepository для каждой комбинации добавленной IvyPublication (смотрите Секцию 35.2 Публикации) с добавленным IvyArtifactRepository (смотрите Секцию 35.3 Хранилища).

35.2. Публикации.

Если вы не знакомы с артефактами и конфигурациями проекта, вам следует прочесть Главу 32 Публикация артефактов, которая представляет эти понятия. Также Глава 32 описывает 'публикацию артефактов' с использованием механизма отличного от описываемого в этой главе. Функциональность публикации, описанная здесь, в конечном счете заменит ту функциональность.

Объекты публикации описывают структуру/конфигурацию публикации, которая будет создана. Публикации публикуются в хранилища посредством задач и настройка объектов публикации определяет то, что публикуется. Все публикации проекта определены в контейнере PublishingExtension.getPublications(). У каждой публикации уникальное имя в рамках проекта.

Для того, чтобы плагин 'ivy-publish' имел какой-либо эффект, к набору публикаций должна быть добавлена IvyPublication. Эта публикация определяет какие артефакты в действительности публикуются, наряду с деталями, включенными в связанный файл описания модуля Ivy. Публикацию можно настроить, добавив компоненты, настроив артефакты и непосредственно изменив сгенерированный файл описания модуля.

35.2.1. Публикация компонента программного обеспечения.

Простейший путь опубликовать проект Gradle в хранилище Ivy - указать SoftwareComponent для публикации. Компоненты доступные для публикации в настоящее время:

Таблица 35.1. Компоненты программного обеспечения
ИмяПредоставленАртефактыЗависимости
javaПлагином JavaСгенерированный jar-файлЗависимости из конфигурации 'runtime'
webПлагином WarСгенерированный war-файлНет зависимостей

В следующем примере, артефакты и зависимости времени выполнения взяты из компонента 'java', который добавлен плагином Java.

Пример 35.2. Публикация модуля Java в Ivy

build.gradle

publications {
    ivyJava(IvyPublication) {
        from components.java
    }
}
	  

35.2.2. Публикация пользовательских артефактов.

Возможна точная настройка того, какие артефакты будут включены в публикацию. Артефакты обычно предоставляемые как сырые файлы или экземпляры AbstractArchiveTask (например, Jar, Zip).

Для каждого пользовательского артефакта возможно указать значения свойств name, extension, type, classifier и conf, используемых публикацией. Обратите внимание, что каждый артефакт должен иметь уникальную комбинацию name/classifier/extension.

Пользовательские артефакты настраиваются так:

Пример 35.3. Публикация дополнительного артефакта в Ivy

build.gradle

task sourceJar(type: Jar) {
    from sourceSets.main.java
    classifier "source"
}
publishing {
    publications {
        ivy(IvyPublication) {
            from components.java
            artifact(sourceJar) {
                type "source"
                conf "runtime"
            }
        }
    }
}
	  

Смотрите класс IvyPublication в документации API, чтобы узнать больше о том, как можно настроить артефакты.

35.2.3. Идентификационные данные для опубликованного проекта.

Сгенерированный файл описания модуля Ivy содержит элемент <info>, который идентифицирует модуль. Значения идентификаторов по умолчанию являются производными от следующих:

Переопределить значения идентификаторов по умолчанию не составляет труда - просто укажите атрибуты organisation, module или revision, когда настраиваете IvyPublication. Атрибут status и branch могут быть установлены посредством свойства descriptor (смотрите IvyModuleDescriptorSpec). Свойство descriptor также может быть использовано для добавления дополнительных пользовательских элементов в качестве дочерних элемента <info>.

Пример 35.4. Настройка идентификационных данных публикации

build.gradle

publishing {
    publications {
        ivy(IvyPublication) {
            organisation 'org.gradle.sample'
            module 'project1-sample'
            revision '1.1'
            descriptor.status = 'milestone'
            descriptor.branch = 'testing'
            descriptor.extraInfo 'http://my.namespace', 'myElement', 'Some value'

            from components.java
        }
    }
}
	  

Gradle обработает любой действительный символ юникода для свойств organisation, module и revision (так же как и для name, extension и classifier). Явно запрещены только значения '\', '/' и любой управляющий символ ISO. Предоставленные значения проверяются в начале публикации.

Определенные хранилища не в состоянии обработать все поддерживаемые символы. Например, символ ':' невозможно использовать в качестве идентификатора при публикации в хранилище, основанное на файловой системе Windows.

35.2.4. Изменение сгенерированного описания модуля.

Временами описание модуля, сгенерированное из информации о проекте, будет необходимо точно настроить перед публикацией. Плагин 'ivy-publish' предоставляет перехватчик, чтобы сделать возможным такие изменения.

Пример 35.5. Настройка файла описания модуля

build.gradle

publications {
    ivyCustom(IvyPublication) {
        descriptor.withXml {
            asNode().info[0].appendNode('description',
                                        'A demonstration of ivy descriptor customization')
        }
    }
}
	  

В этом примере мы просто добавляем элемент 'description' к сгенерированному описанию зависимости Ivy, но этот перехватчик позволяет вам изменять любой аспект сгенерированного описания. Например, вы можете заменить диапазон версий зависимости на актуальную версию, используемую создания сборки.

Чтобы узнать больше, смотрите IvyModuleDescriptorSpec.withXml(org.gradle.api.Action) в документации API.

В случае необходимости можно изменить практически любой аспект созданного описания. Также это означает, что можно изменить описание таким образом, что оно больше не будет действительным описанием модуля Ivy, поэтому при использовании этой функции необходимо соблюдать осторожность.

Идентификатор (organisation, module, revision) опубликованного модуля является исключением; эти значения невозможно изменить в описании с помощью перехватчика 'withXML'.

35.2.5. Публикация нескольких модулей.

Иногда бывает полезно опубликовать несколько модулей из вашей сборки Gradle, без создания отдельного подпроекта. Например, публикация отдельного API и jar-файла с реализацией для вашей библиотеки. С Gradle это просто:

Пример 35.6. Публикация нескольких модулей из одного проекта

build.gradle

task apiJar(type: Jar) {
    baseName "publishing-api"
    from sourceSets.main.output
    exclude '**/impl/**'
}
publishing {
    publications {
        impl(IvyPublication) {
            organisation 'org.gradle.sample.impl'
            module 'project2-impl'
            revision '2.3'

            from components.java
        }
        api(IvyPublication) {
            organisation 'org.gradle.sample'
            module 'project2-api'
            revision '2'
        }
    }
}
	  

Если в проекте заданы несколько публикация, тогда Gradle опубликует каждую из них в заданное хранилище. Каждая публикация должна уникально идентифицироваться, как было описано выше.

35.3. Хранилища.

Публикации публикуются в хранилища. Хранилища для публикации определяются контейнером PublishingExtension.getRepositories().

Пример 35.7. Объявление хранилищ для публикации

build.gradle

repositories {
    ivy {
        // change to point to your repo, e.g. http://my.org/repo
        url "$buildDir/repo"
    }
}
	  

DSL, используемый для объявления хранилищ для публикации, тот же самый, что используется для объявления хранилищ для зависимостей (RepositoryHandler). Однако, в контексте публикации Ivy, только хранилища, созданные методами ivy(), могут быть использованы в качестве места назначения публикаций. Вы не можете опубликовать IvyPublication, например, в хранилище Maven.

35.4. Выполнение публикации.

Плагин 'ivy-publish' автоматически создает задачу PublishToIvyRepository для каждой комбинации IvyPublication и IvyArtifactRepository в контейнерах publishing.publications и publishing.repositories соответственно.

Созданная задача называется 'publish«ИМЯ_ПУБЛИКАЦИИ»PublicationTo«ИМЯ_ХРАНИЛИЩА»Repository'. Например, 'publishIvyJavaPublicationToIvyRepository'. Тип задачи - PublishToIvyRepository.

Пример 35.8. Выбор публикации для публикации

build.gradle

apply plugin: 'java'
apply plugin: 'ivy-publish'

group = 'org.gradle.sample'
version = '1.0'

publishing {
    publications {
        ivyJava(IvyPublication) {
            from components.java
        }
    }
    repositories {
        ivy {
            // change to point to your repo, e.g. http://my.org/repo
            url "$buildDir/repo"
        }
    }
}
	  

Вывод команды gradle publishIvyJavaPublicationToIvyRepository

> gradle publishIvyJavaPublicationToIvyRepository
:generateDescriptorFileForIvyJavaPublication
:compileJava NO-SOURCE
:processResources NO-SOURCE
:classes UP-TO-DATE
:jar
:publishIvyJavaPublicationToIvyRepository

BUILD SUCCESSFUL

Total time: 1 secs
	  

35.4.1. Задача жизненного цикла 'publish'.

Плагин 'publish' (который автоматически применяет плагин 'ivy-publish') добавляет задачу жизненного цикла с именем 'publish', которую можно использовать для публикации всех публикаций во все подходящие хранилища. Если говорить более конкретно, то выполнение этой задачи выполнит все задачи PublishToIvyRepository в проекте. Обычно, это самый удобный способ публикации.

Пример 35.9. Публикация всех публикаций посредством задачи жизненного цикла 'publish'

Вывод команды gradle publish

> gradle publish
:generateDescriptorFileForIvyJavaPublication
:compileJava NO-SOURCE
:processResources NO-SOURCE
:classes UP-TO-DATE
:jar
:publishIvyJavaPublicationToIvyRepository
:publish

BUILD SUCCESSFUL

Total time: 1 secs
	  

35.5. Генерация файла описания модуля Ivy без публикации.

Временами бывает полезно сгенерировать файл описания модуля Ivy (обычно ivy.xml) без публикации вашего модуля в хранилище Ivy. Так как генерация файла описания выполняется отдельной задачей, это легко сделать.

Плагин 'ivy-publish' создает одну задачу GenerateIvyDescriptor для каждой зарегистрированной IvyPublication с именем 'generateDescriptorFileFor«ИМЯ_ПУБЛИКАЦИИ»Publication', которая будет 'generateDescriptorFileForIvyJavaPublication' для предыдущего примера для публикации 'ivyJava'.

Вы можете указать где будет располагаться сгенерированный файл Ivy, установив свойство destination сгенерированной задачи. По умолчанию, файл записывается в 'build/publications/«ИМЯ_ПУБЛИКАЦИИ»/ivy.xml'.

Пример 35.10. Генерация файла описания модуля Ivy

build.gradle

model {
    tasks.generateDescriptorFileForIvyCustomPublication {
        destination = file("$buildDir/generated-ivy.xml")
    }
}
	  

Вывод команды gradle generateDescriptorFileForIvyCustomPublication

> gradle generateDescriptorFileForIvyCustomPublication
:generateDescriptorFileForIvyCustomPublication

BUILD SUCCESSFUL

Total time: 1 secs
	  

Плагин 'ivy-publish' использует экспериментальную поддержку поздней настройки плагина и задача GenerateIvyDescriptor не будет создана до тех пор, пока не будет настроено расширение публикации. Самым простым способом убедиться, что плагин публикации настроен, когда вы пытаетесь обратиться к задаче GenerateIvyDescriptor, является помещение обращения в блок model, как показано в примере выше.

То же самое относится к любой попытке обращения к задачам публикации, таким как PublishToIvyRepository. Ссылаться на такие задачи надо внутри блока model.

35.6. Полный пример.

Следующий пример демонстрирует публикацию в многопроектной сборке. Каждый проект публикует компонент Java и настроенный дополнительный исходный артефакт. Файл описания настроен так, чтобы включать описание проекта для каждого проекта.

Пример 35.11. Публикация модуля Java

build.gradle

subprojects {
    apply plugin: 'java'
    apply plugin: 'ivy-publish'

    version = '1.0'
    group = 'org.gradle.sample'

    repositories {
        mavenCentral()
    }
    task sourceJar(type: Jar) {
        from sourceSets.main.java
        classifier "source"
    }
}

project(":project1") {
    description = "The first project"

    dependencies {
       compile 'junit:junit:4.12', project(':project2')
    }
}

project(":project2") {
    description = "The second project"

    dependencies {
       compile 'commons-collections:commons-collections:3.2.2'
    }
}

subprojects {
    publishing {
        repositories {
            ivy {
                // change to point to your repo, e.g. http://my.org/repo
                url "${rootProject.buildDir}/repo"
            }
        }
        publications {
            ivy(IvyPublication) {
                from components.java
                artifact(sourceJar) {
                    type "source"
                    conf "runtime"
                }
                descriptor.withXml {
                    asNode().info[0].appendNode('description', description)
                }
            }
        }
    }
}
	  

В результате будут опубликованы следующие артефакты для каждого проекта:

  • Файл описания модуля Ivy: 'ivy-1.0.xml'.
  • Основной 'jar'-артефакт компонента Java: 'project1-1.0.jar'.
  • Исходный 'jar'-артефакт, который был явно настроен: 'project1-1.0-source.jar'.

При публикации project1, создаваемое описание модуля (т.е. файл ivy.xml) будет выглядеть так:

Пример 35.12. Пример сгенерированного ivy.xml

output-ivy.xml

<ivy-module version="2.0">
  <info organisation="org.gradle.sample" module="project1" revision="1.0" status="integration" publication="«PUBLICATION-TIME-STAMP»">
    <description>The first project</description>
  </info>
  <configurations>
    <conf name="compile" visibility="public"/>
    <conf name="default" visibility="public" extends="runtime,compile"/>
    <conf name="runtime" visibility="public"/>
  </configurations>
  <publications>
    <artifact name="project1" type="jar" ext="jar" conf="runtime"/>
    <artifact name="project1" type="source" ext="jar" conf="runtime" m:classifier="source" xmlns:m="http://ant.apache.org/ivy/maven"/>
  </publications>
  <dependencies>
    <dependency org="junit" name="junit" rev="4.12" conf="runtime->default"/>
    <dependency org="org.gradle.sample" name="project2" rev="1.0" conf="runtime->default"/>
  </dependencies>
</ivy-module>
	  

Обратите внимание, что 'PUBLICATION-TIME-STAMP' в образце описания модуля Ivy будет меткой времени, когда описание было сгенерировано.

35.7. Будущие возможности.

Функциональность плагина 'ivy-publish', описанная выше, неполная, так как эта возможность пока еще инкубационная. В предстоящих выпусках Gradle, функциональность будет расширена и будет включать (но не будет ограничиваться):

  • Удобную настройку атрибутов модуля (module, organisation и так далее).
  • Удобную настройку зависимостей, описанных в описании модуля.
  • Несколько отдельных публикаций на проект.