Automated Gradle Publish with GitHub Actions (To Maven Central)
In my previous article, “Complete Guide: Publish with Gradle to Maven Central (native)”, I’ve explained how to publish artefacts to Maven Central manually. Now it’s time to show the automated way with GitHub Actions 🤩
If you need to remind yourself on how to build the workflow, here you go with my workflow file (yaml):
The idea behind our following automation is to get automatically triggered with GitHub Actions in the event of a release. And to build and publish our artefact with human approval on Maven Central.
Initially, I aimed for a fully-automated pipeline to publish on Maven Central. During this practice, I figured out that it comes with technical challenges and concerns about unwanted publications. The following points made my decision to aim for automation with human approval:
- Technical challenges can be overcome, but there is a price to pay. To get it automatically published, you would need to know the id of the staging repository. The use of custom code interacting with Sonatype’s REST API or a Gradle plugin would become necessary.
- Technically, I would love to see it fully automated, but to mitigate security and compliance concerns, I recommend the approval workflow. It brings the benefit that we leave the final decision to a human if an artefact is going to be stored on the internet for “eternity”.
Check out the “References, Useful links” section, and there, you will find a script and a Gradle plugin, which may help you if you decide differently than I did, and you head to a fully automated solution.
Before we can launch, we’ve to make sure our base is ready for that. And I assume that if you found this guide, you do
- have a basic understanding of CI/CD.
If not, please read first: https://www.redhat.com/en/topics/devops/what-is-ci-cd*
- have some knowledge about GitHub Actions.
If not, please do it first: https://lab.github.com/githubtraining/github-actions:-hello-world*
- have a project in place where manual releases to Maven Central work.
If not, please read first: https://botscripter.medium.com/complete-guide-publish-with-gradle-to-maven-central-native-7b128addbb6
*I’m no advocate, nor I’m paid to list these links here. I don't even earn anything if you click on them. I googled them or had them in my bookmarks. So it is truly here to assist you and chosen by my personal bias as a developer. Feel free to get the required know-how anywhere else, as you desire — disclaimer end.
Let’s get started! 🥳
The implementation will consist of three tasks to execute. Afterwards, we should successfully have implemented our fully automated Pipeline.
Our first target is to provide all necessary data for our Gradle build. The following image should make you remember what you’ve defined and, therefore, what’s the mentioned needed data.
The only thing not visible above is that we also need the GPG private key and his passphrase for the signing task. If we build “real” non-SNAPSHOT versions.
1) GitHub secrets
You may remember my statement: we’re never allowed to store sensitive data, such as our credentials or private key, in Git? It remains still the case! Therefore we have to make use of encrypted secrets. You will have to create the following secrets:
Your username for the Sonatype Jira login.
Your password for the Sonatype Jira login.
Your ID of the GPG certificate.
Your gpg private key base64 encoded.
Your GPG passphrase, if you have set any. Otherwise, you don’t need to set this secret.
If you don’t know how to do that, visit the following step-by-step guide from GitHub:
Encrypted secrets - GitHub Docs
Secrets are encrypted environment variables that you create in an organisation, repository, or repository environment…
Choose between storing on the repository or global level. And keep in mind that you can’t review a secret set in GitHub.
⚠️ GitHub will mask any detected secrets and not print them in the log. But don’t think that the placed values there is a secret, it’s not! There are still ways to access this sensitive data. Therefore, read your logs and verify that you don’t expose any sensitive data.
Exporting the private key
You need to store your private key as a secret on GitHub. You have to export it in a format suitable for that purpose. For our goal, this would be a base64 encoded string. To do so, execute the following command after you have replaced the string
firstname.lastname@example.org with your corresponding e-mail address used for your GPG key.
gpg --output private.pgp --armor --export-secret-key email@example.com
2) Workflow file
I’ve created eight steps to automate our publishing process fully. First, please create the publish.yml file at the corresponding place in your Git repository.
Copy and paste the content of the following complete example into your newly created publish.yml file. Feel free to delete the comments as soon as you have read them and if they annoy you too. Or maybe only I have issues with comments in my production files 😅.
3) GitHub releases
As the idea is first to create a release, we have to do so to trigger the pipeline. If you need help, visit the following documentation:
Managing releases in a repository — GitHub Docs
You can create new releases with release notes, @mentions of contributors, and links to binary files, as well as edit…
For development reasons, you can think about adding the following configuration to enable manual workflow triggering.
To manually trigger a workflow, use the
workflow_dispatch event. You can manually start a workflow run using the GitHub API, GitHub CLI, or GitHub browser interface. For more information, see "Manually running a workflow."
By now, you are finally done with your whole automation! Congrats 🎉 Let’s continue with releasing it.
As an example, this is how it looked for my release:
4) Releasing to Maven Central
First of all, login into the Nexus Repository Manager:
If you aren’t sure which one you are using, look into your
build.gradle file and verify which releaseRepo you have specified in the publishing/repositories definition block.
You are four clicks away from publishing to Maven Central. What you have to do is to verify what the GitHub Action Workflow has uploaded, and if you agree, then to
- close the staging repository
- release the staging repository
Following is how this looked for my recent release as reference:
If you would like to understand what’s happening under the hood here, have a look at my previous guide, and read section “3 Publishing to Maven Central”
That’s it; we’re done 😎
Details, Explanations, Further Topics, Common Errors
What is an armored GPG key export?
PGP (including GPG) ‘armoring’ is not encryption. Encryption prevents unauthorised use of data (formally, it provides confidentiality) by making it unreadable in a way that can only be reversed by someone who has the secret key. Armoring is a simple process (mostly base64, although not the same base64 used by uuencode) that can be easily reversed by anybody who reads the specification. Armoring looks like text, while unarmored (binary) data looks like garbage to a person who uses inappropriate tools like
cat or a text editor, but they are equally readable by someone competent.
Sonatype’s Nexus Login issues
First of all, it happens to me too often that I open the Legacy Sonatype instead of the new one. You don’t see a difference on the web app itself. Only the URL differs. So double-check if you are on the right site when you receive an invalid username/password message.
If you have lost or forgotten your password, you have to open Sonatype’s Issue Tracker = Jira to reset the password. It’s not apparent but actually how it works. Unfortunately, there is no option on the Nexus itself to reset.
Here is the direct link to request a password reset: https://issues.sonatype.org/secure/ForgotLoginDetails.jspa
I’m always trying to live from the earnings I make by doing stuff I sincerely love ❤️. Writing tech articles 📝 become one of those things I’m passionate about. If my article supported you, I would be honoured to receive a tip ☕. This would enable me to spend even more time writing such articles and boost my motivation. Follow me here on medium for more tech articles and bonus material 😃.
This is the link to support me or to say thanks by buying me a coffee: https://ko-fi.com/botscripter
References, Useful links
- GitHub Actions, Documentation
- Script to Close and Release a Staging Repository
- gradle-release plugin