Automatic Tagging of Releases

Tags are a simple aspect of version control, they allow you to identify specific release versions of your code. You can think of a tag as a functionality that doesn't change.

In the previous post, I pushed the docker image with a hardcoded "latest" tag. I will follow the standard semantic versioning flow to release new changes:

Given a version number Major.Minor.Patch, increment the:

  1. Major version when you make incompatible API changes,
  2. Minor version when you add functionality in a backwards compatible manner, and
  3. Patch version when you make backwards compatible bug fixes.

Define helper script for tagging

  1. Create a build directory in the root application folder
  2. Create a git_update.sh file in the build folder, below are the contents of the shell script:
#!/bin/bash

VERSION=""

# get parameters
while getopts v: flag
do
  case "${flag}" in
    v) VERSION=${OPTARG};;
  esac
done
Read the input parameter
# get highest tag number, and add v0.1.0 if doesn't exist
git fetch --prune --unshallow 2>/dev/null
CURRENT_VERSION=`git describe --abbrev=0 --tags 2>/dev/null`
Fetch latest git tag and start at v0.1.0
# get number parts
VNUM1=${CURRENT_VERSION_PARTS[0]}
VNUM2=${CURRENT_VERSION_PARTS[1]}
VNUM3=${CURRENT_VERSION_PARTS[2]}

if [[ $VERSION == 'major' ]]
then
  VNUM1=v$((VNUM1+1))
elif [[ $VERSION == 'minor' ]]
then
  VNUM2=$((VNUM2+1))
elif [[ $VERSION == 'patch' ]]
then
  VNUM3=$((VNUM3+1))
else
  echo "No version type (https://semver.org/) or incorrect type specified, try: -v [major, minor, patch]"
  exit 1
fi
Based on input parameter, increment the version (major, minor, or patch)
# create new tag
NEW_TAG="$VNUM1.$VNUM2.$VNUM3"
echo "($VERSION) updating $CURRENT_VERSION to $NEW_TAG"

# get current hash and see if it already has a tag
GIT_COMMIT=`git rev-parse HEAD`
NEEDS_TAG=`git describe --contains $GIT_COMMIT 2>/dev/null`

# only tag if no tag already
if [ -z "$NEEDS_TAG" ]; then
  echo "Tagged with $NEW_TAG"
  git tag $NEW_TAG
  git push --tags
  git push
else
  echo "Already a tag on this commit"
fi
Create and push tag to GitHub
echo ::set-output name=git-tag::$NEW_TAG

exit 0
Define git-tag output variable

Add new step for tagging

  1. In the main.yml file, I will add another GitHub action. Every time there's a new commit to the main branch we will increment a specific version (major, minor, or patch):
- name: Automatic Tagging of Releases
        id: increment-git-tag
        run: |
          bash ./build/git_update.sh -v patch
Increment patch version

2. I will then reference the output variable tag for our docker image, we get this from the previous step with the help of the shell script we defined.

IMAGE_TAG: ${{ steps.increment-git-tag.outputs.git-tag }}

See it in action

Commit latest changes to the main branch to see the workflow run the configuration.

Incremented patch version
First tag of our code
Image tagged accordingly

Summary

In general you can increment your version (major, minor, or patch), just replace the specific version on the step that you pass the input:

- name: Automatic Tagging of Releases
        id: increment-git-tag
        run: |
          bash ./build/git_update.sh -v patch

Each time you commit your code will be versioned accordingly, thanks for reading along. In the meantime checkout the repo create-a-ci-pipeline.