3
3
commit_msg_version_bump.py
4
4
5
5
A script to bump the version in pyproject.toml based on the latest commit message.
6
- Adds icons to commit messages depending on their type and ensures that changes are committed in a single step.
6
+ Changes the commit message to include the version bump and adds an icon.
7
+ Ensures that changes are committed in a single step.
7
8
8
9
Usage:
9
10
commit_msg_version_bump.py [--log-level {INFO,DEBUG}]
17
18
from logging .handlers import RotatingFileHandler
18
19
from typing import Optional
19
20
21
+ import toml
20
22
21
23
# Mapping of commit types to icons
22
24
TYPE_MAPPING = {
@@ -126,56 +128,66 @@ def get_latest_commit_message() -> str:
126
128
sys .exit (1 )
127
129
128
130
129
- def add_icon_to_commit_message ( commit_msg : str ) -> str :
131
+ def get_current_version ( pyproject_path : str = "pyproject.toml" ) -> str :
130
132
"""
131
- Adds an icon to the commit message based on its type .
133
+ Retrieves the current version from pyproject.toml .
132
134
133
135
Args:
134
- commit_msg (str): The original commit message .
136
+ pyproject_path (str): Path to the pyproject.toml file .
135
137
136
138
Returns:
137
- str: The commit message with the icon prepended .
139
+ str: The current version string .
138
140
"""
139
- match = COMMIT_TYPE_REGEX .match (commit_msg )
140
- if match :
141
- commit_type = match .group ("type" ).lower ()
142
- icon = TYPE_MAPPING .get (commit_type , "" )
143
- if icon :
144
- # Avoid adding multiple icons
145
- if not commit_msg .startswith (icon ):
146
- new_commit_msg = f"{ icon } { commit_msg } "
147
- logger .debug (f"Updated commit message with icon: { new_commit_msg } " )
148
- return new_commit_msg
149
- logger .debug ("No matching commit type found or icon already present." )
150
- return commit_msg
141
+ try :
142
+ with open (pyproject_path , "r" , encoding = "utf-8" ) as file :
143
+ data = toml .load (file )
144
+ version = data ["tool" ]["poetry" ]["version" ]
145
+ logger .debug (f"Current version: { version } " )
146
+ return version
147
+ except (FileNotFoundError , KeyError , ValueError , toml .TomlDecodeError ) as e :
148
+ logger .error (f"Error retrieving the version from { pyproject_path } : { e } " )
149
+ sys .exit (1 )
151
150
152
151
153
- def determine_version_bump ( commit_msg : str ) -> Optional [ str ] :
152
+ def get_new_version ( pyproject_path : str = "pyproject.toml" ) -> str :
154
153
"""
155
- Determines the version bump part based on the commit message .
154
+ Retrieves the new version from pyproject.toml after bump .
156
155
157
156
Args:
158
- commit_msg (str): The commit message .
157
+ pyproject_path (str): Path to the pyproject.toml file .
159
158
160
159
Returns:
161
- Optional[ str] : The version part to bump ('major', 'minor', 'patch') or None .
160
+ str: The new version string .
162
161
"""
163
- match = VERSION_KEYWORD_REGEX .search (commit_msg )
164
- if match :
165
- keyword = match .group ("keyword" ).lower ()
166
- if "major" in keyword :
167
- return "major"
168
- elif "minor" in keyword :
169
- return "minor"
170
- elif "patch" in keyword :
171
- return "patch"
172
- else :
173
- # Fallback based on commit type
174
- type_match = COMMIT_TYPE_REGEX .match (commit_msg )
175
- if type_match :
176
- commit_type = type_match .group ("type" ).lower ()
177
- return VERSION_BUMP_MAPPING .get (commit_type )
178
- return None
162
+ try :
163
+ with open (pyproject_path , "r" , encoding = "utf-8" ) as file :
164
+ data = toml .load (file )
165
+ new_version = data ["tool" ]["poetry" ]["version" ]
166
+ logger .debug (f"New version: { new_version } " )
167
+ return new_version
168
+ except (FileNotFoundError , KeyError , ValueError , toml .TomlDecodeError ) as e :
169
+ logger .error (f"Error retrieving the new version from { pyproject_path } : { e } " )
170
+ sys .exit (1 )
171
+
172
+
173
+ def add_icon_and_prepare_commit_message (
174
+ commit_type : str , current_version : str , new_version : str
175
+ ) -> str :
176
+ """
177
+ Prepares the new commit message with the icon and version bump.
178
+
179
+ Args:
180
+ commit_type (str): The type of the commit (e.g., 'chore', 'fix').
181
+ current_version (str): The current version before bump.
182
+ new_version (str): The new version after bump.
183
+
184
+ Returns:
185
+ str: The new commit message.
186
+ """
187
+ icon = TYPE_MAPPING .get (commit_type .lower (), "" )
188
+ new_commit_msg = f"{ icon } Bump version: { current_version } → { new_version } "
189
+ logger .debug (f"New commit message: { new_commit_msg } " )
190
+ return new_commit_msg
179
191
180
192
181
193
def bump_version (part : str ) -> None :
@@ -235,25 +247,39 @@ def amend_commit(new_commit_msg: str) -> None:
235
247
236
248
def main () -> None :
237
249
"""
238
- Main function to parse the latest commit message, add an icon, and perform version bumping.
250
+ Main function to parse the latest commit message, add an icon, perform version bumping, and amend the commit .
239
251
"""
240
252
args = parse_arguments ()
241
253
configure_logger (args .log_level )
242
254
243
255
latest_commit_msg = get_latest_commit_message ()
244
256
245
- updated_commit_msg = add_icon_to_commit_message (latest_commit_msg )
257
+ type_match = COMMIT_TYPE_REGEX .match (latest_commit_msg )
258
+ if type_match :
259
+ commit_type = type_match .group ("type" )
260
+ logger .debug (f"Detected commit type: { commit_type } " )
261
+ else :
262
+ commit_type = "chore" # Default to 'chore' if no type is found
263
+ logger .debug ("No commit type detected. Defaulting to 'chore'." )
246
264
247
265
version_bump_part = determine_version_bump (latest_commit_msg )
248
266
249
267
if version_bump_part :
250
268
logger .info (f"Version bump detected: { version_bump_part } " )
269
+
270
+ current_version = get_current_version ()
271
+
251
272
bump_version (version_bump_part )
252
273
274
+ new_version = get_new_version ()
275
+
276
+ updated_commit_msg = add_icon_and_prepare_commit_message (
277
+ commit_type , current_version , new_version
278
+ )
279
+
253
280
# Stage the updated pyproject.toml
254
281
stage_changes ()
255
282
256
- # Amend the commit with the updated message
257
283
amend_commit (updated_commit_msg )
258
284
259
285
logger .info (
@@ -264,5 +290,33 @@ def main() -> None:
264
290
logger .info ("No version bump detected in commit message." )
265
291
266
292
293
+ def determine_version_bump (commit_msg : str ) -> Optional [str ]:
294
+ """
295
+ Determines the version bump part based on the commit message.
296
+
297
+ Args:
298
+ commit_msg (str): The commit message.
299
+
300
+ Returns:
301
+ Optional[str]: The version part to bump ('major', 'minor', 'patch') or None.
302
+ """
303
+ match = VERSION_KEYWORD_REGEX .search (commit_msg )
304
+ if match :
305
+ keyword = match .group ("keyword" ).lower ()
306
+ if "major" in keyword :
307
+ return "major"
308
+ elif "minor" in keyword :
309
+ return "minor"
310
+ elif "patch" in keyword :
311
+ return "patch"
312
+ else :
313
+ # Fallback based on commit type
314
+ type_match = COMMIT_TYPE_REGEX .match (commit_msg )
315
+ if type_match :
316
+ commit_type = type_match .group ("type" ).lower ()
317
+ return VERSION_BUMP_MAPPING .get (commit_type )
318
+ return None
319
+
320
+
267
321
if __name__ == "__main__" :
268
322
main ()
0 commit comments