-
Notifications
You must be signed in to change notification settings - Fork 2
/
release.py
executable file
·135 lines (101 loc) · 3.18 KB
/
release.py
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
#!/usr/bin/env python3
import argparse
import re
from datetime import date
from enum import Enum
from glob import glob
from inspect import cleandoc
VERSION_PATTERN = 'version = "(\d+)\.(\d+)\.(\d+)"'
CHANGELOG_TEMPLATE = (
cleandoc(
"""
<!-- next-header -->\n
## [Unreleased] - ReleaseDate\n
### Added\n
### Changed\n
"""
)
+ "\n"
)
NEXT_URL_TEMPLATE = cleandoc(
"""
<!-- next-url -->
[Unreleased]: https://github.com/pluots/udf-suite/compare/[tag_name]...HEAD"""
)
def get_args():
parser = argparse.ArgumentParser(description="Release a new UDF suite version.")
parser.add_argument("level", choices=("major", "minor", "patch"))
parser.add_argument("--execute", action="store_true")
args = parser.parse_args()
return args
def get_cargo_tomls() -> list[str]:
return glob("**/Cargo.toml")
class SemvarLevel(Enum):
MAJOR = 1
MINOR = 2
PATCH = 3
def get_next_semvar(groups: tuple[str, str, str], level: SemvarLevel) -> str:
s_major, s_minor, s_patch = groups
major, minor, patch = int(s_major), int(s_minor), int(s_patch)
if level == SemvarLevel.MAJOR:
major += 1
minor, patch = 0, 0
elif level == SemvarLevel.MINOR:
minor += 1
patch = 0
elif level == SemvarLevel.PATCH:
patch += 1
return f"{major}.{minor}.{patch}"
def update_all_tomls(level: SemvarLevel, execute: bool = False) -> str:
next_version: str | None = None
next_version_toml: str | None = None
for toml in get_cargo_tomls():
with open(toml, "r") as f:
lines = f.readlines()
res = []
for line in lines:
match = re.match(VERSION_PATTERN, line)
if match and next_version is None:
next_version = get_next_semvar(
match.groups(), SemvarLevel[level.upper()]
)
next_version_toml = f'version = "{next_version}"\n'
if match:
res.append(next_version_toml)
print(f"{toml}: updated '{line.strip()}' -> '{next_version}'")
else:
res.append(line)
if execute:
with open(toml, "w") as f:
f.writelines(res)
assert next_version is not None
return next_version
def update_changelog(version: str, execute: bool):
tag_name = f"v{version}"
with open("CHANGELOG.md", "r") as f:
s = f.read()
s = s.replace("[Unreleased]", f"[{version}]")
s = s.replace("...HEAD", f"...{tag_name}", 1)
s = s.replace("ReleaseDate", f"{date.today()}", 1)
s = s.replace("<!-- next-header -->", CHANGELOG_TEMPLATE, 1)
s = s.replace(
"<!-- next-url -->\n",
NEXT_URL_TEMPLATE.replace("[tag_name]", tag_name),
1,
)
print(s)
if execute:
with open("CHANGELOG.md", "w") as f:
f.write(s)
def main():
args = get_args()
if args.execute:
print("Executing\n")
else:
print("Starting dry run\n")
print("Updating Cargo.toml files")
next_version = update_all_tomls(args.level, args.execute)
print("\nUpdating changelog")
update_changelog(next_version, args.execute)
if __name__ == "__main__":
main()