DEV Community

Kengo TODA
Kengo TODA

Posted on

Deploying to OSSRH with Gradle in 2020

It seems that the method described in the official page is a little bit old. Here I'll introduce a modern way.

Metadata and Signing

Use the maven-publish plugin instead of the maven plugin. No need to configure the artifacts extension.

Jar Files

The classifier property of Jar task is now deprecated. Instead, we can use withJavadocJar() and withSourcesJar() in the java extension.

java {
    withJavadocJar()
    withSourcesJar()
}

Signing artifacts

We're using maven-publish plugin, so the signing extension in our build script will be like the following:

ext.isReleaseVersion = !version.endsWith("SNAPSHOT")

// -------------------------------------
// here 'publishing' extension will come
// -------------------------------------

signing {
    sign publishing.publications.mavenJava
}
tasks.withType(Sign) {
    onlyIf { isReleaseVersion }
}

Metadata Definition and Upload

Instead of uploadArchives extension for the maven plugin, configure publishing extension for the maven-publish plugin.

publishing {
    repositories {
        maven {
            def releaseRepo = "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
            def snapshotRepo = "https://oss.sonatype.org/content/repositories/snapshots/"
            url = isReleaseVersion ? releaseRepo : snapshotRepo
            credentials {
                username = project.hasProperty('ossrhUsername') ? ossrhUsername : "Unknown user"
                password = project.hasProperty('ossrhPassword') ? ossrhPassword : "Unknown password"
            }
        }
    }

    publications {
        mavenJava(MavenPublication) {
            pom {
                groupId = 'com.example'
                name = 'example project'
                description = 'Example Project to learn how to deploy to OSSRH'
                url = 'https://example.com/'
                from components.java
                licenses {
                    license {
                        name = 'The Apache License, Version 2.0'
                        url = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
                    }
                }
                scm {
                    connection = 'scm:git:git@github.com:example.com/example.git'
                    developerConnection = 'scm:git:git@github.com:example.com/example.git'
                    url = 'https://github.com/example.com/example/'
                }
            }
        }
    }
}

Deployment

Use the publishToMavenLocal task to publish artifacts to maven local repository.

Use the publish task to publish artifacts to maven remote repositories. Don't forget to visit oss.sonatype.org to close and release your staging repository.

Oldest comments (4)

Collapse
 
moaxcp profile image
John Mercier

There is a plugin which can also close and release the artifact using gradle: gradle-nexus-staging-plugin. I haven't been able to get it working lately though.

Collapse
 
ascertrobw profile image
RobWalker

Wish I'd found your article yesterday - been battling this same change, and had already just about got there when I found it.

One thing I can't seem to get working is SNAPSHOT publishing to OSSRH - I get the following:

Failed to publish publication 'mavenJava' to repository 'maven'
Could not GET 'oss.sonatype.org/service/local/sta...
/com/ascert/open/openterm/1.6-SNAPSHOT/maven-metadata.xml'. Received status code
400 from server: Bad Request

Pretty sure Gradle is trying to list that location before publishing, and it's not a browsable URL.

Did you also hit this and/or figure a way around?

Collapse
 
ascertrobw profile image
RobWalker

Figured it out - nothing wrong in any of the above, but when using subprojects the 'version' gets evaluated for the root project not the subproject. Sorted it with the following:

ext {

...

    // Make sure we have a default for initial configuration evaluation
    isReleaseVersion = false    
}

allprojects {

   ...    

    // When it comes to publishing we need to ensure we have the subproject version set 
    // rather than the root project version
    afterEvaluate { project -> 
        ext.isReleaseVersion = !version.endsWith("SNAPSHOT")        
    }
}

...

    repositories {            
        maven {
            afterEvaluate { project -> 
                def releaseRepo = "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
                def snapshotRepo = "https://oss.sonatype.org/content/repositories/snapshots/"
                url = (isReleaseVersion) ? releaseRepo : snapshotRepo                    
                credentials {
                    username = project.hasProperty('ossrhUsername') ? ossrhUsername : "Unknown user"
                    password = project.hasProperty('ossrhPassword') ? ossrhPassword : "Unknown password"
                }
            }
        }

...
signing {
    afterEvaluate { project -> 
        required { isReleaseVersion && gradle.taskGraph.hasTask("publish") }
        sign publishing.publications.mavenJava
    }
}
Collapse
 
hohserg1 profile image
hohserg1

Hello! What purpose does an developerConnection serve?