auto-semver/semver/__init__.py

172 lines
6.4 KiB
Python
Raw Normal View History

2018-06-01 20:28:30 +02:00
import argparse
import re
import subprocess
2019-11-22 21:30:58 +01:00
from semver.get_version import get_tag_version
2018-05-23 21:41:35 +02:00
try:
from configparser import ConfigParser
except ImportError:
# Python < 3
from ConfigParser import ConfigParser
2019-11-25 19:33:05 +01:00
version = 'develop'
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')
class SemVer(object):
2018-05-24 22:36:45 +02:00
GET_COMMIT_MESSAGE = re.compile(r"Merge (branch|pull request) '?(.+)'? (into|from) ([\w/-]+)")
2018-05-25 21:10:05 +02:00
# Merge pull request #1 from RightBrain-Networks/feature/PLAT-185-versioning
def __init__(self,global_user=False):
self.global_user = '--local' if global_user else '--global'
self.merged_branch = None
self.main_branch = None
self.version_type = None
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')
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)
# 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(',')]))
# based on commit message see what branches are involved in the merge
2018-05-24 22:36:45 +02: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()
print('Main branch is ' + branch)
matches = self.GET_COMMIT_MESSAGE.search(message)
if matches:
2018-05-24 22:36:45 +02:00
if str(matches.group(4)) == branch:
self.merged_branch = matches.group(2)
else:
self.merged_branch = matches.group(4)
self.main_branch = branch
return bool(matches)
# based on branches involved see what type of versioning should be done
def get_version_type(self):
print('Merged branch is ' + self.merged_branch)
#Get GitHub repo's owner from url
repoOwner = None
remoteUrl = subprocess.Popen(['git', 'config', '--get', 'remote.origin.url'], stdout=subprocess.PIPE).stdout.read().decode('utf-8').rstrip()
if "github.com" in remoteUrl:
repoOwner = re.search("(?<=github.com(:|\/))(.*)(?=\/.*.git)", remoteUrl).group(0)
for prefix in self.major_branches:
if self.merged_branch.startswith(prefix + '/') or self.merged_branch.startswith(str(repoOwner) + '/' + prefix + '/'):
self.version_type = 'major'
return True
for prefix in self.minor_branches:
if self.merged_branch.startswith(prefix + '/') or self.merged_branch.startswith(str(repoOwner) + '/' + prefix + '/'):
self.version_type = 'minor'
return True
for prefix in self.patch_branches:
if self.merged_branch.startswith(prefix + '/') or self.merged_branch.startswith(str(repoOwner) + '/' + prefix + '/'):
self.version_type = 'patch'
return True
return False
# setup git settings so we can commit and tag
def setup_git_user(self):
# setup git user
p = subprocess.Popen(['git', 'config', self.global_user, 'user.email',
'"versioner@semver.com"'],
2018-05-23 21:09:14 +02:00
cwd='.')
p = subprocess.Popen(['git', 'config', self.global_user, 'user.name',
'"Semantic Versioner"'],
2018-05-23 21:09:14 +02:00
cwd='.')
p.wait()
return self
# use bumpversion to increment the appropriate version type
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()
# Update .bumpconfig
pattern = re.compile("current_version = [0-9.]*")
current_config = re.search(pattern, config_file)
if current_config:
config_file.replace(current_config.group(0), "current_version = " + get_tag_version())
2019-11-22 22:10:01 +01:00
else:
config_file.replace("[bumpversion]","[bumpversion]\ncurrent_version = " + get_tag_version())
with open(".bumpversion.cfg", "w") as file:
file.write(config_file)
2019-11-22 21:30:58 +01:00
# version repo
p = subprocess.Popen(['bumpversion', self.version_type],
2018-05-23 21:09:14 +02:00
cwd='.')
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='.')
p.wait()
# push versioning tag
p = subprocess.Popen(['git', 'push', 'origin', '--tags'],
2018-05-23 21:09:14 +02:00
cwd='.')
p.wait()
return self
# 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):
if not self.get_branches():
2018-06-04 23:56:15 +02:00
raise NO_MERGE_FOUND
if self.main_branch not in self.main_branches:
2018-06-04 23:56:15 +02:00
raise NOT_MAIN_BRANCH
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()
self.version_repo()
2018-06-01 20:28:30 +02:00
if push:
self.commit_and_push()
return self
2018-05-23 21:09:14 +02:00
def main():
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')
parser.add_argument('-g','--global-user', help='Set git user at a global level, helps in jenkins', action='store_true', dest='global_user')
2018-06-01 20:28:30 +02:00
args = parser.parse_args()
SemVer(global_user=args.global_user).run(push=args.push)
except Exception as e:
2018-05-23 21:41:35 +02:00
print(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