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 Go language binary. 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 statically-compiled Go binary as an asset.
Prerequisites
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"
Compile GoLang binary
This will be specific to your project and its packaging/dependencies, but for a simple source file ‘src/main.go’ with minimal dependencies, here is an example that would create a ‘build/main’ executable.
# build simple GoLang executable mkdir -p build cp src/main.go build/. cd build go mod init myowner/mypackage go mod tidy go build main.go cd .. # path to executable for upload to the release later go_binary=build/main
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 " > /tmp/$newtag.log # if semantic_version was empty and newtag=v1.0.0 git log --pretty="- %s " > /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 $go_binary
Now if you go to your Github repo’s “Releases” section, you should see something similar to the screenshot below.
I have wrapped up the logic in this article into a Bash script, create_new_gh_release.sh
REFERENCES
stackoverflow, git commits between tags