Skip to content

Instantly share code, notes, and snippets.

@mvsantos
Last active August 9, 2022 16:34
Show Gist options
  • Save mvsantos/4a11a830f796d21583a66c16e274e755 to your computer and use it in GitHub Desktop.
Save mvsantos/4a11a830f796d21583a66c16e274e755 to your computer and use it in GitHub Desktop.
Bump a git repo semver tag.
#!/usr/bin/env bash
set -o errexit
set -o nounset
set -o pipefail
__THIS_FILE__="$(basename "${BASH_SOURCE[0]}")"
SEMVER_REGEX="^[vV]?(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)(\\-[0-9A-Za-z]+){0,1}$"
SEMVER_MAJOR=0
SEMVER_MINOR=0
SEMVER_PATCH=0
SEMVER_SUFFIX=""
NEW_SUFFIX=""
LIGHTWEIGHT_TAG=1
VERSION_BUMPED=0
NEW_VERSION=""
PUSH_TAGS_TO_REPO=""
PREVIOUS_HIGHEST_VERSION=""
function print-usage () {
cat <<USAGE
Usage: bash ${__THIS_FILE__} [OPTIONS]
OPTIONS
--release Creates an annotated tag, instead of the default lightweight git tag.
For more information regarding annotated and lightweight tags see https://git-scm.com/book/en/v2/Git-Basics-Tagging
--major Bumps the 'major' part of the version string. May be used multiple times.
--minor Bumps the 'minor' part of the version string. May be used multiple times.
--patch Bumps the 'patch' part of the version string. May be used multiple times.
This is option is assumed by default if no other option is passed when the script runs.
--suffix <alphanum value> Sets the suffix of the version - e.g. rc1, beta
--push-to <repository> Name of the remote repository to which the newly created tag will be pushed to. e.g. --push-to remote-source-of-truth
USAGE
}
function exit-error () {
echo "$(date +'%Y-%m-%d %H:%M:%S') ERROR: ${1}" 1>&2;
exit 127
}
function set-version-variable () {
NEW_VERSION="v${SEMVER_MAJOR}.${SEMVER_MINOR}.${SEMVER_PATCH}${NEW_SUFFIX}"
}
function extract-version () {
local VERSION=${1}
if [[ "${VERSION}" =~ ${SEMVER_REGEX} ]]; then
SEMVER_MAJOR=${BASH_REMATCH[1]}
SEMVER_MINOR=${BASH_REMATCH[2]}
SEMVER_PATCH=${BASH_REMATCH[3]}
SEMVER_SUFFIX=${BASH_REMATCH[4]}
else
exit-error "Invalid semver string passed to 'extract-version'"
fi
}
function bump-version () {
case "${1}" in
major)
SEMVER_MAJOR=$((SEMVER_MAJOR + 1))
SEMVER_MINOR="0"
SEMVER_PATCH="0"
;;
minor)
SEMVER_MINOR=$((SEMVER_MINOR + 1))
SEMVER_PATCH="0"
;;
patch)
SEMVER_PATCH=$((SEMVER_PATCH + 1))
;;
suffix)
if [[ "${2:-}" =~ ^[0-9A-Za-z]+$ ]]; then
NEW_SUFFIX="-${2}"
else
exit-error "Invalid suffix string."
fi
;;
*)
exit-error "Unknown option passed to 'bump-version'"
;;
esac
VERSION_BUMPED=1
}
function find-last-tag-in-current-repo () {
PREVIOUS_HIGHEST_VERSION=$(git tag -l --sort=-version:refname "v*" | head -n1)
if [[ "x" != "x${PREVIOUS_HIGHEST_VERSION}" ]]; then
echo "This repo's current highest version is ${PREVIOUS_HIGHEST_VERSION}"
echo "This branch's highest version is $(git describe --tags --always --first-parent)"
fi
}
function add-new-tag-to-repo () {
set-version-variable;
if [[ $(git tag -l "${NEW_VERSION}") ]]; then
exit-error "The tag ${NEW_VERSION} already exist."
else
if [[ 1 -eq ${LIGHTWEIGHT_TAG} ]]; then
echo "Creating lightweight tag ${NEW_VERSION}"
git tag "${NEW_VERSION}"
else
echo "Creating annotated tag ${NEW_VERSION}"
git tag -a "${NEW_VERSION}" -m "Release version ${NEW_VERSION}"
fi
fi
}
#
# *** MAIN ***
#
if [[ $# -eq 0 ]]; then
print-usage
exit 0
fi
while [[ $# -gt 0 ]]; do
find-last-tag-in-current-repo
extract-version ${PREVIOUS_HIGHEST_VERSION}
case ${1} in
--major|--minor|--patch )
bump-version ${1//-/}
shift
;;
--suffix )
bump-version suffix ${2}
shift
shift
;;
--release )
LIGHTWEIGHT_TAG=0
shift
;;
--push-to )
PUSH_TAGS_TO_REPO=${2}
shift
shift
;;
-h|--help )
print-usage
exit 0
;;
* )
echo "Error: Unknown option \"${1}\""
exit 127
esac
done
if [[ 1 -eq ${VERSION_BUMPED} ]]; then
[[ -f ./.VERSION ]] && rm -f ./.VERSION
add-new-tag-to-repo
if [[ "x" != "x${PUSH_TAGS_TO_REPO}" ]]; then
echo "# git push --tags \"${PUSH_TAGS_TO_REPO}\" HEAD"
git push --tags "${PUSH_TAGS_TO_REPO}" "refs/tags/${NEW_VERSION}"
fi
echo ${NEW_VERSION} > ./.VERSION
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment