Semi-automate minor/patch version tagging
This commit is contained in:
		
							parent
							
								
									f813ac2642
								
							
						
					
					
						commit
						7d976e5271
					
				
							
								
								
									
										12
									
								
								Makefile
								
								
								
								
							
							
						
						
									
										12
									
								
								Makefile
								
								
								
								
							|  | @ -61,3 +61,15 @@ tools: | ||||||
| TAG  = $(shell git describe --tags --abbrev=0 HEAD) | TAG  = $(shell git describe --tags --abbrev=0 HEAD) | ||||||
| LAST = $(shell git describe --tags --abbrev=0 HEAD^) | LAST = $(shell git describe --tags --abbrev=0 HEAD^) | ||||||
| BODY = "`git log ${LAST}..HEAD --oneline --decorate` `printf '\n\#\#\# [Build Info](${BUILD_URL})'`" | BODY = "`git log ${LAST}..HEAD --oneline --decorate` `printf '\n\#\#\# [Build Info](${BUILD_URL})'`" | ||||||
|  | 
 | ||||||
|  | release/minor: | ||||||
|  | 	git fetch origin master | ||||||
|  | 	bash -c 'if git branch | grep autorelease; then git branch -D autorelease; else echo no branch to be cleaned; fi' | ||||||
|  | 	git checkout -b autorelease origin/master | ||||||
|  | 	hack/semtag final -s minor | ||||||
|  | 
 | ||||||
|  | release/patch: | ||||||
|  | 	git fetch origin master | ||||||
|  | 	bash -c 'if git branch | grep autorelease; then git branch -D autorelease; else echo no branch to be cleaned; fi' | ||||||
|  | 	git checkout -b autorelease origin/master | ||||||
|  | 	hack/semtag final -s patch | ||||||
|  |  | ||||||
|  | @ -754,3 +754,9 @@ See #155 for more information on this topic. | ||||||
| ## Examples | ## Examples | ||||||
| 
 | 
 | ||||||
