GitHub Actions CI pipeline: GitHub Packages, Codecov, release to Maven Central & GitHub

No Comments

Stuck with TravisCI? Looking for a worthy alternative to GitLab CI? Here’s a guide on how to create a full CI pipeline publishing GitHub Packages, Codecov reports, releasing to Maven Central and GitHub, including dynamic commitlogs.

GitHub Actions – blog series

Part 1: GitHub Actions CI pipeline: GitHub Packages, Codecov, release to Maven Central & GitHub
Part 2: Publishing Docker images to GitHub Container Registry with GitHub Actions
Part 3: Stop re-writing pipelines! Why GitHub Actions drive the future of CI/CD

Until late 2020 my advice to customers was quite clear on which Continuous Integration platform they should choose. Taking a look at GitLab was (and is!) not a bad idea (I wrote about “the changing of the guard” from Jenkins to GitLab nearly three years ago). I found that their implementation of the pipeline-as-code pattern was the best to date. Plus, having all the deployment options and being able to “just go” with the open-source version simply fitted most scenarios. Also, in complex scenarios the option to use templates was really nice. No need to search for other solutions – getting up to speed in projects was quick and easy.

My open-source projects remained with TravisCI, though. Since I was able to do nearly everything I needed (including even running full VMs with Vagrant) I simply stayed with Travis. But then, for quite a while, it didn’t feel right any more. I think it all started with Idera buying Travis in 2019, after which quite a few engineers were simply thrown out. I guess habit is quite strong sometimes and after I did an estimate of the time it would take to switch to another CI platform, I didn’t find a time slot to migrate all my stuff. And to which platform anyway? Travis was really nicely integrated and it simply worked …

The problem with TravisCI

Well, at least until GitHub released a new way of integrating with third-party CI platforms along with the availability of their own CI solution called GitHub Actions. Soon Travis started to move their GitHub integration to GitHub Apps. Back then, many of my Travis builds stopped working occasionally. And I had renovate configured to do auto-merging …

This didn’t work very well since either repositories didn’t get updated any more, or renovate just pushed changes without running CI. This meant no build and test were run before merging. Soon many of my repositories were just screwed up. But you know, habit can be powerful. I went through my repositories and migrated them to travis-ci.com, since the new GitHub App integration was only available on a completely new Travis clone they released also. This burned many hours where I wasn’t able to work on interesting stuff … I migrated maybe half of my 100+ repositories.

Then, finally, December 2020 came and I realized what the new pricing model of travis-ci.com meant for open-source repositories. All of my migrated repos builds simply used the 10.000 free credits in less than one month. Which meant that around 50 repositories’ CI builds stopped working again. And the other 50 repositories that remained with the old GitHub integration at travis-ci.org were put into read-only mode on December 31st, 2020. Finally nearly none of my open-source projects had a working build any more.

GitHub Actions to the rescue!

Did I say “nearly”? Yeah! I had some repositories running with GitHub Actions already. I created most of them for my lecture on Software Engineering and Java programming at the University of Applied Sciences Erfurt. And I wanted to introduce my students to Continuous Integration in the simplest possible way. Since they were already used to working with GitHub, using Actions was the way to go. Starting in December 2020, I finally migrated more and more repositories from TravisCI to GitHub Actions. Building and testing a Java application, for example, is quite easy. Just have a look at this example build.yml, which builds a Maven project using three parallel jobs with JDK 8, 11 and 15:

name: build

on: [push]

jobs:
  build:
    runs-on: ubuntu-latest

    strategy:
      matrix:
        java-version: [ 8, 11, 15 ]

    steps:
    - uses: actions/checkout@v2
    - uses: actions/setup-java@v1
      with:
        java-version: ${{ matrix.java-version }}
    - run: mvn -B install --no-transfer-progress --file pom.xml

Even running Docker Compose setups with a great library such as Testcontainers is not a problem. Here’s a simple test class from one of my projects, which uses the Docker Compose integration of Testcontainers if you’re interested.

In the beginning of 2021 I wanted to have the most important repositories migrated to GitHub Actions. This included two of our open-source projects at codecentric: the CXF Spring Boot Starter which I was able to create in one of our projets together with my great colleague Marco Paga. Another big project was Spring Boot Admin, which was mainly driven by my former colleague Johannes Edmeier, and which we’re currently taking over in our Spring Boot Admin Expert Group at codecentric (we’re always looking for people who want to join!).

This article’s setup

