preface

I believe many friends have their own works for maintenance, and hosting in the three Library warehouse open use. It has been a while since Jcenter announced that it would end all of its policies for non-paying users. Without action, the libraries hosted by Jcenter and Jfrog will be gone.

This article walks you through registering your Sonatype account, applying for groupId and MavenCentral publishing, and provides you with a Gradle plugin that makes publishing easier.

background

This year Jfrog announced the decision:

UPDATE: To better support the community in this migration, JFrog has extended the JCenter new package versions submission deadline through March 31st 2021.

To clarify, the JCenter repository will keep serving packages for 12 months until February 1st 2022. Only the JCenter REST API and UI will be sunsetted on May 1st 2021.

This is embarrassing because over time, libraries hosted by non-paying users will no longer be available.

As an aside, Google was also shown off by this wave of operations, and according to Google’s pee, it may support the cause in the future, but it’s not going anywhere.

So, we don’t have many options left:

  • Become aValued paying customers
  • Switch tosonatypeEmbrace the use of free MavenCentral

Register for a Sonatype account

Sonatype plays well and uses JIRA, a well-known tool for agile development management, for business management, so the first thing to do is to sign up for Sonatype’s JIRA account

The registered address

Fill in according to the information guide.

To apply for the GroupId

A Library hosted in a tripartite repository is identified by three messages: GroupId, ArtifactId, and Version

Understandably, we need to apply for a usable GroupId first. Before starting the application process, please read the following information to avoid unnecessary operations:

In line with Sonatype’s business strategy, they use some clever ways to manage GroupId and avoid the risk of squatting

Firstly, there are two types:

  • You own the domain name
  • You don’t have a domain name

The first type of verification method I have not tested, have a domain name can according to the website introduction to try:

  • Add a TXT record to your DNS referencing this JIRA ticket: (JIRA-TASK-ID) (Fastest)
  • Setup a redirect to your Github page (if it does not already exist) You can find more information here: central.sonatype.org/publish/

The second type needs to use a third party (such as Github, Gitlab, Gitee, etc.) to obtain a website hosted on the third-party platform through the “unique constraint on the user name” and “Pages service “of the third party. Take Github as an example: After opening Pages, you can obtain a website by simple configuration: leobert-lan.github.io/

Creating a Pages website

Taking Github as an example, Gitee and others should be similar

The official introduction

Create a repository for {github_user_name}.github. IO

If you already have a personal blog, you can also use a tool like HEXO or Git-book to generate a related blog page and host it

Download the repository and add a not-too-outrageous index.html

Note:

  • Sonatype only concerns whether the domain name exists. According to mapping rules, GroupId is io.github.{github_user_name}
  • Sonatype doesn’t care what the content is (even if it’s not relevant to the project), but don’t make it too outrageous: politics, religion, bad information, etc

Then go to the project Settings

Select branches and paths and save them. You can quickly obtain the deployment result. After the deployment is successful, you can verify it by yourself.

JIRA creates an application task

  • Click “New Task”, the type and so on are default, simple description of your intention;
  • GroupId: IO. Github.{github_user_name}Same goes for Gitlab and Gitee
  • Fill out your Github project’s repository information, etc

After you submit, wait. Usually, a robot will reply first, informing you of the platform’s operation policy and relevant matters needing attention.

Note: Don’t wait. You will be notified by email if the status of the process changes

After receiving the email, reply with remarks to change the process state, and then wait for manual review (if all the information is correct, the machine may be directly reviewed).

Then enter the account attribution authentication

Verify account ownership

This, of course, is where Github or Gitee belongs.

Previously we used these platforms to get a unique domain name, but Sonatype needs to determine that the domain name is yours because:

  • Accounts correspond to Pages
  • Pages corresponds to GroupId
  • The uniqueness check of GroupId is carried out in Task

Sonatype requires you to create a repository that matches TaskID under the corresponding Github account. For example:

Please create a public repo called github.com/leobert-lan… to verify github account ownership.

If you do not own this lot account, both please read: central.sonatype.org/publish/req…

After the creation is successful, we will come back and comment on the process again. After the approval, we will get GroupId


That’s where we get GroupId. Next we need to prepare the signing tool

Library information all exists in poM files, if there is no signature mechanism, there may be a plum instead of peach things.

Here we need to use GPG, GPG website, interested in more research.

Note: GPG cannot be installed when macOs >= 10.15, you may need to find a Window computer to generate the signature key, don’t worry, the key can be exported

Generate a GPG signature key

generate

gpg --full-generate-key
Copy the code

Use the command to enter key generation,

  • Select RSA(for signature only)
  • Set the key length. The default key length is 2048
  • Set the expiration time and make it valid permanently.There’s no need to do this on your own
  • After confirming the information, enter “real name”, “email”, and “key Comment”. The Comment does not participate in any verification and is used to note its role
  • Confirm the information or change it again, after confirming, you need to enter the password twice, please do not forget your password
  • After the generation is complete, information is displayed

Of course, there’s no need to memorize this information,

To use:

gpg --list-keys
Copy the code

or

gpg -K
Copy the code

You can view all generated keys, each key has a long ID, this is the ID of its public key, 41 bits long, of course, its last eight bits can also be used as its ID, in the use of the two are equivalent, generally the last eight bits can be used.

Upload a public key to a public server

I chose “pool.sks-keyservers.net”, but of course there are other public servers that can be hosted.

GPG -- keyServer hkp://pool.sks-keyservers.net -- senders --keys Public key IDCopy the code

Check whether the upload is successful:

GPG -- keyServer hkp://pool.sks-keyservers.net --recv-keys Public key IDCopy the code

Exporting public keys, keys, and Keyrings

#Export the public key to the public-file.key file:
gpg -a -o public-file.key --export KeyId 

#Export the private key to the private-file.key file:
gpg -a -o private-file.key --export-secret-keys KeyId

#Export key string to secring. GPG file:
gpg --keyring secring.gpg --export-secret-keys
Copy the code

Take care of your keys!!

Configuration items

At this point, our preparations are in place to start revising your project:

Changes to the plugin

Given that Gradle 7.0 will deprecate the Maven plugin, we chose the Maven-Publish plugin

plugins {
// Other necessary plug-ins
    
    id 'signing'
    id 'maven-publish'
}
Copy the code

Added maven-publish for publishing and signing for signing

Add necessary information about the signature

signing.keyId=Public key ID. The last eight bits are required
signing.password= Password of the GPG key
signing.secretKeyRingFile=/ Users/leobert. Gnupg/secring. # GPG key string address
Copy the code

Unfortunately I couldn’t find a way to configure it in local.properties, it looks like the signing plugin reads the properties directly from inside.

The gradle.properties file can be removed from Git and ignored for key security reasons.

Configure the Task for generating JavaDoc and Sources

task sourcesJar(type: Jar) {
    classifier = 'sources'
    from sourceSets.main.java.srcDirs
}

// Android projects need to define additional tasks
//task javadoc(type: Javadoc) {
// source = android.sourceSets.main.java.srcDirs
// classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
/ /}

task javadocJar(type: Jar, dependsOn: javadoc) {
    classifier = 'javadoc'
    from javadoc.destinationDir
}

tasks.withType(Javadoc) {
    options.addStringOption('Xdoclint:none'.'-quiet')
    options.addStringOption('encoding'.'UTF-8')
    options.addStringOption('charSet'.'UTF-8')}Copy the code

Note: Android projects need to define additional tasks for Javadoc, java-Library and other project plugins, and pay attention to the path

Configuring publishing Information

Note that the configuration is done after the task is Evaluated, that is, within the afterEvaluate closure

