Categories
Development Devops Software

(almost) Native BASH semver CHECK

Recently I needed a simple way to compare semver strings in a BASH script and was unable to find a solution that I liked so I wrote one. Why almost-native BASH? Leveraging the common available sort utility avoids re-implementing the version sort logic, reduces potential bugs and size of the function to a simple 3 lines vs 30+ lines for most BASH-native solutions.

This is working well in environments I manage. If you notice any bugs or issues please comment.

Function returns a standard -1, 0, 1 response. Basic unit tests included to validate functionality and provide example usage.

Enjoy!

#!/usr/bin/env bash

function semver_check {
  # sort low->high then pick the last one (highest)
  local HV; HV=$(echo -e "$1\n$2" |sort -V |tail -1)
  # They're not the same and $1 is not the high version = -1
  [[ "$1" != "$2" && "$1" != "$HV" ]] && echo -1 && return
  # 0 = they're the same; 1 = not the same
  [[ "$1" == "$2" ]]; echo $?
}

#
# TESTS
#

LV="1.2.3"
HV="2.3.4"

ARGS=("Test A: Ver1 == Ver2" "$LV" "$LV")
echo -n "${ARGS[*]} "
[[ $(semver_check "${ARGS[1]}" "${ARGS[2]}") -eq 0 ]] && echo "PASS" || echo "FAIL"

ARGS=("Test B: Ver1 < Ver2" "$LV" "$HV")
echo -n "${ARGS[*]} "
[[ $(semver_check "${ARGS[1]}" "${ARGS[2]}") -lt 0 ]] && echo "PASS" || echo "FAIL"

ARGS=("Test C: Ver1 > Ver2" "$HV" "$LV")
echo -n "${ARGS[*]} "
[[ $(semver_check "${ARGS[1]}" "${ARGS[2]}") -gt 0 ]] && echo "PASS" || echo "FAIL"

ARGS=("Test D: Ver1 >= Ver2" "$HV" "$LV")
echo -n "${ARGS[*]} "
RESULT="PASS"
[[ $(semver_check "${ARGS[1]}" "${ARGS[2]}") -ge 0 ]] || RESULT="FAIL"
[[ $(semver_check "${ARGS[1]}" "${ARGS[1]}") -ge 0 ]] || RESULT="FAIL"
echo ${RESULT}

ARGS=("Test E: Ver1 <= Ver2" "$LV" "$HV")
echo -n "${ARGS[*]} "
RESULT="PASS"
[[ $(semver_check "${ARGS[1]}" "${ARGS[2]}") -le 0 ]] || RESULT="FAIL"
[[ $(semver_check "${ARGS[1]}" "${ARGS[1]}") -le 0 ]] || RESULT="FAIL"
echo ${RESULT}

Addendum: The sort binary dependency must support natural version sort option (-V, --version-sort) This option is available on GNU coreutils 7+ and is also available on Mac OS 10.14+