However, both projects don’t stop with “normal” build or test cases. Since they are used by many people and organizations out there, they are released on Maven Central. These releases also need to be added as GitHub releases. What’s more, they should ideally contain a changelog of all the cool new stuff inside. Additionally there’s a huge developer community taking part in the development of the projects – especially in Spring Boot Admin. So we also need to publish SNAPSHOT versions of every build. Finally we shouldn’t forget to have coverage reports generated and published into the pull requests and commits in general.

GitHub Actions CI-Pipeline overview with GitHub Packages, Codecov, Maven Central and GitHub Releases

Logo sources: GitHub & GitHub Actions & GitHub Packages logo, Codecov logo, Sonatype logo

Publishing SNAPSHOT versions to GitHub Packages

As I like to write comprehensible posts that allow you to easily adapt every step to your own project, we should now get our hands dirty! Fully working examples can be found in the cxf-spring-boot-starter and spring-boot-admin projects on GitHub.

So let’s first start by publishing our Maven artifacts to the GitHub Packages Registry. There’s also an in-depth description in the docs for Java package publishing, along with many other languages. The idea is to have our SNAPSHOT versions available on GitHub Packages – and to use Maven Central for the release versions later.

Therefore we need to add GitHub Packages to our pom.xml‘s distributionManagement section. As we can’t add two repository tags to distributionManagement, we simply use the snapshotRepository tag here for GitHub Packages configuration:

<distributionManagement>
    <repository>
        <id>oss.sonatype.org</id>
        <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
    </repository>
    <snapshotRepository>
        <id>github</id>
        <name>GitHub Packages</name>
        <url>https://maven.pkg.github.com/codecentric/cxf-spring-boot-starter</url>
    </snapshotRepository>
</distributionManagement>

In contrast to the Sonatype deployment, we need to also mind the url of the GitHub Packages configuration in one of the following steps, since it must match your GitHub organization and repository like this:

https://maven.pkg.github.com/yourOrganisationHere/yourRepositoryNameHere

Otherwise we’ll run into errors like this (I “tried” that several times 🙂 ):

