-
Notifications
You must be signed in to change notification settings - Fork 11
/
validate.py
141 lines (115 loc) · 4.02 KB
/
validate.py
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
import os
import random
import runpy
import copy
import util
import pull_request
def print_points():
print('Points:')
for user, user_points in util.get_user_points().items():
print(' %s: %s' % (user, user_points))
def print_users():
users = util.users()
print('Users:')
for user in users:
print(' %s' % user)
def print_file_changes(pr):
diff = pr.diff()
print('\n')
for category, category_list in [
('added', diff.added_files),
('modified', diff.modified_files),
('removed', diff.removed_files)]:
if category_list:
print('%s:' % category)
for patched_file in category_list:
print(' %s' % patched_file.path)
print()
def print_status(pr):
print('\nAuthor: %s' % pr.author())
print('\nReviews:')
for user, state in sorted(pr.reviews.items()):
print (' %s: %s' % (user, state))
print('Approvals: %s - %s' % (len(pr.approvals), ' '.join(pr.approvals)))
print('Rejections: %s - %s' %(len(pr.rejections), ' '.join(pr.rejections)))
print('Non-participants: %s - %s' %(len(pr.non_participants), ' '.join(pr.non_participants)))
print('\nFYI: this PR has been sitting for %s days' % (
pr.days_since_changed()))
print_file_changes(pr)
def determine_if_mergeable(pr):
print_points()
print_status(pr)
rules = []
for rule_fname in os.listdir('rules'):
rule_priority_str, allow_block, rule_name = rule_fname.split('-', 2)
rule_name, _ = rule_name.rsplit('.', 1)
if allow_block not in ['allow', 'block']:
raise Exception('Invalid rule prefix %s in %s' % (
allow_block, rule_fname))
is_allow = allow_block == 'allow'
rules.append((float(rule_priority_str),
os.path.join('rules', rule_fname),
rule_name,
is_allow))
# Go through rules sorted by priority, with ties broken by the filename.
for rule_priority, rule_full_fname, rule_name, is_allow in sorted(rules):
print('Running rule %s' % rule_name)
pr_copy = copy.deepcopy(pr)
rule_py = runpy.run_path(rule_full_fname)
fn = rule_py['should_allow' if is_allow else 'should_block']
if is_allow:
try:
# Returns truthy to indicate allowing, anything else including raising
# for no judgement.
if fn(pr_copy):
print('\nPASS: %s' % rule_name)
return
except Exception as e:
print(' %s: %s' % (rule_full_fname, e))
else:
# Raises an exception to indicate blocking, anything else for no
# judgement.
fn(pr_copy)
print('\nPASS')
def determine_if_winner():
print_points()
# Pick a winner at random with a single random number. We divide the number
# line up like:
#
# [ a_points | b_points | c_points | ... everything else ... ]
#
# and then we choose a place on the number line randomly:
#
# [ a_points | b_points | c_points | ... everything else ... ]
# ^
#
# or:
# [ a_points | b_points | c_points | ... everything else ... ]
# ^
# You can think of this as assigning a range to each player:
#
# A wins if random is [0, a_points)
# B wins if random is [a_points, a_points + b_points)
# C wins if random is [a_points + b_points, a_points + b_points + c_points)
# no one wins if random is [a_points + b_points + c_points, 1)
rnd = random.random()
points_so_far = 0
for user, user_points in util.get_user_points().items():
if rnd < 0.00001 * (user_points + points_so_far):
raise Exception('%s wins!' % user)
points_so_far += user_points
print('The game continues.')
def start():
travis_pull_request = os.environ['TRAVIS_PULL_REQUEST']
if travis_pull_request == 'false':
determine_if_winner()
else:
target_commit = os.environ['TRAVIS_PULL_REQUEST_SHA']
repo_slug = os.environ['TRAVIS_REPO_SLUG']
determine_if_mergeable(pull_request.PullRequest(
repo=repo_slug,
pr_number=travis_pull_request,
target_commit=target_commit,
users=util.users()))
if __name__ == '__main__':
start()