Decouple from bumpversion

This commit is contained in:
Layla 2020-06-26 13:26:06 -04:00
parent 3d82649a80
commit f28c0950b7
No known key found for this signature in database
GPG Key ID: A494D9357BA1BE31
7 changed files with 120 additions and 19 deletions

View File

@ -2,7 +2,7 @@
# Automatic Semantic Versioning # 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. 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*** ***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 ## 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 ```ini
[bumpversion] [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 argparse
import re import re
import subprocess import subprocess
from enum import IntEnum
from semver.utils import get_tag_version from semver.utils import get_tag_version
from semver.logger import logging, logger, console_logger from semver.logger import logging, logger, console_logger
from semver.bump import bump_version
try: try:
from configparser import ConfigParser from configparser import ConfigParser
@ -12,6 +14,10 @@ except ImportError:
version = '0.0.0' version = '0.0.0'
class VersionType(IntEnum):
MAJOR = 0
MINOR = 1
PATCH = 2
# Define common exceptions; # Define common exceptions;
NO_MERGE_FOUND = Exception('No merge found') NO_MERGE_FOUND = Exception('No merge found')
@ -74,15 +80,15 @@ class SemVer(object):
if merged_prefix: if merged_prefix:
for prefix in self.major_branches: for prefix in self.major_branches:
if prefix == merged_prefix: if prefix == merged_prefix:
self.version_type = 'major' self.version_type = VersionType.MAJOR
return self.version_type return self.version_type
for prefix in self.minor_branches: for prefix in self.minor_branches:
if prefix == merged_prefix: if prefix == merged_prefix:
self.version_type = 'minor' self.version_type = VersionType.MINOR
return self.version_type return self.version_type
for prefix in self.patch_branches: for prefix in self.patch_branches:
if prefix == merged_prefix: if prefix == merged_prefix:
self.version_type = 'patch' self.version_type = VersionType.PATCH
return self.version_type return self.version_type
return False return False
@ -106,9 +112,7 @@ class SemVer(object):
# version repo # version repo
logger.debug("Running bumpversion of type: " + self.version_type) logger.debug("Running bumpversion of type: " + self.version_type)
p = subprocess.Popen(['bumpversion', '--current-version', get_tag_version(), self.version_type], bump_version(get_tag_version(), self.version_type)
cwd='.')
p.wait()
return self return self
def commit_and_push(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.logger import logging, logger, console_logger
from semver.utils import get_tag_version, get_file_version, DEVNULL from semver.utils import get_tag_version, get_file_version, DEVNULL
from semver import SemVer from semver import SemVer
from semver.bump import bump_version
def get_version(build=0,version_format=None,dot=False): def get_version(build=0,version_format=None,dot=False):
version = get_tag_version() version = get_tag_version()
@ -27,9 +28,8 @@ def get_version(build=0,version_format=None,dot=False):
version_type = semver.get_version_type() version_type = semver.get_version_type()
logger.debug("version type is: {}".format(version_type)) logger.debug("version type is: {}".format(version_type))
if 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 = bump_version(get_tag_version(), version_type, False, False)
next_version = re.search("new_version=([0-9]*.[0-9]*.[0-9]*)", bump_output).group(1)
if version_format in ('npm','docker'): if version_format in ('npm','docker'):
return "{}-{}.{}".format(next_version,branch.replace('/','-'),build) return "{}-{}.{}".format(next_version,branch.replace('/','-'),build)

View File

@ -1,7 +1,7 @@
import unittest, os, subprocess, re, semver import unittest, os, subprocess, re, semver
from semver.logger import logging, logger, console_logger from semver.logger import logging, logger, console_logger
from semver import get_version, utils, NO_MERGE_FOUND, GET_COMMIT_MESSAGE from semver import get_version, utils, NO_MERGE_FOUND, GET_COMMIT_MESSAGE, bump
config_data = """ config_data = """
[bumpversion] [bumpversion]
@ -25,17 +25,17 @@ class TestSemverObject(unittest.TestCase):
semver_object = semver.SemVer() semver_object = semver.SemVer()
semver_object.merged_branch = "major/unittest" semver_object.merged_branch = "major/unittest"
semver_object.get_version_type() 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): def test_get_version_type_minor_merge(self):
semver_object = semver.SemVer() semver_object = semver.SemVer()
semver_object.merged_branch = "minor/unittest" semver_object.merged_branch = "minor/unittest"
semver_object.get_version_type() 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): def test_get_version_type_patch_merge(self):
semver_object = semver.SemVer() semver_object = semver.SemVer()
semver_object.merged_branch = "patch/unittest" semver_object.merged_branch = "patch/unittest"
semver_object.get_version_type() 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): def test_run_no_merge(self):
semver_object = semver.SemVer() semver_object = semver.SemVer()
try: try:
@ -155,6 +155,35 @@ class TestGetCommitMessageRegex(unittest.TestCase):
matches = GET_COMMIT_MESSAGE.search("Example unrelated commit message that should get 0 matches") matches = GET_COMMIT_MESSAGE.search("Example unrelated commit message that should get 0 matches")
self.assertEqual(matches, None) 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))
def create_git_environment(): def create_git_environment():
subprocess.call(['rm', '-rf', './.git']) subprocess.call(['rm', '-rf', './.git'])
subprocess.call(['git', 'init']) subprocess.call(['git', 'init'])
@ -172,4 +201,4 @@ if __name__ == "__main__":
with open('.bumpversion.cfg', "w") as config: with open('.bumpversion.cfg', "w") as config:
config.write(config_data) config.write(config_data)
unittest.main() unittest.main()
os.chdir("..") os.chdir("..")

View File

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