@@ -258,7 +258,9 @@ def detect_autorevert_pattern_workflow(self, workflow_name: str) -> List[Dict]:
258
258
for j in suspected_commit1 .failed_jobs
259
259
}
260
260
261
- common_failures = set ()
261
+ # Map to track newer commits for each failure
262
+ failure_to_newer_commit = {}
263
+
262
264
for (
263
265
suspected_failure_class_rule ,
264
266
suspected_failure_job_name ,
@@ -270,25 +272,27 @@ def detect_autorevert_pattern_workflow(self, workflow_name: str) -> List[Dict]:
270
272
)
271
273
)
272
274
if not newer_commit_same_job or not newer_same_jobs :
273
- # No older commit with the same job found
275
+ # No newer commit with the same job found
274
276
continue
275
277
276
278
if any (
277
279
j .classification_rule == suspected_failure_class_rule
278
280
for j in newer_same_jobs
279
281
):
280
282
# The newer commit has the same job failing
281
- common_failures .add (
282
- (
283
- suspected_failure_class_rule ,
284
- suspected_failure_job_name ,
285
- )
283
+ failure_key = (
284
+ suspected_failure_class_rule ,
285
+ suspected_failure_job_name ,
286
286
)
287
+ failure_to_newer_commit [failure_key ] = newer_commit_same_job
287
288
288
- if not common_failures :
289
+ if not failure_to_newer_commit :
289
290
continue
290
291
291
- for failure_rule , job_name in common_failures :
292
+ for (
293
+ failure_rule ,
294
+ job_name ,
295
+ ), newer_commit in failure_to_newer_commit .items ():
292
296
last_commit_with_same_job , last_same_jobs = (
293
297
self ._find_last_commit_with_job (
294
298
(commits [j ] for j in range (i + 1 , len (commits ))), job_name
@@ -319,11 +323,11 @@ def detect_autorevert_pattern_workflow(self, workflow_name: str) -> List[Dict]:
319
323
"workflow_name" : workflow_name ,
320
324
"failure_rule" : failure_rule ,
321
325
"newer_commits" : [
322
- "newer_commit_same_job .head_sha" ,
326
+ newer_commit .head_sha ,
323
327
suspected_commit1 .head_sha ,
324
328
],
325
- "older_commit" : " last_commit_with_same_job.head_sha" ,
326
- "failed_job_names" : list ( "last_same_job .name" ) ,
329
+ "older_commit" : last_commit_with_same_job .head_sha ,
330
+ "failed_job_names" : [ j .name for j in last_same_jobs ] ,
327
331
"older_job_coverage" : [],
328
332
}
329
333
)
@@ -434,3 +438,102 @@ def is_commit_reverted(self, target_commit_sha: str) -> Optional[Dict]:
434
438
}
435
439
436
440
return None # No revert found
441
+
442
+ def extract_revert_categories_batch (self , messages : List [str ]) -> Dict [str , str ]:
443
+ """
444
+ Extract categories from multiple revert commit messages in a single batch query.
445
+
446
+ Categories are specified with -c flag like:
447
+ - nosignal
448
+ - ignoredsignal
449
+ - landrace
450
+ - weird
451
+ - ghfirst
452
+
453
+ Args:
454
+ messages: List of revert commit messages
455
+
456
+ Returns:
457
+ Dict mapping message to category
458
+ """
459
+ # Extract all comment IDs
460
+ comment_ids = []
461
+ message_to_comment_id = {}
462
+
463
+ for message in messages :
464
+ comment_match = re .search (r"#issuecomment-(\d+)" , message )
465
+ if comment_match :
466
+ comment_id = int (comment_match .group (1 ))
467
+ comment_ids .append (comment_id )
468
+ message_to_comment_id [message ] = comment_id
469
+
470
+ # Batch query for all comment bodies
471
+ comment_id_to_category = {}
472
+ if comment_ids :
473
+ try :
474
+ query = """
475
+ SELECT id, body
476
+ FROM issue_comment
477
+ WHERE id IN {comment_ids:Array(Int64)}
478
+ """
479
+ result = CHCliFactory ().client .query (
480
+ query , parameters = {"comment_ids" : comment_ids }
481
+ )
482
+
483
+ for row in result .result_rows :
484
+ comment_id , body = row
485
+ # Look for -c flag in comment body
486
+ match = re .search (r"-c\s+(\w+)" , body )
487
+ if match :
488
+ category = match .group (1 ).lower ()
489
+ if category in [
490
+ "nosignal" ,
491
+ "ignoredsignal" ,
492
+ "landrace" ,
493
+ "weird" ,
494
+ "ghfirst" ,
495
+ ]:
496
+ comment_id_to_category [comment_id ] = category
497
+ except Exception :
498
+ # If query fails, continue without error
499
+ pass
500
+
501
+ # Map messages to categories
502
+ result = {}
503
+ for message in messages :
504
+ comment_id = message_to_comment_id .get (message )
505
+ if comment_id and comment_id in comment_id_to_category :
506
+ result [message ] = comment_id_to_category [comment_id ]
507
+ else :
508
+ result [message ] = "uncategorized"
509
+
510
+ return result
511
+
512
+ def get_commits_reverted_with_info (self ) -> Dict [str , Dict ]:
513
+ """
514
+ Get all commits that were reverted with detailed information including categories.
515
+
516
+ Returns:
517
+ Dict mapping commit SHA to revert information with category
518
+ """
519
+ reverted_commits = {}
520
+ revert_messages = []
521
+
522
+ # First pass: collect all reverted commits and their messages
523
+ for commit in self .commit_history :
524
+ revert_info = self .is_commit_reverted (commit ["sha" ])
525
+ if revert_info :
526
+ reverted_commits [commit ["sha" ]] = revert_info
527
+ revert_messages .append (revert_info ["revert_message" ])
528
+
529
+ # Batch extract categories
530
+ if revert_messages :
531
+ message_to_category = self .extract_revert_categories_batch (revert_messages )
532
+
533
+ # Update revert info with categories
534
+ for _ , info in reverted_commits .items ():
535
+ info ["category" ] = message_to_category .get (
536
+ info ["revert_message" ], "uncategorized"
537
+ )
538
+
539
+ return reverted_commits
0 commit comments