| For more examples, see the [examples/README.md](https://github.com/roboll/helmfile/blob/master/examples/README.md) or the [`helmfile.d`](https://github.com/cloudposse/helmfiles/tree/master/helmfile.d) distribution of helmfiles by [Cloud Posse](https://github.com/cloudposse/). | For more examples, see the [examples/README.md](https://github.com/roboll/helmfile/blob/master/examples/README.md) or the [`helmfile.d`](https://github.com/cloudposse/helmfiles/tree/master/helmfile.d) distribution of helmfiles by [Cloud Posse](https://github.com/cloudposse/). | ||||||
|  | 
 | ||||||
|  | # Attribution | ||||||
|  | 
 | ||||||
|  | We use: | ||||||
|  | 
 | ||||||
|  | - [semtag](https://github.com/pnikosis/semtag) for automated semver tagging. I greatly appreciate the author(pnikosis)'s effort on creating it and their kindness to share it! | ||||||
|  |  | ||||||
|  | @ -0,0 +1,623 @@ | ||||||
|  | #!/usr/bin/env bash | ||||||
|  | 
 | ||||||
|  | PROG=semtag | ||||||
|  | PROG_VERSION="v0.1.0" | ||||||
|  | 
 | ||||||
|  | SEMVER_REGEX="^v?(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(\-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$" | ||||||
|  | IDENTIFIER_REGEX="^\-([0-9A-Za-z-]+)\.([0-9A-Za-z-]+)*$" | ||||||
|  | 
 | ||||||
|  | # Global variables | ||||||
|  | FIRST_VERSION="v0.0.0" | ||||||
|  | finalversion=$FIRST_VERSION | ||||||
|  | lastversion=$FIRST_VERSION | ||||||
|  | hasversiontag="false" | ||||||
|  | scope="patch" | ||||||
|  | displayonly="false" | ||||||
|  | forcetag="false" | ||||||
|  | forcedversion= | ||||||
|  | versionname= | ||||||
|  | identifier= | ||||||
|  | 
 | ||||||
|  | HELP="\ | ||||||
|  | Usage: | ||||||
|  |   $PROG | ||||||
|  |   $PROG getlast | ||||||
|  |   $PROG getfinal | ||||||
|  |   $PROG (final|alpha|beta|candidate) [-s <scope> (major|minor|patch|auto) | -o] | ||||||
|  |   $PROG --help | ||||||
|  |   $PROG --version | ||||||
|  | Options: | ||||||
|  |   -s         The scope that must be increased, can be major, minor or patch. | ||||||
|  |                The resulting version will match X.Y.Z(-PRERELEASE)(+BUILD) | ||||||
|  |                where X, Y and Z are positive integers, PRERELEASE is an optionnal | ||||||
|  |                string composed of alphanumeric characters describing if the build is | ||||||
|  |                a release candidate, alpha or beta version, with a number. | ||||||
|  |                BUILD is also an optional string composed of alphanumeric | ||||||
|  |                characters and hyphens. | ||||||
|  |                Setting the scope as 'auto', the script will chose the scope between | ||||||
|  |                'minor' and 'patch', depending on the amount of lines added (<10% will | ||||||
|  |                choose patch). | ||||||
|  |   -v         Specifies manually the version to be tagged, must be a valid semantic version | ||||||
|  |                in the format X.Y.Z where X, Y and Z are positive integers. | ||||||
|  |   -o         Output the version only, shows the bumped version, but doesn't tag. | ||||||
|  |   -f         Forces to tag, even if there are unstaged or uncommited changes. | ||||||
|  | Commands: | ||||||
|  |   --help     Print this help message. | ||||||
|  |   --version  Prints the program's version. | ||||||
|  |   get        Returns both current final version and last tagged version. | ||||||
|  |   getlast    Returns the latest tagged version. | ||||||
|  |   getfinal   Returns the latest tagged final version. | ||||||
|  |   getcurrent Returns the current version, based on the latest one, if there are uncommited or | ||||||
|  |                unstaged changes, they will be reflected in the version, adding the number of | ||||||
|  |                pending commits, current branch and commit hash. | ||||||
|  |   final      Tags the current build as a final version, this only can be done on the master branch. | ||||||
|  |   candidate  Tags the current build as a release candidate, the tag will contain all | ||||||
|  |                the commits from the last final version. | ||||||
|  |   alpha      Tags the current build as an alpha version, the tag will contain all | ||||||
|  |                the commits from the last final version. | ||||||
|  |   beta       Tags the current build as a beta version, the tag will contain all | ||||||
|  |                the commits from the last final version." | ||||||
|  | 
 | ||||||
|  | # Commands and options | ||||||
|  | ACTION="getlast" | ||||||
|  | ACTION="$1" | ||||||
|  | shift | ||||||
|  | 
 | ||||||
|  | # We get the parameters | ||||||
|  | while getopts "v:s:of" opt; do | ||||||
|  |   case $opt in | ||||||
|  |     v) | ||||||
|  |       forcedversion="$OPTARG" | ||||||
|  |       ;; | ||||||
|  |     s) | ||||||
|  |       scope="$OPTARG" | ||||||
|  |       ;; | ||||||
|  |     o) | ||||||
|  |       displayonly="true" | ||||||
|  |       ;; | ||||||
|  |     f) | ||||||
|  |       forcetag="true" | ||||||
|  |       ;; | ||||||
|  |     \?) | ||||||
|  |       echo "Invalid option: -$OPTARG" >&2 | ||||||
|  |       exit 1 | ||||||
|  |       ;; | ||||||
|  |     :) | ||||||
|  |       echo "Option -$OPTARG requires an argument." >&2 | ||||||
|  |       exit 1 | ||||||
|  |       ;; | ||||||
|  |   esac | ||||||
|  | done | ||||||
|  | 
 | ||||||
