-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathbump_version.py
More file actions
executable file
·187 lines (149 loc) · 5.47 KB
/
bump_version.py
File metadata and controls
executable file
·187 lines (149 loc) · 5.47 KB
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
#!/usr/bin/env python3
"""
Version bump utility for Artwork Uploader for Plex.
This script helps automate version updates and creates git tags for releases.
Usage:
python bump_version.py patch # 0.5.1 -> 0.5.2
python bump_version.py minor # 0.5.1 -> 0.6.0
python bump_version.py major # 0.5.1 -> 1.0.0
python bump_version.py 0.6.0 # Set specific version
"""
import re
import sys
import subprocess
from pathlib import Path
def get_current_version():
"""Read current version from __version__.py"""
version_file = Path(__file__).parent / "core" / "__version__.py"
content = version_file.read_text()
match = re.search(r'__version__ = ["\']([^"\']+)["\']', content)
if match:
return match.group(1)
raise ValueError("Could not find version in __version__.py")
def parse_version(version_str):
"""Parse version string into components"""
match = re.match(r'^(\d+)\.(\d+)\.(\d+)(?:-(.+))?$', version_str)
if not match:
raise ValueError(f"Invalid version format: {version_str}")
major, minor, patch, pre = match.groups()
return int(major), int(minor), int(patch), pre or "patch"
def bump_version(current, bump_type):
"""Calculate new version based on bump type"""
major, minor, patch, pre = parse_version(current)
if bump_type == "major":
return f"{major + 1}.0.0"
elif bump_type == "minor":
return f"{major}.{minor + 1}.0"
elif bump_type == "patch":
return f"{major}.{minor}.{patch + 1}"
else:
# Assume it's a specific version string
try:
parse_version(bump_type) # Validate format
return bump_type
except ValueError:
raise ValueError(f"Invalid bump type or version: {bump_type}")
def update_version_file(new_version):
"""Update __version__.py with new version"""
version_file = Path(__file__).parent / "core" / "__version__.py"
content = version_file.read_text()
# Parse new version
major, minor, patch, pre = parse_version(new_version)
# Update version string
content = re.sub(
r'__version__ = ["\'][^"\']+["\']',
f'__version__ = "{new_version}"',
content
)
# Update version info tuple
content = re.sub(
r'__version_info__ = \([^)]+\)',
f'__version_info__ = ({major}, {minor}, {patch}, "{pre}")',
content
)
version_file.write_text(content)
print(f"✓ Updated {version_file}")
def git_commit_and_tag(version):
"""Commit version change and create git tag"""
try:
# Check if git repo is clean (except for __version__.py)
result = subprocess.run(
["git", "status", "--porcelain"],
capture_output=True,
text=True,
check=True
)
# Filter out __version__.py from changes
other_changes = [
line for line in result.stdout.strip().split('\n')
if line and '__version__.py' not in line
]
if other_changes and other_changes != ['']:
print("⚠ Warning: You have uncommitted changes:")
for line in other_changes:
print(f" {line}")
response = input("Continue anyway? (y/N): ")
if response.lower() != 'y':
print("Aborted.")
return False
# Stage version file
subprocess.run(
["git", "add", "core/__version__.py"],
check=True
)
# Commit
subprocess.run(
["git", "commit", "-m", f"Bump version to {version}"],
check=True
)
print(f"✓ Committed version bump")
# Create tag
tag = f"v{version}"
subprocess.run(
["git", "tag", "-a", tag, "-m", f"Release {tag}"],
check=True
)
print(f"✓ Created tag {tag}")
print(f"\n📦 Ready to release!")
print(f"\nNext steps:")
print(f" 1. Review the changes: git show {tag}")
print(f" 2. Push the commit: git push")
print(f" 3. Push the tag: git push origin {tag}")
print(f"\nThe GitHub Action will automatically create a release when the tag is pushed.")
return True
except subprocess.CalledProcessError as e:
print(f"✗ Git error: {e}")
return False
def main():
if len(sys.argv) != 2:
print(__doc__)
sys.exit(1)
bump_type = sys.argv[1]
try:
current = get_current_version()
print(f"Current version: {current}")
new_version = bump_version(current, bump_type)
print(f"New version: {new_version}")
# Confirm
response = input(f"\nUpdate version from {current} to {new_version}? (y/N): ")
if response.lower() != 'y':
print("Aborted.")
sys.exit(0)
# Update files
update_version_file(new_version)
# Git operations
response = input(f"\nCommit and tag this version? (y/N): ")
if response.lower() == 'y':
if git_commit_and_tag(new_version):
print(f"\n✓ Version {new_version} is ready for release!")
else:
print("\n✗ Failed to create git commit/tag")
sys.exit(1)
else:
print("\nVersion file updated but not committed.")
print("You can manually commit with: git add core/__version__.py && git commit -m 'Bump version'")
except Exception as e:
print(f"Error: {e}")
sys.exit(1)
if __name__ == "__main__":
main()