Master Java Releases with GitHub Actions and Maven Release Plugin

Master Java Releases with GitHub Actions and Maven Release Plugin
Photo by Phạm Chung 🇻🇳 / Unsplash

A comprehensive guide to automating your Java release process: from version management to draft releases

Introduction

In software development, automating the release process is key. It ensures efficiency and consistency in a fast-paced field. Many Java developer struggle with manual release. They face issues with version management and Git tagging. This article will show you how to automate your release process using GitHub Actions and the Maven Release plugin

Prerequisites

Before diving into the implementation, ensure you have

  • A Java project using Maven.
  • A GitHub repository.
  • Basic understanding of GitHub Actions
  • Admin access to your repository.

Maven Release plugin overview

The Maven release plugin helps automate the release process of Maven projects. It handles version updates, git tagging, and deployment of release artifacts. Key benefits include:

  • Automated version management.
  • Consistent git tagging.
  • Build-in rollback mechanisms.
  • Integration with dependency management.

Let’s roll

Let’s configure the plugin in your pom.xml.

<project>
    <!-- Other POM configurations -->
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-release-plugin</artifactId>
                <version>3.0.1</version>
                <configuration>
                    <tagNameFormat>v@{project.version}</tagNameFormat>
                    <checkModificationExcludes>
                        <checkModificationExclude>pom.xml</checkModificationExclude>
                    </checkModificationExcludes>
                    <pushChanges>false</pushChanges>
                    <localCheckout>true</localCheckout>
                    <goals>deploy</goals>
                </configuration>
            </plugin>
        </plugins>
    </build>
<!-- Distribution management is required -->
<distributionManagement>
  <repository>
    <id>github</id>
    <name>GitHub Packages</name>
    <url>https://maven.pkg.github.com/${github.repository}</url>
    </repository>
</distributionManagement>
<scm>
  <developerConnection>scm:git:https://github.com/username/repository.git</developerConnection>
  <tag>HEAD</tag>
</scm>

GitHub Action Workflow

GitHub Actions automates your software workflows right in your repository. We will create a workflow that trigger the Maven release plugin when needed. Here is how to set it up.

name: Maven Release

on:
  workflow_dispatch:
    inputs:
      releaseVersion:
        description: 'Release version'
        required: true
      developmentVersion:
        description: 'Next development version'
        required: true

jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          fetch-depth: 0
          token: ${{ secrets.RELEASE_TOKEN }}

      - name: Set up JDK
        uses: actions/setup-java@v4
        with:
          java-version: '17'
          distribution: 'temurin'
          cache: maven
      - name: Configure Git user
        run: |
          git config user.email "actions@github.com"
          git config user.name "GitHub Actions"
      - name: Commit Changelog
        run: |
          git add CHANGELOG.md
          git commit -m "docs: update changelog for version ${{ github.event.inputs.releaseVersion }}"
          git push origin main
      - name: Setup Maven settings.xml
        uses: s4u/maven-settings-action@v3.0.0
        with:
            servers: |
              [{
                "id": "github",
                "username": "${{ github.actor }}",
                "password": "${{ secrets.RELEASE_TOKEN }}"
              }]
      - name: Prepare Release
        run: |
          set -e
          mvn release:prepare \
          -DreleaseVersion=${{ github.event.inputs.releaseVersion }} \
          -DdevelopmentVersion=${{ github.event.inputs.developmentVersion }} \
          -DtagNameFormat=v@{project.version}
      - name: Perform Release
        run: mvn release:perform
      - name: Push changes
        run: |
          set -e
          git push origin main
          git push origin --tags

Setting up security

To enable the workflow to push changes and create tags, you will need:

  1. Create a Personal Access Token (PAT) with repo scope.
  2. Add the token as repository secret named RELEASE_TOKEN .
  3. Ensure the GitHub Actions workflow has the necessary permissions.

Running a release

To start a release

  1. Naviage to your repository’s “Actions” tab.
  2. Select the “Maven Release” workflow
  3. Click “Run workflow”
  4. Enter the release version, e.g — 1.0.0
  5. Enter the next development version, e.g — 1.1.0-SNAPSHOT
  6. Click “Run workflow”.

The worklow will

  • Prepare the release (update version, create tag).
  • Build and test the project
  • Deploy artifacts
  • Push changes back to the repository

Automated changelog generation

Manually maintaing a detailed changelog is time consuming and error-prone. We can automate this process using the Conventional Commits specification and git-changelog-maven-plugin. Here’s how to set it up

<project>
    <build>
        <plugins>
            <plugin>
                <groupId>se.bjurr.gitchangelog</groupId>
                <artifactId>git-changelog-maven-plugin</artifactId>
                <version>2.2.0</version>
                <executions>
                    <execution>
                        <id>GenerateGitChangelog</id>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>git-changelog</goal>
                        </goals>
                        <configuration>
                            <templateFile>changelog.mustache</templateFile>
                            <readableTagName>-([^-]+?)$</readableTagName>
                            <file>CHANGELOG.md</file>
                            <mediaWiki>false</mediaWiki>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

Create a template file changelog.mustache in your project’s root.

# Changelog

