Merge pull request #49 from RightBrain-Networks/feature/decouplebump

Decouple from `bumpversion`
This commit is contained in:
Derek DeJonghe 2020-06-26 17:45:02 -04:00 committed by GitHub
commit eaebfcc329
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 155 additions and 19 deletions

View File

@ -2,7 +2,7 @@
# Automatic Semantic Versioning
This code repository extends/wraps the bumpversion library to automatically determine which type of increment (Major, Minor, Patch) to perform based on git branch names.
This code repository automatically determines which type of increment (Major, Minor, Patch) to perform based on git branch names.
The tool uses the git log to determine if the last commit was a merge into a main line branch, and if it was, detect the name of the branch being merged in. If the name of the branch begins with one of the key words provided to the configuration file, a new version is produced.
***It is important to note that the tool performs actions on a local Git repository. After completion, it will be necessary to do a `git push --tags` if a commit and/or tag are created***
@ -15,9 +15,9 @@ auto-semver is a pip installable package to install, make sure pip is installed
## Configuration
There are two configuration files that must appear in the top directory of repository for which we want to update the version. These files are `VERSION` and `.bumpversion.cfg`.
There is one configuration file that must appear in the top directory of repository for which we want to update the version, `.bumpversion.cfg`.
Below is an example configuration of a `.bumpversion.cfg` file using commits:
Below is an example configuration of a `.bumpversion.cfg` file:
```ini
[bumpversion]

View File

@ -1 +1,5 @@
bumpversion==0.5.3
# requirements.txt
#
# installs dependencies from ./setup.py, and the package itself,
# in editable mode
-e .

View File

@ -1,8 +1,10 @@
import argparse
import re
import subprocess
from enum import IntEnum
from semver.utils import get_tag_version
from semver.logger import logging, logger, console_logger
from semver.bump import bump_version
try:
from configparser import ConfigParser
@ -12,6 +14,10 @@ except ImportError:
version = '0.0.0'
class VersionType(IntEnum):
MAJOR = 0
MINOR = 1
PATCH = 2
# Define common exceptions;
NO_MERGE_FOUND = Exception('No merge found')
@ -74,15 +80,15 @@ class SemVer(object):
if merged_prefix:
for prefix in self.major_branches:
if prefix == merged_prefix:
self.version_type = 'major'
self.version_type = VersionType.MAJOR
return self.version_type
for prefix in self.minor_branches:
if prefix == merged_prefix:
self.version_type = 'minor'
self.version_type = VersionType.MINOR
return self.version_type
for prefix in self.patch_branches:
if prefix == merged_prefix:
self.version_type = 'patch'
self.version_type = VersionType.PATCH
return self.version_type
return False
@ -106,9 +112,7 @@ class SemVer(object):
# version repo
logger.debug("Running bumpversion of type: " + self.version_type)
p = subprocess.Popen(['bumpversion', '--current-version', get_tag_version(), self.version_type],
cwd='.')
p.wait()
bump_version(get_tag_version(), self.version_type)
return self
def commit_and_push(self):

65
semver/bump.py Normal file
View File

@ -0,0 +1,65 @@
from enum import IntEnum
import subprocess, os
from semver.logger import logging, logger, console_logger
try:
from configparser import ConfigParser
except ImportError:
# Python < 3
from ConfigParser import ConfigParser
def bump_version(version, index=2, tag_repo = True, update_files=True):
v = version.split('.')
# Bump version
v[index] = str(int(v[index]) + 1)
# Reset subversions
i = len(v) - 1
while i > index:
v[i] = '0'
i = i - 1
# Get new version
new_version = '.'.join(v)
# Tag new version
if tag_repo and version != new_version:
p = subprocess.Popen(['git', 'tag', new_version], cwd='.')
p.wait()
# Update local files
if update_files:
update_file_version(new_version, version)
return new_version
def update_file_version(new_version, version="0.0.0"):
# Open up config file
config = ConfigParser()
config.read('./.bumpversion.cfg')
for section in config.sections():
if len(section) > 17 and section[0:17] == "bumpversion:file:":
file_name = section[17:]
if os.path.isfile(file_name):
# Get search val from config
search_val = config.get(section, "search")
search_val = process_config_string(search_val, new_version, version)
# Get replace val from config
replace_val = config.get(section, "replace")
replace_val = process_config_string(replace_val, new_version, version)
# Update replace values in file
with open(file_name, 'r') as file:
filedata = file.read()
filedata =filedata.replace(search_val,replace_val)
with open(file_name, 'w') as file:
file.write(filedata)
else:
logger.warning("Tried to version file: `" + file_name + "` but it doesn't exist!")
def process_config_string(cfg_string, new_version, version):
return cfg_string.replace("{new_version}", new_version).replace("{current_version}", version)

View File

@ -4,6 +4,7 @@ import subprocess
from semver.logger import logging, logger, console_logger
from semver.utils import get_tag_version, get_file_version, DEVNULL
from semver import SemVer
from semver.bump import bump_version
def get_version(build=0,version_format=None,dot=False):
version = get_tag_version()
@ -27,9 +28,8 @@ def get_version(build=0,version_format=None,dot=False):
version_type = semver.get_version_type()
logger.debug("version type is: {}".format(version_type))
if version_type:
p = subprocess.Popen(['bumpversion', '--dry-run', '--verbose', '--current-version', get_tag_version(), version_type], stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd='.')
bump_output = p.stdout.read().decode('utf-8').rstrip()
next_version = re.search("new_version=([0-9]*.[0-9]*.[0-9]*)", bump_output).group(1)
next_version = bump_version(get_tag_version(), version_type, False, False)
if version_format in ('npm','docker'):
return "{}-{}.{}".format(next_version,branch.replace('/','-'),build)

View File

@ -1,7 +1,7 @@
import unittest, os, subprocess, re, semver
from semver.logger import logging, logger, console_logger
from semver import get_version, utils, NO_MERGE_FOUND, GET_COMMIT_MESSAGE
from semver import bump, get_version, utils, NO_MERGE_FOUND, GET_COMMIT_MESSAGE
config_data = """
[bumpversion]
@ -10,6 +10,10 @@ commit = False
tag = True
tag_name = {new_version}
[bumpversion:file:file.txt]
search = 0.0.0
replace = {new_version}
[semver]
main_branches = master
major_branches = major
@ -25,17 +29,17 @@ class TestSemverObject(unittest.TestCase):
semver_object = semver.SemVer()
semver_object.merged_branch = "major/unittest"
semver_object.get_version_type()
self.assertEqual(semver_object.version_type, "major")
self.assertEqual(semver_object.version_type, semver.VersionType.MAJOR)
def test_get_version_type_minor_merge(self):
semver_object = semver.SemVer()
semver_object.merged_branch = "minor/unittest"
semver_object.get_version_type()
self.assertEqual(semver_object.version_type, "minor")
self.assertEqual(semver_object.version_type, semver.VersionType.MINOR)
def test_get_version_type_patch_merge(self):
semver_object = semver.SemVer()
semver_object.merged_branch = "patch/unittest"
semver_object.get_version_type()
self.assertEqual(semver_object.version_type, "patch")
self.assertEqual(semver_object.version_type, semver.VersionType.PATCH)
def test_run_no_merge(self):
semver_object = semver.SemVer()
try:
@ -155,6 +159,66 @@ class TestGetCommitMessageRegex(unittest.TestCase):
matches = GET_COMMIT_MESSAGE.search("Example unrelated commit message that should get 0 matches")
self.assertEqual(matches, None)
class TestVersionBumping(unittest.TestCase):
def test_patch_bump(self):
self.assertEqual("0.0.1", bump.bump_version("0.0.0", semver.VersionType.PATCH, False))
self.assertEqual("0.0.2", bump.bump_version("0.0.1", semver.VersionType.PATCH, False))
self.assertEqual("0.1.1", bump.bump_version("0.1.0", semver.VersionType.PATCH, False))
self.assertEqual("1.0.1", bump.bump_version("1.0.0", semver.VersionType.PATCH, False))
self.assertEqual("1.2.4", bump.bump_version("1.2.3", semver.VersionType.PATCH, False))
self.assertEqual("0.0.11", bump.bump_version("0.0.10", semver.VersionType.PATCH, False))
self.assertEqual("0.10.1", bump.bump_version("0.10.0", semver.VersionType.PATCH, False))
self.assertEqual("10.0.1", bump.bump_version("10.0.0", semver.VersionType.PATCH, False))
def test_minor_bump(self):
self.assertEqual("0.1.0", bump.bump_version("0.0.0", semver.VersionType.MINOR, False))
self.assertEqual("0.1.0", bump.bump_version("0.0.1", semver.VersionType.MINOR, False))
self.assertEqual("0.2.0", bump.bump_version("0.1.0", semver.VersionType.MINOR, False))
self.assertEqual("1.1.0", bump.bump_version("1.0.0", semver.VersionType.MINOR, False))
self.assertEqual("1.3.0", bump.bump_version("1.2.3", semver.VersionType.MINOR, False))
self.assertEqual("0.1.0", bump.bump_version("0.0.10", semver.VersionType.MINOR, False))
self.assertEqual("0.11.0", bump.bump_version("0.10.0", semver.VersionType.MINOR, False))
self.assertEqual("10.1.0", bump.bump_version("10.0.0", semver.VersionType.MINOR, False))
def test_major_bump(self):
self.assertEqual("1.0.0", bump.bump_version("0.0.0", semver.VersionType.MAJOR, False))
self.assertEqual("1.0.0", bump.bump_version("0.0.1", semver.VersionType.MAJOR, False))
self.assertEqual("1.0.0", bump.bump_version("0.1.0", semver.VersionType.MAJOR, False))
self.assertEqual("2.0.0", bump.bump_version("1.0.0", semver.VersionType.MAJOR, False))
self.assertEqual("2.0.0", bump.bump_version("1.2.3", semver.VersionType.MAJOR, False))
self.assertEqual("1.0.0", bump.bump_version("0.0.10", semver.VersionType.MAJOR, False))
self.assertEqual("1.0.0", bump.bump_version("0.10.0", semver.VersionType.MAJOR, False))
self.assertEqual("11.0.0", bump.bump_version("10.0.0", semver.VersionType.MAJOR, False))
class TestFileVersioning(unittest.TestCase):
def test_file_bump(self):
with open('file.txt', 'w') as f:
f.write("0.0.0")
bump.update_file_version("12.34.56")
file_data = ""
with open('file.txt', 'r') as f:
file_data = f.read()
self.assertEqual("12.34.56", file_data)
def test_file_bump_with_text(self):
with open('file.txt', 'w') as f:
f.write("version = 0.0.0")
bump.update_file_version("12.34.56")
file_data = ""
with open('file.txt', 'r') as f:
file_data = f.read()
self.assertEqual("version = 12.34.56", file_data)
def test_file_bump_with_multiline(self):
with open('file.txt', 'w') as f:
f.write("version = 0.0.0\n#An example second line\nThird line!")
bump.update_file_version("12.34.56")
file_data = ""
with open('file.txt', 'r') as f:
file_data = f.read()
self.assertEqual("version = 12.34.56", file_data.split('\n')[0])
def create_git_environment():
subprocess.call(['rm', '-rf', './.git'])
subprocess.call(['git', 'init'])
@ -172,4 +236,4 @@ if __name__ == "__main__":
with open('.bumpversion.cfg', "w") as config:
config.write(config_data)
unittest.main()
os.chdir("..")
os.chdir("..")

View File

@ -98,7 +98,6 @@ setup(
# requirements files see:
# https://packaging.python.org/en/latest/requirements.html
install_requires=[
'bump2version>=0.5.11',
'argparse>=1.2.1'
],