Merge branch 'feature/dev-suffix-for-py-snapshots' into 'main'

Feature/dev suffix for py snapshots

See merge request domaindrivenarchitecture/dda-devops-build!16
This commit is contained in:
Michael Jerger 2023-07-12 06:29:53 +00:00
commit 9aa4d8b5ae
11 changed files with 119 additions and 64 deletions

View file

@ -33,7 +33,7 @@ default_task = "dev"
name = "ddadevops" name = "ddadevops"
MODULE = "not-used" MODULE = "not-used"
PROJECT_ROOT_PATH = "." PROJECT_ROOT_PATH = "."
version = "4.0.11-SNAPSHOT" version = "4.0.11-dev1"
summary = "tools to support builds combining gopass, terraform, dda-pallet, aws & hetzner-cloud" summary = "tools to support builds combining gopass, terraform, dda-pallet, aws & hetzner-cloud"
description = __doc__ description = __doc__
authors = [Author("meissa GmbH", "buero@meissa-gmbh.de")] authors = [Author("meissa GmbH", "buero@meissa-gmbh.de")]

View file

@ -87,7 +87,6 @@ classDiagram
release_type release_type
release_main_branch release_main_branch
release_current_branch release_current_branch
version
} }
class Credentials { class Credentials {
<<AggregateRoot>> <<AggregateRoot>>
@ -130,7 +129,8 @@ classDiagram
TerraformDomain *-- "0..1" ProviderAws: providers TerraformDomain *-- "0..1" ProviderAws: providers
Release o-- "0..1" BuildFile: primary_build_file Release o-- "0..1" BuildFile: primary_build_file
Release o-- "0..n" BuildFile: secondary_build_files Release o-- "0..n" BuildFile: secondary_build_files
BuildFile *-- "1" Version Release "1" *-- "1" Version: version
BuildFile *-- "1" Version: version
C4k *-- DnsRecord: dns_record C4k *-- DnsRecord: dns_record
ProvsK3s *-- DnsRecord: provision_dns ProvsK3s *-- DnsRecord: provision_dns
Credentials *-- "0..n" CredentialMapping: mappings[name] Credentials *-- "0..n" CredentialMapping: mappings[name]

View file

@ -42,7 +42,7 @@ class ReleaseService:
release_version = release.version.create_patch() release_version = release.version.create_patch()
case _: case _:
return return
bump_version = release_version.create_bump("SNAPSHOT") bump_version = release_version.create_bump()
release_message = f"release: {release_version.to_string()}" release_message = f"release: {release_version.to_string()}"
bump_message = f"bump version to: {bump_version.to_string()}" bump_message = f"bump version to: {bump_version.to_string()}"
self.git_api.tag_annotated(release_version.to_string(), release_message, 0) self.git_api.tag_annotated(release_version.to_string(), release_message, 0)

View file

@ -1,6 +1,7 @@
import json import json
import re import re
from enum import Enum from enum import Enum
from typing import Optional
from pathlib import Path from pathlib import Path
from .common import Validateable from .common import Validateable
from .version import Version from .version import Version
@ -26,9 +27,10 @@ class BuildFile(Validateable):
result += [f"Suffix {self.file_path} is unknown."] result += [f"Suffix {self.file_path} is unknown."]
return result return result
def build_file_type(self): def build_file_type(self) -> Optional[BuildFileType]:
result: Optional[BuildFileType] = None
if not self.file_path: if not self.file_path:
return None return result
config_file_type = self.file_path.suffix config_file_type = self.file_path.suffix
match config_file_type: match config_file_type:
case ".json": case ".json":
@ -76,7 +78,7 @@ class BuildFile(Validateable):
except: except:
raise Exception(f"Version not found in file {self.file_path}") raise Exception(f"Version not found in file {self.file_path}")
result = Version.from_str(version_str) result = Version.from_str(version_str, self.get_default_suffix())
result.throw_if_invalid() result.throw_if_invalid()
return result return result
@ -115,6 +117,13 @@ class BuildFile(Validateable):
except: except:
raise Exception(f"Version not found in file {self.file_path}") raise Exception(f"Version not found in file {self.file_path}")
def get_default_suffix(self) -> str:
result = "SNAPSHOT"
match self.build_file_type():
case BuildFileType.PYTHON:
result = "dev"
return result
def __eq__(self, other): def __eq__(self, other):
return other and self.file_path == other.file_path return other and self.file_path == other.file_path

View file

@ -6,7 +6,7 @@ from .common import (
class Version(Validateable): class Version(Validateable):
@classmethod @classmethod
def from_str(cls, input_str: str): def from_str(cls, input_str: str, default_snapshot_suffix):
snapshot_parsed = input_str.split("-") snapshot_parsed = input_str.split("-")
version_str = snapshot_parsed[0] version_str = snapshot_parsed[0]
suffix_str = None suffix_str = None
@ -15,6 +15,7 @@ class Version(Validateable):
version_no_parsed = [int(x) for x in version_str.split(".")] version_no_parsed = [int(x) for x in version_str.split(".")]
return cls( return cls(
version_no_parsed, version_no_parsed,
default_snapshot_suffix,
suffix_str, suffix_str,
input_str, input_str,
) )
@ -22,12 +23,14 @@ class Version(Validateable):
def __init__( def __init__(
self, self,
version_list: list, version_list: list,
default_snapshot_suffix: str,
snapshot_suffix: Optional[str] = None, snapshot_suffix: Optional[str] = None,
version_str: Optional[str] = None, version_str: Optional[str] = None,
): ):
self.version_list = version_list self.version_list = version_list
self.snapshot_suffix = snapshot_suffix
self.version_string = version_str self.version_string = version_str
self.snapshot_suffix = snapshot_suffix
self.default_snapshot_suffix = default_snapshot_suffix
def __eq__(self, other): def __eq__(self, other):
return other and self.to_string() == other.to_string() return other and self.to_string() == other.to_string()
@ -47,6 +50,7 @@ class Version(Validateable):
def validate(self): def validate(self):
result = [] result = []
result += self.__validate_is_not_empty__("version_list") result += self.__validate_is_not_empty__("version_list")
result += self.__validate_is_not_empty__("default_snapshot_suffix")
if self.version_list and len(self.version_list) < 3: if self.version_list and len(self.version_list) < 3:
result += ["version_list must have at least 3 levels."] result += ["version_list must have at least 3 levels."]
if ( if (
@ -59,41 +63,79 @@ class Version(Validateable):
] ]
return result return result
def create_bump(self, snapshot_suffix: Optional[str] = None): def create_bump(self):
tmp_snapshot_suffix = self.default_snapshot_suffix
new_version_list = self.version_list.copy() new_version_list = self.version_list.copy()
if self.is_snapshot(): if self.is_snapshot():
return Version( return Version(
new_version_list, snapshot_suffix=self.snapshot_suffix, version_str=None new_version_list,
self.default_snapshot_suffix,
snapshot_suffix=tmp_snapshot_suffix,
version_str=None,
) )
else: else:
new_version_list[2] += 1 new_version_list[2] += 1
return Version( return Version(
new_version_list, snapshot_suffix=snapshot_suffix, version_str=None new_version_list,
self.default_snapshot_suffix,
snapshot_suffix=tmp_snapshot_suffix,
version_str=None,
) )
def create_patch(self): def create_patch(self):
new_version_list = self.version_list.copy() new_version_list = self.version_list.copy()
if self.is_snapshot(): if self.is_snapshot():
return Version(new_version_list, snapshot_suffix=None, version_str=None) return Version(
new_version_list,
self.default_snapshot_suffix,
snapshot_suffix=None,
version_str=None,
)
else: else:
new_version_list[2] += 1 new_version_list[2] += 1
return Version(new_version_list, snapshot_suffix=None, version_str=None) return Version(
new_version_list,
self.default_snapshot_suffix,
snapshot_suffix=None,
version_str=None,
)
def create_minor(self): def create_minor(self):
new_version_list = self.version_list.copy() new_version_list = self.version_list.copy()
if self.is_snapshot() and new_version_list[2] == 0: if self.is_snapshot() and new_version_list[2] == 0:
return Version(new_version_list, snapshot_suffix=None, version_str=None) return Version(
new_version_list,
self.default_snapshot_suffix,
snapshot_suffix=None,
version_str=None,
)
else: else:
new_version_list[2] = 0 new_version_list[2] = 0
new_version_list[1] += 1 new_version_list[1] += 1
return Version(new_version_list, snapshot_suffix=None, version_str=None) return Version(
new_version_list,
self.default_snapshot_suffix,
snapshot_suffix=None,
version_str=None,
)
def create_major(self): def create_major(self):
new_version_list = self.version_list.copy() new_version_list = self.version_list.copy()
if self.is_snapshot() and new_version_list[2] == 0 and new_version_list[1] == 0: if self.is_snapshot() and new_version_list[2] == 0 and new_version_list[1] == 0:
return Version(new_version_list, snapshot_suffix=None, version_str=None) return Version(
new_version_list,
self.default_snapshot_suffix,
snapshot_suffix=None,
version_str=None,
)
else: else:
new_version_list[2] = 0 new_version_list[2] = 0
new_version_list[1] = 0 new_version_list[1] = 0
new_version_list[0] += 1 new_version_list[0] += 1
return Version(new_version_list, snapshot_suffix=None, version_str=None) return Version(
new_version_list,
self.default_snapshot_suffix,
snapshot_suffix=None,
version_str=None,
)

View file

@ -66,7 +66,7 @@ def devops_config(overrides: dict) -> dict:
def build_devops( def build_devops(
overrides: dict, version: Version = Version.from_str("1.0.0-SNAPSHOT") overrides: dict, version: Version = Version.from_str("1.0.0-SNAPSHOT", "SNAPSHOT")
) -> Devops: ) -> Devops:
return DevopsFactory().build_devops(devops_config(overrides), version=version) return DevopsFactory().build_devops(devops_config(overrides), version=version)

View file

@ -45,7 +45,7 @@ def test_sould_parse_and_set_js():
} }
""", """,
) )
assert sut.get_version() == Version.from_str("1.1.5-SNAPSHOT") assert sut.get_version() == Version.from_str("1.1.5-SNAPSHOT", "SNAPSHOT")
sut = BuildFile( sut = BuildFile(
Path("./package.json"), Path("./package.json"),
@ -67,7 +67,7 @@ def test_sould_parse_and_set_js():
} }
""", """,
) )
sut.set_version(Version.from_str("1.1.5-SNAPSHOT").create_major()) sut.set_version(Version.from_str("1.1.5-SNAPSHOT", "SNAPSHOT").create_major())
assert ( assert (
"""{ """{
"name": "c4k-jira", "name": "c4k-jira",
@ -85,7 +85,7 @@ version = "1.1.5-SNAPSHOT"
""", """,
) )
assert sut.get_version() == Version.from_str("1.1.5-SNAPSHOT") assert sut.get_version() == Version.from_str("1.1.5-SNAPSHOT", "SNAPSHOT")
sut = BuildFile( sut = BuildFile(
Path("./build.gradle"), Path("./build.gradle"),
@ -93,7 +93,7 @@ version = "1.1.5-SNAPSHOT"
version = "1.1.5-SNAPSHOT" version = "1.1.5-SNAPSHOT"
""", """,
) )
sut.set_version(Version.from_str("1.1.5-SNAPSHOT").create_major()) sut.set_version(Version.from_str("1.1.5-SNAPSHOT", "SNAPSHOT").create_major())
assert '\nversion = "2.0.0"\n' == sut.content assert '\nversion = "2.0.0"\n' == sut.content
@ -109,7 +109,7 @@ version = "1.1.5-dev12"
summary = "tools to support builds combining gopass, terraform, dda-pallet, aws & hetzner-cloud" summary = "tools to support builds combining gopass, terraform, dda-pallet, aws & hetzner-cloud"
""", """,
) )
assert sut.get_version() == Version.from_str("1.1.5-dev12") assert sut.get_version() == Version.from_str("1.1.5-dev12", "dev")
sut = BuildFile( sut = BuildFile(
Path("./build.py"), Path("./build.py"),
@ -117,7 +117,7 @@ summary = "tools to support builds combining gopass, terraform, dda-pallet, aws
version = "1.1.5-dev12" version = "1.1.5-dev12"
""", """,
) )
sut.set_version(Version.from_str("1.1.5-dev12").create_major()) sut.set_version(Version.from_str("1.1.5-dev12", "dev").create_major())
assert '\nversion = "2.0.0"\n' == sut.content assert '\nversion = "2.0.0"\n' == sut.content
sut = BuildFile( sut = BuildFile(
@ -131,7 +131,7 @@ version = "1.1.5-SNAPSHOT"
summary = "tools to support builds combining gopass, terraform, dda-pallet, aws & hetzner-cloud" summary = "tools to support builds combining gopass, terraform, dda-pallet, aws & hetzner-cloud"
""", """,
) )
assert sut.get_version() == Version.from_str("1.1.5-SNAPSHOT") assert sut.get_version() == Version.from_str("1.1.5-SNAPSHOT", "SNAPSHOT")
sut = BuildFile( sut = BuildFile(
Path("./build.py"), Path("./build.py"),
@ -139,7 +139,7 @@ summary = "tools to support builds combining gopass, terraform, dda-pallet, aws
version = "1.1.5-SNAPSHOT" version = "1.1.5-SNAPSHOT"
""", """,
) )
sut.set_version(Version.from_str("1.1.5-SNAPSHOT").create_major()) sut.set_version(Version.from_str("1.1.5-SNAPSHOT", "SNAPSHOT").create_major())
assert '\nversion = "2.0.0"\n' == sut.content assert '\nversion = "2.0.0"\n' == sut.content
@ -153,7 +153,7 @@ def test_sould_parse_and_set_version_for_clj():
) )
""", """,
) )
assert sut.get_version() == Version.from_str("1.1.5-SNAPSHOT") assert sut.get_version() == Version.from_str("1.1.5-SNAPSHOT", "SNAPSHOT")
sut = BuildFile( sut = BuildFile(
Path("./project.clj"), Path("./project.clj"),
@ -163,7 +163,7 @@ def test_sould_parse_and_set_version_for_clj():
) )
""", """,
) )
sut.set_version(Version.from_str("1.1.5-SNAPSHOT").create_major()) sut.set_version(Version.from_str("1.1.5-SNAPSHOT", "SNAPSHOT").create_major())
assert ( assert (
'\n(defproject org.domaindrivenarchitecture/c4k-jira "2.0.0"\n :description "jira c4k-installation package"\n)\n' '\n(defproject org.domaindrivenarchitecture/c4k-jira "2.0.0"\n :description "jira c4k-installation package"\n)\n'
== sut.content == sut.content
@ -177,7 +177,7 @@ def test_sould_parse_and_set_version_for_clj():
) )
""", """,
) )
sut.set_version(Version.from_str("1.1.5-SNAPSHOT").create_major()) sut.set_version(Version.from_str("1.1.5-SNAPSHOT", "SNAPSHOT").create_major())
assert ( assert (
'\n(defproject org.domaindrivenarchitecture/c4k-jira "2.0.0"\n:dependencies [[org.clojure/clojure "1.11.0"]]\n)\n ' '\n(defproject org.domaindrivenarchitecture/c4k-jira "2.0.0"\n:dependencies [[org.clojure/clojure "1.11.0"]]\n)\n '
== sut.content == sut.content

View file

@ -45,7 +45,7 @@ def test_devops_factory():
"c4k_grafana_cloud_user": "user", "c4k_grafana_cloud_user": "user",
"c4k_grafana_cloud_password": "password", "c4k_grafana_cloud_password": "password",
}, },
Version.from_str("1.0.0"), Version.from_str("1.0.0", "SNAPSHOT"),
) )
assert sut is not None assert sut is not None
assert sut.specialized_builds[BuildType.C4K] is not None assert sut.specialized_builds[BuildType.C4K] is not None
@ -62,7 +62,7 @@ def test_devops_factory():
"release_current_branch": "my_feature", "release_current_branch": "my_feature",
"release_config_file": "project.clj", "release_config_file": "project.clj",
}, },
Version.from_str("1.0.0"), Version.from_str("1.0.0", "SNAPSHOT"),
) )
assert sut is not None assert sut is not None
assert sut.mixins[MixinType.RELEASE] is not None assert sut.mixins[MixinType.RELEASE] is not None

