Decouple from bumpversion
This commit is contained in:
parent
3d82649a80
commit
f28c0950b7
@ -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]
|
||||||
|
@ -1 +1,5 @@
|
|||||||
bumpversion==0.5.3
|
# requirements.txt
|
||||||
|
#
|
||||||
|
# installs dependencies from ./setup.py, and the package itself,
|
||||||
|
# in editable mode
|
||||||
|
-e .
|
@ -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
65
semver/bump.py
Normal 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)
|
@ -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)
|
||||||
|
@ -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("..")
|
1
setup.py
1
setup.py
@ -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'
|
||||||
],
|
],
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user