|  | # Gets a string with the version and returns an array of maximum size of 5 with all the parts of the sematinc version | ||||||
|  | # $1 The string containing the version in semantic format | ||||||
|  | # $2 The variable to store the result array: | ||||||
|  | #      position 0: major number | ||||||
|  | #      position 1: minor number | ||||||
|  | #      position 2: patch number | ||||||
|  | #      position 3: identifier (or prerelease identifier) | ||||||
|  | #      position 4: build info | ||||||
|  | function explode_version { | ||||||
|  |   local __version=$1 | ||||||
|  |   local __result=$2 | ||||||
|  |   if [[ $__version =~ $SEMVER_REGEX ]] ; then | ||||||
|  |     local __major=${BASH_REMATCH[1]} | ||||||
|  |     local __minor=${BASH_REMATCH[2]} | ||||||
|  |     local __patch=${BASH_REMATCH[3]} | ||||||
|  |     local __prere=${BASH_REMATCH[4]} | ||||||
|  |     local __build=${BASH_REMATCH[5]} | ||||||
|  |     eval "$__result=(\"$__major\" \"$__minor\" \"$__patch\" \"$__prere\" \"$__build\")" | ||||||
|  |   else | ||||||
|  |     eval "$__result=" | ||||||
|  |   fi | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | # Compare two versions and returns -1, 0 or 1 | ||||||
|  | # $1 The first version to compare | ||||||
|  | # $2 The second version to compare | ||||||
|  | # $3 The variable where to store the result | ||||||
|  | function compare_versions { | ||||||
|  |   local __first | ||||||
|  |   local __second | ||||||
|  |   explode_version $1 __first | ||||||
|  |   explode_version $2 __second | ||||||
|  |   local lv=$3 | ||||||
|  | 
 | ||||||
|  |   # Compares MAJOR, MINOR and PATCH | ||||||
|  |   for i in 0 1 2; do | ||||||
|  |     local __numberfirst=${__first[$i]} | ||||||
|  |     local __numbersecond=${__second[$i]} | ||||||
|  |     case $(($__numberfirst - $__numbersecond)) in | ||||||
|  |       0) | ||||||
|  |         ;; | ||||||
|  |       -[0-9]*) | ||||||
|  |         eval "$lv=-1" | ||||||
|  |         return 0 | ||||||
|  |         ;; | ||||||
|  |       [0-9]*) | ||||||
|  |         eval "$lv=1" | ||||||
|  |         return 0 | ||||||
|  |         ;; | ||||||
|  |     esac | ||||||
|  |   done | ||||||
|  | 
 | ||||||
|  |   # Identifiers should compare with the ASCII order. | ||||||
|  |   local __identifierfirst=${__first[3]} | ||||||
|  |   local __identifiersecond=${__second[3]} | ||||||
|  |   if [[ -n "$__identifierfirst" ]] && [[ -n "$__identifiersecond" ]]; then | ||||||
|  |     if [[ "$__identifierfirst" > "$__identifiersecond" ]]; then | ||||||
|  |       eval "$lv=1" | ||||||
|  |       return 0 | ||||||
|  |     elif [[ "$__identifierfirst" < "$__identifiersecond" ]]; then | ||||||
|  |       eval "$lv=-1" | ||||||
|  |       return 0 | ||||||
|  |     fi | ||||||
|  |   elif [[ -z "$__identifierfirst" ]] && [[ -n "$__identifiersecond" ]]; then | ||||||
|  |     eval "$lv=1" | ||||||
|  |     return 0 | ||||||
|  |   elif [[ -n "$__identifierfirst" ]] && [[ -z "$__identifiersecond" ]]; then | ||||||
|  |     eval "$lv=-1" | ||||||
|  |     return 0 | ||||||
|  |   fi | ||||||
|  | 
 | ||||||