View file

@ -27,7 +27,7 @@ def test_should_load_build_file():
GitApiMock(), GitApiMock(),
) )
assert ( assert (
Version.from_str("1.1.5-SNAPSHOT") Version.from_str("1.1.5-SNAPSHOT", "SNAPSHOT")
== sut.initialize(devops_config({})).mixins[MixinType.RELEASE].version == sut.initialize(devops_config({})).mixins[MixinType.RELEASE].version
) )
@ -42,7 +42,7 @@ def test_should_load_build_file():
GitApiMock(), GitApiMock(),
) )
assert ( assert (
Version.from_str("4.0.0-dev73") Version.from_str("4.0.0-dev73", "dev")
== sut.initialize(devops_config({})).mixins[MixinType.RELEASE].version == sut.initialize(devops_config({})).mixins[MixinType.RELEASE].version
) )

View file

@ -22,7 +22,7 @@ def test_sould_validate_release():
"release_current_branch": "main", "release_current_branch": "main",
} }
), ),
Version.from_str("1.3.1-SNAPSHOT"), Version.from_str("1.3.1-SNAPSHOT", "SNAPSHOT"),
) )
assert sut.is_valid() assert sut.is_valid()
@ -33,7 +33,7 @@ def test_sould_validate_release():
"release_current_branch": "some-feature-branch", "release_current_branch": "some-feature-branch",
} }
), ),
Version.from_str("1.3.1-SNAPSHOT"), Version.from_str("1.3.1-SNAPSHOT", "SNAPSHOT"),
) )
assert not sut.is_valid() assert not sut.is_valid()
@ -43,7 +43,7 @@ def test_sould_validate_release():
"release_primary_build_file": 1, "release_primary_build_file": 1,
} }
), ),
Version.from_str("1.3.1-SNAPSHOT"), Version.from_str("1.3.1-SNAPSHOT", "SNAPSHOT"),
) )
assert not sut.is_valid() assert not sut.is_valid()
@ -58,6 +58,6 @@ def test_sould_calculate_build_files():
"release_secondary_build_files": ["package.json"], "release_secondary_build_files": ["package.json"],
} }
), ),
Version.from_str("1.3.1-SNAPSHOT"), Version.from_str("1.3.1-SNAPSHOT", "SNAPSHOT"),
) )
assert ["project.clj", "package.json"] == sut.build_files() assert ["project.clj", "package.json"] == sut.build_files()

