1+ import re
2+ import sys
3+ import os
4+ from pathlib import Path
5+
6+ # --- Get package name from command-line arguments, with a default value ---
7+ args = sys .argv [1 :]
8+ package_name = args [0 ] if args else "libcrypto"
9+
10+
11+ def bump_version (version : str ) -> str :
12+ """Bumps the version number according to a custom logic."""
13+ try :
14+ major , minor , patch = map (int , version .split ('.' ))
15+ except ValueError :
16+ print (f"Error: Invalid version format '{ version } '. Expected 'major.minor.patch'." , file = sys .stderr )
17+ sys .exit (1 )
18+
19+ patch += 1
20+ if patch >= 10 :
21+ patch = 0
22+ minor += 1
23+ if minor >= 10 :
24+ minor = 0
25+ major += 1
26+ if minor == 0 and patch == 0 :
27+ # This keeps your original logic: avoid 1.0.0 by bumping to 1.0.3
28+ patch = 3
29+
30+ return f"{ major } .{ minor } .{ patch } "
31+
32+
33+ def get_init_path (package_name : str ) -> Path :
34+ """Constructs the path to the __init__.py file."""
35+ # Assuming script runs from repo root
36+ current = Path (__file__ ).resolve ().parent
37+ lib_src = current / "src" / package_name
38+ return lib_src / "__init__.py"
39+
40+
41+ def get_version_from_init (init_path : Path ) -> str :
42+ """Reads the version number from the __init__.py file."""
43+ try :
44+ content = init_path .read_text (encoding = 'utf-8' )
45+ except FileNotFoundError :
46+ print (f"Error: __init__.py not found at '{ init_path } '" , file = sys .stderr )
47+ sys .exit (1 )
48+
49+ match = re .search (r"^__version__\s*=\s*['\"]([^'\"]*)['\"]" , content , re .M )
50+ if match :
51+ return match .group (1 )
52+ else :
53+ print ("Error: Unable to find __version__ string in __init__.py" , file = sys .stderr )
54+ sys .exit (1 )
55+
56+
57+ def update_file_version (file_path : Path , pattern : re .Pattern , new_line : str ):
58+ """A generic function to update the version in a given file."""
59+ if not file_path .exists ():
60+ print (f"Info: Skipping update for non-existent file: { file_path } " , file = sys .stderr )
61+ return
62+
63+ try :
64+ content = file_path .read_text (encoding = 'utf-8' )
65+
66+ # Check if the pattern exists before trying to substitute
67+ if not pattern .search (content ):
68+ print (f"Warning: Version pattern not found in { file_path } . Skipping update." , file = sys .stderr )
69+ return
70+
71+ updated = pattern .sub (new_line , content )
72+ file_path .write_text (updated , encoding = 'utf-8' )
73+
74+ print (f"Successfully updated version in: { file_path .name } " , file = sys .stderr )
75+
76+ except Exception as e :
77+ print (f"Error updating file { file_path } : { e } " , file = sys .stderr )
78+
79+
80+ # --- Main execution block ---
81+ if __name__ == "__main__" :
82+ # 1. Get the current version from the single source of truth (__init__.py)
83+ init_path = get_init_path (package_name )
84+ current_version = get_version_from_init (init_path )
85+
86+ # 2. Calculate the new version
87+ new_version = bump_version (current_version )
88+
89+ print (f"{ '=' * 20 } [ Bumping version from { current_version } to { new_version } ]{ '=' * 20 } " , file = sys .stderr )
90+
91+ # 3. Define patterns and replacements for each file
92+ # For __init__.py
93+ init_pattern = re .compile (r"^(__version__\s*=\s*['\"])([^'\"]*)(['\"])" , re .M )
94+ init_new = f'__version__ = "{ new_version } "'
95+
96+ # For setup.py
97+ setup_pattern = re .compile (r"(version\s*=\s*['\"])([^'\"]*)(['\"])" , re .M )
98+ setup_new = f'version="{ new_version } "'
99+
100+ # For pyproject.toml
101+ pyproject_pattern = re .compile (r"^(version\s*=\s*['\"])([^'\"]*)(['\"])" , re .M )
102+ pyproject_new = f'version = "{ new_version } "'
103+
104+ # 4. Update all files
105+ update_file_version (init_path , init_pattern , init_new )
106+ setup_path = Path .cwd () / "setup.py"
107+ update_file_version (setup_path , setup_pattern , setup_new )
108+ pyproject_path = Path .cwd () / "pyproject.toml"
109+ update_file_version (pyproject_path , pyproject_pattern , pyproject_new )
110+
111+ # 5. Write the new version to GitHub environment file for CI/CD
112+ github_env = os .environ .get ("GITHUB_ENV" )
113+ if github_env :
114+ try :
115+ with open (github_env , "a" , encoding = "utf-8" ) as env_file :
116+ env_file .write (f"NEW_VERSION={ new_version } \n " )
117+ print ("Successfully wrote new version to GITHUB_ENV." , file = sys .stderr )
118+ except Exception as e :
119+ print (f"Warning: Could not write NEW_VERSION to GITHUB_ENV: { e } " , file = sys .stderr )
120+ else :
121+ print ("Info: GITHUB_ENV not found. Skipping environment file write." , file = sys .stderr )
122+
123+ # 6. Print the new version to stdout for capture by CI (only the version)
124+ print (new_version )
0 commit comments