<commit_before>
* Has to be able to scale down.
* Adapting between specific worlds.
* Detangle incoming and outgoing.

There are many shortcomings with the existing model and DSL for publishing. This specification describes a plan to implement a new publication model and DSL.

The basic strategy taken here is to incrementally grow the new model along-side the existing model.

Note: this spec is very much a work in progress.

# Use cases

## I want my consumers to use the same dependency versions as I used to build and test my artifacts

AKA 'Ivy deliver'. In this instance, dependency declarations in the generated descriptors should use the resolved versions that were used to build the artifacts.

## I want to customise the Ivy or Maven meta-data for a publication

* Use a (groupId, artifactId, version) identifier that is different to defaults.
* Add some custom Ivy attributes for the module or a configuration or an artifact.
* Mark some dependencies as optional in the pom.xml.
* Map some runtime dependencies to provided scope in the pom.xml.

## I want to publish multiple Ivy or Maven modules from my project

* I have separate API and implementation Jars that I want to publish as separate Maven modules.
* I want to publish test fixtures as a separate module.
* I produce Groovy 1.8 and Groovy 2.0 variants that I want to publish as separate modules.

## I want to customise a publication based in its destination

* I want to map the 32-bit and 64-bit variants of a native library to `mylib-x86-1.2.dll` and `mylib-amd64-1.2.dll` when publishing to an Ivy repository,
  and to `mylib-1.2-x86.dll` and `mylib-1.2-amd64.dll` when publishing to a Maven repository.
* I want a consumer in a different build to use the JAR file, and a consumer in the same build to use the compiled classes dir.

## I want to generate the meta-data descriptor for a publication without publishing

* To smoke test the generated meta-data before publishing.

This list is not complete. There are more use cases to come.

# User visible changes

The end goal is to introduce 2 concepts:

* A software _component_.
* A _publication_.

Both of these are defined in the [dependency model spec](dependency-model.md).

A component is a logical description of a piece of software, such as a Java library or native executable or report.

A publication is a mapping of that component to a set of artifacts and meta-data, ready to be used by some consumer project. A publication is a strongly-typed
model element. There will be 3 types of publication:

* An Ivy publication, for publishing to an Ivy repository.
* A Maven publication, for publishing to a Maven repository.
* A local publication, for consumption within the same build.

The following sections present a series of steps that allow us to evolve towards this model.

At the end of the process described below, a project will have-a set of publications. Each publication will be fully and independently configurable.
The existing Maven deployer and Maven installer DSL will be discontinued, and the existing Configuration DSL will be split into incoming dependencies
and outgoing publications.

Note: for the following discussion, all changes are `@Incubating` unless specified otherwise.

## Customising Ivy and Maven descriptor XML

An initial step will provide some capability to modify the generated `ivy.xml` and `pom.xml` files before publication.

1. Introduce a `Publication` interface. Probably make `Publication` a `Named` thing.
2. Add a `Publication` container to the project. At this stage, this container will be _read-only_.
3. Add `IvyPublication` interface and `IvyDependencyDescriptor` interface.
    * An `IvyPublication` has-a property called `ivy` of type `IvyDependencyDescriptor`.
4. Add an `ivy-publish` plugin that adds a single `IvyPublication` instance to the container. All Ivy repository instances used for upload will share the same `IvyPublication` instance.
5. Add `IvyDependencyDescriptor.withXml()` methods and wire this up to `ivy.xml` generation.
6. Change the defaults used for Ivy publication when the `ivy-publish` plugin is applied:
    * `organisation` == `project.group`
    * `module` == `project.name` (_not_ `archivesBaseName`)
    * `revision` == `project.version`
    * `status` == `project.status`
    * Only dependency declarations from public configurations are included, and no configuration extension is used.
    * Only artifacts from public configurations are included.
7. Add `MavenPublication` interface and `MavenPom` interface.
    * A `MavenPublication` has-a property called `pom` of type `Pom`.
8. Add a `maven-publish` plugin. When both the `maven-publish` and `maven` plugins are applied, then the `mavenInstaller()` and `mavenDeployer()` methods
   add a `MavenPublication` instance to the container for each `MavenPom` instance that the installers and deployers create (ie one for each filter).
9. Add `Pom.withXml()` methods. These can delegate to the associated `MavenPom.withXml()` methods.

