Skip to content

Commit 5bfeef0

Browse files
authored
feat: add release script (#62)
## What I'm changing - Add a script to automate tag creation ## How I did it When I was cutting the release for **stapi-pydantic** yesterday, I had to look up the tag format myself to make sure I didn't get it wrong. If the person who defined the tag format can't remember it, it's probably best to automate the process. Also a good chance to argue with @jkeifer about whether we want to try to do dyanmic versioning in the monorepo 😄 ## Checklist - [x] Tests pass: `uv run pytest` - [x] Checks pass: `uv run pre-commit --all-files`
1 parent 6ea1c79 commit 5bfeef0

File tree

4 files changed

+247
-5
lines changed

4 files changed

+247
-5
lines changed

RELEASING.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@
88
- A new link at the bottom of the CHANGELOG for that header
99
5. `git push -u origin`
1010
6. Once approved, merge the PR
11-
7. `git checkout main && git pull && git tag {package}/v{version} && git push {package}/v{version}`
12-
8. Github actions will automatically publish the release on tag push
13-
9. Create a new [release](https://github.com/stapi-spec/pystapi/releases) pointing to the new tag
11+
7. `git checkout main && git pull && scripts/release {package}`
12+
8. Go to the draft release href provided by the script, update that Github release with information from the CHANGELOG, and publish it
13+
9. Github actions will automatically publish a new PyPI release
1414

15-
> [!NOTE]
16-
> The tag format (`{package}/v{version}`) is very important, because that's how we discover which package to build and publish.
15+
> [!IMPORTANT]
16+
> You'll need to set up [.netrc authentication](https://pygithub.readthedocs.io/en/stable/examples/Authentication.html#netrc-authentication) to use `scripts/release`.
17+
> The tag format created by the script (`{package}/v{version}`) is very important, because that's how we discover which package to build and publish in Github Actions.

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ dev = [
2121
"pre-commit>=4.2.0",
2222
"pre-commit-hooks>=5.0.0",
2323
"fastapi[standard]>=0.115.12",
24+
"pygithub>=2.6.1",
2425
]
2526
docs = [
2627
"mkdocs-material>=9.6.11",

scripts/release

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#!/usr/bin/env python3
2+
3+
"""Create a new DRAFT release.
4+
5+
Usage:
6+
7+
scripts/release pystapi-client # or another package name
8+
9+
You'll need to set up netrc authentication as described in
10+
https://pygithub.readthedocs.io/en/stable/examples/Authentication.html#netrc-authentication.
11+
"""
12+
13+
import sys
14+
from pathlib import Path
15+
16+
import tomllib
17+
from github import Auth, Github
18+
19+
ALLOWED_PACKAGE_NAMES = ["pystapi-client", "pystapi-validator", "stapi-fastapi", "stapi-pydantic"]
20+
21+
if len(sys.argv) != 2:
22+
print("ERROR: invalid usage", file=sys.stderr)
23+
print(f"USAGE: {sys.argv[0]}", "{package_name}", file=sys.stderr)
24+
sys.exit(1)
25+
26+
if sys.argv[1] not in ALLOWED_PACKAGE_NAMES:
27+
print(f"ERROR: invalid package name: {sys.argv[1]}")
28+
print(f"Allowed package names: {','.join(ALLOWED_PACKAGE_NAMES)}")
29+
sys.exit(2)
30+
31+
package_name = sys.argv[1]
32+
33+
with open(Path(__file__).parents[1] / package_name / "pyproject.toml", "rb") as f:
34+
pyproject_toml = tomllib.load(f)
35+
36+
version = pyproject_toml["project"]["version"]
37+
tag = f"{package_name}/v{version}"
38+
39+
github = Github(auth=Auth.NetrcAuth())
40+
print("Logged in as", github.get_user().login)
41+
repo = github.get_repo("stapi-spec/pystapi")
42+
print("Next release:", tag)
43+
# TODO allow for releasing from not the main branch
44+
target = repo.get_branch("main").commit.sha
45+
print(f"Target sha (main): {target}")
46+
git_release = repo.create_git_tag_and_release(
47+
tag=tag,
48+
tag_message=tag,
49+
draft=True,
50+
generate_release_notes=False,
51+
release_name=tag,
52+
release_message=(f"Release created via `scripts/release` by {github.get_user().login}."),
53+
object=target,
54+
type="commit",
55+
)
56+
print(f"Draft release created: {git_release.html_url}")

0 commit comments

Comments
 (0)