4
4
import os
5
5
import sys
6
6
from os .path import join , abspath , dirname
7
+ from operators import itemgetter
7
8
8
9
import settings
9
10
import github_api as gh
@@ -25,99 +26,114 @@ def poll_pull_requests():
25
26
# get all ready prs (disregarding of the voting window)
26
27
prs = gh .prs .get_ready_prs (api , settings .URN , 0 )
27
28
28
- needs_update = False
29
- for pr in prs :
30
- pr_num = pr ["number" ]
31
- __log .info ("processing PR #%d" , pr_num )
32
-
33
- # gather all current votes
34
- votes = gh .voting .get_votes (api , settings .URN , pr )
35
-
36
- # is our PR approved or rejected?
37
- vote_total , variance = gh .voting .get_vote_sum (api , votes )
38
- threshold = gh .voting .get_approval_threshold (api , settings .URN )
39
- is_approved = vote_total >= threshold
40
-
41
- # the PR is mitigated or the threshold is not reached ?
42
- if variance >= threshold or not is_approved :
43
- voting_window = gh .voting .get_extended_voting_window (api , settings .URN )
44
-
45
- # is our PR in voting window?
46
- in_window = gh .prs .is_pr_in_voting_window (pr , voting_window )
47
-
48
- if is_approved :
49
- __log .info ("PR %d status: will be approved" , pr_num )
50
-
51
- gh .prs .post_accepted_status (
52
- api , settings .URN , pr , voting_window , votes , vote_total , threshold )
53
-
54
- if in_window :
55
- __log .info ("PR %d approved for merging!" , pr_num )
56
-
57
- try :
58
- sha = gh .prs .merge_pr (api , settings .URN , pr , votes , vote_total ,
59
- threshold )
60
- # some error, like suddenly there's a merge conflict, or some
61
- # new commits were introduced between finding this ready pr and
62
- # merging it
63
- except gh .exceptions .CouldntMerge :
64
- __log .info ("couldn't merge PR %d for some reason, skipping" ,
65
- pr_num )
66
- gh .prs .label_pr (api , settings .URN , pr_num , ["can't merge" ])
67
- continue
68
-
69
- gh .comments .leave_accept_comment (
70
- api , settings .URN , pr_num , sha , votes , vote_total , threshold )
71
- gh .prs .label_pr (api , settings .URN , pr_num , ["accepted" ])
72
-
73
- # chaosbot rewards merge owners with a follow
74
- pr_owner = pr ["user" ]["login" ]
75
- gh .users .follow_user (api , pr_owner )
76
-
77
- needs_update = True
78
-
79
- else :
80
- __log .info ("PR %d status: will be rejected" , pr_num )
81
-
82
- if in_window :
83
- gh .prs .post_rejected_status (
84
- api , settings .URN , pr , voting_window , votes , vote_total , threshold )
85
- __log .info ("PR %d rejected, closing" , pr_num )
86
- gh .comments .leave_reject_comment (
87
- api , settings .URN , pr_num , votes , vote_total , threshold )
88
- gh .prs .label_pr (api , settings .URN , pr_num , ["rejected" ])
89
- gh .prs .close_pr (api , settings .URN , pr )
90
- elif vote_total < 0 :
91
- gh .prs .post_rejected_status (
92
- api , settings .URN , pr , voting_window , votes , vote_total , threshold )
29
+ # This sets up a voting record, with each user having a count of votes
30
+ # that they have cast.
31
+ try :
32
+ fp = open ('server/voters.json' , 'x' )
33
+ fp .close ()
34
+ except :
35
+ # file already exists, which is what we want
36
+ pass
37
+
38
+ with open ('server/voters.json' , 'r+' ) as fp :
39
+ total_votes = {}
40
+ fs = fp .read ()
41
+ if fs :
42
+ # if the voting record exists, read it in
43
+ total_votes = json .loads (fs )
44
+ # then prepare for overwriting
45
+ fp .seek (0 )
46
+ fp .truncate ()
47
+
48
+ top_contributors = sorted (gh .repos .get_contributors (api , settings .URN ),
49
+ key = itemgetter ('total' ))
50
+ top_contributors = top_contributors [:settings .MERITOCRACY_TOP_CONTRIBUTORS ]
51
+ top_contributors = [user ["login" ].lower () for user in top_contributors ]
52
+ top_voters = sorted (total_votes .iteritems (), key = lambda k , v : (v , k ))
53
+ top_voters = [user [0 ].lower () for user in top_voters [:settings .MERITOCRACY_TOP_VOTERS ]]
54
+ meritocracy = top_voters + top_contributors
55
+
56
+ needs_update = False
57
+ for pr in prs :
58
+ pr_num = pr ["number" ]
59
+ __log .info ("processing PR #%d" , pr_num )
60
+
61
+ # gather all current votes
62
+ votes , meritocracy_satisfied = gh .voting .get_votes (api , settings .URN , pr , meritocracy )
63
+
64
+ # is our PR approved or rejected?
65
+ vote_total , variance = gh .voting .get_vote_sum (api , votes )
66
+ threshold = gh .voting .get_approval_threshold (api , settings .URN )
67
+ is_approved = vote_total >= threshold and meritocracy_satisfied
68
+
69
+ # the PR is mitigated or the threshold is not reached ?
70
+ if variance >= threshold or not is_approved :
71
+ voting_window = gh .voting .get_extended_voting_window (api , settings .URN )
72
+
73
+ # is our PR in voting window?
74
+ in_window = gh .prs .is_pr_in_voting_window (pr , voting_window )
75
+
76
+ if is_approved :
77
+ __log .info ("PR %d status: will be approved" , pr_num )
78
+
79
+ gh .prs .post_accepted_status (
80
+ api , settings .URN , pr , voting_window , votes , vote_total ,
81
+ threshold , meritocracy_satisfied )
82
+
83
+ if in_window :
84
+ __log .info ("PR %d approved for merging!" , pr_num )
85
+
86
+ try :
87
+ sha = gh .prs .merge_pr (api , settings .URN , pr , votes , vote_total ,
88
+ threshold , meritocracy_satisfied )
89
+ # some error, like suddenly there's a merge conflict, or some
90
+ # new commits were introduced between finding this ready pr and
91
+ # merging it
92
+ except gh .exceptions .CouldntMerge :
93
+ __log .info ("couldn't merge PR %d for some reason, skipping" ,
94
+ pr_num )
95
+ gh .prs .label_pr (api , settings .URN , pr_num , ["can't merge" ])
96
+ continue
97
+
98
+ gh .comments .leave_accept_comment (
99
+ api , settings .URN , pr_num , sha , votes , vote_total ,
100
+ threshold , meritocracy_satisfied )
101
+ gh .prs .label_pr (api , settings .URN , pr_num , ["accepted" ])
102
+
103
+ # chaosbot rewards merge owners with a follow
104
+ pr_owner = pr ["user" ]["login" ]
105
+ gh .users .follow_user (api , pr_owner )
106
+
107
+ needs_update = True
108
+
93
109
else :
94
- gh . prs . post_pending_status (
95
- api , settings . URN , pr , voting_window , votes , vote_total , threshold )
96
-
97
- # This sets up a voting record, with each user having a count of votes
98
- # that they have cast.
99
- try :
100
- fp = open ( 'server/voters.json' , 'x' )
101
- fp . close ()
102
- except :
103
- # file already exists, which is what we want
104
- pass
105
-
106
- with open ( 'server/voters.json' , 'r+' ) as fp :
107
- old_votes = {}
108
- fs = fp . read ()
109
- if fs :
110
- # if the voting record exists, read it in
111
- old_votes = json . loads ( fs )
112
- # then prepare for overwriting
113
- fp . seek ( 0 )
114
- fp . truncate ()
110
+ __log . info ( "PR %d status: will be rejected" , pr_num )
111
+
112
+ if in_window :
113
+ gh . prs . post_rejected_status (
114
+ api , settings . URN , pr , voting_window , votes , vote_total ,
115
+ threshold , meritocracy_satisfied )
116
+ __log . info ( "PR %d rejected, closing" , pr_num )
117
+ gh . comments . leave_reject_comment (
118
+ api , settings . URN , pr_num , votes , vote_total , threshold ,
119
+ meritocracy_satisfied )
120
+ gh . prs . label_pr ( api , settings . URN , pr_num , [ "rejected" ])
121
+ gh . prs . close_pr ( api , settings . URN , pr )
122
+ elif vote_total < 0 :
123
+ gh . prs . post_rejected_status (
124
+ api , settings . URN , pr , voting_window , votes , vote_total ,
125
+ threshold , meritocracy_satisfied )
126
+ else :
127
+ gh . prs . post_pending_status (
128
+ api , settings . URN , pr , voting_window , votes , vote_total ,
129
+ threshold , meritocracy_satisfied )
130
+
115
131
for user in votes :
116
- if user in old_votes :
117
- old_votes [user ] += 1
132
+ if user in total_votes :
133
+ total_votes [user ] += 1
118
134
else :
119
- old_votes [user ] = 1
120
- json .dump (old_votes , fp )
135
+ total_votes [user ] = 1
136
+ json .dump (total_votes , fp )
121
137
122
138
# flush all buffers because we might restart, which could cause a crash
123
139
os .fsync (fp )
0 commit comments