def release(): local_head = local_current_head() if is_default_branch(): latest_sha = get_sha1_for_tag(latest_version()) commit_range = f"{latest_sha}..{local_head}" else: remote_head = remote_default_head() commit_range = f"{remote_head}..{local_head}" print(f"Working in branch: {current_branch()}") print(f"On default branch: {is_default_branch()}") print(f"Commit range: {commit_range}") if not is_default_branch(): print('Trying to release while not on master?') sys.exit(1) if has_release(): print('Updating changelog and version') update_for_pending_release() print('Attempting a release.') git("config", "user.name", "Buildkite on behalf of Wellcome Collection") git("config", "user.email", "*****@*****.**") git("remote", "add", "ssh-origin", repo(), exit_on_error=False) git('push', 'ssh-origin', 'HEAD:master') git('push', 'ssh-origin', '--tag') else: print("No release detected, exit gracefully.") sys.exit(0)
def publish(project_name): if has_release(): print(f"Release detected, publishing {project_name}.") git("pull", "origin", remote_default_branch()) sbt(f"project {project_name}", "publish") else: print("No release detected, exit gracefully.") sys.exit(0)
def get_all_tags(): """ Returns a list of all tags in the repo. """ git('fetch', '--tags') result = git('tag') all_tags = result.split('\n') assert len(set(all_tags)) == len(all_tags) return set(all_tags)
def update_for_pending_release(): release_type = update_changelog_and_version() git('rm', RELEASE_FILE) git('add', CHANGELOG_FILE) git('add', BUILD_SBT) git( 'commit', '-m', 'Bump version to %s and update changelog\n\n[skip ci]' % ( new_version(release_type)) ) git('tag', new_version(release_type))
def get_changed_paths(*args, globs=None): """ Returns a set of changed paths in a given commit range. :param args: Arguments to pass to ``git diff``. :param globs: List of file globs to include in changed paths. """ if globs: args = list(args) + ["--", *globs] diff_output = git("diff", "--name-only", *args) return {line.strip() for line in diff_output.splitlines()}
#!/usr/bin/env python3 # -*- encoding: utf-8 from commands import git from provider import current_branch, is_default_branch if __name__ == "__main__": branch_name = current_branch() if is_default_branch(): print(f"Successful completion on {branch_name}, tagging latest.") git("tag", "latest", "--force") git("push", "origin", "latest", "--force") print("Done.") else: print(f"Successful completion on {branch_name}, nothing to do.")
def get_sha1_for_tag(tag): """Use show-ref to discover the hash for a given tag (fetch first so we have all remote tags).""" git("fetch") return git("show-ref", "--hash", tag)
def local_current_head(): """Use rev-parse to discover hash for current commit AKA HEAD (from .git/HEAD).""" return git("rev-parse", "HEAD")
def remote_default_head(): """Inspect refs to discover default branch HEAD @ remote origin.""" return git("show-ref", f"refs/remotes/origin/{remote_default_branch()}", "-s")
def remote_default_branch(): """Inspect refs to discover default branch @ remote origin.""" return git("symbolic-ref", "refs/remotes/origin/HEAD").split("/")[-1]
from commands import make, git from git_utils import get_changed_paths from provider import current_branch, repo if __name__ == "__main__": make("format") # If there are any changes, push to GitHub immediately and fail the # build. This will abort the remaining jobs, and trigger a new build # with the reformatted code. if get_changed_paths(): print("*** There were changes from formatting, creating a commit") git("config", "user.name", "Buildkite on behalf of Wellcome Collection") git("config", "user.email", "*****@*****.**") git("remote", "add", "ssh-origin", repo(), exit_on_error=False) # We checkout the branch before we add the commit, so we don't # include the merge commit that Buildkite makes. git("fetch", "ssh-origin") git("checkout", "--track", f"ssh-origin/{current_branch()}") git("add", "--verbose", "--update") git("commit", "-m", "Apply auto-formatting rules") git("push", "ssh-origin", f"HEAD:{current_branch()}") # We exit here to fail the build, so Buildkite will skip to the next # build, which includes the autoformat commit. sys.exit(1)
def autoformat(): local_head = local_current_head() if is_default_branch(): latest_sha = get_sha1_for_tag(latest_version()) commit_range = f"{latest_sha}..{local_head}" else: remote_head = remote_default_head() commit_range = f"{remote_head}..{local_head}" print(f"Working in branch: {current_branch()}") print(f"On default branch: {is_default_branch()}") print(f"Commit range: {commit_range}") sbt('scalafmt') check_release_file(commit_range) # If there are any changes, push to GitHub immediately and fail the # build. This will abort the remaining jobs, and trigger a new build # with the reformatted code. if get_changed_paths(): print("*** There were changes from formatting, creating a commit") git("config", "user.name", "Buildkite on behalf of Wellcome Collection") git("config", "user.email", "*****@*****.**") git("remote", "add", "ssh-origin", repo(), exit_on_error=False) # We checkout the branch before we add the commit, so we don't # include the merge commit that Buildkite makes. git("fetch", "ssh-origin") git("checkout", "--track", f"ssh-origin/{current_branch()}") git("add", "--verbose", "--update") git("commit", "-m", "Apply auto-formatting rules") git("push", "ssh-origin", f"HEAD:{current_branch()}") # We exit here to fail the build, so Buildkite will skip to the next # build, which includes the autoformat commit. sys.exit(1) else: print("*** There were no changes from auto-formatting")
import sys from commands import git from git_utils import ( get_changed_paths, get_all_tags, remote_default_branch, local_current_head, get_sha1_for_tag, remote_default_head, has_source_changes ) from provider import current_branch, is_default_branch, repo ROOT = git('rev-parse', '--show-toplevel') BUILD_SBT = os.path.join(ROOT, 'build.sbt') RELEASE_FILE = os.path.join(ROOT, 'RELEASE.md') RELEASE_TYPE = re.compile(r"^RELEASE_TYPE: +(major|minor|patch)") MAJOR = 'major' MINOR = 'minor' PATCH = 'patch' VALID_RELEASE_TYPES = (MAJOR, MINOR, PATCH) CHANGELOG_HEADER = re.compile(r"^## v\d+\.\d+\.\d+ - \d\d\d\d-\d\d-\d\d$") CHANGELOG_FILE = os.path.join(ROOT, 'CHANGELOG.md')