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