// Copyright (C) 2024 Gradle, Inc.
//
// Licensed under the Creative Commons Attribution-Noncommercial-ShareAlike 4.0 International License.;
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

[[publishing_ivy]]
= The Ivy Publish Plugin

The Ivy Publish Plugin provides the ability to publish build artifacts in the http://ant.apache.org/ivy/[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.adoc#one-declaring-dependencies,Declaring Dependencies>>) and other tools that understand the Ivy format. You can learn about the fundamentals of publishing in <<publishing_setup.adoc#publishing_overview,Publishing Overview>>.

[[publishing_ivy:usage]]
== Usage

To use the Ivy Publish Plugin, include the following in your build script:

.Applying the Ivy Publish Plugin
====
include::sample[dir="snippets/ivy-publish/quickstart/kotlin",files="build.gradle.kts[tags=use-plugin]"]
include::sample[dir="snippets/ivy-publish/quickstart/groovy",files="build.gradle[tags=use-plugin]"]
====

The Ivy Publish Plugin uses an extension on the project named `publishing` of type link:{groovyDslPath}/org.gradle.api.publish.PublishingExtension.html[PublishingExtension]. This extension provides a container of named publications and a container of named repositories. The Ivy Publish Plugin works with link:{groovyDslPath}/org.gradle.api.publish.ivy.IvyPublication.html[IvyPublication] publications and link:{groovyDslPath}/org.gradle.api.artifacts.repositories.IvyArtifactRepository.html[IvyArtifactRepository] repositories.

[[publishing_ivy:tasks]]
== Tasks

[[publishing_ivy:descriptor]]
`generateDescriptorFileFor__PubName__Publication` — link:{groovyDslPath}/org.gradle.api.publish.ivy.tasks.GenerateIvyDescriptor.html[GenerateIvyDescriptor]::
Creates an Ivy descriptor file for the publication named _PubName_, populating the known metadata such as project name, project version, and the dependencies. The default location for the descriptor file is _build/publications/$pubName/ivy.xml_.

`publish__PubName__PublicationTo__RepoName__Repository` — link:{groovyDslPath}/org.gradle.api.publish.ivy.tasks.PublishToIvyRepository.html[PublishToIvyRepository]::
Publishes the _PubName_ publication to the repository named _RepoName_. If you have a repository definition without an explicit name, _RepoName_ will be "Ivy".

`publish`::
_Depends on_: All `publish__PubName__PublicationTo__RepoName__Repository` tasks
+
An aggregate task that publishes all defined publications to all defined repositories.

[[publishing_ivy:publications]]
== Publications

This plugin provides <<glossary.adoc#sub:terminology_publication,publications>> of type link:{groovyDslPath}/org.gradle.api.publish.ivy.IvyPublication.html[IvyPublication]. To learn how to define and use publications, see the section on <<publishing_setup.adoc#sec:basic_publishing,basic publishing>>.

There are four main things you can configure in an Ivy publication:

 * A <<glossary.adoc#sub:terminology_component,component>> — via link:{groovyDslPath}/org.gradle.api.publish.ivy.IvyPublication.html#org.gradle.api.publish.ivy.IvyPublication:from(org.gradle.api.component.SoftwareComponent)[IvyPublication.from(org.gradle.api.component.SoftwareComponent)].
 * <<publishing_customization.adoc#sec:publishing_custom_artifacts_to_maven,Custom artifacts>> — via the link:{groovyDslPath}/org.gradle.api.publish.ivy.IvyPublication.html#org.gradle.api.publish.ivy.IvyPublication:artifact(java.lang.Object)[IvyPublication.artifact(java.lang.Object)] method. See link:{groovyDslPath}/org.gradle.api.publish.ivy.IvyArtifact.html[IvyArtifact] for the available configuration options for custom Ivy artifacts.
 * Standard metadata like `module`, `organisation` and `revision`.
 * Other contents of the module descriptor — via link:{groovyDslPath}/org.gradle.api.publish.ivy.IvyPublication.html#org.gradle.api.publish.ivy.IvyPublication:descriptor(org.gradle.api.Action)[IvyPublication.descriptor(org.gradle.api.Action)].

