release.py (1997B)
1 """ 2 Release script. 3 """ 4 5 import argparse 6 from subprocess import check_call 7 import sys 8 9 from colorama import Fore 10 from colorama import init 11 from git import Remote 12 from git import Repo 13 14 15 def create_branch(version): 16 """Create a fresh branch from upstream/main""" 17 repo = Repo.init(".") 18 if repo.is_dirty(untracked_files=True): 19 raise RuntimeError("Repository is dirty, please commit/stash your changes.") 20 21 branch_name = f"release-{version}" 22 print(f"{Fore.CYAN}Create {branch_name} branch from upstream main") 23 upstream = get_upstream(repo) 24 upstream.fetch() 25 release_branch = repo.create_head(branch_name, upstream.refs.main, force=True) 26 release_branch.checkout() 27 return repo 28 29 30 def get_upstream(repo: Repo) -> Remote: 31 """Find upstream repository for pluggy on the remotes""" 32 for remote in repo.remotes: 33 for url in remote.urls: 34 if url.endswith(("pytest-dev/pluggy.git", "pytest-dev/pluggy")): 35 return remote 36 raise RuntimeError("could not find pytest-dev/pluggy remote") 37 38 39 def pre_release(version): 40 """Generates new docs, release announcements and creates a local tag.""" 41 create_branch(version) 42 changelog(version, write_out=True) 43 44 check_call(["git", "commit", "-a", "-m", f"Preparing release {version}"]) 45 46 print() 47 print(f"{Fore.GREEN}Please push your branch to your fork and open a PR.") 48 49 50 def changelog(version, write_out=False): 51 if write_out: 52 addopts = [] 53 else: 54 addopts = ["--draft"] 55 print(f"{Fore.CYAN}Generating CHANGELOG") 56 check_call(["towncrier", "build", "--yes", "--version", version] + addopts) 57 58 59 def main(): 60 init(autoreset=True) 61 parser = argparse.ArgumentParser() 62 parser.add_argument("version", help="Release version") 63 options = parser.parse_args() 64 try: 65 pre_release(options.version) 66 except RuntimeError as e: 67 print(f"{Fore.RED}ERROR: {e}") 68 return 1 69 70 71 if __name__ == "__main__": 72 sys.exit(main())