Deploy to Maven Central Repository
Do you need to make your Java library publicly accessible? Is your project hosted on GitHub? Do you like idea of “all-in-one deploy to Maven Central Repository” button? I am going to show how to set it up with usage of maven-release-plugin. Source code is hosted on GitHub, so SSH access to source control will be also described.
There are various steps needed to set up environment for your project. I followed a lot of steps from official SonaType guide, therefore I will refer to it when needed. But this guide also describes a lot of techniques that are not needed for configuring “deploy to Maven Central repository” button.
Consideration
My first approach was to create Jenkins job that would represent the “Deploy to Maven Central” button. This idea is much cleaner for me than pushing from my development machine. I was trying it hardly but couldn’t make Jenkins SSH Agent plugin to register my SSH identity when maven-release-plugin is pushing version update to GitHub. Therefore very simple Linux Bash script is involved in two steps.
1. Create SonaType JIRA ticket for registration of your groupId
SonaType drives one of the biggest Nexus repositories. It is needed to deploy Java artifact there before it can be synced into Maven Central repository. In order to release Java library into SonaType Nexus repository, JIRA ticket is needed. SonaType guide includes detailed description how to create it.
Pick up Maven groupId reflecting your top level domain. It is typically same as main Java package (e.g. com.google, not com.google.guava). This is because you don’t want to create JIRA ticket for each project/library under your domain/main package/groupId. Here is more reading about Java package naming convention.
2. Inherit your Maven artifact from SonaType OSS pom.xml
SonaType parent POM contains
- URL to SonaType Nexus repository
- Configuration of Maven plugins
- Enforcer plugin
- Release plugin – this one is most important
- Source plugin – generates JAR with sources
- JavaDoc plugin – generates JAR with JavaDoc comments
- GPG plugin – signs artefact with GnuPG tool (this is required by Maven Central Repository)
<parent> <groupId>org.sonatype.oss</groupId> <artifactId>oss-parent</artifactId> <version>9</version> </parent>
Existence of this parent POM is handy because otherwise you would need to specify all plugins in your POM. The only problem is that plugin versions are slightly out of date, so I decided to override some versions in my POM this way:
<pluginManagement> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-gpg-plugin</artifactId> <version>1.5</version> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-release-plugin</artifactId> <version>2.4.2</version> </plugin> </plugins> </pluginManagement>
Crucial version update here is GPG plugin one, because updated version have handy features described section about GPG signing.
3. Configure GPG signing of Maven artefact
This is needed because of security policy of Maven Central repository. Include various sub-steps:
- Installing GnuPG tool
- Generate a key pair
- Distribute your public key
- Set up signing of artifact in settings.xml (your local repository configuration).
<profiles> <profile> <id>sonatype-oss-release</id> <properties> <gpg.keyname>F21879F3</gpg.keyname> <gpg.passphrase>*********</gpg.passphrase> <gpg.defaultKeyring>false</gpg.defaultKeyring> <gpg.useagent>true</gpg.useagent> <gpg.lockMode>never</gpg.lockMode> <gpg.homedir>/home/lkrnac/.gnupg</gpg.homedir> <gpg.publicKeyring>/home/lkrnac/.gnupg/pubring.gpg</gpg.publicKeyring> <gpg.secretKeyring>/home/lkrnac/.gnupg/secring.gpg</gpg.secretKeyring> </properties> </profile> </profiles>
F21879F3 is my public GPG key ID. gpg –list-keys command would list it for you. Passphase is password for your private GPG key. .gnupg folder is typically generated in your home directory.
4. Set up your credentials for SonaType Nexus repository
Needed for push to SonaType Nexus repository. Same as SonaType JIRA credentials. Again in settings.xml:
<servers> <server> <id>sonatype-nexus-snapshots</id> <username>lkrnac</username> <password>*************</password> </server> <server> <id>sonatype-nexus-staging</id> <username>lkrnac</username> <password>*************</password> </server> </servers>
5. Fill pom.xml mandatory sections
6. Set up SSH access to GitHub
Follow these sub-steps:
7. Create “Deploy to Maven Central” button
Maven-release-plugin needs to push/check-in version update to source control system and tag the revision. In my case the code is hosted on GitHub. Therefore I need to register my SSH identity (generated in previous step) before invoking maven-release-plugin’s goals. This is done by bash script maven-central-deploy.sh located alongside pom.xml:
!/bin/bash # Deploy maven artefact in current directory into Maven central repository # using maven-release-plugin goals read -p "Really deploy to maven cetral repository (yes/no)? " if ( [ "$REPLY" == "yes" ] ) then ssh-add ~/.ssh/lubos.krnac ssh-add -l mvn release:clean release:prepare release:perform -B -e | tee maven-central-deploy.log ssh-add -D else echo 'Exit without deploy' fi
Make the script executable by
chmod +x maven-central-deploy.sh
8. Push the “Deploy to Maven Central” button
Just run
./maven-central-deploy.sh
confirm and enter SSH private key passphase if required.
9. Release artifact via SonaType Nexus repository
When the artifact is pushed to SonaType Nexus repository. You need to release it. Finally you would need to add comment to the SonaType JIRA issue you created at the beginning and wait until somebody reviews your artifact and sets up the sync to Maven Central. Of course JIRA part would need to be done only once.
Link
- Example project configured this way is hosted on GitHub. (It’s tiny testing library).