afterEvaluate {
    publishing {
        publications {
            mavenAndroid(MavenPublication) {
                groupId GROUP_ID
                artifactId ARTIFACT_ID
                version VERSION_NAME
                artifact sourcesJar
                artifact javadocJar
                artifact('build/libs/xxx.jar') //
                // Configure the POM file format
                pom {
                    packaging = 'jar'
                    name = ARTIFACT_ID
                    description = ARTIFACT_ID
                    url = siteUrl
                    licenses {
                        license {
                            name = The Apache Software License, Version 2.0
                            url = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
                        }
                    }
                    developers {
                        developer {
                            id = 'leobert'
                            name = 'leobert'
                            email = '[email protected]'
                        }
                    }
                    scm {
                        connection = siteUrl
                        developerConnection = gitUrl
                        url = siteUrl
                    }
                }
            }
        }
        // Configure the remote repository
        repositories {
            maven {
                url = 'https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/'
                credentials {
                    username ACCOUNT
                    password PASSWORD
                }
            }
        }
    }

    signing {
        sign publishing.publications.mavenAndroid
    }
}
Copy the code

This is a simple boilerplate, but of course the protocol part, developer part, contributor part, and so on can be expanded. ACCOUNT and PASSWORD are sonatype ACCOUNT passwords,

After the build, execute the Publish task to sign and upload files

The last step

Log into Sonatype’s Maven repository using sonatype’s account password

Navigate to stagingRepositories, find the submitted material, check again that all validation passes, close, refresh and release.

After confirming the success, close the Task of Sonatype-Jira.

Upon success, the committed Components should have entered Sonatype’s release repository and be synchronized to MavenCentral within approximately 1 hour

After the update version, in theory will automatically synchronize.

Writing Gradle plugins makes configuration easier

The Maven-Publish plugin also supports more complex configurations, which may be rarely used in individual projects. After selecting the “sufficient” configuration items, we write a Gradle plugin so that we can avoid repeating templates.

Plug-in source code repository,

  • Gradle. properties to write the necessary information for the signature

Given that this topic is to share the experience of MavenCentral publishing, we have omitted the Gradle plug-in knowledge and the source code of this plug-in. Interested friends can understand the source code through the warehouse.

PS: Most of the time we copy the wild configuration, and often Groovy code, due to the particularity of The Groovy language, these closure configuration items will be compatible with errors, plug-ins are written using Kotlin, reading its source code can deepen the cognition of mamaven – Publish and other plug-in apis

signing.keyId=Public key ID. The last eight bits are required
signing.password= Password of the GPG key
signing.secretKeyRingFile=/ Users/leobert. Gnupg/secring. # GPG key string address
Copy the code
  • Write the sonatype account information in local.properties:
nexus_user=Sonatype account
nexus_pwd= Sonatype password
Copy the code
  • After the plugin is introduced, build.gradle does the necessary configuration:
plugins {
    id 'osp.leobert.maven.publish'
}

EasyPublish {
    sourceSet = android.sourceSets.main.java.srcDirs
    docClassPathAppend = project.files(android.getBootClasspath().join(File.pathSeparator)).asPath
    docExcludes = ["a/b/c/*"]
    artifact {
        value = "build/outputs/aar/android-lib-demo-release.aar"
    }

    developer {
        id = 'leobert'
        name = 'leobert'
        email = '[email protected]'
    }

    //append developers
// developer {
// id = 'aa'
// name = 'bb'
// email = 'cc'
/ /}

    groupId = "io.github.leobert-lan"
    artifactId = "android-demo"
    version = "1.0.0"
    packaging = "aar"
    siteUrl = "https://github.com/leobert-lan/EsayPublish"
    gitUrl = "https://github.com/leobert-lan/EsayPublish.git"
    licenseName = 'Apache 2.0'
    licenseUrl = 'https://github.com/leobert-lan/EsayPublish/blob/master/LICENSE'

    mavenRepoUrl = "https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/"
}
Copy the code

You can publish.