1+ """This script automated the release process for all of the packages in this repository.
2+ In order, this script does the following:
3+
4+ 1. Bump version number in manifest files according to given required arg (see `--help`).
5+ This alters the Cargo.toml in repo root and the package.json files in node-binding.
6+
7+ Requires `yarn` (see https://yarnpkg.com) and `napi` (see https://napi.rs) installed
8+ to bump node-binding versions.
9+
10+ 2. Updates the CHANGELOG.md
11+
12+ Requires `git-cliff` installed (see https://git-cliff.org)
13+ to regenerate the change logs from git history.
14+
15+ NOTE: `git cliff` uses GITHUB_TOKEN env var to access GitHub's REST API for
16+ fetching certain data (like PR labels and commit author's username).
17+
18+ 3. Pushes the changes from above 2 steps to remote
19+
20+ 4. Creates a GitHub Release and uses the section from the CHANGELOG about the new tag
21+ as a release description.
22+
23+ Requires `gh-cli` installed (see https://cli.github.com) to create the release and
24+ push the tag.
25+
26+ NOTE: This step also tags the commit from step 3.
27+ When a tag is pushed to the remote, the CI builds are triggered and
28+
29+ - release assets are uploaded to the Github Release corresponding to the new tag
30+ - packages are published for npm, pip and cargo
31+
32+ NOTE: In a CI run, the GH_TOKEN env var to authenticate access.
33+ Locally, you can use `gh login` to interactively authenticate the user account.
34+ """
35+
136import argparse
237from pathlib import Path
338import subprocess
843)
944VER_REPLACE = 'version = "%d.%d.%d%s" # auto'
1045COMPONENTS = ("major" , "minor" , "patch" , "rc" )
46+ VERSION_LOG = re .compile (rb"^## \[\d+\.\d+\.\d+(?:\-rc)?\d*\]" )
1147
1248
1349class Updater :
@@ -40,10 +76,34 @@ def replace(match: re.Match[str]) -> str:
4076 return VER_REPLACE % (tuple (ver [:3 ]) + (rc_str ,))
4177
4278
79+ def get_release_notes (tag : str = Updater .new_version ):
80+ title , buf = ("" , b"" )
81+ log_file = Path (__file__ ).parent .parent .parent / "CHANGELOG.md"
82+ tag_buf = f"[{ tag } ]" .encode (encoding = "utf-8" )
83+ with open (str (log_file ), "rb" ) as log :
84+ found_notes = False
85+ for line in log .readlines ():
86+ matched = VERSION_LOG .match (line )
87+ if matched is not None :
88+ if tag_buf in matched .group (0 ):
89+ title = tag + line [matched .end () :].decode (encoding = "utf-8" )
90+ found_notes = True
91+ else :
92+ found_notes = False
93+ elif line .startswith (b"[unreleased]: " ) and found_notes :
94+ found_notes = False
95+ elif found_notes :
96+ buf += line
97+ elif line .startswith (tag_buf + b": " ):
98+ buf += line .replace (tag_buf , b"Full commit diff" , 1 )
99+ return title .rstrip (), buf .strip ()
100+
101+
43102def main ():
44103 parser = argparse .ArgumentParser ()
45104 parser .add_argument ("component" , default = "patch" , choices = COMPONENTS )
46105 parser .parse_args (namespace = Updater )
106+
47107 cargo_path = Path ("Cargo.toml" )
48108 doc = cargo_path .read_text (encoding = "utf-8" )
49109 doc = VER_PATTERN .sub (Updater .replace , doc )
@@ -63,20 +123,34 @@ def main():
63123 )
64124 subprocess .run (["napi" , "version" ], cwd = "node-binding" , check = True )
65125 print ("Updated version in node-binding/**package.json" )
66- tag = "v" + Updater .new_version
126+
127+ subprocess .run (["git" , "cliff" , "--tag" , Updater .new_version ], check = True )
128+ print ("Updated CHANGELOG.md" )
129+
67130 subprocess .run (["git" , "add" , "--all" ], check = True )
68- subprocess .run (["git" , "commit" , "-m" , f"bump version to { tag } " ], check = True )
131+ tag = "v" + Updater .new_version
132+ subprocess .run (["git" , "commit" , "-m" , f"Bump version to { tag } " ], check = True )
69133 try :
70134 subprocess .run (["git" , "push" ], check = True )
71135 except subprocess .CalledProcessError as exc :
72136 raise RuntimeError ("Failed to push commit for version bump" ) from exc
73- print ("Pushed commit to 'bump version to" , tag , "'" )
74- try :
75- subprocess .run (["git" , "tag" , tag ], check = True )
76- except subprocess .CalledProcessError as exc :
77- raise RuntimeError ("Failed to create tag for commit" ) from exc
78- print ("Created tag" , tag )
79- print (f"Use 'git push origin refs/tags/{ tag } ' to publish a release" )
137+
138+ title , notes = get_release_notes ()
139+ print ("Pushed commit to 'Bump version to" , tag , "'" )
140+ gh_cmd = [
141+ "gh" ,
142+ "release" ,
143+ "create" ,
144+ tag ,
145+ "--title" ,
146+ title ,
147+ "--notes" ,
148+ notes .decode ("utf-8" ),
149+ ]
150+ if Updater .component == "rc" :
151+ gh_cmd .append ("--prerelease" )
152+ subprocess .run (gh_cmd , check = True )
153+ print ("Created tag" , tag , "and corresponding GitHub Release" )
80154
81155
82156if __name__ == "__main__" :
0 commit comments