Release your maven project using Github actions

Quentin Castel
8 min readFeb 14, 2021

Every commits as a release

We will see how you can use maven release inside a GitHub actions, to release your Java project and make every commits to be a release.

Disclaimer: I am the author of the GitHub action that I will show you how to leverage today: https://github.com/qcastel/github-actions-maven-release but as every github actions, it’s open source.

Sample repository

A few words about the material we will use during this blog post.

We will use a sample repository to illustrate how this GitHub actions. It’s a basic Java application that I generated from https://start.spring.io/ and then configured for illustrating how to use the maven release github action.

The repository for this sample application can be found here: https://github.com/qcastel/github-actions-maven-release-sample

What we will achieve today?

We will first configure our repository so every commits is a release. Using maven release, this means that we will automatically bump the maven project version each time some commits to master.

We will then see how to push a new docker image each time we release

To finish, we will see how you can use a CI Bot, using commits signature, for enhancing the security of your release.

Prepare your repository

Before you even begin setting up this github action, you would need to set up your pom.xml first to be ready for maven releases. We recommend you to refer to the maven release plugin documentation for more details: https://maven.apache.org/maven-release/maven-release-plugin/

Here is a quick walk through of what I did for the sample repository

Configure the SCM

For our sample repository, we will use the SSH remote URL to setup the scm:

<scm>
<connection>scm:git:${project.scm.url}</connection>
<developerConnection>scm:git:${project.scm.url}</developerConnection>
<url>git@github.com:qcastel/github-actions-maven-release-sample.git</url>
<tag>HEAD</tag>
</scm>

Next, you need to add the maven plugin:

<properties>
<maven-release-plugin.version>2.5.3</maven-release-plugin.version>
</properties>
<plugin>
<artifactId>maven-release-plugin</artifactId>
<version>${maven-release-plugin.version}</version>
<configuration>
<scmCommentPrefix>[ci skip]</scmCommentPrefix>
<tagNameFormat>@{project.version}</tagNameFormat>
</configuration>
</plugin>

Note: We will use the prefix [ci skip] which allows us to skip more easily any commits generated by the bot from the CI.

Now your repository is setup for maven release.

Setup a basic CI as a base for our release sample

In our sample repository, we will assume we already got a basic CI in place that build our Java application.

We will start with a basic .github/workflows/release.yaml:

name: release versionon:
push:
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Build and Test
uses: qcastel/github-actions-maven-cmd@master
with:
maven-args: "clean install -Ddockerfile.skip -DdockerCompose.skip -Djib.skip"

All it does is compiling our application at each commits. You don’t need to do the same for your repository, you can keep what you already got setup.

Setup SSH key for release

Maven release will bump the version and will therefore commit into the git repository. In order to authorised our CI to commits via maven release, we need to setup an authentication to our git repository via the CI. For the sample, we will use SSH.

For generating a dedicating SSH key, we will use a docker container to avoid affecting your local OS. Here is a suggested way of how you can generate a SSH public and private key:

docker run -it qcastel/maven-release:latest  bash

Then run:

ssh-keygen -b 2048 -t rsa -f /tmp/sshkey -q -N ""
export SSH_PRIVATE_KEY=$(base64 /tmp/sshkey)
export SSH_PUBLIC_KEY=$(cat /tmp/sshkey.pub)
echo -n "Copy the following SSH private key and add it to your repo secrets under the name 'SSH_PRIVATE_KEY':"
echo $SSH_PRIVATE_KEY
echo "Copy the encoded SSH public key and add it as one of your repo deploy keys with write access:"
echo $SSH_PUBLIC_KEY
exit

As an output, we got:

Copy the following SSH private key and add it to your repo secrets under the name 'SSH_PRIVATE_KEY':LS0tLS1CRUdJTiBPUEVOUXXXX=
Copy the encoded SSH public key and add it as one of your repo deploy keys with write access:
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC/nPud195W04be0kZkg14rH1NC/ky0PoFzFa8oqO8M4V5czs3iAMD7YXbUAE9yyMikXkMqwQinQiU27iEwBocf/IsMMBfGLgVw2cpcz+Ov1Rtl7y+QfmtVtayCDutuiJPUS9rfw/5H1DPH3+qDUTRR/ThFBc02thZYWwqq7uciPuUU+Mv5lVG/5EATDTUVCeh6Tdx7uiNKV5cFoMQPGzVQZsO/pXNr5DQlXRMd/1MJ9UgQyHTW4n3gFIGi6DlmvVnlLCEVDSEc/HAB71NB3RGk6+0kt/0/4IGqSzZ2tgtjBc/F/FPIsKYPPpWZ5IJT4wlebSZF7PYzWL4iR3Ve5Rhl root@aceee9600aee

We then go to our project repository, in the secret sections and add the key as follow:

Note: For security reason, I masked a bit the private key, the one you will copy will be much longer.

Next, we add the SSH public key as a deploy key with write access by going to the Deploy keyssection:

Our CI will now have access to this SSH key, that is setup accordingly to allow our CI to commits.

Setup the maven release GitHub action

We are now ready to setup the maven release GitHub actions job. We will setup the minimal setup for starting and we will then enhance it:

