Table of Contents
This chapter describes the new Ivy publishing support provided by the Ivy Publish Plugin. This new publishing support is the preferred option for publishing artifacts and will eventually replace publishing via the Upload task.
If you are looking for documentation on the original Ivy publishing support using the Upload task please see the chapter on publishing artifacts.
The Ivy Publish Plugin provides the ability to publish build artifacts in the Apache Ivy format, usually to a repository for consumption by other builds or projects. What is published is one or more artifacts created by the build, and an Ivy module descriptor (normally ivy.xml) that describes the artifacts and the dependencies of the artifacts, if any.
A published Ivy module can be consumed by Gradle (see Declaring Dependencies) and other tools that understand the Ivy format.
The Ivy Publish Plugin uses an extension on the project named publishing of type PublishingExtension. This extension provides a container of named publications and a container of named repositories. The Ivy Publish Plugin works with IvyPublication publications and IvyArtifactRepository repositories.
To use the Ivy Publish Plugin, include the following in your build script:
Applying the Ivy Publish Plugin does the following:
Automatically creates a
GenerateIvyDescriptortask for eachIvyPublicationadded (see the section called “Publications”).Automatically creates a
PublishToIvyRepositorytask for the combination of eachIvyPublicationadded (see the section called “Publications”), with eachIvyArtifactRepositoryadded (see the section called “Repositories”).
If you are not familiar with project artifacts and configurations, you should read Publishing artifacts, which introduces these concepts. That chapter also describes publishing artifacts using a different mechanism than the one described in this chapter. The publishing functionality described here will eventually supersede that functionality.
Publication objects describe the structure/configuration of a publication to be created. Publications are published to repositories via tasks, and the configuration of the publication object determines exactly what is published. All of the publications of a project are defined in the PublishingExtension.getPublications() container. Each publication has a unique name within the project.
For the Ivy Publish Plugin to have any effect, an IvyPublication must be added to the set of publications. This publication determines which artifacts are actually published as well as the details included in the associated Ivy module descriptor file. A publication can be configured by adding components, customizing artifacts, and by modifying the generated module descriptor file directly.
The simplest way to publish a Gradle project to an Ivy repository is to specify a SoftwareComponent to publish. The components presently available for publication are:
java— provider: Java PluginGenerated JAR file, dependencies from
runtimeconfigurationweb— provider: War PluginGenerated WAR file, no dependencies
In the following example, artifacts and runtime dependencies are taken from the java component, which is added by the Java Plugin.
Example: Publishing a Java module to Ivy
build.gradle
publications {
ivyJava(IvyPublication) {
from components.java
}
}
It is also possible to explicitly configure artifacts to be included in the publication. Artifacts are commonly supplied as raw files, or as instances of AbstractArchiveTask (e.g. Jar or Zip).
For each custom artifact, it is possible to specify the name, extension, type, classifier and conf values to use for publication. Note that each artifacts must have a unique name/classifier/extension combination.
Configure custom artifacts as follows:
Example: Adding an additional archive artifact to an IvyPublication
build.gradle
task sourceJar(type: Jar) {
from sourceSets.main.java
classifier "source"
}
publishing {
publications {
ivy(IvyPublication) {
from components.java
artifact(sourceJar) {
type "source"
conf "compile"
}
}
}
}
In addition, instances of PublishArtifact can be added to a publication. For example, let’s assume you have a custom rpm task that produces an RPM package of your application and writes it to rpmFile. The following sample demonstrates how to create a PublishArtifact using the artifacts.add() method and add it to a publication:
Example: Adding an additional custom artifact to an IvyPublication
build.gradle
def rpmFile = file("$buildDir/rpms/my-package.rpm") def rpmArtifact = artifacts.add("archives", rpmFile) { type "rpm" builtBy "rpm" } publishing { publications { ivy(IvyPublication) { artifact rpmArtifact } } }
See the IvyPublication class in the API documentation for more detailed information on how artifacts can be customized.
The generated Ivy module descriptor file contains an <info> element that identifies the module. The default identity values are derived from the following:
organisation-Project.getGroup()module-Project.getName()revision-Project.getVersion()status-Project.getStatus()branch- (not set)
Overriding the default identity values is easy: simply specify the organisation, module or revision attributes when configuring the IvyPublication. The status and branch attributes can be set via the descriptor property (see IvyModuleDescriptorSpec). The descriptor property can also be used to add additional custom elements as children of the <info> element.
Example: customizing the publication identity
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
}
}
}
Certain repositories are not able to handle all supported characters. For example, the : character cannot be used as an identifier when publishing to a filesystem-backed repository on Windows.
Gradle will handle any valid Unicode character for organisation, module and revision (as well as artifact name, extension and classifier). The only values that are explicitly prohibited are \, / and any ISO control character. The supplied values are validated early during publication.
At times, the module descriptor file generated from the project information will need to be tweaked before publishing. The Ivy Publish Plugin provides a DSL for that purpose. Please see IvyModuleDescriptorSpec in the DSL Reference for the complete documentation of available properties and methods. The following sample shows how to use the most common ones:
Example: Customizing the module descriptor file
build.gradle
publications {
ivyCustom(IvyPublication) {
descriptor {
license {
name = 'The Apache License, Version 2.0'
url = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
}
author {
name = 'Jane Doe'
url = 'http://example.com/users/jane'
}
description {
text = 'A concise description of my library'
homepage = 'http://www.example.com/library'
}
}
}
}
Sometimes it’s useful to publish multiple modules from your Gradle build, without creating a separate Gradle subproject. An example is publishing a separate API and implementation JAR for your library. With Gradle this is simple:
Example: Publishing multiple modules from a single project
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'
}
}
}
If a project defines multiple publications then Gradle will publish each of these to the defined repositories. Each publication must be given a unique identity as described above.
Publications are published to repositories. The repositories to publish to are defined by the PublishingExtension.getRepositories() container.
Example: Declaring repositories to publish to
build.gradle
repositories {
ivy {
// change to point to your repo, e.g. http://my.org/repo
url "$buildDir/repo"
}
}
The DSL used to declare repositories for publishing is the same DSL that is used to declare repositories for dependencies (RepositoryHandler). However, in the context of Ivy publication only the repositories created by the ivy() methods can be used as publication destinations. You cannot publish an IvyPublication to a Maven repository for example.
The Ivy Publish Plugin automatically creates a PublishToIvyRepository task for each IvyPublication and IvyArtifactRepository combination in the publishing.publications and publishing.repositories containers respectively.
The created task is named publish«PUBNAME»PublicationTo«REPONAME»Repository, which is publishIvyJavaPublicationToIvyRepository for this example. This task is of type PublishToIvyRepository.
Example: Choosing a particular publication to publish
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" } } }
Output of gradle publishIvyJavaPublicationToIvyRepository
> gradle publishIvyJavaPublicationToIvyRepository > Task :generateDescriptorFileForIvyJavaPublication > Task :compileJava NO-SOURCE > Task :processResources NO-SOURCE > Task :classes UP-TO-DATE > Task :jar > Task :publishIvyJavaPublicationToIvyRepository BUILD SUCCESSFUL in 0s 3 actionable tasks: 3 executed
The publish lifecycle task can be used to publish all publications to all applicable repositories. In more concrete terms, executing this task will execute all PublishToIvyRepository tasks in the project. This is usually the most convenient way to perform a publish.
Example: Publishing all publications via the `publish` lifecycle task
Output of gradle publish
> gradle publish > Task :generateDescriptorFileForIvyJavaPublication > Task :compileJava NO-SOURCE > Task :processResources NO-SOURCE > Task :classes UP-TO-DATE > Task :jar > Task :publishIvyJavaPublicationToIvyRepository > Task :publish BUILD SUCCESSFUL in 0s 3 actionable tasks: 3 executed
When you have defined multiple publications or repositories, you often want to control which publications are published to which repositories. For instance, consider the following sample that defines two publications and two repositories:
Example: Adding multiple publications and repositories
build.gradle
publishing {
publications {
binary(IvyPublication) {
from components.java
}
binaryAndSources(IvyPublication) {
from components.java
artifact sourcesJar
}
}
repositories {
// change URLs to point to your repos, e.g. http://my.org/repo
ivy {
name "external"
url "$buildDir/repos/external"
}
ivy {
name "internal"
url "$buildDir/repos/internal"
}
}
}
You may not want build users publishing both types of publications to both repositories, but the plugin automatically generates tasks for all possible combinations. So how do you stop someone from publishing the binaryAndSources publication to the external repository?
You can configure the tasks generated by the Ivy Publish Plugin to be skipped based on certain criteria. The following sample demonstrates how to restrict the binary publication to the external repository and the binaryAndSources publication to the internal repository.
Example: Configuring which artifacts should be published to which repositories
build.gradle
tasks.withType(PublishToIvyRepository) {
onlyIf {
if (repository == publishing.repositories.external)
return publication == publishing.publications.binary
if (repository == publishing.repositories.internal)
return publication == publishing.publications.binaryAndSources
return false
}
}
Output of gradle publish
> gradle publish > Task :generateDescriptorFileForBinaryAndSourcesPublication > Task :compileJava > Task :processResources > Task :classes > Task :jar > Task :sourcesJar > Task :publishBinaryAndSourcesPublicationToExternalRepository SKIPPED > Task :publishBinaryAndSourcesPublicationToInternalRepository > Task :generateDescriptorFileForBinaryPublication > Task :publishBinaryPublicationToExternalRepository > Task :publishBinaryPublicationToInternalRepository SKIPPED > Task :publish BUILD SUCCESSFUL in 0s 8 actionable tasks: 8 executed
Moreover, you may want to define your own shorthand tasks to fit your workflow. The following sample defines two tasks: publishToExternalRepository to publish all publications to the external repository and publishToInternalRepository for the internal repository:
Example: Defining your own shorthand tasks for publishing
build.gradle
task publishToExternalRepository {
group "publishing"
description "Publishes all Ivy publications to Ivy repository 'external'."
dependsOn tasks.withType(PublishToIvyRepository).matching {
it.repository == publishing.repositories.external
}
}
task publishToInternalRepository {
group "publishing"
description "Publishes all Ivy publications to Ivy repository 'internal'."
dependsOn tasks.withType(PublishToIvyRepository).matching {
it.repository == publishing.repositories.internal
}
}
At times it is useful to generate the Ivy module descriptor file (normally ivy.xml) without publishing your module to an Ivy repository. Since descriptor file generation is performed by a separate task, this is very easy to do.
The Ivy Publish Plugin creates one GenerateIvyDescriptor task for each registered IvyPublication, named generateDescriptorFileFor«PUBNAME»Publication, which will be generateDescriptorFileForIvyJavaPublication for the previous example of the ivyJava publication.
You can specify where the generated Ivy file will be located by setting the destination property on the generated task. By default this file is written to build/publications/«PUBNAME»/ivy.xml.
Example: Generating the Ivy module descriptor file
build.gradle
generateDescriptorFileForIvyCustomPublication {
destination = file("$buildDir/generated-ivy.xml")
}
Output of gradle generateDescriptorFileForIvyCustomPublication
> gradle generateDescriptorFileForIvyCustomPublication > Task :generateDescriptorFileForIvyCustomPublication BUILD SUCCESSFUL in 0s 1 actionable task: 1 executed
The following example demonstrates publishing with a multi-project build. Each project publishes a Java component and a configured additional source artifact. The descriptor file is customized to include the project description for each project.
Example: Publishing a Java module
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 "compile"
}
descriptor.description {
text = description
}
}
}
}
}
The result is that the following artifacts will be published for each project:
The Ivy module descriptor file:
ivy-1.0.xml.The primary JAR artifact for the Java component:
project1-1.0.jar.The source JAR artifact that has been explicitly configured:
project1-1.0-source.jar.
When project1 is published, the module descriptor (i.e. the ivy.xml file) that is produced will look like:
Note that «PUBLICATION-TIME-STAMP» in this example Ivy module descriptor will be the timestamp of when the descriptor was generated.
Example: Example generated ivy.xml
output-ivy.xml
<?xml version="1.0" encoding="UTF-8"?> <ivy-module version="2.0" xmlns:m="http://ant.apache.org/ivy/maven"> <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="compile,runtime"/> <conf name="runtime" visibility="public"/> </configurations> <publications> <artifact name="project1" type="source" ext="jar" conf="compile" m:classifier="source"/> <artifact name="project1" type="jar" ext="jar" conf="compile"/> </publications> <dependencies> <dependency org="junit" name="junit" rev="4.12" conf="compile->default"/> <dependency org="org.gradle.sample" name="project2" rev="1.0" conf="compile->default"/> </dependencies> </ivy-module>