async def status_for_repo_new_commits(*, github_access_token, repo_info, release_pr): """ Check if there are new commits to be part of a release Args: github_access_token (str): The github access token repo_info (RepoInfo): Repository info release_pr (ReleasePR): The info for the release PR Returns: bool: Whether or not there are new commits """ async with init_working_dir(github_access_token, repo_info.repo_url) as working_dir: last_version = await get_project_version(repo_info=repo_info, working_dir=working_dir) default_branch = await get_default_branch(working_dir) return await any_commits_between_branches( branch1="origin/release-candidate" if release_pr and release_pr.open else f"v{last_version}", branch2=default_branch, root=working_dir, )
async def publish(*, repo_info, version, github_access_token, npm_token): """ Publish a package to the appropriate repository Args: repo_info (RepoInfo): The repository info version (str): The version of the project to upload github_access_token (str): The github access token npm_token (str): The NPM token """ branch = f"v{version}" async with init_working_dir(github_access_token, repo_info.repo_url, branch=branch) as working_dir: if repo_info.packaging_tool == NPM: await upload_to_npm( npm_token=npm_token, project_dir=working_dir, ) elif repo_info.packaging_tool == SETUPTOOLS: await upload_to_pypi(project_dir=working_dir, ) else: raise Exception( f"Unexpected value for packaging tool {repo_info.packaging_tool} for {repo_info.name}" )
async def release(*, github_access_token, repo_info, new_version, branch=None, commit_hash=None): """ Run a release Args: github_access_token (str): The github access token repo_info (RepoInfo): RepoInfo for a repo new_version (str): The version of the new release branch (str): The branch to initialize the release from commit_hash (str): Commit hash to cherry pick in case of a hot fix """ await validate_dependencies() async with init_working_dir(github_access_token, repo_info.repo_url, branch=branch) as working_dir: default_branch = await get_default_branch(working_dir) await check_call(["git", "checkout", "-qb", "release-candidate"], cwd=working_dir) if commit_hash: try: await check_call(["git", "cherry-pick", commit_hash], cwd=working_dir) except CalledProcessError as ex: raise ReleaseException( f"Cherry pick failed for the given hash {commit_hash}" ) from ex old_version = await update_version( repo_info=repo_info, new_version=new_version, working_dir=working_dir, readonly=False, ) if parse_version(old_version) >= parse_version(new_version): raise ReleaseException( f"old version is {old_version} but the new version {new_version} is not newer" ) base_branch = "release-candidate" if commit_hash else default_branch await verify_new_commits(old_version, base_branch=base_branch, root=working_dir) await update_release_notes(old_version, new_version, base_branch=base_branch, root=working_dir) await build_release(root=working_dir) return await generate_release_pr( github_access_token=github_access_token, repo_url=repo_info.repo_url, old_version=old_version, new_version=new_version, base_branch=base_branch, root=working_dir, )
async def release(github_access_token, repo_url, new_version, branch=None, commit_hash=None): """ Run a release Args: github_access_token (str): The github access token repo_url (str): URL for a repo new_version (str): The version of the new release branch (str): The branch to initialize the release from commit_hash (str): Commit hash to cherry pick in case of a hot fix """ await validate_dependencies() async with init_working_dir(github_access_token, repo_url, branch=branch) as working_dir: await check_call(["git", "checkout", "-qb", "release-candidate"], cwd=working_dir) if commit_hash: try: await check_call(["git", "cherry-pick", commit_hash], cwd=working_dir) except CalledProcessError: raise ReleaseException( f"Cherry pick failed for the given hash {commit_hash}") old_version = update_version(new_version, working_dir=working_dir) if parse_version(old_version) >= parse_version(new_version): raise ReleaseException( "old version is {old} but the new version {new} is not newer". format( old=old_version, new=new_version, )) base_branch = "release-candidate" if commit_hash else "master" await verify_new_commits(old_version, base_branch=base_branch, root=working_dir) await update_release_notes(old_version, new_version, base_branch=base_branch, root=working_dir) await build_release(root=working_dir) await generate_release_pr( github_access_token=github_access_token, repo_url=repo_url, old_version=old_version, new_version=new_version, base_branch=base_branch, root=working_dir, ) print(f"version {old_version} has been updated to {new_version}") print("Go tell engineers to check their work. PR is on the repo.") print("After they are done, run the finish_release.py script.")
async def get_version_tag(*, github_access_token, repo_url, commit_hash): """ Determines the version tag (or None) of the given commit hash Args: github_access_token (str): The access token repo_url (str): The URL for the git repo of the project commit_hash (str): The commit hash where we expect to find a tag with the version number """ async with init_working_dir(github_access_token, repo_url) as working_dir: output = await check_output( ["git", "tag", "-l", "--points-at", commit_hash], cwd=working_dir ) return output.decode().strip()
async def get_commit_oneline_message(*, github_access_token, repo_url, commit_hash): """ Get the git commit message plus a piece of the hash for display purposes Args: github_access_token (str): The access token repo_url (str): The URL for the git repo of the project commit_hash (str): The commit hash where we expect to find a tag with the version number """ async with init_working_dir(github_access_token, repo_url) as working_dir: output = await check_output( ["git", "log", "--oneline", f"{commit_hash}^1..{commit_hash}", "--"], cwd=working_dir, ) return output.decode().strip()