Problem
Publishing to Maven Central is currently failing with:
Failed to publish publication 'release' to repository 'MavenCentral'
> Could not PUT 'https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/io/github/hellocuriosity/curiosity/1.0.0/curiosity-1.0.0.aar'.
Received status code 402 from server: Payment Required
Sonatype sunset the legacy OSSRH endpoints (oss.sonatype.org / s01.oss.sonatype.org) on 30 June 2025. Requests to the old Nexus staging API now return 401/402. Our gradle/publishing.gradle.kts still targets https://s01.oss.sonatype.org/service/local/staging/deploy/maven2, which is why releases are blocked.
Proposed fix
Migrate to the Central Publisher Portal using the Vanniktech Maven publish plugin, which speaks the new Portal API natively and removes most of our hand-rolled publishing config.
Code changes
Replace the body of gradle/publishing.gradle.kts with the Vanniktech plugin's DSL:
plugins {
id(\"com.vanniktech.maven.publish\")
}
mavenPublishing {
publishToMavenCentral()
signAllPublications()
coordinates(\"io.github.hellocuriosity\", artifactId, project.version.toString())
pom {
name.set(publicationName)
description.set(publicationDescription)
url.set(\"https://github.com/HelloCuriosity/curiosity\")
licenses {
license {
name.set(\"MIT Licence\")
url.set(\"https://github.com/HelloCuriosity/curiosity/blob/main/LICENSE\")
}
}
developers {
developer { id.set(\"hopeman15\"); name.set(\"Kyle Roe\") }
}
scm {
connection.set(\"scm:git:https://github.com/HelloCuriosity/curiosity.git\")
developerConnection.set(\"scm:git:https://github.com/HelloCuriosity/curiosity.git\")
url.set(\"https://github.com/HelloCuriosity/curiosity\")
}
}
}
Register the plugin in the root build.gradle.kts:
plugins {
id(\"com.vanniktech.maven.publish\") version \"0.30.0\" apply false
}
The plugin handles Android library component selection, sources/javadoc jars, and signing — so the current afterEvaluate / plugins.hasPlugin(\"com.android.library\") branching can be deleted.
CI / secrets changes
Generate a User Token at https://central.sonatype.com/account and replace the GitHub Actions secrets accordingly. The plugin reads from these Gradle properties (set via env in CI):
| Old secret |
New env var |
SONATYPE_USER |
ORG_GRADLE_PROJECT_mavenCentralUsername |
SONATYPE_PWD |
ORG_GRADLE_PROJECT_mavenCentralPassword |
SIGNING_KEY |
ORG_GRADLE_PROJECT_signingInMemoryKey |
SIGNING_PWD |
ORG_GRADLE_PROJECT_signingInMemoryKeyPassword |
CI task stays ./gradlew publishToMavenCentral (or switch to publishAndReleaseToMavenCentral to skip the Portal staging step).
Alternative considered
Sonatype provides a temporary OSSRH-compat shim at https://ossrh-staging-api.central.sonatype.com/service/local/staging/deploy/maven2/ that accepts the legacy Nexus protocol. Switching the URL is a one-liner, but the shim is explicitly a migration aid and will be retired — so it would just defer the same migration work.
Acceptance criteria
Problem
Publishing to Maven Central is currently failing with:
Sonatype sunset the legacy OSSRH endpoints (
oss.sonatype.org/s01.oss.sonatype.org) on 30 June 2025. Requests to the old Nexus staging API now return401/402. Ourgradle/publishing.gradle.ktsstill targetshttps://s01.oss.sonatype.org/service/local/staging/deploy/maven2, which is why releases are blocked.Proposed fix
Migrate to the Central Publisher Portal using the Vanniktech Maven publish plugin, which speaks the new Portal API natively and removes most of our hand-rolled publishing config.
Code changes
Replace the body of
gradle/publishing.gradle.ktswith the Vanniktech plugin's DSL:plugins { id(\"com.vanniktech.maven.publish\") } mavenPublishing { publishToMavenCentral() signAllPublications() coordinates(\"io.github.hellocuriosity\", artifactId, project.version.toString()) pom { name.set(publicationName) description.set(publicationDescription) url.set(\"https://github.com/HelloCuriosity/curiosity\") licenses { license { name.set(\"MIT Licence\") url.set(\"https://github.com/HelloCuriosity/curiosity/blob/main/LICENSE\") } } developers { developer { id.set(\"hopeman15\"); name.set(\"Kyle Roe\") } } scm { connection.set(\"scm:git:https://github.com/HelloCuriosity/curiosity.git\") developerConnection.set(\"scm:git:https://github.com/HelloCuriosity/curiosity.git\") url.set(\"https://github.com/HelloCuriosity/curiosity\") } } }Register the plugin in the root
build.gradle.kts:plugins { id(\"com.vanniktech.maven.publish\") version \"0.30.0\" apply false }The plugin handles Android library component selection, sources/javadoc jars, and signing — so the current
afterEvaluate/plugins.hasPlugin(\"com.android.library\")branching can be deleted.CI / secrets changes
Generate a User Token at https://central.sonatype.com/account and replace the GitHub Actions secrets accordingly. The plugin reads from these Gradle properties (set via env in CI):
SONATYPE_USERORG_GRADLE_PROJECT_mavenCentralUsernameSONATYPE_PWDORG_GRADLE_PROJECT_mavenCentralPasswordSIGNING_KEYORG_GRADLE_PROJECT_signingInMemoryKeySIGNING_PWDORG_GRADLE_PROJECT_signingInMemoryKeyPasswordCI task stays
./gradlew publishToMavenCentral(or switch topublishAndReleaseToMavenCentralto skip the Portal staging step).Alternative considered
Sonatype provides a temporary OSSRH-compat shim at
https://ossrh-staging-api.central.sonatype.com/service/local/staging/deploy/maven2/that accepts the legacy Nexus protocol. Switching the URL is a one-liner, but the shim is explicitly a migration aid and will be retired — so it would just defer the same migration work.Acceptance criteria
gradle/publishing.gradle.ktsno longer referencess01.oss.sonatype.orgio.github.hellocuriositynamespace verified on the Central Portal