1
1
import os
2
+ import re
2
3
from pathlib import Path
3
4
from typing import NamedTuple , Optional
4
5
@@ -12,6 +13,52 @@ class GitDescribeVersion(NamedTuple):
12
13
hash : Optional [str ] = None
13
14
14
15
16
+ def determine_version_bump (repo_path = "." ):
17
+ try :
18
+
19
+ repo = Repo (repo_path )
20
+ if repo .bare :
21
+ raise ValueError ("Not a valid Git repository." )
22
+
23
+ tags = sorted (repo .tags , key = lambda t : t .commit .committed_date , reverse = True )
24
+ version_tags = [tag for tag in tags if tag .name .startswith ("v" )]
25
+ if not version_tags :
26
+ raise ValueError ("No version tags found." )
27
+
28
+ last_tag = version_tags [0 ]
29
+ commits = repo .iter_commits (f"{ last_tag .name } ..HEAD" )
30
+
31
+ ignored_types = ["chore" , "style" , "refactor" , "test" ]
32
+ patch_types = ["fix" , "docs" , "perf" ]
33
+
34
+ minor_change = False
35
+ patch_change = False
36
+
37
+ for commit in commits :
38
+ message = commit .message .strip ()
39
+
40
+ if any (re .match (rf"^{ ignored_type } (\([^\)]+\))?:" , message ) for ignored_type in ignored_types ):
41
+ continue
42
+
43
+ if "BREAKING CHANGE:" in message or re .match (r"^feat(\([^\)]+\))?!:" , message ):
44
+ return "major"
45
+
46
+ if re .match (r"^feat(\([^\)]+\))?:" , message ):
47
+ minor_change = True
48
+
49
+ if any (re .match (rf"^{ patch_types } (\([^\)]+\))?:" , message ) for ignored_type in ignored_types ):
50
+ patch_change = True
51
+
52
+ if minor_change :
53
+ return "minor"
54
+ if patch_change :
55
+ return "patch"
56
+ return None
57
+
58
+ except Exception as e :
59
+ raise RuntimeError (f"Error: { e } " )
60
+
61
+
15
62
def get_current_version_from_git () -> Version :
16
63
repo = Repo (Path .cwd ())
17
64
@@ -21,7 +68,13 @@ def get_current_version_from_git() -> Version:
21
68
22
69
version = Version (git_version .version [1 :])
23
70
if git_version .commits is not None and git_version .commits != "0" :
24
- version = version .next_patch ()
71
+ next_version = determine_version_bump ()
72
+ if next_version == "major" :
73
+ version = version .next_major ()
74
+ elif next_version == "minor" :
75
+ version = version .next_minor ()
76
+ elif next_version == "patch" :
77
+ version = version .next_patch ()
25
78
version .prerelease = ("dev" , git_version .commits )
26
79
27
80
return version
@@ -34,3 +87,7 @@ def get_version() -> Version:
34
87
return Version (os .environ ["CZ_PRE_NEW_VERSION" ])
35
88
36
89
return get_current_version_from_git ()
90
+
91
+
92
+ if __name__ == "__main__" :
93
+ print (get_version ())
0 commit comments