How to use github actions to create and deploy springboot jar and the corresponding docker image?
While GitHub has been the primary choice for an SCM tool for many of us, with the integration of various CI tools and ready-made actions, it is growing as an end-to-end solution for complete DevOps practices.
At my workplace, we are now using GitLab for various purposes(migrated from Bitbucket and TeamCity), and it has been a smooth migration so far. But I wanted to explore similar features in GitHub as I was already familiar with the interface and hosting almost all of my side projects there.
For this purpose, I set up a build pipeline for a springboot project. The project is dependent on another library project, so I had to build the library repository first to refer to its jar as a dependency while running a Maven build on the springboot project. I also wanted to publish the docker image of the springboot project as part of the same build pipeline.
To summarize the sequence of steps, here is an overview:
Thanks to the availability of re-usable actions like actions/checkout@v3
or actions/setup-java@v3
, this step was straightforward. All I had to do was include the repository
tag in distributionManagement
section in the pom.xml and add a GitHub action to push the jar in the package repository.
<distributionManagement>
<repository>
<id>github</id>
<name>GitHub Packages</name>
<url>https://maven.pkg.github.com/owner/repo-name</url>
</repository>
</distributionManagement>
And here is the github workflow that I used:
name: build
# trigger the build on push to master branch (excluding some files)
# or when a PR is raised on master branch
on:
push:
branches: [ master ]
paths-ignore:
- 'README.md'
- '**/*.yml'
pull_request:
branches: [ master ]
workflow_dispatch:
# to be used later
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
jobs:
build:
# base image to be used for running pipeline
runs-on: ubuntu-latest
steps:
# checkout code
- name: Checkout code
uses: actions/checkout@v3
# setup openjdk20
- name: Set up Java
uses: actions/setup-java@v3
with:
java-version: '20'
distribution: 'oracle'
cache: maven
# run maven build
- name: Build and Test
run: |
mvn clean install
# if the current event is a push on master
# branch, publish the corrresponding jar to
# github package repository
- name: Publish JAR to GitHub Package Registry
if: ${{ github.event_name != 'pull_request' }}
run: mvn --batch-mode deploy
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
The workflow will handle the maven build and jar push to the GitHub package repository. As mentioned in the comments, there are two triggers for this:
It may be because I am a newbie in the GitHub actions world, but building the springboot repository was a bit more complicated due to the following reasons:
To start with, one needs a personal access token (PAT) with read/write permissions for the user.
Additionally, create a settings.xml file with relevant private repository details to fetch the dependent jar. This setting.xml will contain the required credentials to access the private repository.
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
http://maven.apache.org/xsd/settings-1.0.0.xsd">
<activeProfiles>
<activeProfile>github</activeProfile>
</activeProfiles>
<profiles>
<profile>
<id>github</id>
<repositories>
<repository>
<id>central</id>
<url>https://repo1.maven.org/maven2</url>
</repository>
<repository>
<id>github</id>
<url>https://maven.pkg.github.com/owner/repo-name</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
<releases>
<enabled>true</enabled>
</releases>
</repository>
</repositories>
</profile>
</profiles>
<servers>
<server>
<id>github</id>
<username>${GH_USERNAME}</username>
<password>${GH_TOKEN}</password>
</server>
</servers>
</settings>
The GH_USERNAME
and GH_TOKEN
map to the current user and its personal token, respectively. Once the settings file is available in the SpringBoot repository, we create these two secrets in the same repository with the relevant details.
The next step is to trigger the GitHub action workflow and direct it to use this settings.xml to download the library jar from the private repository.
name: build
on:
push:
branches: [ master ]
paths-ignore:
- 'README.md'
- '**/*.yml'
pull_request:
branches: [ master ]
workflow_dispatch:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Set up Java
uses: actions/setup-java@v3
with:
java-version: '20'
distribution: 'oracle'
cache: maven
- name: Build and Test
run: |
mvn clean install -s settings.xml -DGH_USERNAME=${{ secrets.GH_USERNAME }} -DGH_TOKEN=${{ secrets.GH_TOKEN }}
- name: Publish JAR to GitHub Package Registry
if: ${{ github.event_name != 'pull_request' }}
run: mvn --batch-mode deploy
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Publish Docker image to GitHub Container Registry
if: ${{ github.event_name != 'pull_request' }}
# some issue with the post formatting here
# the three lines in run command are to the
# right (two space indentation)
run: |
echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $GITHUB_ACTOR --password-stdin
docker build -t ghcr.io/$GITHUB_REPOSITORY/image-name:latest .
docker push ghcr.io/$GITHUB_REPOSITORY/image-name:latest
Pay close attention to mvn clean install -s settings.xml -DGH_USERNAME=${{ secrets.GH_USERNAME }} -DGH_TOKEN=${{ secrets.GH_TOKEN }}
where we trigger the maven build with a custom settings.xml, passing the credentials to access private repository.
And that’s it. With the help of reusable actions, we are able to run end-to-end build pipelines that deploy the final artifacts to respective repositories.
That is all for this post. If you want to share any feedback, please drop me an email, or contact me on any social platforms. I’ll try to respond at the earliest. Also, please consider subscribing feed for regular updates.
Be notified of new posts. Subscribe to the RSS feed.