2018-06-01 20:28:30 +02:00
|
|
|
import argparse
|
2017-02-27 20:58:44 +01:00
|
|
|
import re
|
2017-02-23 23:11:55 +01:00
|
|
|
import subprocess
|
2020-06-15 22:01:33 +02:00
|
|
|
from semver.utils import get_tag_version
|
2020-02-21 23:44:15 +01:00
|
|
|
from semver.logger import logging, logger, console_logger
|
2019-11-22 21:30:58 +01:00
|
|
|
|
2018-05-23 21:41:35 +02:00
|
|
|
try:
|
|
|
|
from configparser import ConfigParser
|
|
|
|
except ImportError:
|
|
|
|
# Python < 3
|
|
|
|
from ConfigParser import ConfigParser
|
2017-02-23 23:11:55 +01:00
|
|
|
|
2019-11-25 19:35:15 +01:00
|
|
|
version = '0.0.0'
|
2017-02-23 23:11:55 +01:00
|
|
|
|
2018-06-04 23:56:15 +02:00
|
|
|
|
|
|
|
# Define common exceptions;
|
|
|
|
NO_MERGE_FOUND = Exception('No merge found')
|
|
|
|
NOT_MAIN_BRANCH = Exception('Not merging into a main branch')
|
|
|
|
NO_GIT_FLOW = Exception('No git flow branch found')
|
|
|
|
|
2020-02-28 17:56:50 +01:00
|
|
|
# Important regex
|
|
|
|
GET_COMMIT_MESSAGE = re.compile(r"Merge (branch|pull request) '?([^']+)'? (into|from) (?:'(.+)'|[^\/]+\/(.+))")
|
|
|
|
|
2017-02-27 20:58:44 +01:00
|
|
|
class SemVer(object):
|
2017-02-23 23:11:55 +01:00
|
|
|
|
2018-05-25 21:10:05 +02:00
|
|
|
# Merge pull request #1 from RightBrain-Networks/feature/PLAT-185-versioning
|
2017-02-23 23:11:55 +01:00
|
|
|
|
2019-03-21 20:25:17 +01:00
|
|
|
def __init__(self,global_user=False):
|
|
|
|
self.global_user = '--local' if global_user else '--global'
|
2017-02-27 20:58:44 +01:00
|
|
|
self.merged_branch = None
|
|
|
|
self.main_branch = None
|
|
|
|
self.version_type = None
|
2017-02-23 23:11:55 +01:00
|
|
|
|
2018-05-25 20:14:29 +02:00
|
|
|
self.main_branches = self._setting_to_array('main_branches')
|
|
|
|
self.major_branches = self._setting_to_array('major_branches')
|
|
|
|
self.minor_branches = self._setting_to_array('minor_branches')
|
|
|
|
self.patch_branches = self._setting_to_array('patch_branches')
|
2017-02-27 21:41:06 +01:00
|
|
|
|
2018-05-25 20:14:29 +02:00
|
|
|
def _setting_to_array(self, setting):
|
|
|
|
config = ConfigParser()
|
|
|
|
config.read('./.bumpversion.cfg')
|
|
|
|
value = config.get('semver', setting)
|
2017-02-27 21:41:06 +01:00
|
|
|
# filter() removes empty string which is what we get if setting is blank
|
2018-05-25 20:14:29 +02:00
|
|
|
return list(filter(bool, [v.strip() for v in value.split(',')]))
|
2017-02-27 21:41:06 +01:00
|
|
|
|
|
|
|
# based on commit message see what branches are involved in the merge
|
2017-02-27 20:58:44 +01:00
|
|
|
def get_branches(self):
|
|
|
|
p = subprocess.Popen(['git', 'log', '-1'], stdout=subprocess.PIPE,
|
2018-05-23 21:09:14 +02:00
|
|
|
cwd='.')
|
2018-05-24 22:36:45 +02:00
|
|
|
#check current branch
|
|
|
|
b = subprocess.Popen(['git', 'rev-parse', '--abbrev-ref', 'HEAD'], stdout=subprocess.PIPE,
|
|
|
|
cwd='.')
|
2018-05-23 21:41:35 +02:00
|
|
|
message = str(p.stdout.read())
|
2018-06-01 19:53:13 +02:00
|
|
|
branch = b.stdout.read().decode('utf-8').rstrip()
|
2020-02-21 23:44:15 +01:00
|
|
|
logger.info('Main branch is ' + branch)
|
2020-02-28 17:56:50 +01:00
|
|
|
matches = GET_COMMIT_MESSAGE.search(message)
|
2017-02-27 20:58:44 +01:00
|
|
|
if matches:
|
2018-05-24 22:36:45 +02:00
|
|
|
if str(matches.group(4)) == branch:
|
|
|
|
self.merged_branch = matches.group(2)
|
|
|
|
else:
|
2020-02-27 22:56:15 +01:00
|
|
|
self.merged_branch = matches.group(5)
|
2018-05-24 22:36:45 +02:00
|
|
|
self.main_branch = branch
|
2017-02-27 20:58:44 +01:00
|
|
|
return bool(matches)
|
|
|
|
|
2017-02-27 21:41:06 +01:00
|
|
|
# based on branches involved see what type of versioning should be done
|
2017-02-27 20:58:44 +01:00
|
|
|
def get_version_type(self):
|
2020-02-21 23:44:15 +01:00
|
|
|
logger.info('Merged branch is ' + self.merged_branch)
|
2019-07-18 21:16:25 +02:00
|
|
|
|
2019-12-13 22:51:05 +01:00
|
|
|
merged_prefix = None
|
2019-12-16 22:48:34 +01:00
|
|
|
matches = re.findall("[^\/]*/", self.merged_branch)
|
|
|
|
if len(matches) >= 1:
|
|
|
|
merged_prefix = matches[-1][0:-1]
|
2019-07-18 21:16:25 +02:00
|
|
|
|
2019-12-13 22:51:05 +01:00
|
|
|
if merged_prefix:
|
|
|
|
for prefix in self.major_branches:
|
|
|
|
if prefix == merged_prefix:
|
|
|
|
self.version_type = 'major'
|
2020-06-15 22:01:33 +02:00
|
|
|
return self.version_type
|
2019-12-13 22:51:05 +01:00
|
|
|
for prefix in self.minor_branches:
|
|
|
|
if prefix == merged_prefix:
|
|
|
|
self.version_type = 'minor'
|
2020-06-15 22:01:33 +02:00
|
|
|
return self.version_type
|
2019-12-13 22:51:05 +01:00
|
|
|
for prefix in self.patch_branches:
|
|
|
|
if prefix == merged_prefix:
|
|
|
|
self.version_type = 'patch'
|
2020-06-15 22:01:33 +02:00
|
|
|
return self.version_type
|
2017-02-27 21:41:06 +01:00
|
|
|
return False
|
2017-02-27 20:58:44 +01:00
|
|
|
|
2017-02-27 21:41:06 +01:00
|
|
|
# setup git settings so we can commit and tag
|
2017-02-27 20:58:44 +01:00
|
|
|
def setup_git_user(self):
|
|
|
|
# setup git user
|
2019-03-21 20:25:17 +01:00
|
|
|
p = subprocess.Popen(['git', 'config', self.global_user, 'user.email',
|
2017-02-27 20:58:44 +01:00
|
|
|
'"versioner@semver.com"'],
|
2018-05-23 21:09:14 +02:00
|
|
|
cwd='.')
|
2019-03-21 20:25:17 +01:00
|
|
|
p = subprocess.Popen(['git', 'config', self.global_user, 'user.name',
|
2017-02-27 20:58:44 +01:00
|
|
|
'"Semantic Versioner"'],
|
2018-05-23 21:09:14 +02:00
|
|
|
cwd='.')
|
2017-02-27 20:58:44 +01:00
|
|
|
p.wait()
|
|
|
|
return self
|
|
|
|
|
2017-02-27 21:41:06 +01:00
|
|
|
# use bumpversion to increment the appropriate version type
|
2017-02-27 20:58:44 +01:00
|
|
|
def version_repo(self):
|
2019-11-22 21:30:58 +01:00
|
|
|
config_file = ""
|
|
|
|
with open(".bumpversion.cfg", "r") as file:
|
|
|
|
config_file = file.read()
|
|
|
|
|
2017-02-27 20:58:44 +01:00
|
|
|
# version repo
|
2020-02-21 23:44:15 +01:00
|
|
|
logger.debug("Running bumpversion of type: " + self.version_type)
|
2019-11-25 22:12:58 +01:00
|
|
|
p = subprocess.Popen(['bumpversion', '--current-version', get_tag_version(), self.version_type],
|
2018-05-23 21:09:14 +02:00
|
|
|
cwd='.')
|
2017-02-27 20:58:44 +01:00
|
|
|
p.wait()
|
|
|
|
return self
|
|
|
|
|
|
|
|
def commit_and_push(self):
|
|
|
|
# push versioning commit
|
2018-05-24 22:36:45 +02:00
|
|
|
p = subprocess.Popen(['git', 'push', 'origin', self.main_branch],
|
2018-05-23 21:09:14 +02:00
|
|
|
cwd='.')
|
2017-02-27 20:58:44 +01:00
|
|
|
p.wait()
|
|
|
|
|
|
|
|
# push versioning tag
|
|
|
|
p = subprocess.Popen(['git', 'push', 'origin', '--tags'],
|
2018-05-23 21:09:14 +02:00
|
|
|
cwd='.')
|
2017-02-27 20:58:44 +01:00
|
|
|
p.wait()
|
|
|
|
return self
|
|
|
|
|
2017-02-27 21:41:06 +01:00
|
|
|
# 1) get branches from last commit message
|
|
|
|
# 2) see if we're merging into a main branch
|
|
|
|
# 3) see what type of versioning we should do
|
|
|
|
# 4) version the repo
|
2018-06-01 20:28:30 +02:00
|
|
|
def run(self,push=True):
|
2017-02-27 20:58:44 +01:00
|
|
|
if not self.get_branches():
|
2018-06-04 23:56:15 +02:00
|
|
|
raise NO_MERGE_FOUND
|
2017-02-27 21:41:06 +01:00
|
|
|
if self.main_branch not in self.main_branches:
|
2018-06-04 23:56:15 +02:00
|
|
|
raise NOT_MAIN_BRANCH
|
2017-02-27 20:58:44 +01:00
|
|
|
if not self.get_version_type():
|
2018-06-04 23:56:15 +02:00
|
|
|
raise NO_GIT_FLOW
|
2018-06-04 23:47:51 +02:00
|
|
|
if push:
|
|
|
|
self.setup_git_user()
|
2017-02-27 20:58:44 +01:00
|
|
|
self.version_repo()
|
2018-06-01 20:28:30 +02:00
|
|
|
if push:
|
|
|
|
self.commit_and_push()
|
2017-02-27 20:58:44 +01:00
|
|
|
return self
|
2017-02-23 23:11:55 +01:00
|
|
|
|
2018-05-23 21:09:14 +02:00
|
|
|
def main():
|
2017-10-27 18:41:20 +02:00
|
|
|
try:
|
2018-06-01 20:28:30 +02:00
|
|
|
parser = argparse.ArgumentParser(description='Bump Semantic Version.')
|
|
|
|
parser.add_argument('-n','--no-push', help='Do not try to push', action='store_false', dest='push')
|
2019-03-21 20:25:17 +01:00
|
|
|
parser.add_argument('-g','--global-user', help='Set git user at a global level, helps in jenkins', action='store_true', dest='global_user')
|
2020-02-21 23:44:15 +01:00
|
|
|
parser.add_argument('-D', '--debug', help='Sets logging level to DEBUG', action='store_true', dest='debug', default=False)
|
2018-06-01 20:28:30 +02:00
|
|
|
args = parser.parse_args()
|
2020-02-21 23:44:15 +01:00
|
|
|
|
|
|
|
|
|
|
|
if args.debug:
|
|
|
|
console_logger.setLevel(logging.DEBUG)
|
|
|
|
|
2019-03-21 20:25:17 +01:00
|
|
|
SemVer(global_user=args.global_user).run(push=args.push)
|
2017-10-27 18:41:20 +02:00
|
|
|
except Exception as e:
|
2020-02-21 23:44:15 +01:00
|
|
|
logger.error(e)
|
2018-06-04 23:56:15 +02:00
|
|
|
if e == NO_MERGE_FOUND:
|
|
|
|
exit(1)
|
|
|
|
elif e == NOT_MAIN_BRANCH:
|
|
|
|
exit(2)
|
|
|
|
elif e == NO_GIT_FLOW:
|
|
|
|
exit(3)
|
|
|
|
else:
|
|
|
|
exit(128)
|
2018-05-23 21:09:14 +02:00
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
try: main()
|
|
|
|
except: raise
|