#!/usr/bin/python3 import argparse import re import subprocess import sys from github import Github import os def main(): # set up parser parser = argparse.ArgumentParser() parser.add_argument('-v', '--version', type=str, help='Version to release.') parser.add_argument('-t', '--token', type=str, help='GitHub access token.', default=os.getenv('GITHUB_ACCESS_TOKEN', None)) args = parser.parse_args() # check github access token if args.token is None: print('No GitHub access token found.') return 1 # get repo name repo_remote = shell('git config --get remote.origin.url') if not repo_remote: print("Not a git repository.") sys.exit(1) m = re.search(r'github\.com[:/](.*)\.git$', repo_remote) if m is None: print('Could not identify GitHub repository.') return 1 repo_name = m.group(1) repo_owner = shell('git config --get user.name') print(f'Repository: {repo_name}') print(f'User: {repo_owner}') # pyproject.toml? if not os.path.exists('pyproject.toml'): print('No pyproject.toml found.') return 1 # Poetry? try: shell('poetry') except subprocess.CalledProcessError: print('No poetry found.') return 1 # current version version = get_current_version() print(f'Current version: {version}') # connect to GitHub print() print('Connecting to GitHub...') gh = Github(args.token) print('Fetching repository...') repo = gh.get_repo(repo_name) branches = repo.get_branches() branch_names = [b.name for b in branches] if 'develop' not in branch_names: print('No develop branch found.') return 1 main_branch = 'main' if main_branch not in branch_names: main_branch = 'master' if main_branch not in branch_names: print('No main/master branch found.') return 1 # currently in develop? cur_branch = shell('git rev-parse --abbrev-ref HEAD') if cur_branch != 'develop': print('Current branch is not develop.') return 1 # print plan print() print('Will perform the following tasks:') if args.version is None: print(f'1. Set new version using "poetry version patch"') set_version = 'patch' else: print(f'1. Set new version using "poetry version {args.version}"') set_version = args.version print(f'2. Commit and pull change.') print(f'3. Create PR develop -> {main_branch}') print(f'4. Merge PR') print(f'5. Create tag and release with new version') # continue if input('Continue [y/N]') not in 'yY': return 0 # set new version print() print('Setting new version...') shell(f'poetry version {set_version}') version = get_current_version() print(f'New version: {version}') # commit it shell(f'git commit -m "v{version}" pyproject.toml') shell(f'git push') # shortcuts title = f'v{version}' body = f'version {version}' # create PR print('Creating PR...') pr = repo.create_pull(title=title, body=body, head='develop', base=main_branch) # merge PR print('Merging PR...') pr.merge(commit_title=title, commit_message=body) # get last commit print('Fetching last commit...') commit = repo.get_commits()[0] print(f'Commit is {commit.sha}.') # tag & release print('Create tag and release...') repo.create_git_tag_and_release(tag=title, tag_message=body, release_name=title, release_message=body, object=commit.sha, type='commit') print('Done.') def shell(cmd, check=True): result = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, check=check) return result.stdout.decode('utf-8').strip() def get_current_version(): return shell('poetry version').split()[1].strip() if __name__ == '__main__': code = main() sys.exit(code)