...

Text file src/github.com/emissary-ingress/emissary/v3/releng/start-sanity-check

Documentation: github.com/emissary-ingress/emissary/v3/releng

     1#!/usr/bin/env python3
     2"""Do a sanity check that you're at something that's ready for you to
     3cut an RC from; that you're in the right repo, that you're on the
     4right branch, that all of the subtrees are up-to-date...
     5"""
     6
     7from typing import Generator
     8
     9import sys
    10import time
    11
    12import os.path
    13
    14from os import getenv
    15from contextlib import contextmanager
    16
    17from lib import assert_eq, git_check_clean, parse_bool, vX, vY, re_ga, re_ea
    18from lib.uiutil import Checker, CheckResult, run
    19from lib.uiutil import run_txtcapture as run_capture
    20
    21
    22DEFAULT_REPO = 'git@github.com:emissary-ingress/emissary'
    23
    24
    25def main(next_ver: str, quiet: bool = False, allow_untracked: bool = False) -> int:
    26    print(f'Starting work on "v{next_ver}"...')
    27    print()
    28    remote_repo = getenv('AMBASSADOR_RELEASE_REPO_OVERRIDE')
    29    if remote_repo is None or remote_repo == '':
    30        remote_repo = DEFAULT_REPO
    31
    32    checker = Checker()
    33
    34    @contextmanager
    35    def check(name: str) -> Generator[CheckResult, None, None]:
    36        with checker.check(name) as subcheck:
    37            # time.sleep(1)  # it's stupid, but honestly the delay makes the output more readable
    38            yield subcheck
    39
    40    is_private = False
    41
    42    with check(f"You're in a clone of {remote_repo}"):
    43        url = run_capture(['git', 'remote', 'get-url', '--push', 'origin'])
    44        if url.endswith("/"):
    45            url = url[:-len("/")]
    46        if url.endswith(".git"):
    47            url = url[:-len(".git")]
    48        if url.endswith("-private"):
    49            is_private = True
    50            url = url[:-len("-private")]
    51        assert_eq(url, remote_repo)
    52
    53    with check("You're in the toplevel of the clone"):
    54        toplevel = run_capture(['git', 'rev-parse', '--show-toplevel'])
    55        if not os.path.samefile(toplevel, '.'):
    56            raise Exception(f"Not in {toplevel}")
    57
    58    with check("You're in a clean checkout"):
    59        git_check_clean(allow_untracked=allow_untracked)
    60
    61    # Cache the name of our remote...
    62    remote_name = f'{remote_repo}.git' if is_private else 'origin'
    63
    64    # ...make sure the passed-in version is OK...
    65    m = re_ga.match(next_ver)
    66    if not m:
    67        m = re_ea.match(next_ver)
    68    assert m
    69
    70    # ...and figure out some branch names.
    71    release_branch = os.environ.get("RELEASE_BRANCH") or f"release/v{m[vX]}.{m[vY]}"
    72    cur_branch = ""
    73
    74    with check(f"You're on master or {release_branch}"):
    75        cur_branch = run_capture(['git', 'rev-parse', '--abbrev-ref', 'HEAD'])
    76
    77        if (cur_branch != "master") and (cur_branch != release_branch):
    78            raise AssertionError(f"You can't start a release from {cur_branch}")
    79
    80    if checker.ok:
    81        with check("You're up-to-date with ambassador.git"):
    82            remote_name = f'{remote_repo}.git' if is_private else 'origin'
    83
    84            branch_up_to_date(
    85                remote=remote_name,
    86                branch=cur_branch,
    87                update_cmd=f'git pull {remote_name} {cur_branch}',
    88            )
    89
    90        if is_private:
    91            with check("You're up-to-date with ambassador-private.git"):
    92                branch_up_to_date(
    93                    remote='f{remote_repo}-private.git',
    94                    branch=cur_branch,
    95                    update_cmd=f'git pull {remote_repo}-private.git {cur_branch}',
    96                )
    97
    98    if checker.ok:
    99        if not quiet:
   100            print()
   101            print("Yep, looks like you're good to proceed to running `start-update-version`.")
   102        return 0
   103    else:
   104        print()
   105        print("Looks like there's something wrong with your tree that you need to address before continuing.")
   106        return 1
   107
   108
   109def branch_exists(remote: str, branch: str) -> None:
   110    # Allow exceptions to propagate upward
   111    run(['git', 'fetch', remote, f'refs/heads/{branch}'])
   112
   113
   114def branch_up_to_date(remote: str, branch: str, update_cmd: str) -> None:
   115    run(['git', 'fetch', remote, f'refs/heads/{branch}'])
   116    try:
   117        run(['git', 'merge-base', '--is-ancestor', 'FETCH_HEAD', 'HEAD'])
   118    except Exception as err:
   119        print(f"HEAD is not up-to-date with '{remote}' '{branch}':")
   120        print("You need to update it with:")
   121        print()
   122        print(f"    $ {update_cmd}")
   123        print()
   124        raise
   125
   126
   127subtree_up_to_date = branch_up_to_date
   128
   129if __name__ == '__main__':
   130    args = sys.argv[1:]
   131    quiet = False
   132
   133    allow_untracked = parse_bool(getenv("ALLOW_UNTRACKED", "false"))
   134
   135    if args and (args[0] == '--quiet'):
   136        quiet = True
   137        args.pop(0)
   138
   139    if len(args) != 1 or (not re_ga.match(args[0]) and not re_ea.match(args[0])):
   140        sys.stderr.write(f"{os.path.basename(sys.argv[0])} Version must match X.Y.Z(-ea)\n")
   141        sys.exit(2)
   142
   143    sys.exit(main(next_ver=args[0], quiet=quiet, allow_untracked=allow_untracked))

View as plain text