-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathupdate_version.py
136 lines (107 loc) · 3.78 KB
/
update_version.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
import re
import subprocess
import sys
from contextlib import contextmanager
from typing import Generator, List
import toml
from audit_logger.custom_logger import get_logger
logger = get_logger("audit_logger")
semver_regex = r"^\d+\.\d+\.\d+$"
def poetry_lock_no_update() -> None:
try:
result = subprocess.run(
["poetry", "lock", "--no-update"],
check=True,
capture_output=True,
text=True,
)
logger.info("Poetry lock updated. %s", result.stdout)
except subprocess.CalledProcessError as e:
logger.error("Error running poetry lock: %s %s", e, e.stderr)
def get_current_version() -> str:
file_path = "pyproject.toml"
try:
pyproject_data = toml.load(file_path)
current_version = pyproject_data["tool"]["poetry"]["version"]
return current_version
except FileNotFoundError:
logger.error("%s not found", file_path)
sys.exit(1)
except KeyError as e:
logger.error("Error loading %s: %s", file_path, e)
sys.exit(1)
arg_current_version = get_current_version()
arg_new_version = None
try:
# Check if both versions match the Semantic Versioning pattern.
if not re.match(semver_regex, arg_current_version):
logger.error(
f"Error: Current version '{arg_current_version}' "
f"does not match the Semantic Versioning pattern."
)
sys.exit(1)
arg_new_version = input(
f"The current version is '{arg_current_version}'. Enter the new version number: "
)
if not re.match(semver_regex, arg_new_version):
logger.error(
f"Error: New version '{arg_new_version}' "
f"does not match the Semantic Versioning pattern."
)
sys.exit(1)
# Abort if both versions are identical.
if arg_current_version == arg_new_version:
logger.error(
f"Error: New version '{arg_new_version}' is the same as the current version "
f"'{arg_current_version}' (nothing to do here...bye!)."
)
sys.exit(1)
except KeyboardInterrupt:
logger.error("Operation aborted")
sys.exit(1)
# File paths where the version numbers should be updated.
file_path_list = ["pyproject.toml", "audit_logger/__init__.py", "audit_logger/main.py"]
error_messages = []
@contextmanager
def update_version_in_file(
file_path: str, current_version: str, new_version: str
) -> Generator[None, None, None]:
with open(file_path, "r") as file:
content = file.read()
version_pattern = re.compile(
r'(__version__\s*=\s*|version\s*=\s*)["\']'
+ re.escape(current_version)
+ "[\"']"
)
# Check if the current version is in the file.
if not version_pattern.search(content):
error_messages.append(
f"Error: current version '{current_version}' not found in '{file_path}'"
)
yield
return
try:
# Write the updated content back to the file.
with open(file_path, "w") as file:
# Replace the current version with the new version.
file.write(version_pattern.sub(r'\g<1>"' + new_version + '"', content))
except Exception as e:
error_messages.append(f"Error: {e}")
yield
return
logger.info("Updated version in %s to %s", file_path, new_version)
yield
def update_versions(
file_paths: List[str], current_version: str, new_version: str
) -> None:
for file_path in file_paths:
with update_version_in_file(file_path, current_version, new_version):
pass
if error_messages:
for error in error_messages:
logger.error(error)
sys.exit(1)
else:
poetry_lock_no_update()
# Update the versions.
update_versions(file_path_list, arg_current_version, arg_new_version)