@@ -78,7 +78,7 @@ def getPullRequest(self, number):
78
78
def isContributor (self , username ):
79
79
if not self .contributors :
80
80
contributor_list = self .repository .iter_contributors ()
81
- self .contributors = [contributor [ 'login' ] for contributor in contributor_list ]
81
+ self .contributors = [str ( contributor ) for contributor in contributor_list ]
82
82
return username in self .contributors
83
83
84
84
def isCollaborator (username ):
@@ -94,6 +94,7 @@ class PullRequest:
94
94
labels = False
95
95
def __init__ (self , repository , number ):
96
96
self .repository = repository
97
+ self .consensus = repository .getConsensus ()
97
98
self .number = number
98
99
self .pr = self .repository .client .pull_request (self .repository .user , self .repository .name , number )
99
100
@@ -105,6 +106,11 @@ def __init__(self, repository, number):
105
106
self .yes = []
106
107
self .no = []
107
108
self .abstain = []
109
+
110
+ self .contributors_yes = []
111
+ self .contributors_no = []
112
+ self .contributors_abstain = []
113
+
108
114
self .users = []
109
115
self .doubles = []
110
116
for reaction in reactions :
@@ -115,6 +121,10 @@ def __init__(self, repository, number):
115
121
if username in self .doubles :
116
122
continue
117
123
124
+ if 'blacklist' in self .repository .rules and self .repository .rules ['blacklist' ]:
125
+ if username in self .repository .blacklist :
126
+ continue
127
+
118
128
if 'collaborators_only' in self .repository .rules and self .repository .rules ['collaborators_only' ]:
119
129
if not isCollaborator (username ):
120
130
continue
@@ -138,17 +148,38 @@ def __init__(self, repository, number):
138
148
self .no .remove (username )
139
149
if username in self .abstain :
140
150
self .abstain .remove (username )
151
+ if username in self .contributors_yes :
152
+ self .contributors_yes .remove (username )
153
+ if username in self .contributors_no :
154
+ self .contributors_no .remove (username )
155
+ if username in self .contributors_abstain :
156
+ self .contributors_abstain .remove (username )
141
157
continue
142
158
143
159
if content == '+1' :
144
- self .yes .append (user ['login' ])
145
160
self .users .append (user ['login' ])
161
+ self .yes .append (user ['login' ])
162
+ if self .repository .isContributor (user ['login' ]):
163
+ self .contributors_yes .append (user ['login' ])
146
164
elif content == '-1' :
147
- self .no .append (user ['login' ])
148
165
self .users .append (user ['login' ])
166
+ self .no .append (user ['login' ])
167
+ if seld .repository .isContributor (user ['login' ]):
168
+ self .contributors_no .append (user ['login' ])
149
169
elif content == 'confused' :
150
- self .abstain .append (user ['login' ])
151
170
self .users .append (user ['login' ])
171
+ self .abstain .append (user ['login' ])
172
+ if seld .repository .isContributor (user ['login' ]):
173
+ self .contributors_abstain .append (user ['login' ])
174
+
175
+ files = self .pr .iter_files ()
176
+ self .changes_consensus = False
177
+ self .changes_license = False
178
+ for changed_file in files :
179
+ if changed_file .filename == '.gitconsensus.yaml' :
180
+ self .changes_consensus = True
181
+ if changed_file .filename .lower ().startswith ('license' ):
182
+ self .changes_license = True
152
183
153
184
def hoursSinceLastCommit (self ):
154
185
commits = self .pr .iter_commits ()
@@ -158,31 +189,35 @@ def hoursSinceLastCommit(self):
158
189
159
190
# 2017-08-19T23:29:31Z
160
191
commit_date = datetime .datetime .strptime (commit_date_string , '%Y-%m-%dT%H:%M:%SZ' )
161
- now = datetime .datetime .now ()
192
+ now = datetime .datetime .utcnow ()
162
193
delta = now - commit_date
163
194
return delta .seconds / 3600
164
195
165
196
def hoursSincePullOpened (self ):
166
- now = datetime .datetime .now ()
197
+ now = datetime .datetime .utcnow ()
167
198
delta = now - self .pr .created_at .replace (tzinfo = None )
168
199
return delta .seconds / 3600
169
200
170
201
def hoursSinceLastUpdate (self ):
171
202
hoursOpen = self .hoursSincePullOpened ()
172
203
hoursSinceCommit = self .hoursSinceLastCommit ()
173
-
174
204
if hoursOpen < hoursSinceCommit :
175
205
return hoursOpen
176
206
return hoursSinceCommit
177
207
208
+ def changesConsensus (self ):
209
+ return self .changes_consensus
210
+
211
+ def changesLicense (self ):
212
+ return self .changes_license
213
+
178
214
def getIssue (self ):
179
215
return self .repository .repository .issue (self .number )
180
216
181
217
def validate (self ):
182
218
if self .repository .rules == False :
183
219
return False
184
- consenttest = self .repository .getConsensus ()
185
- return consenttest .validate (self )
220
+ return self .consensus .validate (self )
186
221
187
222
def shouldClose (self ):
188
223
if 'timeout' in self .repository .rules :
@@ -193,11 +228,13 @@ def shouldClose(self):
193
228
def close (self ):
194
229
self .pr .close ()
195
230
self .addLabels (['gc-closed' ])
231
+ self .cleanInfoLabels ()
196
232
self .commentAction ('closed' )
197
233
198
234
def vote_merge (self ):
199
235
self .pr .merge ('GitConsensus Merge' )
200
236
self .addLabels (['gc-merged' ])
237
+ self .cleanInfoLabels ()
201
238
202
239
if 'extra_labels' in self .repository .rules and self .repository .rules ['extra_labels' ]:
203
240
self .addLabels ([
@@ -208,18 +245,53 @@ def vote_merge(self):
208
245
])
209
246
self .commentAction ('merged' )
210
247
248
+ def addInfoLabels (self ):
249
+ labels = self .getLabelList ()
250
+
251
+ licenseMessage = 'License Change'
252
+ if self .changesLicense ():
253
+ self .addLabels ([licenseMessage ])
254
+ else :
255
+ self .removeLabels ([licenseMessage ])
256
+
257
+ consensusMessage = 'Consensus Change'
258
+ if self .changesConsensus ():
259
+ self .addLabels ([consensusMessage ])
260
+ else :
261
+ self .removeLabels ([consensusMessage ])
262
+
263
+ hasQuorumMessage = 'Has Quorum'
264
+ needsQuorumMessage = 'Needs Votes'
265
+ if self .consensus .hasQuorum (self ):
266
+ self .addLabels ([hasQuorumMessage ])
267
+ self .removeLabels ([needsQuorumMessage ])
268
+ else :
269
+ self .removeLabels ([hasQuorumMessage ])
270
+ self .addLabels ([needsQuorumMessage ])
271
+
272
+ passingMessage = 'Passing'
273
+ failingMessage = 'Failing'
274
+ if self .consensus .hasVotes (self ):
275
+ self .addLabels ([passingMessage ])
276
+ self .removeLabels ([failingMessage ])
277
+ else :
278
+ self .removeLabels ([passingMessage ])
279
+ self .addLabels ([failingMessage ])
280
+
281
+ def cleanInfoLabels (self ):
282
+ self .removeLabels (['Failing' , 'Passing' , 'Needs Votes' , 'Has Quorum' ])
283
+
211
284
def commentAction (self , action ):
212
285
table = self .buildVoteTable ()
213
- consensus = self .repository .getConsensus ()
214
286
message = message_template % (
215
287
action ,
216
288
str (len (self .yes )),
217
289
str (len (self .no )),
218
290
str (len (self .abstain )),
219
291
str (len (self .users )),
220
292
table ,
221
- consensus .hasQuorum (self ),
222
- consensus .hasVotes (self )
293
+ self . consensus .hasQuorum (self ),
294
+ self . consensus .hasVotes (self )
223
295
)
224
296
225
297
if len (self .doubles ) > 0 :
@@ -251,11 +323,19 @@ def buildVoteTable(self):
251
323
table = "%s\n %s" % (table , row )
252
324
return table
253
325
254
-
255
326
def addLabels (self , labels ):
327
+ existing = self .getLabelList ()
256
328
issue = self .getIssue ()
257
329
for label in labels :
258
- issue .add_labels (label )
330
+ if label not in existing :
331
+ issue .add_labels (label )
332
+
333
+ def removeLabels (self , labels ):
334
+ existing = self .getLabelList ()
335
+ issue = self .getIssue ()
336
+ for label in labels :
337
+ if label in existing :
338
+ issue .remove_label (label )
259
339
260
340
def addComment (self , comment_string ):
261
341
return self .getIssue ().create_comment (comment_string )
@@ -320,8 +400,13 @@ def hasAged(self, pr):
320
400
if hours >= self .rules ['mergedelay' ]:
321
401
return True
322
402
if 'delayoverride' in self .rules and self .rules ['delayoverride' ]:
403
+ if pr .changesConsensus () or pr .changesLicense ():
404
+ return False
405
+ if 'mergedelaymin' in self .rules and self .rules ['mergedelaymin' ]:
406
+ if hours < self .rules ['mergedelaymin' ]:
407
+ return False
323
408
if len (pr .no ) > 0 :
324
409
return False
325
- if len (pr .yes ) >= self .rules ['delayoverride' ]:
410
+ if len (pr .contributors_yes ) >= self .rules ['delayoverride' ]:
326
411
return True
327
412
return False
0 commit comments