Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Check we're on the right branch before tagging, and on the right tag before uploading #12556

Merged
merged 10 commits into from
May 3, 2022
1 change: 1 addition & 0 deletions changelog.d/12556.misc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Release script: confirm the commit to be tagged before tagging.
63 changes: 37 additions & 26 deletions scripts-dev/release.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,13 +87,7 @@ def prepare():
"""

# Make sure we're in a git repo.
try:
repo = git.Repo()
except git.InvalidGitRepositoryError:
raise click.ClickException("Not in Synapse repo.")

if repo.is_dirty():
raise click.ClickException("Uncommitted changes exist.")
repo = get_repo_and_check_clean_checkout()

click.secho("Updating git repo...")
repo.remote().fetch()
Expand Down Expand Up @@ -167,9 +161,7 @@ def prepare():
assert not parsed_new_version.is_devrelease
assert not parsed_new_version.is_postrelease

release_branch_name = (
f"release-v{parsed_new_version.major}.{parsed_new_version.minor}"
)
release_branch_name = get_release_branch_name(parsed_new_version)
release_branch = find_ref(repo, release_branch_name)
if release_branch:
if release_branch.is_remote():
Expand Down Expand Up @@ -269,13 +261,7 @@ def tag(gh_token: Optional[str]):
"""Tags the release and generates a draft GitHub release"""

# Make sure we're in a git repo.
try:
repo = git.Repo()
except git.InvalidGitRepositoryError:
raise click.ClickException("Not in Synapse repo.")

if repo.is_dirty():
raise click.ClickException("Uncommitted changes exist.")
repo = get_repo_and_check_clean_checkout()

click.secho("Updating git repo...")
repo.remote().fetch()
Expand All @@ -288,6 +274,15 @@ def tag(gh_token: Optional[str]):
if tag_name in repo.tags:
raise click.ClickException(f"Tag {tag_name} already exists!\n")

# Check we're on the right release branch
release_branch = get_release_branch_name(current_version)
if repo.active_branch.name != release_branch:
click.echo(
f"Need to be on the release branch ({release_branch}) before tagging. "
f"Currently on ({repo.active_branch.name})."
)
click.get_current_context().abort()

# Get the appropriate changelogs and tag.
changes = get_changes_for_version(current_version)

Expand Down Expand Up @@ -348,21 +343,15 @@ def tag(gh_token: Optional[str]):
@cli.command()
@click.option("--gh-token", envvar=["GH_TOKEN", "GITHUB_TOKEN"], required=True)
def publish(gh_token: str):
"""Publish release."""
"""Publish release on GitHub."""

# Make sure we're in a git repo.
try:
repo = git.Repo()
except git.InvalidGitRepositoryError:
raise click.ClickException("Not in Synapse repo.")

if repo.is_dirty():
raise click.ClickException("Uncommitted changes exist.")
get_repo_and_check_clean_checkout()

current_version = get_package_version()
tag_name = f"v{current_version}"

if not click.confirm(f"Publish {tag_name}?", default=True):
if not click.confirm(f"Publish release {tag_name} on GitHub?", default=True):
return

# Publish the draft release
Expand Down Expand Up @@ -396,6 +385,13 @@ def upload():
current_version = get_package_version()
tag_name = f"v{current_version}"

# Check we have the right tag checked out.
repo = get_repo_and_check_clean_checkout()
tag = repo.tag(f"refs/tags/{tag_name}")
if repo.head.commit != tag.commit:
click.echo("Tag {tag_name} (tag.commit) is not currently checked out!")
click.get_current_context().abort()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is actually necessary for upload as we don't interact with the repo at all, we just download and reupload files.

Though might make sense to keep the check purely for sanity reasons.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I didn't realise we downloaded the wheel and sdist; I assumed we'd build them locally.

I guess I'll leave it in. (The line echoes an instruction to do a git merge, so it can't hurt)


pypi_asset_names = [
f"matrix_synapse-{current_version}-py3-none-any.whl",
f"matrix-synapse-{current_version}.tar.gz",
Expand Down Expand Up @@ -459,6 +455,21 @@ def get_package_version() -> version.Version:
return version.Version(version_string)


def get_release_branch_name(version_number: version.Version) -> str:
return f"release-v{version_number.major}.{version_number.minor}"


def get_repo_and_check_clean_checkout() -> git.Repo:
"""Get the project repo and check it's not got any uncommitted changes."""
try:
repo = git.Repo()
except git.InvalidGitRepositoryError:
raise click.ClickException("Not in Synapse repo.")
if repo.is_dirty():
raise click.ClickException("Uncommitted changes exist.")
return repo


def find_ref(repo: git.Repo, ref_name: str) -> Optional[git.HEAD]:
"""Find the branch/ref, looking first locally then in the remote."""
if ref_name in repo.refs:
Expand Down