- name: Release
uses: qcastel/github-actions-maven-release@master
with:
git-release-bot-name: "bot-idhub"
git-release-bot-email: "bot@idhub.io"
maven-args: "-Dmaven.javadoc.skip=true -DskipTests -DskipITs -Ddockerfile.skip -DdockerCompose.skip -Dmaven.deploy.skip=true"
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}

Note: We will skip the deployment of the docker image as some of you may not have the need to containerised their Java application. We will however see how to push to docker hub in a later section.

We will also add a filter to avoid having your CI running on the commits generated by the maven release itself:

jobs:
build:
runs-on: ubuntu-latest
if: "!contains(github.event.head_commit.message, '[ci skip]')"

Once you committed this change, if everything goes well, you should see that the CI did a commit that bump version change in your repository:

Congratulations! At this point you should have a functional maven release in place, which bump the version automatically.

You can stop there if that’s what you were after from this maven release plugin. The other sections are optional.

Supporting this Github action

You like this GitHub actions and would like to give your support and bring it up in the GitHub market place? Add a star to this repository :)

Surprisingly, it seems to be the only way in the Github market place to highlight popular Github actions. The number of uses of the action in CIs is not visible and therefore not used to highlight the most popular used GitHub actions. If you intend to use this GitHub actions, adding a star to it will help it to be more popular and therefore maintained by the GitHub community! Thanks!

Push to docker hub

How to containerise a Java application is out of scope of this article. Although as I want to show you how to push to docker hub, we will quickly containerised our sample application, using Jib:

<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>jib-maven-plugin</artifactId>
<configuration>
<skip>false</skip>
<from>
<image>qcastel/docker-alpine-with-bash:0.3</image>
</from>
<to>
<image>registry.hub.docker.com/qcastel/github-actions-maven-release-sample</image>
<tags>
<tag>${project.parent.version}</tag>
<tag>latest</tag>
</tags>
</to>
</configuration>
</plugin>

Then we setup the GitHub actions to access the docker hub credentials:

with:
docker-registry-id: registry.hub.docker.com
docker-registry-username: qcastel
docker-registry-password: ${{ secrets.DOCKER_REGISTRY_PASSWORD }}

As you can see, it is setup to read a repository GitHub secrets. Here is how I setup the secret for the sample:

We then need to update our maven release job to not skip the docker build anymore. Our maven arguments now look like:

maven-args: "-Dmaven.javadoc.skip=true -DskipTests -DskipITs -Dmaven.deploy.skip=true"

Once you commit those changes, you should see that a new docker images has been pushed to docker hub!

Setup a CI bot with GPG signature

You may be interested or need to enforce git commit signature to your repository. It’s actually particularly important for the CI release commits as they are the one that will ultimately produce the artefacts for your CD. In this section, we will see how you can make the CI commits done by a CI bot, with GPG signature on top.

Step 1: Create a bot account

There is currently no way in GitHub to create a bot without actually creating a GitHub account for it. Not much of a problem for public repositories but an issue for when you are paying got every users of your GitHub organisation. Unfortunately I don’t have another solution to offer you, other than allocating one user of your organisation for the bot. This not a problem related to this Github actions but more a limitation of Github itself.

Step 2: Find a cool avatar for your bot

Very important step, don’t skip it! ;)

Step 3: Add the SSH public key to the bot account

We added earlier our SSH public key as deploy key. This is fine if you don’t intend to use a bot. In our case, now that we want to use the bot instead, we will delete that deploy key and set the public SSH key to the bot instead.

  • Go to the Deploy key and delete the SSH key
  • Go to the bot github account and add the SSH key to it

Step 4: Create a GPG key for the bot

You can follow the documentation of GitHub: https://docs.github.com/en/github/authenticating-to-github/generating-a-new-gpg-key

For this sample repository, I will try to not go too much in details on how to generate a GPG key but please note that in the GitHub actions readme, we got a section dedicated for GPG that may help you: https://github.com/qcastel/github-actions-maven-release#setup-the-bot-gpg-key

Step 5: Invite the bot in your repository

Go to Manage access and add the bot in there. If you got an organisation, add him at the organisation level instead.

Accept the invitation that GitHub sent to the bot email.

Step 6 Add the GPG key ID and private key as secrets

The CI will need to access the GPG details and it is best that they are stored as secrets.

Add the following two secrets:

  • GPG_KEY: Copy the GPG private key (base64 encoded!)
  • GPG_KEY_ID: Copy the GPG key ID

You can then add to the GitHub actions the following config:

with:
gpg-enabled: true
gpg-key-id: ${{ secrets.GPG_KEY_ID }}
gpg-key: ${{ secrets.GPG_KEY }}

Once you committed those changes, you should see that the release commits are now highlighted with your bot avatar and marked as verified.

Conclusion

We saw how you can use maven release as part of your Github CI. From a basic setup, to push to docker hub and using a bot for your CI commits.

Your Java application may have some specificity that you need to adapt in using this Github action. For example, you need Java 8 or 15, a private repository or even setup a specific branch for your release. Hopefully this should be capture in one of the options from the Github action. You can find more details in the repository of the Github action itself: https://github.com/qcastel/github-actions-maven-release

As a reminder, you can find the sample project we used during this article here: https://github.com/qcastel/github-actions-maven-release-sample

Thanks for having followed this article until the end an I hope you successfully managed to use this Github action to make every of your commits a release for your Java application!

--

--

Quentin Castel

Back-end/Dev-ops engineer, specialised in identity, API security and Open Banking.