|  |   eval "$lv=0" | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | # Returns the last version of two | ||||||
|  | # $1 The first version to compare | ||||||
|  | # $2 The second version to compare | ||||||
|  | # $3 The variable where to store the last one | ||||||
|  | function get_latest_of_two { | ||||||
|  |   local __first=$1 | ||||||
|  |   local __second=$2 | ||||||
|  |   local __result | ||||||
|  |   local __latest=$3 | ||||||
|  |   compare_versions $__first $__second __result | ||||||
|  |   case $__result in | ||||||
|  |     0) | ||||||
|  |       eval "$__latest=$__second" | ||||||
|  |       ;; | ||||||
|  |     -1) | ||||||
|  |       eval "$__latest=$__second" | ||||||
|  |       ;; | ||||||
|  |     1) | ||||||
|  |       eval "$__latest=$__first" | ||||||
|  |       ;; | ||||||
|  |   esac | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | # Assigns a 2 size array with the identifier, having the identifier at pos 0, and the number in pos 1 | ||||||
|  | # $1 The identifier in the format -id.# | ||||||
|  | # $2 The vferiable where to store the 2 size array | ||||||
|  | function explode_identifier { | ||||||
|  |   local __identifier=$1 | ||||||
|  |   local __result=$2 | ||||||
|  |   if [[ $__identifier =~ $IDENTIFIER_REGEX ]] ; then | ||||||
|  |     local __id=${BASH_REMATCH[1]} | ||||||
|  |     local __number=${BASH_REMATCH[2]} | ||||||
|  |     if [[ -z "$__number" ]]; then | ||||||
|  |       __number=1 | ||||||
|  |     fi | ||||||
|  |     eval "$__result=(\"$__id\" \"$__number\")" | ||||||
|  |   else | ||||||
|  |     eval "$__result=" | ||||||
|  |   fi | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | # Gets a list of tags and assigns the base and latest versions | ||||||
|  | # Receives an array with the tags containing the versions | ||||||
|  | # Assigns to the global variables finalversion and lastversion the final version and the latest version | ||||||
|  | function get_latest { | ||||||
|  |   local __taglist=("$@") | ||||||
|  |   local __tagsnumber=${#__taglist[@]} | ||||||
|  |   local __current | ||||||
|  |   case $__tagsnumber in | ||||||
|  |     0) | ||||||
|  |       finalversion=$FIRST_VERSION | ||||||
|  |       lastversion=$FIRST_VERSION | ||||||
|  |       ;; | ||||||
|  |     1) | ||||||
|  |       __current=${__taglist[0]} | ||||||
|  |       explode_version $__current ver | ||||||
|  |       if [ -n "$ver" ]; then | ||||||
|  |         if [ -n "${ver[3]}" ]; then | ||||||
|  |           finalversion=$FIRST_VERSION | ||||||
|  |         else | ||||||
|  |           finalversion=$__current | ||||||
|  |         fi | ||||||
|  |         lastversion=$__current | ||||||
|  |       else | ||||||
|  |         finalversion=$FIRST_VERSION | ||||||
|  |         lastversion=$FIRST_VERSION | ||||||
|  |       fi | ||||||
|  |       ;; | ||||||
|  |     *) | ||||||
|  |       local __lastpos=$(($__tagsnumber-1)) | ||||||
|  |       for i in $(seq 0 $__lastpos) | ||||||
|  |       do | ||||||
|  |         __current=${__taglist[i]} | ||||||
|  |         explode_version ${__taglist[i]} ver | ||||||
|  |         if [ -n "$ver" ]; then | ||||||
|  |           if [ -z "${ver[3]}" ]; then | ||||||
|  |             get_latest_of_two $finalversion $__current finalversion | ||||||
|  |             get_latest_of_two $lastversion $finalversion lastversion | ||||||
|  |           else | ||||||
|  |             get_latest_of_two $lastversion $__current lastversion | ||||||
|  |           fi | ||||||
|  |         fi | ||||||
|  |       done | ||||||
|  |       ;; | ||||||
|  |   esac | ||||||
|  | 
 | ||||||
|  |   if git rev-parse -q --verify "refs/tags/$lastversion" >/dev/null; then | ||||||
|  |     hasversiontag="true" | ||||||
|  |   else | ||||||
|  |     hasversiontag="false" | ||||||
|  |   fi | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | # Gets the next version given the provided scope | ||||||
|  | # $1 The version that is going to be bumped | ||||||
|  | # $2 The scope to bump | ||||||
|  | # $3 The variable where to stoer the result | ||||||
|  | function get_next_version { | ||||||
|  |   local __exploded | ||||||
|  |   local __fromversion=$1 | ||||||
|  |   local __scope=$2 | ||||||
|  |   local __result=$3 | ||||||
|  |   explode_version $__fromversion __exploded | ||||||
|  |   case $__scope in | ||||||
|  |     major) | ||||||
|  |       __exploded[0]=$((${__exploded[0]}+1)) | ||||||
|  |       __exploded[1]=0 | ||||||
|  |       __exploded[2]=0 | ||||||
|  |     ;; | ||||||
|  |     minor) | ||||||
|  |       __exploded[1]=$((${__exploded[1]}+1)) | ||||||
|  |       __exploded[2]=0 | ||||||
|  |     ;; | ||||||
|  |     patch) | ||||||
|  |       __exploded[2]=$((${__exploded[2]}+1)) | ||||||
|  |     ;; | ||||||
|  |   esac | ||||||
|  | 
 | ||||||
