DEV Community

Fran Iglesias
Fran Iglesias

Posted on

versiontag updated. Supports remove command and --force option

Some days ago I published a simple utility to manage semantic versioning in git projects.

Today, I've just updated it to manage a --force option to avoid the confirmation questions and do the tagging in one shot.

Also, I've added a remove command that helps to remove the last tag, useful if you tag the development without being properly done.

The project is here

GitHub logo franiglesias / versiontag

Bash command to automate tag semantic versioning

versiontag

Bash command to automate tagging with semantic versioning in a git repository.

Current version: v2.1.3

Features

Allow easy maintenance of semantic versioning in git projects.

Since 1.4.2 supports .semver file writing.

Since 2.0.0 tags are not annotated by default. You must use the option -m or --message to annotate the tag.

Commands

help - Shows a help
current - Shows the last version tag found. If there is none it defaults to v0.0.0
patch - Increases patch version: v1.0.0 -> v1.0.1
minor - Increases minor version (and resets patch): v1.0.5 -> v1.1.0
major - Increases major version (and resets minor and patch): v1.3.4 -> v2.0.0
remove - Removes the last tag in the repository. This command doesn't support the -f|--force option.

Options

-h|--help - Shows help.
-f|--force - Script won't ask for confirmation.
-d|--dry - Executes without perform any change.
-m|--message - Annotates the tag with the message.
-s|--semver

And this is the current code for the utility. Feel free to suggest any improvement. I'm learning bash scripting so it would be great to have any help to better organize the code and improve it in any way.

#!/bin/bash

function execute {
    cmd=("$@")
    echo
    echo "Executing ${cmd[*]} ..."
    echo
    # execute the command:
    "${cmd[@]}"
}

function confirm() {
    read -p "$1 ([y]es or [N]o): "
    case $(echo $REPLY | tr '[A-Z]' '[a-z]') in
        y|yes) echo "yes" ;;
        *)     echo "no" ;;
    esac
}

function getMessage() {
    if [[ -z "$@" ]]
    then
        echo false;
    fi

    echo $@
}

function showHelp() {
    echo
    echo "versiontag"
    echo "=========="
    echo
    echo "Automates version tag creation."
    echo 
    echo "Commands: patch|minor|major|current 'Tag message'"
    echo "          remove"
    echo "          current"
    echo
    echo "Examples:"
    echo "---------"
    echo 
    echo "Show current version: ./versiontag current"
    echo "Patch version:        ./versiontag patch 'Fix broken view'"
    echo "Minor version:        ./versiontag minor 'Add Customer filter by email'"
    echo "Major version:        ./versiontag major 'Blog module'"
    echo "Remove last version:  ./versiontag remove"
    echo
    exit 0
}

function showSuccess() {
    echo
    echo "Tag v$major.$minor.$patch was created in local repository."
    echo
    echo "Push it:"
    echo
    echo "    git push origin v$major.$minor.$patch"
    echo
    echo "Delete tag:"
    echo
    echo "    git tag -d v$major.$minor.$patch"
    echo
}


lasttag=`git describe --tags --long` || true

if [[ -z "$lasttag" ]]; then
    lasttag='v0.0.0'
fi

cleantag=${lasttag%%-*}

parts=(${cleantag//./ })

major=${parts[0]:1}
minor=${parts[1]}
patch=${parts[2]}

major=${major:0}
minor=${minor:0}
patch=${patch:0}

last="v$major.$minor.$patch"

mode=''
force=false

while [ -n "$1" ]
do
    case "$1" 
    in
        -f|--force)
            force=true;;
        -h|--help)
            showHelp
            exit 0;;
        patch) 
            patch=$((patch + 1)) 
            msg=$(getMessage "$2")
            shift 1
            mode='patch';;
        minor) 
            minor=$((minor + 1))
            patch=0 
            msg=$(getMessage "$2")
            shift 1
            mode='minor';;
        major) 
            major=$((major + 1)); minor=0
            patch=0 
            msg=$(getMessage "$2")
            shift 1
            mode='major';;
        current)
            echo "Current version: $last"
            exit 0;;
        remove)
            if [[ "yes" == $(confirm "Do you want to remove $last?") ]]; then
                execute git tag -d "$last"
                execute git push origin ":$last"
            fi
            exit 0;;
        help)
            showHelp;;
        *)
            echo "$1 option is not valid"
            exit 1;;
    esac

    shift 1;
done

if [[ false == "$msg" ]]; then
    echo
    echo "No message."
    exit 1;
fi

if [[ -z "$mode" ]]; then
    showHelp;
    exit 0;
fi   

echo "Current version : $last"
echo "New tag         : v$major.$minor.$patch"
echo
echo "Message         : $msg"

if [[ "$force" = true ]]; then
    execute git tag -a "v$major.$minor.$patch" -m "$msg ($mode version)"
    execute git push origin "v$major.$minor.$patch"
    echo 
    echo "Version tag created and pushed"
    exit 0;
fi

if [[ "no" == $(confirm "Do you agree?") ]]; then
    echo
    echo "No tag was created"
    exit 0;
fi

execute git tag -a "v$major.$minor.$patch" -m "$msg ($mode version)"

showSuccess;

if [[ "yes" == $(confirm "Do you want to push this tag right now?") ]]; then
    execute git push origin "v$major.$minor.$patch"
fi

exit 0
Enter fullscreen mode Exit fullscreen mode

Top comments (0)