Could not find artifact de.codecentric:cxf-spring-boot-starter:jar:2.4.0-20210112.171149-1 in github (https://maven.pkg.github.com/jonashackt/cxf-spring-boot-starter)

A new GitHub Action job

The next step is to create a new publish-snapshot job inside our build.yml workflow. My requirement was to only start the publish-snapshot job if the build job was successfully done. Because if you simply describe two jobs inside a workflow, both jobs will be run in parallel (see this build log for example):

jobs run in parallel if they aren't triggering themselfs

In GitHub Actions we have two options to implement a sequence of jobs. The first possibility is to create a separate workflow in a separate yaml file and use the workflow_run event:

This event occurs when a workflow run is requested or completed, and allows you to execute a workflow based on the finished result of another workflow.

This event is quite similar to the workflow_dispatch event we’ll use later on since it is only triggerable on the default branch (which is master in our example repositories). Using the completed keyword, the workflow_run event can be configured to only run when another workflow has finished. An example publish-snapshot.yml looks like this:

name: publish-snapshot
 
# Only trigger a SNAPSHOT release to GitHub Packages, when the build workflow succeeded
on:
  workflow_run:
    workflows: ["build"]
    types:
      - completed

jobs:
  publish-snapshot:
    runs-on: ubuntu-latest

    steps:
    ...

The “needs” keyword as an elegant trigger

The second option on how to run GitHub Action jobs in sequence is to simply use the needs keyword inside a job definition. This is very elegant since we’re able to define the sequence of Action jobs inside the same workflow file like this:

name: build

on: [push]

jobs:
  build:
    runs-on: ubuntu-latest

    strategy:
      matrix:
        java-version: [ 8, 11, 15 ]

    steps:
    - uses: actions/checkout@v2
    - uses: actions/setup-java@v1
      with:
        java-version: ${{ matrix.java-version }}
    - run: mvn -B install --no-transfer-progress --file pom.xml

  publish-snapshot:
    needs: build
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v2

      - name: Set up settings.xml for GitHub Packages
        uses: actions/setup-java@v1
        with:
          java-version: 8

      - name: Publish SNAPSHOT version to GitHub Packages (we can skip tests since we only deploy if the build workflow succeeded)
        run: mvn -B --no-transfer-progress deploy -DskipTests --projects cxf-spring-boot-starter
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Now the publish-snapshot job is only triggered when our build workflow has successfully done its matrix build with three Java versions. If you don’t need the matrix build, you can even do the mvn install and mvn deploy in one single step if you like. In my scenario I also added the -DskipTests parameter, since the second job doesn’t need to run all tests again. This is already done by our build job. Additionally I added --projects cxf-spring-boot-starter because I have a Maven multi-module project and only wanted this module to be published as a GitHub Package (not the samples).

Last but not least, the GitHub Actions UI implements this kind of sequence quite nicely because we see all depending jobs in one overview:

the build job triggers the publish-snapshot job

After a successful mvn deploy to GitHub Packages, you should also see a new entry on the front page of your repository like this:

GitHub Packages will be listed at the front page of the repository

Also, all of your packages, regardless which repository they were published in, are listed at the top level of your GitHub organization. The docs contain even more detailed information on where your packages will be visible.

Adding coverage reports with JaCoCo

After we have our SNAPSHOT versions published to GitHub Packages, we should also make sure we have a regular coverage report for our builds. Looking at Java-based projects, there’s a widely used framework called JaCoCo (Java Code Coverage library) with a corresponding jacoco-maven-plugin available. Since I wanted to create a separate GitHub Actions job for the coverage report, I also applied a separate Maven profile inside our pom.xml like this:

        <profile>
        <id>coverage</id>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.jacoco</groupId>
                    <artifactId>jacoco-maven-plugin</artifactId>
                    <version>${build-plugin.jacoco.version}</version>
                    <executions>
                        <!-- Prepares the property pointing to the JaCoCo runtime agent
                        which is passed as VM argument when Maven the Surefire plugin is executed. -->
                        <execution>
                            <goals>
                                <goal>prepare-agent</goal>
                            </goals>
                        </execution>
                        <!-- Ensures that the code coverage report is created after
                        all tests have been run. -->
                        <execution>
                            <id>generate-report</id>
                            <goals>
                                <goal>report</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    </profile>

Using the Maven command mvn verify -P coverage, we can now generate the coverage report. It will be placed inside the usual target/site/jacoco directory. But that’s only half the battle. We also need some sort of frontend where we can get insights into the coverage reports over time. Additionally it would be great to have an integration into our CI process to see if coverage increases or decreases with new commits and pull requests. For many years I used coveralls.io in many of my open-source repositories. But sadly the Coveralls GitHub Action doesn’t support JaCoCo/Java out-of-the-box at the moment (see this issue) and there doesn’t seem to be a roadmap as to whether this is going to be supported in the near future.

Visualizing coverage reports using Codecov.io

It’s often a good start to get some inspiration by looking into the issue’s discussions. For example, the cucumber-jvm team switched over to Codecov. As I’d had it on my list for a long time, I thought, why not also use it inside our repos? And the Codecov GitHub Action supports Java and JaCoCo out-of-the-box. Now we can create a new GitHub Actions job inside our build.yml workflow that does everything coverage-related. The job again uses the needs keyword to be dependent on the build job:

...
  coverage:
    needs: build
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-java@v1
        with:
          java-version: 15
      - run: mvn -B verify -P coverage --no-transfer-progress

      - uses: codecov/codecov-action@v1
        with:
          file: ./**/target/site/jacoco/jacoco.xml
          name: codecov
...

As already done with the publish-snapshot job, we use only one Java version and explicitly specify our coverage Maven profile here. Be sure to also create a Codecov orga if you don’t have it already. Simply log in at codecov.com with your GitHub login, for example. You can also add the repository to your Codecov orga. Just click on the Settings tag of your newly created Codecov repo and you should see a nice badge generated for your repo’s README.md.

Now, running our GitHub Actions build workflow including the new coverage job, we should see the reports of all of our repos inside the Codecov portal like this:

the Codecov portal shows all coverage reports

If a new commit or pull request is submitted to our repository, we now also see a great overview on how the coverage changed with those code changes:

Codecov coverage report inside a pull request

The full build.yml workflow file with matrix build, coverage, and SNAPSHOT publishing is available on GitHub.

Learning from rultor …

Let’s now focus on the release to Maven Central. Already having a dedicated GitHub Actions workflow for our default build, it would be great to be able to have another workflow file specifically for the Maven Central release. As it’s absolutely no problem to have multiple workflow files with GitHub Actions we simply create a second workflow called release-to-maven-central.yml.

Thinking about the Maven Central release, I often realize that this process is something you don’t do on an everyday basis. Looking at the two Spring-Boot-related projects mentioned above, I see a pattern, namely that we tend to release about once every 1-3 months. For the cxf-spring-boot-starter project I learned to love the tooling around rultor. There was also a great blog post from the inventor of rultor back then on how to release to Maven Central with just mentioning a bot inside a GitHub issue. I found that this kind of solution was a great fit for many small to medium open-source projects since mentioning a person or bot is something you always remember how to do – even if it was months ago.

A UI trigger for the Maven Central release

However, since the rultor development somehow stopped in mid-2020 and the Maven version was quite old, I wanted to create a similar experience using GitHub Actions’s built-in tooling only. After some research I found a great feature on how to trigger GitHub Actions through the GitHub Actions UI. This incorporates the workflow_dispatch event, which I included into our newly created release-to-maven-central.yml inside our .github/workflows directory:

name: release-to-maven-central
on:
  workflow_dispatch:
    inputs:
      releaseversion:
        description: 'Release version'
        required: true
        default: '2.4.0'
jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
    - run: |
        echo "Release version ${{ github.event.inputs.releaseversion }}!"

Using the workflow_dispatch:inputs field, we can configure a UI element where we can set the release version dynamically right before triggering the Maven Central release workflow (or any other release workflow). There’s only one small pain point which is mentioned in the docs:

To trigger the workflow_dispatch event on GitHub, your workflow must be in the default branch.

Therefore we need to merge this workflow to master/main first. After the merge, our GitHub Actions UI should look as intended:

The GitHub Actions UI shows a menu item for the version number and the button to trigger the release workflow

Also, the variable we defined inside the workflow_dispatch:inputs field is accessible inside the GitHub Actions workflow! The variable ${{ github.event.inputs.releaseversion }} can be simply printed into the build log as shown in the code above. Now clicking onto run workflow, it will print the version into the log:

The variable definded in the workflow_dispatch could be used inside the workflow itself

Preparing your project for the Maven Central deployment

This article assumes that you already have a suitable pom.xml to run a successful Maven Central deployment. Both example projects also provide a pom.xml that has everything in place. Escpecially a correct distributionManagement section (we’ll cover that in a moment) and a separate Maven profile like central-deploy containing no less than five plugins are crucial. Just to be sure you don’t miss anything, these are: the maven-source-plugin & maven-javadoc-plugin, the maven-deploy-plugin & the nexus-staging-maven-plugin and finally the maven-gpg-plugin.

Escpecially for the latter, one needs to generate a key pair with GPG and distribute the public key to key servers. There’s a good article in the Sonatype docs on how to do that. In this post we assume that you already created and distributed your key as described in the linked Sonatype docs. To make sure you didn’t miss anything, I recommend you take a look into the Sonatype docs on how to deploy to Maven Central. Here’s also a fully working example pom.xml of the cxf-spring-boot-starter project containing all the necessary plugins inside the central-deploy profile.

Creating encrypted variables in GitHub Actions

Now coming back to GitHub Actions, I have to admit I was really amazed at one thing. The GitHub Action setup-java already ships with a pre-configured settings.xml we can use for the Maven Central deployment!

“…it also configures a Maven settings.xml for publishing packages. By default, the settings file will be configured for GitHub Packages, but it can be configured to deploy to another package registry, such as the Maven Central Repository.

So the only thing we need to do here is to create some variables containing the required credentials for the Sonatype Maven repo! In fact we need to configure four encrypted variables for the Maven Central release process. Both OSS_SONATYPE_USERNAME and OSS_SONATYPE_PASSWORD are crucial for the Sonatype Nexus access. The MAVEN_GPG_PRIVATE_KEY and MAVEN_GPG_PASSPHRASE are important for the signing of our artifacts that will get uploaded to the Sonatype Nexus. Therefore, head over to the Settings tab of your repository and go to Secrets. There should be a button New repository secret:

Using GitHub encrypted secrets to store the needed variables

Use your Sonatype Nexus credentials to create the variables OSS_SONATYPE_USERNAME and OSS_SONATYPE_PASSWORD. Then you need to also create the other two variables. If you have multiple private keys listed when running gpg --list-secret-keys, you need to export the one you chose for signing the Sonatype artifacts only! This can be done with:

gpg --output private.pgp --armor --export-secret-key username@email

Now fill the contents of the newly exported private.pgp into the GitHub repository secret named MAVEN_GPG_PRIVATE_KEY and the corresponding passphrase into MAVEN_GPG_PASSPHRASE. As we only use this key for the signing of Maven Central artifacts, it should be okay to simply use GitHub encrypted secrets here. If you want to know more about GitHub’s encrypted variables, take a look at the docs. Please never ever use a key you use for any other use case here!

Completing the GitHub Actions Maven Central release workflow

We’re nearly there now! We can now start using the pre-configured settings.xml from the setup-java Action to do our Maven release. Depending on your pom.xml‘s distributionManagement section, we need to configure the server-id correctly. In the cxf-spring-boot-starter project’s pom.xml this is oss.sonatype.org. Make sure to also have the correct url to the Sonatype repo inside the distributionManagement section:

<distributionManagement>
    <repository>
        <id>oss.sonatype.org</id>
        <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
    </repository>
    <snapshotRepository>
        <id>github</id>
        <name>GitHub Packages</name>
        <url>https://maven.pkg.github.com/codecentric/cxf-spring-boot-starter</url>
    </snapshotRepository>
</distributionManagement>

Now let’s complete the release-to-maven-central.yml GitHub Actions workflow file. Therefore we use our newly created encrypted secrets to override the values of the pre-configured settings.xml:

name: release-to-maven-central
on:
  workflow_dispatch:
    inputs:
      releaseversion:
        description: 'Release version'
        required: true
        default: '2.4.0'
jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - run: echo "Will start a Maven Central upload with version ${{ github.event.inputs.releaseversion }}"

      - uses: actions/checkout@v2

      - name: Set up Maven Central Repository
        uses: actions/setup-java@v1
        with:
          java-version: 11
          server-id: oss.sonatype.org
          server-username: MAVEN_USERNAME
          server-password: MAVEN_PASSWORD
          gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }}
          gpg-passphrase: MAVEN_GPG_PASSPHRASE

      - name: Set projects Maven version to GitHub Action GUI set version
        run: mvn versions:set "-DnewVersion=${{ github.event.inputs.releaseversion }}"

      - name: Publish package
        run: mvn --batch-mode clean deploy -P central-deploy -DskipTests=true
        env:
          MAVEN_USERNAME: ${{ secrets.OSS_SONATYPE_USERNAME }}
          MAVEN_PASSWORD: ${{ secrets.OSS_SONATYPE_PASSWORD }}
          MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}

Using the maven-versions-plugin, we also set the version number to the value that was inserted into the GitHub actions UI we created with the workflow_dispatch event. Defining some environment variables, we finally deploy our application to Maven Central.

Only if you run into the Tackling the 'gpg: signing failed: Inappropriate ioctl for device' error should you examine the configuration of the maven-gpg-plugin inside your pom.xml more closely. Just add the following gpgArguments to the configuration using the --pinentry-mode parameter:

<plugin>
	<artifactId>maven-gpg-plugin</artifactId>
	<version>${maven-gpg-plugin.version}</version>
	<executions>
	  <execution>
	    <id>sign-artifacts</id>
	    <phase>verify</phase>
	    <goals>
	      <goal>sign</goal>
	    </goals>
		<configuration>
		  <!-- This is necessary for gpg to not try to use the pinentry programs -->
		  <gpgArguments>
			  <arg>--pinentry-mode</arg>
			  <arg>loopback</arg>
		  </gpgArguments>
		</configuration>
	  </execution>
	</executions>
</plugin>

Now it’s time to let our release-to-maven-central workflow run again! Create a new release by simply clicking on Run workflow. The resulting build log output should look similar to this successful Maven Central Release GitHub Actions build. If you check Maven Central, you should find the newly released artifact also (this could take some time though due to synchronization issues):

