55# "uv>=0.8.6",
66# ]
77# ///
8- """Make a release."""
8+ """Create a release."""
99
10- # ruff: noqa: T201
10+ # ruff: noqa: S603, T201
1111
1212from __future__ import annotations
1313
1414import argparse
15- import enum
1615import json
1716import subprocess
1817import sys
3231)
3332
3433
35- class Bump (enum .StrEnum ):
36- """The enumeration of supported version bump semantics."""
37-
38- MAJOR = enum .auto ()
39- MINOR = enum .auto ()
40- PATCH = enum .auto ()
41- STABLE = enum .auto ()
42- ALPHA = enum .auto ()
43- BETA = enum .auto ()
44- RC = enum .auto ()
45- POST = enum .auto ()
46- DEV = enum .auto ()
47-
48-
4934def create_parser () -> argparse .ArgumentParser :
5035 """Create the argument parser."""
5136 parser = argparse .ArgumentParser (description = "make a release" )
@@ -56,8 +41,6 @@ def create_parser() -> argparse.ArgumentParser:
5641 )
5742 mutex .add_argument (
5843 "--bump" ,
59- type = Bump ,
60- choices = Bump ,
6144 help = "update the version using the given semantics" ,
6245 )
6346 parser .add_argument (
@@ -89,7 +72,7 @@ def update_version(version: str | None = None, bump: str | None = None) -> str:
8972 cmd .extend (("--bump" , bump ))
9073
9174 try :
92- version_json = subprocess .check_output (cmd ) # noqa: S603
75+ version_json = subprocess .check_output (cmd )
9376
9477 except subprocess .CalledProcessError :
9578 print_err ("An error occurred while bumping the version." )
@@ -139,13 +122,25 @@ def switch_to_branch(branch: str) -> Generator[None]:
139122 print (f"Removed branch { branch !r} and switched back to { base_branch !r} ." )
140123
141124
142- def build_changelog (version : str ) -> None :
143- """Build the changelog."""
125+ def get_release_notes (version : str ) -> str :
126+ """Return the release notes."""
127+ release_notes = subprocess .check_output (
128+ ("towncrier" , "build" , "--version" , version , "--draft" ),
129+ stderr = subprocess .DEVNULL ,
130+ text = True ,
131+ ).rstrip ()
132+ release_notes = "" .join (release_notes .splitlines (keepends = True )[1 :])
133+ release_notes = release_notes .strip ()
134+ return f"## Release notes\n \n { release_notes } "
135+
136+
137+ def update_changelog (version : str ) -> None :
138+ """Update the changelog."""
144139 try :
145- run (("towncrier" , "build" , "--yes " , "--version" , version ))
140+ run (("towncrier" , "build" , "--version " , version , "--yes" ))
146141
147142 except subprocess .CalledProcessError :
148- print_err ("An error occurred while building the changelog." )
143+ print_err ("An error occurred while updating the changelog." )
149144 raise SystemExit (1 ) from None
150145
151146
@@ -165,14 +160,13 @@ def create_release_tag(version: str) -> str:
165160 return release_tag
166161
167162
168- def push_changes (branch : str , remote_branch : str = "main" ) -> None :
169- """Push changes to the origin remote."""
170- run (("git" , "push" , "origin" , f"{ branch } :{ remote_branch } " , "--follow-tags" ))
171- print (f"Pushed changes from { branch !r} to 'origin/{ remote_branch } '." )
163+ def create_release (release_tag : str , release_notes : str ) -> None :
164+ """Create the GitHub release."""
165+ run (("gh" , "release" , "create" , release_tag , "--notes" , release_notes ))
172166
173167
174168def main (argv : Sequence [str ] | None = None ) -> int :
175- """Prepare a new release."""
169+ """Create a release."""
176170 parser = create_parser ()
177171 args = parser .parse_args (argv )
178172
@@ -183,11 +177,12 @@ def main(argv: Sequence[str] | None = None) -> int:
183177 release_branch = f"release/{ version } "
184178
185179 with switch_to_branch (release_branch ):
186- build_changelog (version )
180+ release_notes = get_release_notes (version )
181+ update_changelog (version )
187182
188183 # Commit changes.
189184 run (("git" , "add" , ":/pyproject.toml" , ":/uv.lock" ))
190- run (("git" , "add" , "-A" , ":/changelog.d/* " , ":/CHANGELOG.md" ))
185+ run (("git" , "add" , "-A" , ":/changelog.d" , ":/CHANGELOG.md" ))
191186 message = f"chore: prepare release { version } "
192187 run (("git" , "commit" , "--no-verify" , "-m" , message ))
193188 print (f"Committed changes on branch { release_branch !r} ." )
@@ -201,7 +196,14 @@ def main(argv: Sequence[str] | None = None) -> int:
201196 print (f"Removed release tag { release_tag !r} ." )
202197 return 0
203198
204- push_changes (release_branch , "main" )
199+ # Push changes to the origin remote.
200+ run (
201+ ("git" , "push" , "--atomic" , "origin" , f"{ release_branch } :main" , release_tag )
202+ )
203+ print (f"Pushed changes from branch { release_branch !r} to branch 'origin/main'." )
204+ print (f"Pushed release tag { release_tag !r} to the origin remote." )
205+
206+ create_release (release_tag , release_notes )
205207
206208 # Switch to the main branch.
207209 run (("git" , "checkout" , "main" ))
0 commit comments