View file

@ -9,106 +9,110 @@ from .helper import build_devops, devops_config
def test_version_creation(): def test_version_creation():
sut = Version.from_str("1.2.3") sut = Version.from_str("1.2.3", "SNAPSHOT")
assert sut.to_string() == "1.2.3" assert sut.to_string() == "1.2.3"
assert sut.version_list == [1, 2, 3] assert sut.version_list == [1, 2, 3]
assert sut.is_snapshot() == False assert sut.is_snapshot() == False
sut = Version.from_str("1.2.3-SNAPSHOT") sut = Version.from_str("1.2.3-SNAPSHOT", "SNAPSHOT")
assert sut.to_string() == "1.2.3-SNAPSHOT" assert sut.to_string() == "1.2.3-SNAPSHOT"
assert sut.version_list == [1, 2, 3] assert sut.version_list == [1, 2, 3]
assert sut.is_snapshot() == True assert sut.is_snapshot() == True
def test_should_validate_version_list(): def test_should_validate_version_list():
sut = Version(None) sut = Version(None, "SNAPSHOT")
assert not sut.is_valid() assert not sut.is_valid()
sut = Version([]) sut = Version([], "SNAPSHOT")
assert not sut.is_valid() assert not sut.is_valid()
sut = Version([1, 2]) sut = Version([1, 2], "SNAPSHOT")
assert not sut.is_valid() assert not sut.is_valid()
sut = Version([1, 2, 3]) sut = Version([1, 2, 3], "SNAPSHOT")
assert sut.is_valid() assert sut.is_valid()
def test_should_validate_parsing(): def test_should_validate_parsing():
sut = Version.from_str("1.2") sut = Version.from_str("1.2", "SNAPSHOT")
assert not sut.is_valid() assert not sut.is_valid()
sut = Version.from_str("1.2.3") sut = Version.from_str("1.2.3", "SNAPSHOT")
sut.version_list = [2, 2, 2] sut.version_list = [2, 2, 2]
assert not sut.is_valid() assert not sut.is_valid()
sut = Version.from_str("1.2.3") sut = Version.from_str("1.2.3", "SNAPSHOT")
assert sut.is_valid() assert sut.is_valid()
sut = Version.from_str("1.2.3-SNAPSHOT") sut = Version.from_str("1.2.3-SNAPSHOT", "SNAPSHOT")
assert sut.is_valid() assert sut.is_valid()
sut = Version.from_str("1.2.3-dev") sut = Version.from_str("1.2.3-dev", "dev")
assert sut.is_valid() assert sut.is_valid()
def test_should_create_patch(): def test_should_create_patch():
version = Version.from_str("1.2.3-SNAPSHOT") version = Version.from_str("1.2.3-SNAPSHOT", "SNAPSHOT")
sut = version.create_patch() sut = version.create_patch()
assert sut.to_string() == "1.2.3" assert sut.to_string() == "1.2.3"
assert version.to_string() == "1.2.3-SNAPSHOT" assert version.to_string() == "1.2.3-SNAPSHOT"
version = Version.from_str("1.2.3") version = Version.from_str("1.2.3", "SNAPSHOT")
sut = version.create_patch() sut = version.create_patch()
assert sut.to_string() == "1.2.4" assert sut.to_string() == "1.2.4"
assert version.to_string() == "1.2.3" assert version.to_string() == "1.2.3"
def test_should_create_minor(): def test_should_create_minor():
version = Version.from_str("1.2.3-SNAPSHOT") version = Version.from_str("1.2.3-SNAPSHOT", "SNAPSHOT")
sut = version.create_minor() sut = version.create_minor()
assert sut.to_string() == "1.3.0" assert sut.to_string() == "1.3.0"
version = Version.from_str("1.2.3") version = Version.from_str("1.2.3", "SNAPSHOT")
sut = version.create_minor() sut = version.create_minor()
assert sut.to_string() == "1.3.0" assert sut.to_string() == "1.3.0"
version = Version.from_str("1.3.0-SNAPSHOT") version = Version.from_str("1.3.0-SNAPSHOT", "SNAPSHOT")
sut = version.create_minor() sut = version.create_minor()
assert sut.to_string() == "1.3.0" assert sut.to_string() == "1.3.0"
version = Version.from_str("1.3.0") version = Version.from_str("1.3.0", "SNAPSHOT")
sut = version.create_minor() sut = version.create_minor()
assert sut.to_string() == "1.4.0" assert sut.to_string() == "1.4.0"
def test_should_create_major(): def test_should_create_major():
version = Version.from_str("1.2.3-SNAPSHOT") version = Version.from_str("1.2.3-SNAPSHOT", "SNAPSHOT")
sut = version.create_major() sut = version.create_major()
assert sut.to_string() == "2.0.0" assert sut.to_string() == "2.0.0"
version = Version.from_str("1.2.3") version = Version.from_str("1.2.3", "SNAPSHOT")
sut = version.create_major() sut = version.create_major()
assert sut.to_string() == "2.0.0" assert sut.to_string() == "2.0.0"
version = Version.from_str("1.0.0-SNAPSHOT") version = Version.from_str("1.0.0-SNAPSHOT", "SNAPSHOT")
sut = version.create_major() sut = version.create_major()
assert sut.to_string() == "1.0.0" assert sut.to_string() == "1.0.0"
version = Version.from_str("1.0.0") version = Version.from_str("1.0.0", "SNAPSHOT")
sut = version.create_major() sut = version.create_major()
assert sut.to_string() == "2.0.0" assert sut.to_string() == "2.0.0"
def test_should_create_bump(): def test_should_create_bump():
version = Version.from_str("1.2.3-SNAPSHOT") version = Version.from_str("1.2.3-SNAPSHOT", "SNAPSHOT")
sut = version.create_bump() sut = version.create_bump()
assert sut.to_string() == "1.2.3-SNAPSHOT" assert sut.to_string() == "1.2.3-SNAPSHOT"
version = Version.from_str("1.2.3") version = Version.from_str("1.2.3", "SNAPSHOT")
sut = version.create_bump("SNAPSHOT") sut = version.create_bump()
assert sut.to_string() == "1.2.4-SNAPSHOT" assert sut.to_string() == "1.2.4-SNAPSHOT"
version = Version.from_str("1.0.0") version = Version.from_str("1.0.0", "SNAPSHOT")
sut = version.create_bump("SNAPSHOT") sut = version.create_bump()
assert sut.to_string() == "1.0.1-SNAPSHOT" assert sut.to_string() == "1.0.1-SNAPSHOT"
version = Version.from_str("1.0.0", "dev")
sut = version.create_bump()
assert sut.to_string() == "1.0.1-dev"