|  |   eval "$__result=v${__exploded[0]}.${__exploded[1]}.${__exploded[2]}" | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function bump_version { | ||||||
|  |   ## First we try to get the next version based on the existing last one | ||||||
|  |   if [ "$scope" == "auto" ]; then | ||||||
|  |     get_scope_auto scope | ||||||
|  |   fi | ||||||
|  | 
 | ||||||
|  |   local __candidatefromlast=$FIRST_VERSION | ||||||
|  |   local __explodedlast | ||||||
|  |   explode_version $lastversion __explodedlast | ||||||
|  |   if [[ -n "${__explodedlast[3]}" ]]; then | ||||||
|  |     # Last version is not final | ||||||
|  |     local __idlast | ||||||
|  |     explode_identifier ${__explodedlast[3]} __idlast | ||||||
|  |      | ||||||
|  |     # We get the last, given the desired id based on the scope | ||||||
|  |     __candidatefromlast="v${__explodedlast[0]}.${__explodedlast[1]}.${__explodedlast[2]}" | ||||||
|  |     if [[ -n "$identifier" ]]; then | ||||||
|  |       local __nextid="$identifier.1" | ||||||
|  |       if [ "$identifier" == "${__idlast[0]}" ]; then | ||||||
|  |         # We target the same identifier as the last so we increase one | ||||||
|  |         __nextid="$identifier.$(( ${__idlast[1]}+1 ))" | ||||||
|  |         __candidatefromlast="$__candidatefromlast-$__nextid" | ||||||
|  |       else | ||||||
|  |         # Different identifiers, we make sure we are assigning a higher identifier, if not, we increase the version | ||||||
|  |         __candidatefromlast="$__candidatefromlast-$__nextid" | ||||||
|  |         local __comparedwithlast | ||||||
|  |         compare_versions $__candidatefromlast $lastversion __comparedwithlast | ||||||
|  |         if [ "$__comparedwithlast" == -1 ]; then | ||||||
|  |           get_next_version $__candidatefromlast $scope __candidatefromlast | ||||||
|  |           __candidatefromlast="$__candidatefromlast-$__nextid" | ||||||
|  |         fi | ||||||
|  |       fi | ||||||
|  |     fi | ||||||
|  |   fi | ||||||
|  | 
 | ||||||
|  |   # Then we try to get the version based on the latest final one | ||||||
|  |   local __candidatefromfinal=$FIRST_VERSION | ||||||
|  |   get_next_version $finalversion $scope __candidatefromfinal | ||||||
|  |   if [[ -n "$identifier" ]]; then | ||||||
|  |     __candidatefromfinal="$__candidatefromfinal-$identifier.1" | ||||||
|  |   fi | ||||||
|  | 
 | ||||||
|  |   # Finally we compare both candidates | ||||||
|  |   local __resultversion | ||||||
|  |   local __result | ||||||
|  |   compare_versions $__candidatefromlast $__candidatefromfinal __result | ||||||
|  |   case $__result in | ||||||
|  |     0) | ||||||
|  |       __resultversion=$__candidatefromlast | ||||||
|  |       ;; | ||||||
|  |     -1) | ||||||
|  |       __resultversion="$__candidatefromfinal" | ||||||
|  |       ;; | ||||||
|  |     1) | ||||||
|  |       __resultversion=$__candidatefromlast | ||||||
|  |       ;; | ||||||
|  |   esac | ||||||
|  | 
 | ||||||
