dave
04/19/2025, 9:47 AMPatrick Lannigan
04/19/2025, 12:59 PMPatrick Lannigan
04/19/2025, 1:02 PMdave
04/19/2025, 1:38 PMdave
04/19/2025, 2:25 PMThey explicitly say that they're won't be official gradle support until after the shutdown. So it seems to be a "pick from this collection of 15 options, good luck".Thinking more about it - this is a significant risk to the security of the JVM open source ecosystem. Let's imagine a scenario: 1. They shut off publishing of OSS libraries to the legacy OSSRH on 30th June 2. A high risk CVE is found in a project that currently uses the gradle plugin. 3. But there is no support in Gradle using the official plugin for ??? time after 30th June. 4. The project in question have not been lucky enough to trip over this announcement in the mere 90-odd days Which means that in order to actually get a fix out, the OSS team need to both fix it AND migrate to a new release pipeline. And let's be honest - it wasn't exactly easy the first time around (at least for us) to get it working.
Andrew O'Hara
04/19/2025, 6:10 PMdave
04/19/2025, 6:11 PMmbonnin
04/19/2025, 6:43 PMmbonnin
04/19/2025, 6:44 PMmbonnin
04/19/2025, 6:44 PMmbonnin
04/19/2025, 6:45 PMdave
04/19/2025, 6:46 PMmbonnin
04/19/2025, 6:46 PMdave
04/19/2025, 6:47 PMdave
04/19/2025, 6:47 PMmbonnin
04/19/2025, 6:47 PMmbonnin
04/19/2025, 6:48 PMmbonnin
04/19/2025, 6:49 PMI actually read it differently... it says "expect less support as we get to the deadline"... Not pastThat might be it. Want to write to central-support@sonatype.com to ask for clarification? They are usually quite responsive
dave
04/19/2025, 6:53 PMmbonnin
04/19/2025, 6:54 PMSami Eljabali
04/20/2025, 12:10 PMmbonnin
04/20/2025, 2:53 PMdave
04/20/2025, 2:58 PMdave
04/20/2025, 2:58 PMmbonnin
04/20/2025, 3:08 PMmbonnin
04/20/2025, 3:09 PMdave
04/20/2025, 3:17 PMSami Eljabali
04/20/2025, 3:48 PMmbonnin
04/20/2025, 3:54 PMSami Eljabali
04/20/2025, 3:55 PMmbonnin
04/20/2025, 3:58 PMdave
04/22/2025, 9:29 PMdave
04/22/2025, 9:29 PMHello David,
> There will be no official Gradle support (ie. Using the maven-publish plugin) for this new publishing mechanism as of the above date. Changing publishing mechanisms has been left at "please use one of these unofficial plugins" ([<https://central.sonatype.org/publish/publish-portal-gradle/](https://central.sonatype.org/publish/publish-portal-gradle/)>) without any examples or support being provided. It seems that Gradle is also not treating this is an important issue: [<https://github.com/gradle/gradle/issues/28120#issuecomment-1954266992](https://github.com/gradle/gradle/issues/28120#issuecomment-1954266992)>.
To clarify, this particular point is where there is some miscommunication. We agree with you that Gradle support is important to a large percentage of the community and that it would cause significant issues to leave Gradle publishers without a way forward (and that it would exacerbate security issues). To address this, we created the [OSSRH Staging API](<https://central.sonatype.org/publish/publish-portal-ossrh-staging-api/>), which should allow you to point the built-in Gradle `maven-publish` plugin at a different URL, generate a Portal token instead of an OSSRH one, and add a single extra web request at the end of your build to indicate that your upload has completed and it should be propagated to the Portal (this is akin to manually logging in to the OSSRH UI and closing the repository or calling a dedicated Nexus Repository Manager 2 endpoint).
The reason for this decision is that we wanted to have a publishing solution that could temporarily accommodate all publishers (Gradle, Maven, SBT, Bazel, etc.) while we worked both internally and with external partners such as Gradle to develop high-quality plugins that meet each ecosystem's needs. By decoupling that effort from the end-of-life of Sonatype Nexus Repository 2, we hope to buy ourselves more time to make the migration to the Portal a smoother experience.
From the news article that you linked, we indicated
> Once OSSRH is sunset, we will have more roadmap capacity to begin working on a first-party Gradle plugin. We are working with Sonatype's legal department to streamline the process of open sourcing Central-related plugins. This discussion is currently focused on our Maven plugin, but we intend to launch a first-party Gradle plugin as open source from day one.
We hope that you understand that we treat this as seriously as you do and we understand that the Gradle community in particular is an increasingly significant portion of publishers to Maven Central.
> Tangentially, there are no download statistics at all available on the new central portal. This is a big problem for projects like ours which use the download statistics as a way of determining migration activities amongst other things.
We're actively working on implementing stats for the Portal, but we are not comfortable giving a public estimate of when they will be available due to the cross-team collaboration with Sonatype's data team, who have their own priorities and initiatives. If you have a need for statistics in the meantime, please contact support and we can arrange a temporary solution.
We would be interested in more information about what you mean by "determining migration activities" and what other ways the statistics are useful to your project. This would allow us to better understand the use-case(s) of statistics that any new solution would need to take into consideration,
Thank you,
The Central Team
mbonnin
04/22/2025, 10:57 PMmbonnin
04/22/2025, 10:59 PMOleg Nenashev
04/23/2025, 6:30 AMNeeme Praks
04/28/2025, 8:14 AM./gradlew -Dorg.gradle.daemon=false -Dkotlin.incremental=false clean publishToMavenCentral
It is based on @bnorm piecemeal project build system, I took that as an example and simplified it (maybe could be simplified even more). Piecemeal seems to release via a Github action.
You can see from the build file that both projects use gradle-maven-publish-plugin from vanniktech — it was quite simple to set up.Nick
05/09/2025, 2:18 AMmbonnin
05/09/2025, 8:03 AMopportunity to manually review my publication before releasing the repositoryYou can review the list of files in the central portal UI but not use it as a plain maven repo like you used to be able to with OSSRH
my login stopped workingGo to https://central.sonatype.com/api/auth/login and reset your password. Use that new password in OSSRH. This has worked for me in the past.
dave
05/09/2025, 8:06 AMNick
05/10/2025, 2:00 AMdave
05/10/2025, 4:46 AMNick
05/10/2025, 4:53 AMOleg Nenashev
05/12/2025, 10:00 AM#maven-central-publishing
channel on the Gradle Community Slack to coordinate the efforts: http://slack.gradle.org/. Everyone is welcome to join!Nick
05/13/2025, 5:04 AMThat is expected, you can only login in Central Portal after migration.
seems like you are locked out from OSSRH the minute you initiate migration. so this explains why my login no longer works 😔
Oleg Nenashev
05/13/2025, 5:51 AMdave
05/13/2025, 5:58 AMmbonnin
05/13/2025, 7:16 AMmbonnin
05/13/2025, 7:17 AMmbonnin
05/13/2025, 7:17 AMMatt Nelson
05/26/2025, 11:59 AMmbonnin
05/26/2025, 12:07 PMMatt Nelson
05/26/2025, 12:20 PMIf you're using vanniktech's plugin it's a one line changeBeautiful... ❤️ I use it in all my projects I'm mainly concerned about the OSSHR migration process; have a lot of publications & snapshots...
mbonnin
05/26/2025, 12:29 PMOleg Nenashev
05/26/2025, 12:53 PMOleg Nenashev
05/30/2025, 10:06 AMMalcolm Smith
05/30/2025, 11:27 AMIn the process of sunsetting we are stopping support for stats until we are able to migrate the feature over to portal. We are unable to provide an accurate date on when this feature will arrive but we will be making it a priority shortly after the sunset date. we apologize for any inconvenience not having the statistics may cause.So it looks like there will be a period when nobody has any statistics at all.
Nick
06/21/2025, 5:47 PMAlexander Ioffe
06/25/2025, 7:56 AMmbonnin
06/25/2025, 8:32 AMmbonnin
06/25/2025, 8:33 AMmbonnin
06/25/2025, 8:33 AMAlexander Ioffe
06/25/2025, 8:34 AMAlexander Ioffe
06/25/2025, 8:35 AM<https://ossrh-staging-api.central.sonatype.com/service/local/staging/profiles/.../start>
API still works but it's impossible to use the output)mbonnin
06/25/2025, 8:38 AMTo produce artifacts for projects with Apple targets, you'd normally need an Apple machine. However, if you want to use other hosts, set this option in your gradle.properties file
kotlin.native.enableKlibsCrossCompilation=true
mbonnin
06/25/2025, 8:38 AMAlexander Ioffe
06/25/2025, 8:40 AMmbonnin
06/25/2025, 8:41 AMmbonnin
06/25/2025, 8:43 AMUSER_MANAGED
mode and then release both deployment from the portal UI. Once a deployment is validated, I have never seen it fail the "release" step so it's atomic in a wayAlexander Ioffe
06/25/2025, 6:36 PM<https://ossrh-staging-api.central.sonatype.com/service/local/staging/deploy/maven2/>
is completely awful for a KMP build because when you're doing many it's impossible to tell what Central staged artifact is coming from where. The IP-based isolation issue is an utter nightmare for anyone using github actions. Also, I can't build everything from a single-container because I've got the sqlite lib which is bonafide c-interop that I can go without.Alexander Ioffe
06/25/2025, 6:39 PM<https://ossrh-staging-api.central.sonatype.com/service/local/staging/deployByRepositoryId/$repositoryId/>
DOES actually work so long as you're working within the confines of the IP-based isolation. That is to say, you need to create the staging repo on the same github actions container (which is also annoying because you can't use nexus-actions/create-nexus-staging-repo
anymore) which you could do inside of gradle with some HttpClient calls.Alexander Ioffe
06/25/2025, 6:44 PM/service/local/staging/profiles/$pid/start
and then manual/upload/repository/$REPO_ID_ENCODED?publishing_type=user_managed
but its a headache that every single KMP OSS maintainer is about to need to go through.Alexander Ioffe
06/25/2025, 6:46 PMmbonnin
06/25/2025, 7:02 PMmbonnin
06/25/2025, 7:04 PM<https://central.sonatype.com/api/v1/publisher/>
and you upload a big zip there with one or several maven componentAlexander Ioffe
06/25/2025, 7:06 PMmbonnin
06/25/2025, 7:07 PMshared-volume
?mbonnin
06/25/2025, 7:07 PMAlexander Ioffe
06/25/2025, 7:08 PMmbonnin
06/25/2025, 7:08 PMAlexander Ioffe
06/25/2025, 7:09 PMmbonnin
06/25/2025, 7:10 PMUSER_MANAGED
publishingType and then finalized them with a job that retrieves all the deploymentIds and publishes them (or drops them) all at once using https://central.sonatype.org/publish/publish-portal-api/#publish-or-drop-the-deploymentmbonnin
06/25/2025, 7:10 PMdump everything intermediately produced into some maven repoJust use the portal API as the intermediate storage. It will hold your deployment until you finalize everything
Alexander Ioffe
06/25/2025, 7:10 PMmanual/upload/repository/$REPO_ID_ENCODED?publishing_type=user_managed
Alexander Ioffe
06/25/2025, 7:11 PMmbonnin
06/25/2025, 7:12 PMdeployments
instead of before a single staging repo
but really it should be similar.mbonnin
06/25/2025, 7:13 PMnexus-actions
equivalent for the Publisher APImbonnin
06/25/2025, 7:14 PMcreate-staging-repo
. On the other hand, each build job needs to output its deploymentId
Alexander Ioffe
06/25/2025, 7:19 PM/service/local/staging/profiles/$pid/start
actually creates the staging repo. That is what nexus-actions
does on the inside with either a CURL or some typescript code. Either way, this job is completely useless because it's keyed by the IP of the host and GitHub actions containers and the only useful way to invoke that is a common container at the beginning of the build.Alexander Ioffe
06/25/2025, 7:21 PMnexus-actions/create-nexus-staging-repo
inside of each matrix-build if you can capture its output.mbonnin
06/25/2025, 7:21 PMmbonnin
06/25/2025, 7:21 PMmbonnin
06/25/2025, 7:22 PMmbonnin
06/25/2025, 7:22 PMmbonnin
06/25/2025, 7:23 PMmbonnin
06/25/2025, 7:23 PMAlexander Ioffe
06/25/2025, 7:23 PMAlexander Ioffe
06/25/2025, 7:23 PMmbonnin
06/25/2025, 7:24 PMmbonnin
06/25/2025, 7:25 PMmbonnin
06/25/2025, 7:25 PMmbonnin
06/25/2025, 7:26 PMnexus-actions
anymore so someone needs to write the equivalent GitHub actions but this is all doableAlexander Ioffe
06/25/2025, 7:34 PMnexus-actions
does. The nexus-actions
thing is literally a couple of curl calls. The create-nexus-staging-repo
is literally just this (here):
jsonOutput=$(
curl -s --request POST -u "$INPUT_USERNAME:$INPUT_PASSWORD" \
--url ${INPUT_BASE_URL}staging/profiles/"${INPUT_STAGING_PROFILE_ID}"/start \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--data '{ "data": {"description" : "'"$INPUT_DESCRIPTION"'"} }'
)
Even TheMrMilchmann's variation of it is just this (here):
return await nexusRequest<NexusDTO<CreateStagingRepoResponseDTO>>(
"POST",
`/service/local/staging/profiles/${stagingProfileId}/start`,
request
).then(it => it.data);
All of these things are tiny wrappers around Nexus's built in functionalityAlexander Ioffe
06/25/2025, 7:34 PMmbonnin
06/25/2025, 7:35 PMmbonnin
06/25/2025, 7:36 PMmbonnin
06/25/2025, 7:36 PMAlexander Ioffe
06/25/2025, 7:37 PMpublish_command: >-
:controller-core:publishMacosX64PublicationToOss
:controller-core:publishMacosArm64PublicationToOss
:controller-core:publishIosX64PublicationToOss
:controller-core:publishIosArm64PublicationToOssRepository
:controller-core:publishIosSimulatorArm64PublicationToOss
:controller-core:publishTvosX64PublicationToOss
:controller-core:publishTvosArm64PublicationToOss
:controller-core:publishWatchosX64PublicationToOss
:controller-core:publishWatchosArm32PublicationToOss
:controller-core:publishWatchosArm64PublicationToOss
:controller-native:publishMacosX64PublicationToOss
:controller-native:publishMacosArm64PublicationToOss
:controller-native:publishIosX64PublicationToOss
:controller-native:publishIosArm64PublicationToOssRepository
:controller-native:publishIosSimulatorArm64PublicationToOss
:controller-native:publishTvosX64PublicationToOss
:controller-native:publishTvosArm64PublicationToOss
:controller-native:publishWatchosX64PublicationToOss
:controller-native:publishWatchosArm32PublicationToOss
:controller-native:publishWatchosArm64PublicationToOss
:terpal-sql-core:publishMacosX64PublicationToOss
:terpal-sql-core:publishMacosArm64PublicationToOss
:terpal-sql-core:publishIosX64PublicationToOss
:terpal-sql-core:publishIosArm64PublicationToOssRepository
:terpal-sql-core:publishIosSimulatorArm64PublicationToOss
:terpal-sql-core:publishTvosX64PublicationToOss
:terpal-sql-core:publishTvosArm64PublicationToOss
:terpal-sql-core:publishWatchosX64PublicationToOss
:terpal-sql-core:publishWatchosArm32PublicationToOss
:terpal-sql-core:publishWatchosArm64PublicationToOss
:terpal-sql-native:publishMacosX64PublicationToOss
:terpal-sql-native:publishMacosArm64PublicationToOss
:terpal-sql-native:publishIosX64PublicationToOss
:terpal-sql-native:publishIosArm64PublicationToOssRepository
:terpal-sql-native:publishIosSimulatorArm64PublicationToOss
:terpal-sql-native:publishTvosX64PublicationToOss
:terpal-sql-native:publishTvosArm64PublicationToOss
:terpal-sql-native:publishWatchosX64PublicationToOss
:terpal-sql-native:publishWatchosArm32PublicationToOss
:terpal-sql-native:publishWatchosArm64PublicationToOss
Alexander Ioffe
06/25/2025, 7:37 PMAlexander Ioffe
06/25/2025, 7:37 PMAlexander Ioffe
06/25/2025, 7:37 PMmbonnin
06/25/2025, 7:38 PMpublishAggregationToCentralPortal
?Alexander Ioffe
06/25/2025, 7:39 PMpublishAllPublicationsToOss
on my OSX builds because that causes horror.Alexander Ioffe
06/25/2025, 7:40 PMAlexander Ioffe
06/25/2025, 7:41 PMnmcpAggregation(project(":module1"))
mbonnin
06/25/2025, 7:41 PMAlexander Ioffe
06/25/2025, 7:42 PMAlexander Ioffe
06/25/2025, 7:43 PMAlexander Ioffe
06/25/2025, 7:44 PMmbonnin
06/25/2025, 7:46 PMmbonnin
06/25/2025, 7:46 PMAlexander Ioffe
06/25/2025, 7:47 PMAlexander Ioffe
06/25/2025, 7:47 PMmbonnin
06/25/2025, 7:48 PMmbonnin
06/25/2025, 7:49 PMmbonnin
06/25/2025, 7:49 PMAlexander Ioffe
06/25/2025, 7:52 PMAlexander Ioffe
06/25/2025, 7:53 PMmbonnin
06/25/2025, 7:53 PMmbonnin
06/25/2025, 7:53 PMAlexander Ioffe
06/25/2025, 7:54 PMAlexander Ioffe
06/25/2025, 7:54 PMmbonnin
06/25/2025, 7:54 PMAlexander Ioffe
06/25/2025, 7:57 PMAlexander Ioffe
06/25/2025, 7:58 PMAlexander Ioffe
06/25/2025, 7:58 PMmbonnin
06/25/2025, 8:03 PMAlexander Ioffe
06/25/2025, 8:03 PMAlexander Ioffe
06/25/2025, 8:04 PMmbonnin
06/25/2025, 8:04 PMAlexander Ioffe
06/25/2025, 8:04 PMmbonnin
06/25/2025, 8:04 PMmbonnin
06/25/2025, 8:05 PMdave
06/25/2025, 8:07 PMAlexander Ioffe
06/25/2025, 8:07 PMAlexander Ioffe
06/25/2025, 8:10 PMAlexander Ioffe
06/27/2025, 2:13 AMossrh-staging-api
was even more problematic then I thought. Whenever you try to do an upload to a repo-key username/ip/repo-id
combo whose IP you are not currently on e.g say:
SIDUNF/96.227.221.53/io.exoquery--1a8de2d9-3a89-4d54-b478-a1d1491bd0b0
...and you are not on 96.227.221.53
then the gradle publish won't even tell you the publish didn't go through. It will just fail silently!
That means that if you do have a <http://ossrh>...service/local/staging/deployByRepositoryId
with a repo-id (from: profile/start
) you've meticulously woven through your build... the whole thing will fail silently if GitHub actions randomly decides to hand you a new IP address. This is what was happening in my macOS-latest
matrix build. GitHub assigned a new IP to the whole container which meant that the key was no longer valid and my uploads were missing artifacts.
What was so awful about this whole thing is that there is zero indication that anything is wrong. In their "infinite wisdom", all three ChatGPT, Claude, and Perplexity kept telling me it was an issue of one Wagon connection clobbering another and some magic combination of --max-workers 1
and --no-parallel
would make my problem go away. I even introduced a 20 second timeout between my gradle upload tasks which of course did nothing.
Of course at some point I just randomly started playing around with crap and found out that if I replaced setUrl
from <https://ossrh>.../service/local/staging/deployByRepositoryId/$repositoryId/
to <https://ossrh>.../service/local/staging/deploy/maven2/
and then manually deployed the SIDUNF/<IP>/io.exoquery--default-repository
entries I would suddenly see my expected macOS-latest
artifacts spread across multiple default-repository
entries (it certainly doesn't help that it's impossible to see what files are inside a repo key via the OSSRH rest API!!). Then I realized that it's this silent-wrong-IP failure issue that I happened to know about previously!
All of this nonsense can easily set a developer back one or even multiple weeks. I will re-iterate, the feature-set that Central Publishing has is extremely primitive compared to what Nexus does. You can't even get the repo "description" fields into this publishing/deployments
thing! Let alone the fact that in s01/oss there were no nonsense IP-isolation restrictions, not only were there statistics, you could even modify a repo (even a closed one!) if validation failed, the most common reason for which was artifact duplication.
Bottom line... it's very nice that after ~10 years they're finally working on real self-service Maven-Central infrastructure but I really miss s01/oss Nexus! I think the whole JVM OSS community is about to as well.
(P.S. I also think the UI of publishing/deployments is also much worse than the old s01/oss one. In >99% of cases you don't want to see artifacts that have already been published, just the latest unpublished ones.)Alexander Ioffe
06/30/2025, 6:04 PM<https://central.sonatype.com/repository/maven-snapshots>
too btw.
The UI for it is completely broken.dave
07/01/2025, 9:18 PMdave
07/01/2025, 9:18 PMmbonnin
07/01/2025, 9:19 PMdave
07/01/2025, 9:20 PMmbonnin
07/01/2025, 9:20 PMmbonnin
07/01/2025, 9:21 PMmbonnin
07/01/2025, 9:22 PMsigning {
useInMemoryPgpKeys(signingKey, signingPassword)
}
dave
07/01/2025, 9:23 PMmbonnin
07/01/2025, 9:23 PMdave
07/01/2025, 9:23 PMmbonnin
07/01/2025, 9:24 PMsigning {
useInMemoryPgpKeys(System.getenv("GPG_KEY"), System.getenv("GPG_KEY_PASSWORD"))
}
mbonnin
07/01/2025, 9:24 PMdave
07/01/2025, 9:24 PMmbonnin
07/01/2025, 9:25 PMmbonnin
07/01/2025, 9:25 PMmbonnin
07/01/2025, 9:25 PMmbonnin
07/01/2025, 9:26 PMdave
07/01/2025, 9:27 PMdave
07/01/2025, 9:28 PMmbonnin
07/01/2025, 9:29 PMdave
07/01/2025, 9:30 PMdave
07/01/2025, 9:32 PMmbonnin
07/01/2025, 9:32 PMdave
07/01/2025, 9:37 PMhttp4k-core-6.15.1.0-sources.jar.asc.sha512
mbonnin
07/01/2025, 9:37 PM.asc
is the signaturesmbonnin
07/01/2025, 9:38 PMdave
07/01/2025, 9:38 PMmbonnin
07/01/2025, 9:38 PMmbonnin
07/01/2025, 9:38 PMdave
07/01/2025, 9:39 PMsigning {
val signingKey: String? by project
val signingPassword: String? by project
useInMemoryPgpKeys(signingKey, signingPassword)
sign(publishing.publications) <----
}
dave
07/01/2025, 9:39 PMdave
07/01/2025, 9:39 PMmbonnin
07/01/2025, 9:40 PMdave
07/01/2025, 9:42 PMOleg Nenashev
07/01/2025, 9:49 PM