{"id":13483798,"url":"https://github.com/gradle-nexus/publish-plugin","last_synced_at":"2025-03-27T15:30:33.995Z","repository":{"id":41518063,"uuid":"208000474","full_name":"gradle-nexus/publish-plugin","owner":"gradle-nexus","description":"Gradle plugin for publishing to Nexus repositories","archived":false,"fork":false,"pushed_at":"2025-03-14T23:48:53.000Z","size":1070,"stargazers_count":414,"open_issues_count":76,"forks_count":30,"subscribers_count":10,"default_branch":"master","last_synced_at":"2025-03-15T00:28:38.580Z","etag":null,"topics":["gradle","nexus-repository-manager","publishing"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gradle-nexus.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-09-12T08:22:47.000Z","updated_at":"2025-03-14T23:48:56.000Z","dependencies_parsed_at":"2023-12-01T23:23:45.582Z","dependency_job_id":"38a9261c-484f-457c-ba1c-ab01e99f1d6f","html_url":"https://github.com/gradle-nexus/publish-plugin","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gradle-nexus%2Fpublish-plugin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gradle-nexus%2Fpublish-plugin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gradle-nexus%2Fpublish-plugin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gradle-nexus%2Fpublish-plugin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gradle-nexus","download_url":"https://codeload.github.com/gradle-nexus/publish-plugin/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245871682,"owners_count":20686246,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["gradle","nexus-repository-manager","publishing"],"created_at":"2024-07-31T17:01:15.386Z","updated_at":"2025-03-27T15:30:33.377Z","avatar_url":"https://github.com/gradle-nexus.png","language":"Kotlin","funding_links":[],"categories":["Kotlin"],"sub_categories":[],"readme":"# Gradle Nexus Publish Plugin\n\n[![CI Status](https://github.com/gradle-nexus/publish-plugin/workflows/CI/badge.svg)](https://github.com/gradle-nexus/publish-plugin/actions?workflow=CI) [![Gradle Plugin Portal](https://img.shields.io/maven-metadata/v/https/plugins.gradle.org/m2/io.github.gradle-nexus/publish-plugin/maven-metadata.xml.svg?label=Gradle%20Plugin%20Portal)](https://plugins.gradle.org/plugin/io.github.gradle-nexus.publish-plugin)\n\nThis Gradle plugin is a turn-key solution for publishing to Nexus. You can use it to publish your artifacts to any Nexus Repository Manager 2.x instance (internal or public). It is great for publishing your open source to Sonatype, and then to [Maven Central][maven-central], in a fully automated fashion.\n\nVanilla Gradle is great, but it cannot fully automate publications to Nexus. This plugin enables isolation of staging repositories so that you can reliably publish from CI, and each publication uses a brand new, explicitly created staging repo ([more](https://github.com/gradle-nexus/publish-plugin/issues/63)). Moreover, the plugin provides tasks to close and release staging repositories, covering the whole releasing process to Maven Central.\n\nThis plugin is intended as a replacement of the [Gradle Nexus Staging Plugin](https://github.com/Codearte/gradle-nexus-staging-plugin/) and [Nexus Publish Plugin](https://github.com/marcphilipp/nexus-publish-plugin) duo. See a dedicated [migration guide](https://github.com/gradle-nexus/publish-plugin/wiki/Migration-from-gradle_nexus_staging-plugin---nexus_publish-plugin-duo).\n\n## Usage\n\n### Applying the plugin\n\nThe plugin must be applied to the root project and requires Gradle 6.2 or later. It is important to\nset the group and the version to the root project, so the plugin can detect if it is a snapshot\nversion or not in order to select the correct repository where artifacts will be published.\n\n```groovy\nplugins {\n    id(\"io.github.gradle-nexus.publish-plugin\") version \"«version»\"\n}\n\ngroup = \"com.example.library\"\nversion = \"1.0.0\"\n```\n\n#### Java compatibility\n\nAs of version 2.x, support for JDK \u003c11 is [deprecated](https://github.com/gradle-nexus/publish-plugin/issues/171). The JDK taget compatibility is still set to 8, however, it is encouraged to use the latest possible Java version (e.g. 21+). As being deprecated, support for JDK \u003c11 might be dropped in a future minor plugin version (i.e. 2.x).\n\n### Publishing to Maven Central via Sonatype OSSRH\n\nIn order to publish to Maven Central (aka the Central Repository or just Central) via Sonatype's OSSRH Nexus, you simply need to add the `sonatype()` repository like in the example below. Its `nexusUrl` and `snapshotRepositoryUrl` values are pre-configured.\n\n```groovy\nnexusPublishing {\n    repositories {\n        sonatype()\n    }\n}\n```\n\n**Important**. Users registered in Sonatype after [24 February 2021](https://central.sonatype.org/news/20210223_new-users-on-s01/) need to customize the following URLs:\n\n```groovy\nnexusPublishing {\n    repositories {\n        sonatype {  //only for users registered in Sonatype after 24 Feb 2021\n            nexusUrl.set(uri(\"https://s01.oss.sonatype.org/service/local/\"))\n            snapshotRepositoryUrl.set(uri(\"https://s01.oss.sonatype.org/content/repositories/snapshots/\"))\n        }\n    }\n}\n```\n(if unsure check the server address in a corresponding ticket for your project in Sonatype's Jira)\n\nIn addition, for both groups of users, you need to set your Nexus credentials. To increase security, it is advised to use the [user token's username and password pair](https://blog.solidsoft.pl/2015/09/08/deploy-to-maven-central-using-api-key-aka-auth-token/) (instead of regular username and password). Those values should be set as the `sonatypeUsername` and `sonatypePassword` project properties, e.g. in `~/.gradle/gradle.properties` or via the `ORG_GRADLE_PROJECT_sonatypeUsername` and `ORG_GRADLE_PROJECT_sonatypePassword` environment variables.\n\nAlternatively, you can configure credentials in the `sonatype` block:\n\n```groovy\nnexusPublishing {\n    repositories {\n        sonatype {\n            username = \"your-user-token-username\"\n            password = \"your-user-token-password\"\n        }\n    }\n}\n```\n\n#### Configure [Signing](https://docs.gradle.org/current/userguide/signing_plugin.html#sec:signing_publications) ####\n\nAdd the signing plugin:\n```kotlin\nplugins {\n    // ...\n    signing\n}\n```\nthen configure:\n```kotlin\nsigning {\n    sign(publishing.publications[\"mavenJava\"])\n}\n```\n\n#### Publishing with Ivy ####\n\nThere are cases where it may be necessary to use the `ivy-publish` plugin instead of `maven-publish`.\nFor example, when publishing Sbt plugins the directory structure needs to be customized which is only possible with Gradle's `IvyArtifactRepository`.\n\nIn such cases, you need to apply the `ivy-publish` plugin and configure the `publicationType` fore each `NexusRepository`, that should be ivy compatible, to `IVY` (default is `MAVEN`).\n\nIn case of Ivy publishing, because of compatibility with Sonatype the nexus repository layout will be used by default\n\n```groovy\nnexusPublishing {\n    respositories {\n        ivyRepository {\n            publicationType = io.github.gradlenexus.publishplugin.NexusRepository.PublicationType.IVY\n        }\n    }\n}\n```\n\nOr use the kotlin DSL:\n\n```kotlin\nnexusPublishing {\n    respositories {\n        register(\"ivyRepository\") {\n            publicationType.set(io.github.gradlenexus.publishplugin.NexusRepository.PublicationType.IVY)\n        }\n    }    \n}\n```\n\n##### Using Ivy repositories with different artifact patterns ####\n\nIn case of ivy it's possible to override the default artifact pattern that is used, which is the Maven pattern due to compatibility reasons with sonatype\n\nTo change the pattern of artifacts and ivy files configure the `ivyPatternLayout` on each repository that should be used with this layout with:\n\n```groovy\nnexusPublishing {\n    respositories {\n        ivyRepository {\n            ivyPatternLayout {\n                artifact \"[organisation]/[module]_foo/[revision]/[artifact]-[revision](-[classifier])(.[ext])\"\n                m2compatible = true\n            }\n        }\n    }\n}\n```\n\nOr use the kotlin DSL:\n\n```kotlin\nnexusPublishing {\n    respositories {\n        register(\"ivyRepository\") {\n            ivyPatternLayout {\n                ivyPatternLayout {\n                    artifact(\"[organisation]/[module]_foo/[revision]/[artifact]-[revision](-[classifier])(.[ext])\")\n                    m2compatible = true\n                }\n            }\n        }\n    }\n}\n```\n\n#### Add Metadata ####\n\nSee the [Maven publishing page in Gradle documentation](https://docs.gradle.org/current/userguide/publishing_maven.html#publishing_maven:publications) for what these mean, default values, and how to override coordinates (`groupId:artifactId:version`).\n\n```kotlin\npublishing {\n    publications {\n        create\u003cMavenPublication\u003e(\"mavenJava\") {\n            from(components[\"java\"])\n\n            pom {\n                name.set(\"\u003c\u003cComponent Name\u003e\u003e\")\n                description.set(\"\u003c\u003cComponent Description\u003e\u003e\")\n                url.set(\"\u003c\u003cComponent URL\u003e\u003e\")\n                licenses {\n                    license {\n                        name.set(\"\u003c\u003cLicense Name\u003e\u003e\")\n                        url.set(\"\u003c\u003cLicense URL\u003e\u003e\")\n                    }\n                }\n                developers {\n                    developer {\n                        id.set(\"\u003c\u003cDeveloper ID\u003e\u003e\")\n                        name.set(\"\u003c\u003cDeveloper Name\u003e\u003e\")\n                        email.set(\"\u003c\u003cDeveloper Email\u003e\u003e\")\n                    }\n                }\n                scm {\n                    connection.set(\"\u003c\u003cSCM Connection URL\u003e\u003e\")\n                    developerConnection.set(\"\u003c\u003cSCM Dev Connection URL\u003e\u003e\")\n                    url.set(\"\u003c\u003cSource URL\u003e\u003e\")\n                }\n            }\n        }\n    }\n}\n```\n\nFinally, call `publishToSonatype closeAndReleaseSonatypeStagingRepository` to publish all publications to Sonatype's OSSRH Nexus and subsequently close and release the corresponding staging repository, effectively making the artifacts available in Maven Central (usually after a few minutes).\n\nPlease bear in mind that - especially on the initial project publishing to Maven Central - it might be wise to call just `publishToSonatype closeSonatypeStagingRepository` and manually verify that the artifacts placed in the closed staging repository in Nexus looks ok. After that, the staging repository might be dropped (if needed) or manually released from the Nexus UI.  \n\n#### Publishing and closing in different Gradle invocations\n\nYou might want to publish and close in different Gradle invocations. For example, you might want to publish from CI\nand close and release from your local machine.\nAn alternative use case is to publish and close the repository and let others review and preview the publication before\nthe release.\n\nThe use case is possible by using `find${repository.name.capitalize()}StagingRepository` (e.g. `findSonatypeStagingRepository`) task.\nBy default, `initialize${repository.name.capitalize()}StagingRepository` task adds a description to the repository which defaults to\n`$group:$module:$version` of the root project, so the repository can be found later using the same description.\n\nThe description can be customized via:\n* `io.github.gradlenexus.publishplugin.NexusPublishExtension.getRepositoryDescription` property (default: `$group:$module:$version` of the root project)\n* `io.github.gradlenexus.publishplugin.InitializeNexusStagingRepository.repositoryDescription` property\n* `io.github.gradlenexus.publishplugin.FindStagingRepository.descriptionRegex` property (regex, default: `\"\\\\b\" + Regex.escape(repositoryDescription) + \"(\\\\s|$)\"`)\n\nSo the steps to publish and release in different Gradle invocations are:\n1. Publish the artifacts to the staging repository: `./gradlew publishToSonatype`\n2. Close the staging repository: `./gradlew findSonatypeStagingRepository closeSonatypeStagingRepository`\n3. Release the staging repository: `./gradlew findSonatypeStagingRepository releaseSonatypeStagingRepository`\n\n(in the above example, steps 1 and 2 could be also combined into `./gradlew publishToSonatype closeSonatypeStagingRepository`, to make only the releasing done in a separate step)\n\n### Summary Tasks\n\nIf you declare multiple repositories, you get a separate set of tasks for each of the repositories.\nIf you for example declared the repositories `sonatype` and `otherNexus`, you get these tasks:\n- `closeSonatypeStagingRepository`\n- `closeOtherNexusStagingRepository`\n- `releaseSonatypeStagingRepository`\n- `releaseOtherNexusStagingRepository`\n- `closeAndReleaseSonatypeStagingRepository`\n- `closeAndReleaseOtherNexusStagingRepository`\n\nFor convenience there are also summary tasks generated, that group the tasks for the different repositories, which are\n- `closeStagingRepositories`\n- `releaseStagingRepositories`\n- `closeAndReleaseStagingRepositories`\n\nIn the typical use-case, which is only one repository for publishing to Maven Central, these tasks still are useful,\nespecially if you are using Kotlin DSL build scripts, because those summary tasks are always added, independent of\ndeclared repositories. Due to that there are type-safe accessors generated that can be used conveniently for task dependencies.\n\n### Full example\n\n#### Groovy DSL\n\n```groovy\nplugins {\n    id \"java-library\"\n    id \"maven-publish\"\n    id \"signing\"\n    id \"io.github.gradle-nexus.publish-plugin\" version \"«version»\"\n}\n\npublishing {\n    publications {\n        mavenJava(MavenPublication) {\n            from(components.java)\n\n            pom {\n                name = \"\u003c\u003cComponent Name\u003e\u003e\"\n                description = \"\u003c\u003cComponent Description\u003e\u003e\"\n                url = \"\u003c\u003cComponent URL\u003e\u003e\"\n                licenses {\n                    license {\n                        name = \"\u003c\u003cLicense Name\u003e\u003e\"\n                        url = \"\u003c\u003cLicense URL\u003e\u003e\"\n                    }\n                }\n                developers {\n                    developer {\n                        id = \"\u003c\u003cDeveloper ID\u003e\u003e\"\n                        name = \"\u003c\u003cDeveloper Name\u003e\u003e\"\n                        email = \"\u003c\u003cDeveloper Email\u003e\u003e\"\n                    }\n                }\n                scm {\n                    connection = \"\u003c\u003cSCM Connection URL\u003e\u003e\"\n                    developerConnection = \"\u003c\u003cSCM Dev Connection URL\u003e\u003e\"\n                    url = \"\u003c\u003cSource URL\u003e\u003e\"\n                }\n            }\n        }\n    }\n}\n\nnexusPublishing {\n    repositories {\n        myNexus {\n            nexusUrl = uri(\"https://your-server.com/staging\")\n            snapshotRepositoryUrl = uri(\"https://your-server.com/snapshots\")\n            username = \"your-username\" // defaults to project.properties[\"myNexusUsername\"]\n            password = \"your-password\" // defaults to project.properties[\"myNexusPassword\"]\n        }\n    }\n}\n\nsigning {\n    sign publishing.publications.mavenJava\n}\n```\n\n#### Kotlin DSL\n\n```kotlin\nplugins {\n    `java-library`\n    `maven-publish`\n    signing\n    id(\"io.github.gradle-nexus.publish-plugin\") version \"«version»\"\n}\n\npublishing {\n    publications {\n        create\u003cMavenPublication\u003e(\"mavenJava\") {\n            from(components[\"java\"])\n\n            pom {\n                name.set(\"\u003c\u003cComponent Name\u003e\u003e\")\n                description.set(\"\u003c\u003cComponent Description\u003e\u003e\")\n                url.set(\"\u003c\u003cComponent URL\u003e\u003e\")\n                licenses {\n                    license {\n                        name.set(\"\u003c\u003cLicense Name\u003e\u003e\")\n                        url.set(\"\u003c\u003cLicense URL\u003e\u003e\")\n                    }\n                }\n                developers {\n                    developer {\n                        id.set(\"\u003c\u003cDeveloper ID\u003e\u003e\")\n                        name.set(\"\u003c\u003cDeveloper Name\u003e\u003e\")\n                        email.set(\"\u003c\u003cDeveloper Email\u003e\u003e\")\n                    }\n                }\n                scm {\n                    connection.set(\"\u003c\u003cSCM Connection URL\u003e\u003e\")\n                    developerConnection.set(\"\u003c\u003cSCM Dev Connection URL\u003e\u003e\")\n                    url.set(\"\u003c\u003cSource URL\u003e\u003e\")\n                }\n            }\n        }\n    }\n}\n\nnexusPublishing {\n    repositories {\n        create(\"myNexus\") {\n            nexusUrl.set(uri(\"https://your-server.com/staging\"))\n            snapshotRepositoryUrl.set(uri(\"https://your-server.com/snapshots\"))\n            username.set(\"your-username\") // defaults to project.properties[\"myNexusUsername\"]\n            password.set(\"your-password\") // defaults to project.properties[\"myNexusPassword\"]\n        }\n    }\n}\n\nsigning {\n    sign(publishing.publications[\"mavenJava\"])\n}\n```\n\n### HTTP Timeouts\n\nYou can configure the `connectTimeout` and `clientTimeout` properties on the `nexusPublishing` extension to set the connect and read/write timeouts (both default to 5 minutes). Good luck!\n\n### Retries for state transitions\n\nWhen closing or releasing a staging repository the plugin first initiates the transition and then retries a configurable number of times with a configurable delay after each attempt.\nBoth can be configured like this:\n\n#### Groovy DSL\n\n```gradle\nimport java.time.Duration\n\nnexusPublishing {\n    transitionCheckOptions {\n        maxRetries = 100\n        delayBetween = Duration.ofSeconds(5)\n    }\n}\n```\n\n#### Kotlin DSL\n\n```gradle\nimport java.time.Duration\n\nnexusPublishing {\n    transitionCheckOptions {\n        maxRetries.set(100)\n        delayBetween.set(Duration.ofSeconds(5))\n    }\n}\n```\n\n- `maxRetries` default value is 60.\n- `delayBetween` default value is 10 seconds.\n\n### Compatibility\n\n| Nexus Version                                      | Compatible?        |\n|----------------------------------------------------|--------------------|\n| Sonatype [Maven Central Repository][maven-central] | Yes                |\n| Sonatype Nexus Repository Manager 2.x              | Yes                |\n| Sonatype Nexus Repository Manager 3.x              | [No][nexus-compat] / https://github.com/gradle-nexus/publish-plugin/issues/320 |\n\n### Troubleshooting\n\nLog into your staging repository account. On the left side, expand \"Build Promotion\", then click \"Staging Repositories\".\nHere, you should see your newly created repositories. You can click on one of them, then select the \"Activity\" tab to\nsee any errors that have occurred.\n\n---\n\n## Behind the scenes\n\nThe plugin does the following:\n\n- configure a Maven artifact repository for each repository defined in the `nexusPublishing { repositories { ... } }` block in each subproject that applies the `maven-publish` or the `ivy-publish` plugin\n- creates a `retrieve{repository.name.capitalize()}StagingProfile` task that retrieves the staging profile id from the remote Nexus repository. This is a diagnostic task to enable setting the configuration property `stagingProfileId` in  `nexusPublishing { repositories { myRepository { ... } } }`. Specifying the configuration property rather than relying on the API call is considered a performance optimization.  \n- create a `initialize${repository.name.capitalize()}StagingRepository` task that starts a new staging repository in case the project's version does not end with `-SNAPSHOT` (customizable via the `useStaging` property) and sets the URL of the corresponding Maven artifact repository accordingly. In case of a multi-project build, all subprojects with the same `nexusUrl` will use the same staging repository.\n- make all publishing tasks for each configured repository depend on the `initialize${repository.name.capitalize()}StagingRepository` task\n- create a `publishTo${repository.name.capitalize()}` lifecycle task that depends on all publishing tasks for the corresponding Maven artifact repository\n- create `close${repository.name.capitalize()}StagingRepository` and `release${repository.name.capitalize()}StagingRepository` tasks that must run after the all publishing tasks\n  - to simplify the common use case also a `closeAndRelease${repository.name.capitalize()}StagingRepository` task is created which depends on all the `close*` and `release*` tasks for a given repository\n\n---\n\n## Historical background\n\nIn 2015, [Marcin Zajączkowski](https://blog.solidsoft.pl/) created [gradle-nexus-staging-plugin](https://github.com/Codearte/gradle-nexus-staging-plugin/) which was providing an ability to close and release staging repositories in Nexus repository manager. It opened an opportunity to manage releasing Gradle projects to Maven Central completely from code. Over the years, it has been adopted by various projects across the globe, however there was a small problem. Due to technical limitations in the publishing process in Gradle, it was required to use heuristics to track implicitly created staging repositories, what often failed for multiple repositories in a given state. The situation became even worse when Travis changed its network architecture in late 2019 and the majority of releases started to fail.\nHere, [Marc Philipp](https://github.com/marcphilipp/) entered the stage who created [Nexus Publish Plugin](https://github.com/marcphilipp/nexus-publish-plugin) which was enriching the publishing mechanism in Gradle to explicitly create staging repositories and publish (upload) artifacts directly to it.\n\nThose two plugins nicely worked together, providing a reliable way to handle publishing artifacts to Maven Central (and to other Nexus instances in general). However, the need of using two plugins was very often confusing for users. As a result, an idea to create one plugin mixing the aforementioned capabilities emerged. It materialized in 2020/2021 as Gradle Nexus Publish Plugin, an effect of combined work of Marc and Marcin, supported by a pack of [contributors](https://github.com/gradle-nexus/publish-plugin/graphs/contributors).      \n\n[nexus-compat]: https://help.sonatype.com/en/nexus-repository-2-vs--nexus-repository-3-feature-equivalency-matrix.html#:~:text=API%20documentation.-,Note,-Note%20that%20NexusRepository\n[maven-central]: https://central.sonatype.com/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgradle-nexus%2Fpublish-plugin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgradle-nexus%2Fpublish-plugin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgradle-nexus%2Fpublish-plugin/lists"}