Update release script to be poetry-aware

Poetry now manages the project version in pyproject.toml.
This commit is contained in:
David Robertson 2022-04-26 10:56:12 +01:00
parent 99ab45423a
commit 730fcda546
No known key found for this signature in database
GPG Key ID: 903ECE108A39DEDD
1 changed files with 21 additions and 47 deletions

View File

@ -25,13 +25,13 @@ import sys
import urllib.request import urllib.request
from os import path from os import path
from tempfile import TemporaryDirectory from tempfile import TemporaryDirectory
from typing import List, Optional, Tuple from typing import List, Optional
import attr import attr
import click import click
import commonmark import commonmark
import git import git
import redbaron
from click.exceptions import ClickException from click.exceptions import ClickException
from github import Github from github import Github
from packaging import version from packaging import version
@ -100,7 +100,7 @@ def prepare():
repo.remote().fetch() repo.remote().fetch()
# Get the current version and AST from root Synapse module. # Get the current version and AST from root Synapse module.
current_version, parsed_synapse_ast, version_node = parse_version_from_module() current_version = get_package_version()
# Figure out what sort of release we're doing and calcuate the new version. # Figure out what sort of release we're doing and calcuate the new version.
rc = click.confirm("RC", default=True) rc = click.confirm("RC", default=True)
@ -162,7 +162,7 @@ def prepare():
click.get_current_context().abort() click.get_current_context().abort()
# Switch to the release branch. # Switch to the release branch.
parsed_new_version = version.parse(new_version) parsed_new_version: version.Version = version.parse(new_version)
# We assume for debian changelogs that we only do RCs or full releases. # We assume for debian changelogs that we only do RCs or full releases.
assert not parsed_new_version.is_devrelease assert not parsed_new_version.is_devrelease
@ -207,17 +207,15 @@ def prepare():
# Create the new release branch # Create the new release branch
release_branch = repo.create_head(release_branch_name, commit=base_branch) release_branch = repo.create_head(release_branch_name, commit=base_branch)
# Switch to the release branch and ensure its up to date. # Switch to the release branch and ensure it's up to date.
repo.git.checkout(release_branch_name) repo.git.checkout(release_branch_name)
update_branch(repo) update_branch(repo)
# Update the `__version__` variable and write it back to the file. # Update the version specified in pyproject.toml.
version_node.value = '"' + new_version + '"' subprocess.check_output(["poetry", "version", new_version])
with open("synapse/__init__.py", "w") as f:
f.write(parsed_synapse_ast.dumps())
# Generate changelogs. # Generate changelogs.
generate_and_write_changelog(current_version) generate_and_write_changelog(current_version, new_version)
# Generate debian changelogs # Generate debian changelogs
if parsed_new_version.pre is not None: if parsed_new_version.pre is not None:
@ -284,7 +282,7 @@ def tag(gh_token: Optional[str]):
repo.remote().fetch() repo.remote().fetch()
# Find out the version and tag name. # Find out the version and tag name.
current_version, _, _ = parse_version_from_module() current_version = get_package_version()
tag_name = f"v{current_version}" tag_name = f"v{current_version}"
# Check we haven't released this version. # Check we haven't released this version.
@ -362,7 +360,7 @@ def publish(gh_token: str):
if repo.is_dirty(): if repo.is_dirty():
raise click.ClickException("Uncommitted changes exist.") raise click.ClickException("Uncommitted changes exist.")
current_version, _, _ = parse_version_from_module() current_version = get_package_version()
tag_name = f"v{current_version}" tag_name = f"v{current_version}"
if not click.confirm(f"Publish {tag_name}?", default=True): if not click.confirm(f"Publish {tag_name}?", default=True):
@ -396,7 +394,7 @@ def publish(gh_token: str):
def upload(): def upload():
"""Upload release to pypi.""" """Upload release to pypi."""
current_version, _, _ = parse_version_from_module() current_version = get_package_version()
tag_name = f"v{current_version}" tag_name = f"v{current_version}"
pypi_asset_names = [ pypi_asset_names = [
@ -424,7 +422,7 @@ def upload():
def announce(): def announce():
"""Generate markdown to announce the release.""" """Generate markdown to announce the release."""
current_version, _, _ = parse_version_from_module() current_version = get_package_version()
tag_name = f"v{current_version}" tag_name = f"v{current_version}"
click.echo( click.echo(
@ -455,37 +453,11 @@ Announce the release in
) )
def parse_version_from_module() -> Tuple[ def get_package_version() -> version.Version:
version.Version, redbaron.RedBaron, redbaron.Node version_string = subprocess.check_output(["poetry", "version", "--short"]).decode(
]: "utf-8"
# Parse the AST and load the `__version__` node so that we can edit it )
# later. return version.Version(version_string)
with open("synapse/__init__.py") as f:
red = redbaron.RedBaron(f.read())
version_node = None
for node in red:
if node.type != "assignment":
continue
if node.target.type != "name":
continue
if node.target.value != "__version__":
continue
version_node = node
break
if not version_node:
print("Failed to find '__version__' definition in synapse/__init__.py")
sys.exit(1)
# Parse the current version.
current_version = version.parse(version_node.value.value.strip('"'))
assert isinstance(current_version, version.Version)
return current_version, red, version_node
def find_ref(repo: git.Repo, ref_name: str) -> Optional[git.HEAD]: def find_ref(repo: git.Repo, ref_name: str) -> Optional[git.HEAD]:
@ -565,11 +537,13 @@ def get_changes_for_version(wanted_version: version.Version) -> str:
return "\n".join(version_changelog) return "\n".join(version_changelog)
def generate_and_write_changelog(current_version: version.Version): def generate_and_write_changelog(current_version: version.Version, new_version: str):
# We do this by getting a draft so that we can edit it before writing to the # We do this by getting a draft so that we can edit it before writing to the
# changelog. # changelog.
result = run_until_successful( result = run_until_successful(
"python3 -m towncrier --draft", shell=True, capture_output=True f"python3 -m towncrier build --draft --version {new_version}",
shell=True,
capture_output=True,
) )
new_changes = result.stdout.decode("utf-8") new_changes = result.stdout.decode("utf-8")
new_changes = new_changes.replace( new_changes = new_changes.replace(