A successful Maven Central release shows up in the webfrontend

That’s great news! We successfully released to Maven Central 🙂

Creating a GitHub release with every Maven Central release

We could stop here. But there’s one more thing, I guess. Being now able to automatically create Maven Central releases of our project using GitHub Actions, we can go one step further. Wouldn’t it be cool to have a GitHub release on our repository’s front page containing the newly released jar files?

There are multiple release actions out there. I went with the GitHub default create-release action, which should easily create a new release for us. Let’s enhance our release-to-maven-central.yml:

      - name: Create GitHub Release
        id: create_release
        uses: actions/create-release@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          tag_name: ${{ github.event.inputs.releaseversion }}
          release_name: ${{ github.event.inputs.releaseversion }}
          body: |
            Grab the new version from Maven central https://repo1.maven.org/maven2/de/codecentric/cxf-spring-boot-starter/${{ github.event.inputs.releaseversion }}/ by using it in your deps (also use the newest cxf-spring-boot-starter-maven-plugin https://github.com/codecentric/cxf-spring-boot-starter-maven-plugin):

            ```
            <dependencies>
            	<dependency>
            	    <groupId>de.codecentric</groupId>
            	    <artifactId>cxf-spring-boot-starter</artifactId>
            	    <version>${{ github.event.inputs.releaseversion }}</version>
            	</dependency>
            </dependencies>
            ```
          draft: false
          prerelease: false