To customise the `pom.xml`:

    apply plugin: 'maven'
    apply plugin: 'maven-publish'

    uploadArchives {
        repositories { mavenDeployer { ... } }
    }

    publications.withType(MavenPublication) {<commit_msg>Added an extra item to the first story.<commit_after>
* Has to be able to scale down.
* Adapting between specific worlds.
* Detangle incoming and outgoing.

There are many shortcomings with the existing model and DSL for publishing. This specification describes a plan to implement a new publication model and DSL.

The basic strategy taken here is to incrementally grow the new model along-side the existing model.

Note: this spec is very much a work in progress.

# Use cases

## I want my consumers to use the same dependency versions as I used to build and test my artifacts

AKA 'Ivy deliver'. In this instance, dependency declarations in the generated descriptors should use the resolved versions that were used to build the artifacts.

## I want to customise the Ivy or Maven meta-data for a publication

* Use a (groupId, artifactId, version) identifier that is different to defaults.
* Add some custom Ivy attributes for the module or a configuration or an artifact.
* Mark some dependencies as optional in the pom.xml.
* Map some runtime dependencies to provided scope in the pom.xml.

## I want to publish multiple Ivy or Maven modules from my project

* I have separate API and implementation Jars that I want to publish as separate Maven modules.
* I want to publish test fixtures as a separate module.
* I produce Groovy 1.8 and Groovy 2.0 variants that I want to publish as separate modules.

## I want to customise a publication based in its destination

* I want to map the 32-bit and 64-bit variants of a native library to `mylib-x86-1.2.dll` and `mylib-amd64-1.2.dll` when publishing to an Ivy repository,
  and to `mylib-1.2-x86.dll` and `mylib-1.2-amd64.dll` when publishing to a Maven repository.
* I want a consumer in a different build to use the JAR file, and a consumer in the same build to use the compiled classes dir.

## I want to generate the meta-data descriptor for a publication without publishing

* To smoke test the generated meta-data before publishing.

This list is not complete. There are more use cases to come.

# User visible changes

The end goal is to introduce 2 concepts:

* A software _component_.
* A _publication_.

Both of these are defined in the [dependency model spec](dependency-model.md).

A component is a logical description of a piece of software, such as a Java library or native executable or report.

A publication is a mapping of that component to a set of artifacts and meta-data, ready to be used by some consumer project. A publication is a strongly-typed
model element. There will be 3 types of publication:

* An Ivy publication, for publishing to an Ivy repository.
* A Maven publication, for publishing to a Maven repository.
* A local publication, for consumption within the same build.

The following sections present a series of steps that allow us to evolve towards this model.

At the end of the process described below, a project will have-a set of publications. Each publication will be fully and independently configurable.
The existing Maven deployer and Maven installer DSL will be discontinued, and the existing Configuration DSL will be split into incoming dependencies
and outgoing publications.

Note: for the following discussion, all changes are `@Incubating` unless specified otherwise.

## Customising Ivy and Maven descriptor XML

An initial step will provide some capability to modify the generated `ivy.xml` and `pom.xml` files before publication.

1. Introduce a `Publication` interface. Probably make `Publication` a `Named` thing.
2. Add a `Publication` container to the project. At this stage, this container will be _read-only_.
3. Add `IvyPublication` interface and `IvyDependencyDescriptor` interface.
    * An `IvyPublication` has-a property called `ivy` of type `IvyDependencyDescriptor`.
4. Add an `ivy-publish` plugin that adds a single `IvyPublication` instance to the container. All Ivy repository instances used for upload will share the same `IvyPublication` instance.
5. Add `IvyDependencyDescriptor.withXml()` methods and wire this up to `ivy.xml` generation.
6. Change the defaults used for Ivy publication when the `ivy-publish` plugin is applied:
    * `organisation` == `project.group`
    * `module` == `project.name` (_not_ `archivesBaseName`)
    * `revision` == `project.version`
    * `status` == `project.status`
    * Only dependency declarations from public configurations are included, and no configuration extension is used.
    * Only artifacts from public configurations are included.
7. Add `MavenPublication` interface and `MavenPom` interface.
    * A `MavenPublication` has-a property called `pom` of type `Pom`.
8. Add a `maven-publish` plugin. When both the `maven-publish` and `maven` plugins are applied, then the `mavenInstaller()` and `mavenDeployer()` methods
   add a `MavenPublication` instance to the container for each `MavenPom` instance that the installers and deployers create (ie one for each filter).
9. Add `Pom.withXml()` methods. These can delegate to the associated `MavenPom.withXml()` methods.
10. Deprecate `PomFilterContainer.setMavenPom()` and `PomFilter.setPomTemplate()`. These should fail with an exception when the `maven-publish` plugin has
  been applied.

To customise the `pom.xml`:

    apply plugin: 'maven'
    apply plugin: 'maven-publish'

    uploadArchives {
        repositories { mavenDeployer { ... } }
    }

    publications.withType(MavenPublication) {
{'fraction_non_alphanumeric': 0.061450417487569194, 'fraction_numerical': 0.006754855052068675, 'mean_word_length': 4.233186057928326, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 12}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '949788', 'n_tokens_mistral': 2859, 'n_tokens_neox': 2711, 'n_words': 1511}