Search code examples
shparameter-expansion

semver increment in shell script


I am trying to implement a solution to increment a version. Here's what I have come up with:

#!/bin/sh -x

VAR=1.0.1 # retrieved from Gitlab API

case $1 in
patch)
    TAG=${VAR%.*}.$((${VAR##*.} + 1))
    ;;

major)
    TAG=$((${VAR%%.*} + 1)).0.0
    ;;

*)
    tmp=${VAR%.*}
    minor=${tmp#*.}
    TAG=${VAR%%.*}.$((minor + 1)).0
    ;;
esac

echo $TAG

major & patch work as expected; however, I'm facing problems incrementing minor.

When bumping 1.0.1, the minor should be 1.1.0; however, my code produces 1.2.0. What am I doing wrong?

Some more info, the script is executed inside a GitlabCI pipeline.

Edit: Updated the code with the suggested answer from @jhnc


Solution

  • Your computation for incrementing minor is:

    TAG=${VAR%%.*}.$((${VAR##*.} + 1)).0
    

    However, ${VAR##*.} gives the patch value, not the minor value, and thus your incorrect result.

    To extract minor, you can use a temporary variable:

    tmp=${VAR%.*}
    minor=${tmp#*.}
    TAG=${VAR%%.*}.$((minor + 1)).0
    

    Alternatively, it may be more readable to set IFS and split the string on dots:

    TAG=$(
       echo "$VAR" | while IFS=. read major minor patch; do
           # add sanity-checks here
           case "$1" in
              patch)
                 echo "$major.$minor.$((patch+1))"
                 ;;
              major)
                 echo "$((major+1).0.0"
                 ;;
              minor|*)
                 echo "$major.$((minor+1)).0" 
                 ;;
           esac
       done
    )
    

    You should probably add sanity-checks to ensure VAR is actually of form "digits dot digits dot digits".