You can see all of these in action in the <<#publishing_ivy:example,complete publishing example>>. The API documentation for `IvyPublication` has additional code samples.

[[sec:identity_values_for_the_published_project]]
=== Identity values for the published project

The generated Ivy module descriptor file contains an `&lt;info&gt;` element that identifies the module. The default identity values are derived from the following:

* `organisation` - link:{groovyDslPath}/org.gradle.api.Project.html#org.gradle.api.Project:group[Project.getGroup()]
* `module` - link:{groovyDslPath}/org.gradle.api.Project.html#org.gradle.api.Project:name[Project.getName()]
* `revision` - link:{groovyDslPath}/org.gradle.api.Project.html#org.gradle.api.Project:version[Project.getVersion()]
* `status` - link:{groovyDslPath}/org.gradle.api.Project.html#org.gradle.api.Project:status[Project.getStatus()]
* `branch` - (not set)

Overriding the default identity values is easy: simply specify the `organisation`, `module` or `revision` properties when configuring the link:{groovyDslPath}/org.gradle.api.publish.ivy.IvyPublication.html[IvyPublication]. `status` and `branch` can be set via the `descriptor` property — see link:{groovyDslPath}/org.gradle.api.publish.ivy.IvyModuleDescriptorSpec.html[IvyModuleDescriptorSpec].

The `descriptor` property can also be used to add additional custom elements as children of the `&lt;info&gt;` element, like so:

.customizing the publication identity
====
include::sample[dir="snippets/ivy-publish/customize-identity/kotlin",files="build.gradle.kts[tags=customize-identity]"]
include::sample[dir="snippets/ivy-publish/customize-identity/groovy",files="build.gradle[tags=customize-identity]"]
====

TIP: 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 the artifact's `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.

[[sec:modifying_the_generated_module_descriptor]]
=== Customizing the generated module descriptor

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 link:{groovyDslPath}/org.gradle.api.publish.ivy.IvyModuleDescriptorSpec.html[IvyModuleDescriptorSpec] in the DSL Reference for the complete documentation of available properties and methods.

The following sample shows how to use the most common aspects of the DSL:

.Customizing the module descriptor file
====
include::sample[dir="snippets/ivy-publish/descriptor-customization/kotlin",files="build.gradle.kts[tags=customize-descriptor]"]
include::sample[dir="snippets/ivy-publish/descriptor-customization/groovy",files="build.gradle[tags=customize-descriptor]"]
====

In this example we are simply adding a 'description' element to the generated Ivy dependency descriptor, but this hook allows you to modify any aspect of the generated descriptor. For example, you could replace the version range for a dependency with the actual version used to produce the build.

You can also add arbitrary XML to the descriptor file via link:{groovyDslPath}/org.gradle.api.publish.ivy.IvyModuleDescriptorSpec.html#org.gradle.api.publish.ivy.IvyModuleDescriptorSpec:withXml(org.gradle.api.Action)[IvyModuleDescriptorSpec.withXml(org.gradle.api.Action)], but you cannot use it to modify any part of the module identifier (organisation, module, revision).

CAUTION: It is possible to modify the descriptor in such a way that it is no longer a valid Ivy module descriptor, so care must be taken when using this feature.

[[publishing_ivy:resolved_dependencies]]
=== Customizing dependencies versions

Two strategies are supported for publishing dependencies:

Declared versions (default)::
This strategy publishes the versions that are defined by the build script author with the dependency declarations in the `dependencies` block.
Any other kind of processing, for example through <<resolution_rules.adoc#using-resolution-rules,a rule changing the resolved version>>, will not be taken into account for the publication.

