The GitHub “Release” page for a repository can provide your consumers a convenient way to download a binary version of your software as well as track the latest changes and enhancements.
In this article, I will show how to invoke a local release process for a Java Spring Boot jar built with Gradle. A new Github release will be created based on semantic tags (e.g. v1.0.1) that includes the relevant commits as release notes and the Spring Boot jar as an asset.
If you want to instead use an automated Github Actions workflow to generate the release, see my other article here.
Prerequisites
- Install the Github CLI
- Install a Java compiler
- sudo apt search openjdk-* | grep ‘^openjdk\-‘ | grep ‘\-jdk’
- sudo apt install openjdk-xx-jdk
Calculate Semantic version tag
Our process will be to create a semantic tag for every release (e.g. v1.0.1). If there is already a semantic tag defined, we will increment its minor patch to get the next release (e.g. v1.0.1 -> v1.0.2).
We need to discover if the current branch is already semantically tagged. If it is, then we will increment the minor patch. If not, then we assume we are at “v1.0.0”
# get current list of semantic tags git tag --sort=-committerdate | grep ^v # get latest semantic tag, will be empty if none defined yet semantic_version=$(git tag --sort=-committerdate | grep ^v | grep -Po '^v[0-9]*.[0-9]*.[0-9]*' | head -n1) # if non-empty, calculate next patch version major_minor=$(echo "$semantic_version" | cut -d'.' -f1-2) patch=$(echo "$semantic_version" | cut -d'.' -f3) ((patch++)) newtag="${major_minor}.${patch}" # if latest semantic_version was empty, that means we are starting fresh [ -n "$semantic_version" ] || newtag="v1.0.0" echo "The new semantic tag is: $newtag"
Gradle build of Spring Boot jar
You can view my build.gradle for an example, or you can build a project from scratch using https://start.spring.io/
# should have a 'bootJar' task ./gradlew tasks | grep bootJar # build jar without version name in suffix ./gradlew bootJar -Pversion='' # get path to boot jar for uploading to release later artifact_name=$(cat settings.gradle | grep 'rootProject.name' | awk '{print $3}' | tr -d "'") boot_jar=build/libs/$artifact_name.jar [ -f $boot_jar ] && echo "boot_jar exists as $boot_jar" || echo "cannot find $boot_jar"
Generate Release notes
Each release has a set of optional release notes so consumers can see what has changed, been fixed, etc.
For our small, single contributor project we just want the release notes to be based on direct commits to the repository.
# commits between latest HEAD and the previous version git log HEAD...${semantic_version} --pretty="- %s " | tee /tmp/$newtag.log # if semantic_version was empty and newtag=v1.0.0 git log --pretty="- %s " | tee /tmp/$newtag.log
Note: the Github CLI has a ‘generate-notes‘ flag that will create release notes based on merged pull requests.
Create Github Release
Finally, create the release in the Github repository.
# commit all changes git commit -a -m "changes for new tag $newtag" # create new tag and push git tag $newtag && git push origin $newtag # pull all commits git push # create release, attach Go binary gh release create $newtag -F /tmp/$newtag.log $boot_jar
Now if you go to your Github repo’s “Releases” section, you should see something similar to the screenshot below with release notes and the Spring Boot jar as an asset.
I have wrapped up the logic in this article into a Bash script, create_new_gh_release.sh
REFERENCES
stackoverflow, git commits between tags
cli.github.com, Github CLI manual
spring.start.io – starter for Spring Boot Project, provides entire project skeleton for gradle
NOTES
Example of starting Spring Boot project with Gradle using spring.start.io
# variables to be used in project creation id=spring-boot-example artifact_id="${id//-}" SpringAppClassName=SpringMain version="0.0.1-SNAPSHOT" groupId="org.fabianlee" # send parameters that create zip containing SpringBoot project curl https://start.spring.io/starter.zip \ -d type=gradle-project \ -d dependencies=web,prometheus,devtools,actuator \ -d javaVersion=11 \ -d bootVersion=2.7.0 \ -d groupId=$groupId \ -d artifactId=$artifact_id \ -d name=$SpringAppClassName \ -d baseDir=$id \ -d version=$version \ -o $id.zip # unzip archive to directory unzip $id.zip cd $id chmod +x ./gradlew # validate jar build is successful, with no errors ./gradlew bootJar