-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathrelease.py
More file actions
111 lines (79 loc) · 3.3 KB
/
release.py
File metadata and controls
111 lines (79 loc) · 3.3 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
import subprocess
import re
def run(cmd: str, check: bool = True) -> str:
result = subprocess.run(cmd, shell=True, check=check, stdout=subprocess.PIPE)
return result.stdout.decode().strip()
def get_current_version() -> str:
out = run("bumpver show")
for line in out.splitlines():
if line.startswith("Current Version"):
_, version = line.split(":")
return version.strip().strip('"').strip("'")
raise RuntimeError("Could not find current_version")
def bump_version(level: str = "patch") -> str:
print(f"🔧 Bumping version with level: {level}")
run(f"bumpver update --{level}")
return get_current_version()
def create_branch(branch: str) -> None:
print(f"🌿 Creating and switching to branch {branch}...")
run(f"git checkout -b {branch}")
def commit_bump(version: str) -> None:
print(f"📦 Committing version bump for {version}...")
run(f'git commit -am "Bump version to {version}"')
def push_branch_and_tag(branch: str, version: str) -> None:
run(f"git push origin {branch}")
tag = f"v{version}"
print(f"🏷️ Creating and pushing tag {tag}...")
run(f"git tag {tag}")
run(f"git push origin {tag}")
def push_tag_and_branch(version: str) -> str:
branch = f"release-v{version}"
tag = f"v{version}"
print(f"🌿 Creating branch {branch}...")
run(f"git checkout -b {branch}")
run(f"git push origin {branch}")
print(f"🏷️ Creating tag {tag}...")
# Check if tag already exists
existing_tags = run("git tag")
if tag not in existing_tags.split():
run(f"git tag {tag}")
else:
print(f"✅ Tag {tag} already exists.")
run(f"git push origin {tag}")
return branch
def create_pull_request(branch: str, version: str) -> None:
print(f"🔁 Creating pull request for {branch} → main...")
run(
f'gh pr create --title "Release v{version}" '
f'--body "This PR bumps the version to v{version} and tags the release." '
f"--base main --head {branch}"
)
def open_release_draft(tag: str) -> None:
repo = run("git remote get-url origin")
match = re.search(r"github\.com[:/](.*?)(\.git)?$", repo)
if not match:
print("❌ Could not detect GitHub repo")
return
repo_path = match.group(1)
url = f"https://github.com/{repo_path}/releases/new?tag={tag}&title={tag}"
print(f"🌐 Open the release page:\n{url}")
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--level", choices=["patch", "minor", "major"], default="patch", help="Version bump level")
parser.add_argument("--no-pr", action="store_true", help="Don't create pull request")
parser.add_argument("--no-draft", action="store_true", help="Don't open GitHub release page")
args = parser.parse_args()
# always start from main branch
run("git checkout main")
run("git pull origin main") # make sure it's up-to-date
version = bump_version(args.level)
branch = f"release-v{version}"
create_branch(branch)
commit_bump(version)
push_branch_and_tag(branch, version)
if not args.no_pr:
create_pull_request(branch, version)
if not args.no_draft:
open_release_draft(f"v{version}")
print(f"\n✅ Release flow completed for version {version}!")