Here is a script to find out the next suggested SemVer
versions for a Github project. The script
works on both private and public repositories. If using a private repo, you need to export an environment variable named
GITHUB_PAT
with the value of your github personal access token
. This script depends mainly on the git tags
. If you
use a custom prefix for your git tags, you need to provide it as an option.
You can run the script without any options to view the help content.
Prerequisites
The script requires git
command to be available in the PATH. Please ensure that you have git
installed on your system.
Using the script
Below are the steps to use the script.
- Copy the below script and save it as
next-github-project-version.sh
. - Change the executable bit by running:
chmod +x next-github-project-version.sh
. - The script is now ready to be run. It takes two mandatory commandline arguments and an optional third argument.
- The first argument is the
github organization
name. - The second argument is the
github project
name. - The optional, third argument is the
tag-prefix
which you might be using while adding git tags. Ex., v is the tag-prefix in v1.2.0.
- The first argument is the
1#!/bin/bash
2
3set -e
4set -m
5
6if [ $# -lt 2 ]; then
7 echo -e "Usage: $(basename $0) <github-org> <github-project> [tag-prefix]"
8 echo -e "NOTE: If the project needs authentication, export GITHUB_PAT env variable with your Github personal access token."
9 echo -e "tag-prefix is optional and is empty by default."
10
11 exit 1
12fi
13
14org_name=$1
15project_name=$2
16tag_prefix=$3
17
18OLD_IFS=$IFS
19
20## Generate the Github base-url
21if [ -n "${GITHUB_PAT}" ]; then
22 url_base="https://${GITHUB_PAT}@github.com"
23else
24 url_base="https://github.com"
25fi
26
27## We are not considering versions with alphanumeric endings.
28## The supported version number format is major.minor.patch.build
29ver_regex="(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)?$"
30extver_regex="(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$"
31
32## Sample version values for testing
33#ver_tag="ref/tags/v2.1.3"
34#extver_tag="ref/tags/v2.1.3-alpha.19+asfs.239"
35
36sorted_tags="$(git ls-remote --tags --sort=version:refname ${url_base}/${org_name}/${project_name}.git | awk {'print $2'})"
37
38if [ -n "$tag_prefix" ]; then
39 ver_tag=$(echo "$sorted_tags" | grep -P "refs/tags/${tag_prefix}${ver_regex}" | tail -1)
40 extver_tag=$(echo "$sorted_tags" | grep -P "refs/tags/${tag_prefix}${extver_regex}" | tail -1)
41else
42 ver_tag=$(echo "$sorted_tags" | grep -P "refs/tags/${ver_regex}" | tail -1)
43 extver_tag=$(echo "$sorted_tags" | grep -P "refs/tags/${extver_regex}" | tail -1)
44fi
45
46## Suggest next possible versions
47if [ -n "${ver_tag}" ]; then
48 if [ -n "$tag_prefix" ]; then
49 curr_ver=$(echo $ver_tag | awk -F '/' {'print $3'} | sed -e "s%${tag_prefix}%%")
50 else
51 curr_ver=$(echo $ver_tag | awk -F '/' {'print $3'})
52 fi
53
54 IFS='.' read -r -a ver_parts <<<"$curr_ver"
55
56 ver_major=${ver_parts[0]}
57 ver_minor=${ver_parts[1]}
58 ver_patch=${ver_parts[2]}
59fi
60
61if [ -n "${extver_tag}" ]; then
62 if [ -n "$tag_prefix" ]; then
63 curr_extver=$(echo $extver_tag | awk -F '/' {'print $3'} | sed -e "s%${tag_prefix}%%")
64 else
65 curr_extver=$(echo $extver_tag | awk -F '/' {'print $3'})
66 fi
67
68 IFS='-' read -ra parts <<<"$curr_extver"
69 IFS='.' read -r -a core_parts <<<"${parts[0]}"
70 IFS='+' read -r -a ext_parts <<<"${parts[1]}"
71
72 extver_major=${core_parts[0]}
73 extver_minor=${core_parts[1]}
74 extver_patch=${core_parts[2]}
75 extver_pre=${ext_parts[0]}
76 extver_bld=${ext_parts[1]}
77
78 echo -e "Current version information:"
79 echo -e "############################\n"
80 echo -e "Major: $extver_major, Minor: $extver_minor, Patch: $extver_patch"
81 echo -e "Pre-release: $extver_pre, Build: $extver_bld"
82fi
83
84if [ -n "$extver_pre" ]; then
85 if [ -n "$ver_tag" ]; then
86 curr_major=$ver_major
87 curr_minor=$ver_minor
88 curr_patch=$ver_patch
89
90 use_extver=0
91
92 if [ $extver_major -gt $ver_major ]; then
93 use_extver=1
94 elif [ $extver_major -eq $ver_major ] && [ $extver_minor -gt $ver_minor ]; then
95 use_extver=1
96 elif [ $extver_major -eq $ver_major ] && [ $extver_minor -eq $ver_minor ] && [ $extver_patch -gt $ver_patch ]; then
97 use_extver=1
98 fi
99
100 if [ $use_extver -eq 1 ]; then
101 curr_major=$extver_major
102 curr_minor=$extver_minor
103 curr_patch=$extver_patch
104 fi
105 else
106 curr_major=$extver_major
107 curr_minor=$extver_minor
108 curr_patch=$extver_patch
109 fi
110
111 ## Compute next versions of pre-release and build parts.
112 if [ -n "$extver_bld" ]; then
113 bldver_num=$(echo $extver_bld | grep -o -E "[0-9]+$")
114
115 if [ -n "$bldver_num" ]; then
116 bldver_txt=$(echo $extver_bld | sed -e "s|${bldver_num}$||")
117 nxtver_bld="${bldver_txt}$((bldver_num + 1))"
118 fi
119
120 nxtver_pre=$extver_pre
121 fi
122
123 prever_num=$(echo $extver_pre | grep -o -E "[0-9]+$")
124
125 if [ -n "$prever_num" ]; then
126 prever_txt=$(echo $extver_pre | sed -e "s|${prever_num}$||")
127 nxtver_pre="${prever_txt}$((prever_num + 1))"
128 fi
129else
130 curr_major=$ver_major
131 curr_minor=$ver_minor
132 curr_patch=$ver_patch
133fi
134
135echo -e "\nNEXT SUGGESTED VERSIONS:"
136echo -e "########################\n"
137echo -e "Next Major: $((curr_major + 1)).0.0"
138echo -e "Next Minor: ${curr_major}.$((curr_minor + 1)).0"
139
140if [ -n "$nxtver_pre" ]; then
141 if [ $use_extver -eq 1 ]; then
142 echo -e "Next Patch (GA): ${curr_major}.${curr_minor}.${curr_patch}"
143 else
144 echo -e "Next Patch: ${curr_major}.${curr_minor}.$((curr_patch + 1))"
145 fi
146 echo -e "Next Pre-Release: ${curr_major}.${curr_minor}.${curr_patch}-${nxtver_pre}"
147else
148 echo -e "Next Patch: ${curr_major}.${curr_minor}.$((curr_patch + 1))"
149fi
150
151if [ -n "$nxtver_bld" ]; then
152 echo -e "Next Build: ${curr_major}.${curr_minor}.${curr_patch}-${extver_pre}+${nxtver_bld}"
153fi
154
155IFS=$OLD_IFS
156
157exit 0
Comments