Skip to content

Commit ce4eb37

Browse files
committed
Add basic make_release.py tool
1 parent 4f8fa4f commit ce4eb37

3 files changed

Lines changed: 183 additions & 4 deletions

File tree

make_release.py

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
import argparse
2+
import subprocess
3+
import tomllib
4+
5+
BETA_BRANCH = "beta"
6+
MAIN_BRANCH = "main"
7+
8+
9+
def get_parser() -> argparse.ArgumentParser:
10+
parser = argparse.ArgumentParser()
11+
version_group = parser.add_mutually_exclusive_group()
12+
version_group.add_argument(
13+
"--major", help="bump up the major version", action="store_true"
14+
)
15+
version_group.add_argument(
16+
"--minor", help="bump up the minor version", action="store_true"
17+
)
18+
version_group.add_argument(
19+
"--patch", help="bump up the patch version", action="store_true"
20+
)
21+
22+
parser.add_argument(
23+
"--push", help="Push the current changes to origin", action="store_true"
24+
)
25+
parser.add_argument("--dry", help="Dry run", action="store_true")
26+
27+
return parser
28+
29+
30+
def get_git_branch():
31+
result = subprocess.run(
32+
["git", "rev-parse", "--abbrev-ref", "HEAD"], text=True, capture_output=True
33+
)
34+
return result.stdout.strip()
35+
36+
37+
def get_latest_tag():
38+
result = subprocess.run(
39+
["git", "describe", "--tags", "--abbrev=0"], text=True, capture_output=True
40+
)
41+
return result.stdout.strip()
42+
43+
44+
def get_current_version():
45+
with open("pyproject.toml", "rb") as f:
46+
data = tomllib.load(f)
47+
return data["bumpver"]["current_version"]
48+
49+
50+
def get_update_mode(args: argparse.Namespace):
51+
if args.major:
52+
return "major"
53+
elif args.minor:
54+
return "minor"
55+
56+
return "patch"
57+
58+
59+
def update_version_with_bumpver(mode: str, dry_run: bool) -> tuple[bool, str]:
60+
command = ["uv", "run", "bumpver", "update", f"--{mode}"]
61+
if dry_run:
62+
command.append("--dry")
63+
64+
print("Upgrading version, running:", " ".join(command))
65+
result = subprocess.run(command, text=True, capture_output=True)
66+
if result.returncode != 0:
67+
return False, result.stderr
68+
else:
69+
return True, result.stdout
70+
71+
72+
def handle_beta_version_update(args: argparse.Namespace):
73+
print("[WARNING] You're about to upgrade the BETA version.")
74+
result = input("Do you want to continue? (y/n): ")
75+
if result == "y":
76+
if not any([args.major, args.minor, args.patch]):
77+
print("No upgrade path selected. WIll try to upgrade beta tag instead.")
78+
else:
79+
success, result = update_version_with_bumpver(
80+
get_update_mode(args), args.dry
81+
)
82+
if not success:
83+
print("Upgrade failed. Exiting.")
84+
print(f"\nTrace:\n{result}")
85+
exit(1)
86+
else:
87+
print("Version upgrade successful!")
88+
print("Result:\n", result)
89+
90+
latest_version = get_current_version()
91+
latest_tag = get_latest_tag()
92+
93+
if latest_tag.startswith(f"v{latest_version}") and "beta" in latest_tag:
94+
current_beta = latest_tag[len(latest_version) + 1 :]
95+
beta_number = int(current_beta[6:])
96+
tag_to_set = "v{}-beta.{}".format(latest_version, beta_number + 1)
97+
else:
98+
tag_to_set = "v{}-beta.1".format(latest_version)
99+
100+
print("Setting tag: ", tag_to_set)
101+
if not args.dry:
102+
subprocess.run(
103+
["git", "tag", "-a", tag_to_set, "-m", f"Release {tag_to_set}"]
104+
)
105+
else:
106+
print("Dry run enabled, skipping")
107+
else:
108+
print("Exiting...")
109+
exit(0)
110+
111+
112+
def handle_main_version_update(args: argparse.Namespace):
113+
print("[WARNING] You're about to upgrade the MAIN version.")
114+
result = input("Do you want to continue? (y/n): ")
115+
116+
if result.lower() == "y":
117+
if not any([args.major, args.minor, args.patch]):
118+
print("No upgrade path selected. Exiting.")
119+
exit(0)
120+
121+
success, result = update_version_with_bumpver(get_update_mode(args), args.dry)
122+
if not success:
123+
print("Upgrade failed. Exiting.")
124+
print(f"\nTrace:\n{result}")
125+
exit(1)
126+
else:
127+
print("Version upgrade successful!")
128+
print("Result:\n", result)
129+
130+
current_version = get_current_version()
131+
tag_to_set = f"v{current_version}"
132+
print("Tagging after upgrade to: ", tag_to_set)
133+
if not args.dry:
134+
subprocess.run(
135+
["git", "tag", "-a", tag_to_set, "-m", f"Release {tag_to_set}"]
136+
)
137+
else:
138+
print("Dry run enabled, skipping")
139+
140+
else:
141+
print("Exiting...")
142+
exit(0)
143+
144+
145+
def main():
146+
print("Welcome to a release maker helper!")
147+
print("First, let's check the branch:\n")
148+
current_branch = get_git_branch()
149+
print(f"\nCurrent branch is: {current_branch} \n")
150+
151+
if current_branch not in [BETA_BRANCH, MAIN_BRANCH]:
152+
print("You're not on one of the supported branches!")
153+
print("Switch to `beta` or `main` in order to make a release!")
154+
exit(0)
155+
156+
parser = get_parser()
157+
parsed_args = parser.parse_args()
158+
159+
if not parsed_args.dry:
160+
print("[WARNING] You're not in dry run mode.")
161+
result = input("Do you want to continue? (y/n): ")
162+
if result.lower() != "y":
163+
exit(0)
164+
165+
if current_branch == BETA_BRANCH:
166+
handle_beta_version_update(parsed_args)
167+
else:
168+
handle_main_version_update(parsed_args)
169+
170+
if parsed_args.push:
171+
if parsed_args.dry:
172+
print("Would push to origin with `git push --follow-tags`")
173+
exit(0)
174+
175+
subprocess.run(["git", "push", "--follow-tags"])
176+
177+
178+
if __name__ == "__main__":
179+
main()

pyproject.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ dev = [
1212
]
1313

1414
[bumpver]
15-
current_version = "1.7.1-beta.2"
16-
version_pattern = "MAJOR.MINOR.PATCH[-TAG[.NUM]]"
15+
current_version = "1.7.1"
16+
version_pattern = "MAJOR.MINOR.PATCH"
1717
tag_message = "v{new_version}"
1818
commit = true
19-
tag = true
19+
tag = false
2020
push = false
2121

2222
[bumpver.file_patterns]

uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)