Resolved versions::
This strategy publishes the versions that were resolved during the build, possibly by applying resolution rules and automatic conflict resolution.
This has the advantage that the published versions correspond to the ones the published artifact was tested against.

Example use cases for resolved versions:

* A project uses dynamic versions for dependencies but prefers exposing the resolved version for a given release to its consumers.
* In combination with <<dependency_locking.adoc#locking-versions,dependency locking>>, you want to publish the locked versions.
* A project leverages the rich versions constraints of Gradle, which have a lossy conversion to Ivy.
Instead of relying on the conversion, it publishes the resolved versions.

This is done by using the `versionMapping` DSL method which allows to configure the link:{javadocPath}/org/gradle/api/publish/VersionMappingStrategy.html[VersionMappingStrategy]:

.Using resolved versions
====
include::sample[dir="snippets/ivy-publish/descriptor-customization/kotlin",files="build.gradle.kts[tags=versions-resolved]"]
include::sample[dir="snippets/ivy-publish/descriptor-customization/groovy",files="build.gradle[tags=versions-resolved]"]
====

In the example above, Gradle will use the versions resolved on the `runtimeClasspath` for dependencies declared in `api`, which are mapped to the `compile` configuration of Ivy.
Gradle will also use the versions resolved on the `runtimeClasspath` for dependencies declared in `implementation`, which are mapped to the `runtime` configuration of Ivy.
`fromResolutionResult()` indicates that Gradle should use the default classpath of a variant and `runtimeClasspath` is the default classpath of `java-runtime`.

[[publishing_ivy:repositories]]
== Repositories

This plugin provides <<glossary.adoc#sub:terminology_repository,repositories>> of type link:{groovyDslPath}/org.gradle.api.artifacts.repositories.IvyArtifactRepository.html[IvyArtifactRepository]. To learn how to define and use repositories for publishing, see the section on <<publishing_setup.adoc#sec:basic_publishing,basic publishing>>.

Here's a simple example of defining a publishing repository:

.Declaring repositories to publish to
====
include::sample[dir="snippets/ivy-publish/quickstart/kotlin",files="build.gradle.kts[tags=repositories]"]
include::sample[dir="snippets/ivy-publish/quickstart/groovy",files="build.gradle[tags=repositories]"]
====

The two main things you will want to configure are the repository's:

 * URL (required)
 * Name (optional)

You can define multiple repositories as long as they have unique names within the build script. You may also declare one (and only one) repository without a name. That repository will take on an implicit name of "Ivy".

You can also configure any authentication details that are required to connect to the repository. See link:{groovyDslPath}/org.gradle.api.artifacts.repositories.IvyArtifactRepository.html[IvyArtifactRepository] for more details.


[[publishing_ivy:example]]
== Complete example

The following example demonstrates publishing with a multi-project build.
Each project publishes a Java component configured to also build and publish Javadoc and source code artifacts.
The descriptor file is customized to include the project description for each project.

.Publishing a Java module
====
include::sample[dir="snippets/ivy-publish/java-multi-project/kotlin",files="settings.gradle.kts[];buildSrc/build.gradle.kts[];buildSrc/src/main/kotlin/myproject.publishing-conventions.gradle.kts[];project1/build.gradle.kts[];project2/build.gradle.kts[]"]
include::sample[dir="snippets/ivy-publish/java-multi-project/groovy",files="settings.gradle[];buildSrc/build.gradle[];buildSrc/src/main/groovy/myproject.publishing-conventions.gradle[];project1/build.gradle[];project2/build.gradle[]"]
====

The result is that the following artifacts will be published for each project:

* The Gradle Module Metadata file: `project1-1.0.module`.
* The Ivy module metadata file: `ivy-1.0.xml`.
* The primary JAR artifact for the Java component: `project1-1.0.jar`.
* The Javadoc and sources JAR artifacts of the Java component (because we configured `withJavadocJar()` and `withSourcesJar()`): `project1-1.0-javadoc.jar`, `project1-1.0-source.jar`.