|  |   eval "$1=$__resultversion" | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function increase_version { | ||||||
|  |   local __version= | ||||||
|  | 
 | ||||||
|  |   if [ -z $forcedversion ]; then | ||||||
|  |     bump_version __version | ||||||
|  |   else | ||||||
|  |     if [[ $forcedversion =~ $SEMVER_REGEX ]] ; then | ||||||
|  |       compare_versions $forcedversion $lastversion __result | ||||||
|  |       if [ $__result -le 0 ]; then | ||||||
|  |         echo "Version can't be lower than last version: $lastversion" | ||||||
|  |         exit 1 | ||||||
|  |       fi | ||||||
|  |     else | ||||||
|  |       echo "Non valid version to bump" | ||||||
|  |       exit 1 | ||||||
|  |     fi | ||||||
|  |     __version=$forcedversion | ||||||
|  |   fi | ||||||
|  | 
 | ||||||
|  |   if [ "$displayonly" == "true" ]; then | ||||||
|  |     echo "$__version" | ||||||
|  |   else | ||||||
|  |     if [ "$forcetag" == "false" ]; then | ||||||
|  |       check_git_dirty_status | ||||||
|  |     fi | ||||||
|  |     local __commitlist | ||||||
|  |     if [ "$finalversion" == "$FIRST_VERSION" ] || [ "$hasversiontag" != "true" ]; then | ||||||
|  |       __commitlist="$(git log --pretty=oneline | cat)" | ||||||
|  |     else | ||||||
|  |       __commitlist="$(git log --pretty=oneline $finalversion... | cat)" | ||||||
|  |     fi | ||||||
|  | 
 | ||||||
|  |     # If we are forcing a bump, we add bump to the commit list | ||||||
|  |     if [[ -z $__commitlist && "$forcetag" == "true" ]]; then | ||||||
|  |       __commitlist="bump" | ||||||
|  |     fi | ||||||
|  | 
 | ||||||
|  |     if [[ -z $__commitlist ]]; then | ||||||
|  |       echo "No commits since the last final version, not bumping version" | ||||||
|  |     else | ||||||
|  |       if [[ -z $versionname ]]; then | ||||||
|  |         versionname=$(date -u +"%Y-%m-%dT%H:%M:%SZ") | ||||||
|  |       fi | ||||||
|  |       local __message="$versionname | ||||||
|  | $__commitlist" | ||||||
|  | 
 | ||||||
|  |       # We check we have info on the user | ||||||
|  |       local __username=$(git config user.name) | ||||||
|  |       if [ -z "$__username" ]; then | ||||||
|  |         __username=$(id -u -n) | ||||||
|  |         git config user.name $__username | ||||||
|  |       fi | ||||||
|  |       local __useremail=$(git config user.email) | ||||||
|  |       if [ -z "$__useremail" ]; then | ||||||
|  |         __useremail=$(hostname) | ||||||
|  |         git config user.email "$__username@$__useremail" | ||||||
|  |       fi | ||||||
|  | 
 | ||||||
|  |       git tag -a $__version -m "$__message"  | ||||||
|  | 
 | ||||||
|  |       # If we have a remote, we push there | ||||||
|  |       local __remote=$(git remote) | ||||||
|  |       if [[ -n $__remote ]]; then | ||||||
|  |         git push $__remote $__version > /dev/null | ||||||
|  |         if [ $? -eq 0 ]; then | ||||||
|  |           echo "$__version" | ||||||
|  |         else | ||||||
|  |           echo "Error pushing the tag $__version to $__remote" | ||||||
|  |           exit 1 | ||||||
|  |         fi | ||||||
|  |       else | ||||||
|  |         echo "$__version" | ||||||
|  |       fi | ||||||
|  |     fi | ||||||
|  |   fi | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function check_git_dirty_status { | ||||||
|  |   local __repostatus= | ||||||
|  |   get_work_tree_status __repostatus | ||||||
|  | 
 | ||||||
|  |   if [ "$__repostatus" == "uncommitted" ]; then | ||||||
|  |     echo "ERROR: You have uncommitted changes" | ||||||
|  |     git status --porcelain | ||||||
|  |     exit 1 | ||||||
|  |   fi | ||||||
|  | 
 | ||||||
|  |   if [ "$__repostatus" == "unstaged" ]; then | ||||||
|  |     echo "ERROR: You have unstaged changes" | ||||||
|  |     git status --porcelain | ||||||
|  |     exit 1 | ||||||
|  |   fi | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | # Get the total amount of lines of code in the repo | ||||||
|  | function get_total_lines { | ||||||
|  |   local __empty_id="$(git hash-object -t tree /dev/null)" | ||||||
|  |   local __changes="$(git diff --numstat $__empty_id | cat)" | ||||||
|  |   local __added_deleted=$1 | ||||||
|  |   get_changed_lines "$__changes" $__added_deleted | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | # Get the total amount of lines of code since the provided tag | ||||||
|  | function get_sincetag_lines { | ||||||
|  |   local __sincetag=$1 | ||||||
|  |   local __changes="$(git diff --numstat $__sincetag | cat)" | ||||||
|  |   local __added_deleted=$2 | ||||||
|  |   get_changed_lines "$__changes" $__added_deleted | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function get_changed_lines { | ||||||
|  |   local __changes_numstat=$1 | ||||||
|  |   local __result=$2 | ||||||
|  |   IFS=$'\n' read -rd '' -a __changes_array <<<"$__changes_numstat" | ||||||
|  |   local __diff_regex="^([0-9]+)[[:space:]]+([0-9]+)[[:space:]]+.+$" | ||||||
|  | 
 | ||||||
|  |   local __total_added=0 | ||||||
|  |   local __total_deleted=0 | ||||||
|  |   for i in "${__changes_array[@]}" | ||||||
|  |   do | ||||||
|  |     if [[ $i =~ $__diff_regex ]] ; then | ||||||
|  |       local __added=${BASH_REMATCH[1]} | ||||||
|  |       local __deleted=${BASH_REMATCH[2]} | ||||||
|  |       __total_added=$(( $__total_added+$__added )) | ||||||
|  |       __total_deleted=$(( $__total_deleted+$__deleted )) | ||||||
|  |     fi | ||||||
|  |   done | ||||||
|  |   eval "$2=( $__total_added $__total_deleted )" | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function get_scope_auto { | ||||||
|  |   local __verbose=$2 | ||||||
|  |   local __total=0 | ||||||
|  |   local __since=0 | ||||||
|  |   local __scope= | ||||||
|  | 
 | ||||||
|  |   get_total_lines __total | ||||||
|  |   get_sincetag_lines $finalversion __since | ||||||
|  | 
 | ||||||
|  |   local __percentage=0 | ||||||
|  |   if [ "$__total" != "0" ]; then | ||||||
|  |     local __percentage=$(( 100*$__since/$__total )) | ||||||
|  |     if [ $__percentage -gt "10" ]; then | ||||||
|  |       __scope="minor" | ||||||
|  |     else | ||||||
|  |       __scope="patch" | ||||||
|  |     fi | ||||||
|  |   fi | ||||||
|  | 
 | ||||||
|  |   eval "$1=$__scope" | ||||||
|  |   if [[ -n "$__verbose" ]]; then | ||||||
|  |     echo "[Auto Scope] Percentage of lines changed: $__percentage" | ||||||
|  |     echo "[Auto Scope] : $__scope" | ||||||
|  |   fi | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function get_work_tree_status { | ||||||
|  |   # Update the index | ||||||
|  |   git update-index -q --ignore-submodules --refresh > /dev/null | ||||||
|  |   eval "$1=" | ||||||
|  | 
 | ||||||
|  |   if ! git diff-files --quiet --ignore-submodules -- > /dev/null | ||||||
|  |   then | ||||||
|  |     eval "$1=unstaged" | ||||||
|  |   fi | ||||||
|  | 
 | ||||||
|  |   if ! git diff-index --cached --quiet HEAD --ignore-submodules -- > /dev/null | ||||||
|  |   then | ||||||
|  |     eval "$1=uncommitted" | ||||||
|  |   fi | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function get_current { | ||||||
|  |   if [ "$hasversiontag" == "true" ]; then | ||||||
|  |     local __commitcount="$(git rev-list $lastversion.. --count)" | ||||||
|  |   else | ||||||
|  |     local __commitcount="$(git rev-list --count HEAD)" | ||||||
|  |   fi | ||||||
|  |   local __status= | ||||||
|  |   get_work_tree_status __status | ||||||
|  |    | ||||||
|  |   if [ "$__commitcount" == "0" ] && [ -z "$__status" ]; then | ||||||
|  |     eval "$1=$lastversion" | ||||||
|  |   else | ||||||
|  |     local __buildinfo="$(git rev-parse --short HEAD)" | ||||||
|  |     local __currentbranch="$(git rev-parse --abbrev-ref HEAD)" | ||||||
|  |     if [ "$__currentbranch" != "master" ]; then | ||||||
|  |       __buildinfo="$__currentbranch.$__buildinfo" | ||||||
|  |     fi | ||||||
|  | 
 | ||||||
|  |     local __suffix= | ||||||
|  |     if [ "$__commitcount" != "0" ]; then | ||||||
|  |       if [ -n "$__suffix" ]; then | ||||||
|  |         __suffix="$__suffix." | ||||||
|  |       fi | ||||||
|  |       __suffix="$__suffix$__commitcount" | ||||||
|  |     fi | ||||||
|  |     if [ -n "$__status" ]; then | ||||||
|  |       if [ -n "$__suffix" ]; then | ||||||
|  |         __suffix="$__suffix." | ||||||
|  |       fi | ||||||
|  |       __suffix="$__suffix$__status" | ||||||
|  |     fi | ||||||
|  | 
 | ||||||
|  |     __suffix="$__suffix+$__buildinfo" | ||||||
|  |     if [ "$lastversion" == "$finalversion" ]; then | ||||||
|  |       scope="patch" | ||||||
|  |       identifier= | ||||||
|  |       local __bumped= | ||||||
|  |       bump_version __bumped | ||||||
|  |       eval "$1=$__bumped-dev.$__suffix" | ||||||
|  |     else | ||||||
|  |       eval "$1=$lastversion.$__suffix" | ||||||
|  |     fi | ||||||
|  |   fi | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function init { | ||||||
|  |   git fetch > /dev/null | ||||||
|  |   TAGS="$(git tag)" | ||||||
|  |   IFS=$'\n' read -rd '' -a TAG_ARRAY <<<"$TAGS" | ||||||
|  | 
 | ||||||
|  |   get_latest ${TAG_ARRAY[@]} | ||||||
|  |   currentbranch="$(git rev-parse --abbrev-ref HEAD)" | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | case $ACTION in | ||||||
|  |   --help) | ||||||
|  |     echo -e "$HELP" | ||||||
|  |     ;; | ||||||
|  |   --version) | ||||||
|  |     echo -e "${PROG}: $PROG_VERSION" | ||||||
|  |     ;; | ||||||
|  |   final) | ||||||
|  |     init | ||||||
|  |     diff=$(git diff master | cat) | ||||||
|  |     if [ "$forcetag" == "false" ]; then | ||||||
|  |       if [ -n "$diff" ]; then | ||||||
|  |         echo "ERROR: Branch must be updated with master for final versions" | ||||||
|  |         exit 1 | ||||||
|  |       fi | ||||||
|  |     fi | ||||||
|  |     increase_version | ||||||
|  |     ;; | ||||||
|  |   alpha|beta) | ||||||
|  |     init | ||||||
|  |     identifier="$ACTION" | ||||||
|  |     increase_version | ||||||
|  |     ;; | ||||||
|  |   candidate) | ||||||
|  |     init | ||||||
|  |     identifier="rc" | ||||||
|  |     increase_version | ||||||
|  |     ;; | ||||||
|  |   getlast) | ||||||
|  |     init | ||||||
|  |     echo "$lastversion" | ||||||
|  |     ;; | ||||||
|  |   getfinal) | ||||||
|  |     init | ||||||
|  |     echo "$finalversion" | ||||||
|  |     ;; | ||||||
|  |   getcurrent) | ||||||
|  |     init | ||||||
|  |     get_current current | ||||||
|  |     echo "$current" | ||||||
|  |     ;; | ||||||
|  |   get) | ||||||
|  |     init | ||||||
|  |     echo "Current final version: $finalversion" | ||||||
|  |     echo "Last tagged version:   $lastversion" | ||||||
|  |     ;; | ||||||
|  |   *) | ||||||
|  |     echo "'$ACTION' is not a valid command, see --help for available commands." | ||||||
|  |     ;; | ||||||
|  | esac | ||||||
		Loading…
	
		Reference in New Issue