Inside the release_name and tag_name variables we simply use the version number we defined through the GitHub Actions workflow UI. The action also creates a Git tag inside our repo for us – so no need to do this ourselves. Using the body tag’s capabilities of multi-line comments, we also add a description of where our newly released jar can be downloaded from (Maven Central) and how to embed it into your project. All this is dynamically based on the ${{ github.event.inputs.releaseversion }} variable again.

Extending the GitHub Release with a changelog

We can even improve our GitHub release even more if we add a changelog to the body. Again, there are multiple actions that generate changelogs for us automatically. Maybe you’re looking for a really simple one which only lists the commits that are new inside this release compared to the last one. Then you can check out metcalfc/changelog-generator. It’s really straightforward to use. Before our create-release phase, we add it to generate the changelog:

- name: Generate changelog
  id: changelog
  uses: metcalfc/changelog-generator@v0.4.4
  with:
    myToken: ${{ secrets.GITHUB_TOKEN }}

Now we’re able to use the generated log inside the body tag with ${{ steps.changelog.outputs.changelog }} in our create-release step:

      - name: Create GitHub Release
        id: create_release
        uses: actions/create-release@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          tag_name: ${{ github.event.inputs.releaseversion }}
          release_name: ${{ github.event.inputs.releaseversion }}
          body: |
            Grab the new version from Maven central https://repo1.maven.org/maven2/de/codecentric/cxf-spring-boot-starter/${{ github.event.inputs.releaseversion }}/ by using it in your deps (also use the newest cxf-spring-boot-starter-maven-plugin https://github.com/codecentric/cxf-spring-boot-starter-maven-plugin):

            ```
            <dependencies>
            	<dependency>
            	    <groupId>de.codecentric</groupId>
            	    <artifactId>cxf-spring-boot-starter</artifactId>
            	    <version>${{ github.event.inputs.releaseversion }}</version>
            	</dependency>
            </dependencies>
            ```
 
            ### Things that changed in this release
            ${{ steps.changelog.outputs.changelog }}
          draft: false
          prerelease: false

Finally, after another release-to-maven-central workflow run, we should see a new release on our repository’s front page:

A new GitHub Release shows up at the repository's front page

Digging into the very details of this release, we should see a customized download advice to our released JAR – together with a nice changelog list:

A GitHub Release detail description incorporating a changelog

GitHub Actions are here to stay!

Wow! I have to admit I really fell in love with GitHub Actions in the end 🙂 I also have to admit that in the beginning I wasn’t really aware of the power implicit in the second part of the name – “Actions”. But what makes GitHub Actions really a pleasure to work with is the great variety of all the many different actions out there. Be it GitHub’s own maintained actions – or all the community actions available. Quoting from the docs:

Actions are the smallest portable building block of a workflow. You can create your own actions, or use actions created by the GitHub community.

From my experience as an architect and developer who has worked in the DevOps space for more than a decade, this could be a game changer! None of the CI/CD platforms I know have this advantage that brings you up to speed as quickly. No more creating your own building blocks – just pick the ones you need and get started! I hope I was able to show some of the magic that’s possible with GitHub Actions. We publish our SNAPSHOT versions to GitHub Packages and create Codecov coverage reports on every push made to our repository. Also, we crafted a nice way to do our Maven Central releases with GitHub Actions and didn’t even forget to create cool GitHub releases including commitlogs.

I really hope I was able to inspire you to check out GitHub Actions. I think they are absolutely worth a try. If you’re working on open-source projects on GitHub, there’s hardly anything better at the moment. I’d really like to hear about your experiences in the comments!

Jonas Hecht

After falling in love with Spring, Jonas also developed an interest in all container- and infrastructure-related topics. Now he focuses on bringing methods like Test-driven Development and Continuous Integration into the world of infrastructure code. He founded the codecentric branch in Erfurt/Thuringia and is involved in the local community, organizing the Java User Group Thüringen, DevOps Thüringen, and IoT Thüringen meetups. He loves to write blog posts & give lectures at Thuringian universities. Spare time is reserved for his family and mountain biking.

Comment

Your email address will not be published. Required fields are marked *