A Comprehensive CI/CD Guide: Deploying a Spring Boot Application on Choreo

Buddhima Udaranga
4 min readDec 10, 2023

--

Embarking on the journey of deploying a Spring Boot application as a Docker container in Choreo? Look no further. This concise guide walks you through setting up a robust CI/CD pipeline, ensuring seamless integration from version control to Choreo deployment.

Whether you’re a seasoned developer or new to CI/CD, this tutorial simplifies the process, covering automated testing, containerization, and deployment. By the end, you’ll have a Spring Boot app ready for Choreo, streamlining your development and ensuring reliable application delivery. Ready to dive in? Let’s get started!

Spring Boot Application Development

I used a sample spring boot application that we can simply create using https://start.spring.io/. Since this blog is more focused on the CI CD process I will not go in to Spring Boot Java code level.

https://github.com/Buddhimah/demo-vehicle-service

You can refer to the code from here. This has some APIs related to employee’s. These APIs will return and has the possibility to update some mock data provided using a sql file in resources.

CI Build Automation

For this I have used github actions. This github action is responsible for building the java project and releasing a versioned artifact.

Triggers

We have configured this Github action to trigger on a push to the branch main on this repo, Also this can be triggered by a pull request as well.

Jobs

Here I have used Jobs in Github actions. Job is a set of steps that get executed in a same VM to collectively perform a specific task. Since the task is to build then identify whether build is successful. And if the build is successful trigger a release with release artifacts with latest changes. The version numbers should auto increment.

Since the build and release should happen in the same environment although those two are two steps I used Jobs.

Here I have configured java using a built in Github action actions/setup-java@v3. I have specified java version as Java 17 as the distribution I have used temurin since it is community driven and opensource.

To improve build timing I have added cache: maven, This enables caching in maven dependencies.

Steps

The job consists of two steps the first one is responsible for building the repo with the latest version and creating a release artifact.

  1. Building with the latest version

To fetch the latest version the github action should have access to the latest tag. This requires a token. You can add a token to your github actions via your repo settings.

To retrieve the latest tag of a repository using a GitHub token, you need to ensure that the token has at least read access to the repository. Specifically, the token should have the repo scope, which includes the necessary permissions for reading repository-related data.

Here are the steps to create a GitHub token with the required scope:

Here are the steps to create a GitHub token with the required scope:

  • Go to your GitHub account settings.
  • Navigate to “Developer settings” and then “Personal access tokens.”
  • Click on “Generate token.”
  • Provide a token description and select the appropriate scopes.

At a minimum, you need to select the repo scope. If you only need read access, you can unselect other unnecessary scopes.

Click on “Generate token” to create the token.

You can go to https://github.com/<GITHUB USERNAME>/<REPO NAME>/settings/secrets/actions to configure the created token.

To use this token in github action you can use the following code snippet.

echo ${{ secrets.TOEKN }} | gh auth login — with-token

To fetch the latest tag you can use the following gh command

current_tag=$(gh api repos/Buddhimah/demo-vehicle-service/releases/latest | jq -r ‘.tag_name’)

I have used the following logic to increment the tag version to create the next version.

regex=”v([0–9]+).([0–9]+).([0–9]+)”

Usually we have three number versioning system to identify major minor and patch version changes. So I have defined a regular expression to match with semantic versioning.

if [[ $current_tag =~ $regex ]]; then

major=”${BASH_REMATCH[1]}”

minor=”${BASH_REMATCH[2]}”

patch=”${BASH_REMATCH[3]}”

else

echo “Invalid tag format”

exit 1

fi

Above logic is responsible for matching the latest version with the regular expression and then extracting each of the version numbers.

# Increment the patch version

patch=$((patch + 1))

Assuming all the releases are patch releases this workflow will increment the patch number one by one using the above logic

# Form the new tag

new_tag=”v${major}.${minor}.${patch}”

Finally the new patch number will be appended to the major and minor versions and create the new version.

mvn clean install

mvn -Dmaven.repo.local=./target/ install:install-file -Dfile=./target/employee-0.0.1-SNAPSHOT.jar -DgroupId=com.example -DartifactId=employee -Dversion=$new_version -Dpackaging=jar

The maven clean install command will build the code with tests. During this build if there are any failures that will fail the build.

If the build passes then the next command will have a employee-0.0.1-SNAPSHOT.jar in the target directory. If the build failed the next command will also fail.

Mvn install command manually installing a JAR file into the local Maven repository with specific coordinates (group ID, artifact ID, version). Here I will be installing the employee-0.0.1-SNAPSHOT.jar file as the latest version

echo “new_tag=$new_tag” >> $GITHUB_ENV

echo “new_version=$new_version” >> $GITHUB_ENV

Since the new version and the new tag should be passed to the next step they are being write in to the GITHUB environment variable.

Releasing the artifact

gh release create — title “Release” — notes “Release $new_tag” $new_tag ./target/com/example/employee/$new_version/employee-$new_version.jar

Im using the above gh command to create a release with the new artifact built.

This is the first of a blog series. The next blog will explain on how to create a docker image for this application and then lets discuss on how to deploy this on choreo.

--

--