@@ -245,6 +245,8 @@ pub struct AggregatePrMetrics {
245245 pub p100_needs_review_to_complete : Option < TimeDelta > ,
246246
247247 pub iteration_counts : BTreeMap < usize , usize > ,
248+
249+ pub reviewed_by_counts : BTreeMap < ReviewedBy , usize > ,
248250}
249251
250252impl AggregatePrMetrics {
@@ -271,10 +273,12 @@ impl AggregatePrMetrics {
271273 } ) ;
272274
273275 let mut iteration_counts = BTreeMap :: new ( ) ;
276+ let mut reviewed_by_counts = BTreeMap :: new ( ) ;
274277 for metric in metrics {
275278 if metric. first_complete . is_some ( ) {
276279 * iteration_counts. entry ( metric. iterations ) . or_default ( ) += 1 ;
277280 }
281+ * reviewed_by_counts. entry ( metric. reviewed_by ) . or_default ( ) += 1 ;
278282 }
279283
280284 AggregatePrMetrics {
@@ -288,6 +292,7 @@ impl AggregatePrMetrics {
288292 p90_needs_review_to_complete,
289293 p100_needs_review_to_complete,
290294 iteration_counts,
295+ reviewed_by_counts,
291296 }
292297 }
293298
@@ -322,6 +327,7 @@ pub struct PrMetrics {
322327 pub first_reviewed : Option < chrono:: DateTime < chrono:: Utc > > ,
323328 pub first_complete : Option < chrono:: DateTime < chrono:: Utc > > ,
324329 pub iterations : usize ,
330+ pub reviewed_by : ReviewedBy ,
325331}
326332
327333impl PrMetrics {
@@ -343,6 +349,7 @@ impl PrMetrics {
343349 first_needs_review = Some ( event. time ) ;
344350 }
345351 } else if event. actor != pr. author {
352+ reviewed_by. observe_also ( & event. actor , staff) ;
346353 if event. label == "Reviewed" {
347354 iterations += 1 ;
348355 if first_reviewed. is_none ( ) {
@@ -365,6 +372,7 @@ impl PrMetrics {
365372 first_reviewed,
366373 first_complete,
367374 iterations,
375+ reviewed_by,
368376 }
369377 }
370378
@@ -385,6 +393,39 @@ impl PrMetrics {
385393 }
386394}
387395
396+ #[ derive( Clone , Copy , Debug , PartialEq , Eq , Serialize , PartialOrd , Ord , strum_macros:: Display ) ]
397+ pub enum ReviewedBy {
398+ NoOne ,
399+ OnlyStaff ,
400+ OnlyVolunteer ,
401+ StaffAndVolunteer ,
402+ }
403+
404+ impl ReviewedBy {
405+ fn observe_also ( & mut self , user : & GithubLogin , staff : & BTreeSet < GithubLogin > ) {
406+ match self {
407+ ReviewedBy :: NoOne => {
408+ if staff. contains ( user) {
409+ * self = ReviewedBy :: OnlyStaff ;
410+ } else {
411+ * self = ReviewedBy :: OnlyVolunteer ;
412+ }
413+ }
414+ ReviewedBy :: OnlyStaff => {
415+ if !staff. contains ( user) {
416+ * self = ReviewedBy :: StaffAndVolunteer ;
417+ }
418+ }
419+ ReviewedBy :: OnlyVolunteer => {
420+ if staff. contains ( user) {
421+ * self = ReviewedBy :: StaffAndVolunteer ;
422+ }
423+ }
424+ ReviewedBy :: StaffAndVolunteer => { }
425+ }
426+ }
427+ }
428+
388429#[ derive( Clone , Debug , PartialEq , Eq , Serialize ) ]
389430pub struct LabelAddEvent {
390431 pub actor : GithubLogin ,
@@ -521,6 +562,7 @@ pub(crate) async fn get_review_metrics(
521562 octocrab : & Octocrab ,
522563 github_org : & str ,
523564 pr : Pr ,
565+ staff : & BTreeSet < GithubLogin > ,
524566) -> Result < PrMetrics , Error > {
525567 let events = all_pages ( "timeline events" , octocrab, async || {
526568 octocrab
@@ -561,7 +603,7 @@ pub(crate) async fn get_review_metrics(
561603 )
562604 . collect ( ) ;
563605 let created_at = pr. created_at ;
564- Ok ( PrMetrics :: new ( pr, created_at, label_add_events) )
606+ Ok ( PrMetrics :: new ( pr, created_at, label_add_events, staff ) )
565607}
566608
567609// Ideally this would be a more general shared function, but async closures aren't super stable yet.
0 commit comments