/ archive / python / bump_version.py
bump_version.py
  1  #!/usr/bin/env python3
  2  """
  3  Automatic version bumping for Kamaji.
  4  
  5  Usage:
  6      python bump_version.py patch   # 0.1.0 -> 0.1.1
  7      python bump_version.py minor   # 0.1.0 -> 0.2.0
  8      python bump_version.py major   # 0.1.0 -> 1.0.0
  9  """
 10  
 11  import re
 12  import sys
 13  from pathlib import Path
 14  
 15  
 16  def get_current_version():
 17      """Read current version from setup.py."""
 18      setup_file = Path(__file__).parent / "setup.py"
 19  
 20      with open(setup_file, 'r') as f:
 21          content = f.read()
 22  
 23      match = re.search(r'version=["\']([^"\']+)["\']', content)
 24      if match:
 25          return match.group(1)
 26  
 27      raise ValueError("Could not find version in setup.py")
 28  
 29  
 30  def parse_version(version_str):
 31      """Parse version string into (major, minor, patch)."""
 32      parts = version_str.split('.')
 33      if len(parts) != 3:
 34          raise ValueError(f"Invalid version format: {version_str}")
 35  
 36      return tuple(int(p) for p in parts)
 37  
 38  
 39  def bump_version(current, bump_type):
 40      """Bump version based on type (major, minor, patch)."""
 41      major, minor, patch = parse_version(current)
 42  
 43      if bump_type == "major":
 44          return f"{major + 1}.0.0"
 45      elif bump_type == "minor":
 46          return f"{major}.{minor + 1}.0"
 47      elif bump_type == "patch":
 48          return f"{major}.{minor}.{patch + 1}"
 49      else:
 50          raise ValueError(f"Invalid bump type: {bump_type}")
 51  
 52  
 53  def update_version_in_file(file_path, old_version, new_version):
 54      """Update version in a file."""
 55      with open(file_path, 'r') as f:
 56          content = f.read()
 57  
 58      # Replace version string
 59      updated = content.replace(
 60          f'version="{old_version}"',
 61          f'version="{new_version}"'
 62      ).replace(
 63          f"version='{old_version}'",
 64          f"version='{new_version}'"
 65      ).replace(
 66          f'__version__ = "{old_version}"',
 67          f'__version__ = "{new_version}"'
 68      ).replace(
 69          f"__version__ = '{old_version}'",
 70          f"__version__ = '{new_version}'"
 71      )
 72  
 73      with open(file_path, 'w') as f:
 74          f.write(updated)
 75  
 76      print(f"āœ… Updated {file_path.name}: {old_version} → {new_version}")
 77  
 78  
 79  def main():
 80      if len(sys.argv) != 2:
 81          print("Usage: python bump_version.py [major|minor|patch]")
 82          sys.exit(1)
 83  
 84      bump_type = sys.argv[1].lower()
 85      if bump_type not in ["major", "minor", "patch"]:
 86          print("Error: bump type must be major, minor, or patch")
 87          sys.exit(1)
 88  
 89      # Get current version
 90      current_version = get_current_version()
 91      print(f"šŸ“¦ Current version: {current_version}")
 92  
 93      # Calculate new version
 94      new_version = bump_version(current_version, bump_type)
 95      print(f"šŸ†™ New version: {new_version}")
 96  
 97      # Update files
 98      project_root = Path(__file__).parent
 99  
100      files_to_update = [
101          project_root / "setup.py",
102          project_root / "kamaji" / "__init__.py",
103      ]
104  
105      for file_path in files_to_update:
106          if file_path.exists():
107              update_version_in_file(file_path, current_version, new_version)
108          else:
109              print(f"āš ļø  File not found: {file_path}")
110  
111      print(f"\n✨ Version bumped from {current_version} to {new_version}")
112      print("\nšŸ“ Next steps:")
113      print(f"   git add -A")
114      print(f'   git commit -m "Bump version to {new_version}"')
115      print(f"   git tag v{new_version}")
116      print(f"   git push && git push --tags")
117  
118  
119  if __name__ == "__main__":
120      main()