""" Finalize the repo for a release. Invokes towncrier and bumpversion. """ __requires__ = ['bump2version', 'towncrier'] import subprocess import pathlib import re import sys def release_kind(): """ Determine which release to make based on the files in the changelog. """ # use min here as 'major' < 'minor' < 'patch' return min( 'major' if 'breaking' in file.name else 'minor' if 'change' in file.name else 'patch' for file in pathlib.Path('changelog.d').iterdir() ) bump_version_command = [ sys.executable, '-m', 'bumpversion', release_kind(), ] def get_version(): cmd = bump_version_command + ['--dry-run', '--verbose'] out = subprocess.check_output(cmd, text=True) return re.search('^new_version=(.*)', out, re.MULTILINE).group(1) def update_changelog(): cmd = [ sys.executable, '-m', 'towncrier', 'build', '--version', get_version(), '--yes', ] subprocess.check_call(cmd) _repair_changelog() def _repair_changelog(): """ Workaround for #2666 """ changelog_fn = pathlib.Path('CHANGES.rst') changelog = changelog_fn.read_text() fixed = re.sub(r'^(v[0-9.]+)v[0-9.]+$', r'\1', changelog, flags=re.M) changelog_fn.write_text(fixed) subprocess.check_output(['git', 'add', changelog_fn]) def bump_version(): cmd = bump_version_command + ['--allow-dirty'] subprocess.check_call(cmd) def ensure_config(): """ Double-check that Git has an e-mail configured. """ subprocess.check_output(['git', 'config', 'user.email']) def check_changes(): """ Verify that all of the files in changelog.d have the appropriate names. """ allowed = 'deprecation', 'breaking', 'change', 'doc', 'misc' except_ = 'README.rst', '.gitignore' news_fragments = ( file for file in pathlib.Path('changelog.d').iterdir() if file.name not in except_ ) unrecognized = [ str(file) for file in news_fragments if not any(f".{key}" in file.suffixes for key in allowed) ] if unrecognized: raise ValueError(f"Some news fragments have invalid names: {unrecognized}") if __name__ == '__main__': print("Cutting release at", get_version()) ensure_config() check_changes() update_changelog() bump_version()