{{#tags}}
## {{name}}
{{#commits}}
* {{{messageTitle}}}
{{#messageBodyItems}}
  * {{.}}
{{/messageBodyItems}}
{{/commits}}

{{/tags}}

Update your GitHub Actions workflow to include changelog generation.

- name: Generate Changelog
        run: mvn git-changelog-maven-plugin:git-changelog
      - name: Commit Changelog
        run: |
          git add CHANGELOG.md
          git commit -m "docs: update changelog for version ${{ github.event.inputs.releaseVersion }}"
          git push origin main

Creating GitHub Release

Automating the release process is powerful, but some steps enjoy human oversight. We’ll configure our workflow to create a draft release that we can review before publishing. This gives us a chance to verify the changelog, check the attached aritfacts, and ensure everything is in order.

- name: Get Changelog Entry
        id: changelog
        run: |
          CHANGELOG_ENTRY=$(sed -n "/## ${GITHUB_REF#refs/tags/}/,/## /p" CHANGELOG.md | sed '$d')
          echo "changelog<<EOF" >> $GITHUB_OUTPUT
          echo "$CHANGELOG_ENTRY" >> $GITHUB_OUTPUT
          echo "EOF" >> $GITHUB_OUTPUT
          
- name: Create GitHub Release
  uses: softprops/action-gh-release@v1
  with:
    tag_name: v${{ github.event.inputs.releaseVersion }}
    name: Release v${{ github.event.inputs.releaseVersion }}
    body: ${{ steps.changelog.outputs.changelog }}
    files: |
      target/*.jar
      target/*.pom
    draft: true
    prerelease: false
    env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Affter the workflow completes, a maintainer should:

  1. Visit the repository’s release page.
  2. Review the draft release content.
  3. Ensure that correct files attached.
  4. Verify that the changelog content is appropriate.
  5. Publish the release when you feel satisfied.

This review steps helps catch issues like

  1. Incorrect version number.
  2. Missing or malformed artifacts
  3. Incomplete or unclear changelog entries.
  4. Premature releases of features.

Once published, your users can see the release. They can download the artifacts through GitHub’s interface.

Best practices

When using the Maven Release plugin with GitHub Actions, follow best practices. They can save you from common pitfalls. For versioning, use semantic versioning (MAJOR.MINOR.PATCH). It shows the impact of changes. Always use SNAPSHOT designators for dev versions. Keep version numbers consistent across all modules in multi — module projects.

Release notes deserve special attention as they serve as a crucial communication tool with your users. Keep a CHANGELOG.md file. It must document all significant changes, breaking changes, and include migration guide. This doucmentation is vital for users to know what has changed between version.

Error handling requires a proactive approach. Set up notifications to alert relevant team members when workflow fail. Well — documented rollback procedures are essential. You don’t want to figure out how to revert a failed release while you team faces a blockage. Regular monitoring of deployment status helps catch issues early.

Security considerations should never be an afterthought. Set a regular schedule to rotate access tokens. Review workflow permissions at regular intervals. Use environment secrets for sensitive data and make sure they have the appropriate scope. A security breach in your release process could have sever effects. So, treat security as continuous process, not a one-time setup.

Troubleshooting

Authentication issues often manifest during release. If you get authentication failures, first check you Personal Access Token (PAT) for the correct permissions. Sometimes token expire or get revoked without notice. Check your secret configuration in the repo settings. Ensure the token names match those in your workflow file.

Build failures during release can occur for various reasons. Start by examinging any test failures in detail. Dependencies might have version conflicts. This is likely uif you use version ranges instead of specific versions. Someone might have misconfigured the build environment. Ensure that your workflow uses the correct Java version and that you have installed all necessary build tools.

Branch protection rules might prevent the workflow from pushing changes, even witha PAT. Double check your Git config in the workflow. Pay attention to the user email and name settings. Push failures can occure to rare network issues between GitHub Actions and your repository.

Remember that the GitHub Actions logs are your best friend when troubleshooting. They provide detailed information about each step in the process and can help pinpoint exactly where things went wrong.

Conclusion

We’ve come a long way in this guide. After all the headaches of manual releases — version updates, git tags, changelogs — we’ve built an automated process. It handles all these tedious tasks for us.

Think about what we’ve done: to make a release now, click button in GitHub Actions, input your version, and let automation do its thing. The Maven release plugin handles version bumps and tagging. Our workflow manages everything from building to creating a draft release. No more manual changelog updates. It’s all generated from your commit message.

But we didn’t go fo full automation wihtout oversight. By creating a draft release, you still get that final check before anything goes public. So, you can review changes, check that all is right, and then publish when ready.

The best part? This isn’t a theoretical setup — you can take this workflow and adapt it to your need. Start with this foundation and customize it as your team gros and your requirements evolve.

Remember, a good software release process shoudn’t be a source of stress or confusion. With the setup we’ve create you can focus your attention on what truly matters — developing excellent feature for your users.

References

  1. Maven Release plugin
  2. GitHub Actions
  3. Conventional commits
  4. GitHub Releases

Subscribe to Egor Voronianskii | Java Development and whatsoever

Sign up now to get access to the library of members-only issues.
Jamie Larson
Subscribe