1010{% - endif %}
1111# ]
1212# ///
13- """Make a release."""
13+ """Create a release."""
1414
1515# ruff: noqa: T201
1616
1717from __future__ import annotations
1818
1919import argparse
2020{% - if not dynamic_version %}
21- import enum
2221import json
2322{% - endif %}
2423import subprocess
@@ -40,21 +39,7 @@ run = partial(
4039 stderr=subprocess.DEVNULL,
4140)
4241
43- {% if not dynamic_version %}
44- class Bump(enum.StrEnum):
45- """The enumeration of supported version bump semantics."""
46-
47- MAJOR = enum.auto()
48- MINOR = enum.auto()
49- PATCH = enum.auto()
50- STABLE = enum.auto()
51- ALPHA = enum.auto()
52- BETA = enum.auto()
53- RC = enum.auto()
54- POST = enum.auto()
55- DEV = enum.auto()
5642
57- {% endif %}
5843def create_parser() -> argparse.ArgumentParser:
5944 """Create the argument parser."""
6045 parser = argparse.ArgumentParser(description="make a release")
@@ -72,8 +57,6 @@ def create_parser() -> argparse.ArgumentParser:
7257 )
7358 mutex.add_argument(
7459 "--bump",
75- type=Bump,
76- choices=Bump,
7760 help="update the version using the given semantics",
7861 )
7962{% - endif %}
@@ -156,10 +139,22 @@ def switch_to_branch(branch: str) -> Generator[None]:
156139 print(f"Removed branch {branch!r} and switched back to {base_branch!r}.")
157140
158141
159- def build_changelog(version: str) -> None:
160- """Build the changelog."""
142+ def get_release_notes(version: str) -> str:
143+ """Return the release notes."""
144+ release_notes = subprocess.check_output(
145+ ("towncrier", "build", "--version", version, "--draft"),
146+ stderr=subprocess.DEVNULL,
147+ text=True,
148+ ).rstrip()
149+ release_notes = "".join(release_notes.splitlines(keepends=True)[1:])
150+ release_notes = release_notes.strip()
151+ return f"## Release notes\n\n{release_notes}"
152+
153+
154+ def update_changelog(version: str) -> None:
155+ """Update the changelog."""
161156 try:
162- run(("towncrier", "build", "--yes ", "--version", version ))
157+ run(("towncrier", "build", "--version ", version, "--yes" ))
163158
164159 except subprocess.CalledProcessError:
165160 print_err("An error occurred while building the changelog.")
@@ -182,14 +177,13 @@ def create_release_tag(version: str) -> str:
182177 return release_tag
183178
184179
185- def push_changes(branch: str, remote_branch: str = "main") -> None:
186- """Push the changes to the origin remote."""
187- run(("git", "push", "origin", f"{branch}:{remote_branch}", "--follow-tags"))
188- print(f"Pushed changes from {branch!r} to 'origin/{remote_branch}'.")
180+ def create_release(release_tag: str, release_notes: str) -> None:
181+ """Create the GitHub release."""
182+ run(("gh", "release", "create", release_tag, "--notes", release_notes))
189183
190184
191185def main(argv: Sequence[str] | None = None) -> int:
192- """Prepare a new release."""
186+ """Create a release."""
193187 parser = create_parser()
194188 args = parser.parse_args(argv)
195189
@@ -202,13 +196,14 @@ def main(argv: Sequence[str] | None = None) -> int:
202196 release_branch = f"release/{version}"
203197
204198 with switch_to_branch(release_branch):
205- build_changelog(version)
199+ release_notes = get_release_notes(version)
200+ update_changelog(version)
206201
207202 # Commit changes.
208203{% - if not dynamic_version %}
209204 run(("git", "add", ":/pyproject.toml", ":/uv.lock"))
210205{% - endif %}
211- run(("git", "add", "-A", ":/changelog.d/* ", ":/CHANGELOG.md"))
206+ run(("git", "add", "-A", ":/changelog.d", ":/CHANGELOG.md"))
212207 message = f"chore: prepare release {version}"
213208 run(("git", "commit", "--no-verify", "-m", message))
214209 print(f"Committed changes on branch {release_branch!r}.")
@@ -222,7 +217,13 @@ def main(argv: Sequence[str] | None = None) -> int:
222217 print(f"Removed release tag {release_tag!r}.")
223218 return 0
224219
225- push_changes(release_branch, "main")
220+ run(
221+ ("git", "push", "--atomic", "origin", f"{release_branch}:main", release_tag)
222+ )
223+ print(f"Pushed changes from branch {release_branch!r} to branch 'origin/main'.")
224+ print(f"Pushed release tag {release_tag!r} to the origin remote.")
225+
226+ create_release(release_tag, release_notes)
226227
227228 # Switch to the main branch.
228229 run(("git", "checkout", "main"))
0 commit comments