1# Copyright 2020 The Chromium Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4# pylint: disable=too-many-lines 5 6from __future__ import print_function 7from __future__ import division 8from __future__ import absolute_import 9 10import datetime 11import json 12import uuid 13 14from google.appengine.ext import ndb 15 16from dashboard.common import namespaced_stored_object 17from dashboard.common import testing_common 18from dashboard.common import utils 19from dashboard.models import alert_group 20from dashboard.models import alert_group_workflow 21from dashboard.models import anomaly 22from dashboard.models import subscription 23 24_SERVICE_ACCOUNT_EMAIL = 'service-account@chromium.org' 25 26 27class AlertGroupWorkflowTest(testing_common.TestCase): 28 29 def setUp(self): 30 super(AlertGroupWorkflowTest, self).setUp() 31 self.maxDiff = None 32 self._issue_tracker = testing_common.FakeIssueTrackerService() 33 self._sheriff_config = testing_common.FakeSheriffConfigClient() 34 self._pinpoint = testing_common.FakePinpoint() 35 self._crrev = testing_common.FakeCrrev() 36 self._gitiles = testing_common.FakeGitiles() 37 self._revision_info = testing_common.FakeRevisionInfoClient( 38 infos={ 39 'r_chromium_commit_pos': { 40 'name': 41 'Chromium Commit Position', 42 'url': 43 'http://test-results.appspot.com/revision_range?start={{R1}}&end={{R2}}', 44 }, 45 }, 46 revisions={ 47 'master/bot/test_suite/measurement/test_case': { 48 0: { 49 'r_chromium_commit_pos': '0' 50 }, 51 100: { 52 'r_chromium_commit_pos': '100' 53 }, 54 } 55 }) 56 self._service_account = lambda: _SERVICE_ACCOUNT_EMAIL 57 58 @staticmethod 59 def _AddAnomaly(**kwargs): 60 default = { 61 'test': 'master/bot/test_suite/measurement/test_case', 62 'start_revision': 1, 63 'end_revision': 100, 64 'is_improvement': False, 65 'median_before_anomaly': 1.1, 66 'median_after_anomaly': 1.3, 67 'ownership': { 68 'component': 'Foo>Bar', 69 'emails': ['x@google.com', 'y@google.com'], 70 'info_blurb': 'This is an info blurb.', 71 }, 72 } 73 default.update(kwargs) 74 75 tests = default['test'].split('/') 76 77 def GenerateTestDict(tests): 78 if not tests: 79 return {} 80 return {tests[0]: GenerateTestDict(tests[1:])} 81 82 testing_common.AddTests([tests[0]], [tests[1]], GenerateTestDict(tests[2:])) 83 default['test'] = utils.TestKey(default['test']) 84 85 return anomaly.Anomaly(**default).put() 86 87 @staticmethod 88 def _AddAlertGroup(anomaly_key, 89 subscription_name=None, 90 issue=None, 91 anomalies=None, 92 status=None, 93 project_id=None, 94 bisection_ids=None): 95 anomaly_entity = anomaly_key.get() 96 group = alert_group.AlertGroup( 97 id=str(uuid.uuid4()), 98 name=anomaly_entity.benchmark_name, 99 subscription_name=subscription_name or 'sheriff', 100 status=alert_group.AlertGroup.Status.untriaged, 101 project_id=project_id or 'chromium', 102 active=True, 103 revision=alert_group.RevisionRange( 104 repository='chromium', 105 start=anomaly_entity.start_revision, 106 end=anomaly_entity.end_revision, 107 ), 108 bisection_ids=bisection_ids or [], 109 ) 110 if issue: 111 group.bug = alert_group.BugInfo( 112 bug_id=issue.get('id'), 113 project=issue.get('projectId', 'chromium'), 114 ) 115 group.project_id = issue.get('projectId', 'chromium') 116 if anomalies: 117 group.anomalies = anomalies 118 if status: 119 group.status = status 120 return group.put() 121 122 def testAddAnomalies_GroupUntriaged(self): 123 anomalies = [self._AddAnomaly(), self._AddAnomaly()] 124 added = [self._AddAnomaly(), self._AddAnomaly()] 125 group = self._AddAlertGroup(anomalies[0], anomalies=anomalies) 126 self._sheriff_config.patterns = { 127 '*': [subscription.Subscription(name='sheriff')], 128 } 129 w = alert_group_workflow.AlertGroupWorkflow( 130 group.get(), 131 sheriff_config=self._sheriff_config, 132 issue_tracker=self._issue_tracker, 133 ) 134 w.Process( 135 update=alert_group_workflow.AlertGroupWorkflow.GroupUpdate( 136 now=datetime.datetime.utcnow(), 137 anomalies=ndb.get_multi(anomalies + added), 138 issue={}, 139 )) 140 141 self.assertEqual(len(group.get().anomalies), 4) 142 for a in added: 143 self.assertIn(a, group.get().anomalies) 144 145 def testAddAnomalies_GroupTriaged_IssueOpen(self): 146 anomalies = [self._AddAnomaly(), self._AddAnomaly()] 147 added = [self._AddAnomaly(), self._AddAnomaly()] 148 group = self._AddAlertGroup( 149 anomalies[0], 150 issue=self._issue_tracker.issue, 151 anomalies=anomalies, 152 status=alert_group.AlertGroup.Status.triaged, 153 ) 154 self._issue_tracker.issue.update({ 155 'state': 'open', 156 }) 157 self._sheriff_config.patterns = { 158 '*': [ 159 subscription.Subscription(name='sheriff', auto_triage_enable=True) 160 ], 161 } 162 w = alert_group_workflow.AlertGroupWorkflow( 163 group.get(), 164 sheriff_config=self._sheriff_config, 165 issue_tracker=self._issue_tracker, 166 ) 167 w.Process( 168 update=alert_group_workflow.AlertGroupWorkflow.GroupUpdate( 169 now=datetime.datetime.utcnow(), 170 anomalies=ndb.get_multi(anomalies + added), 171 issue=self._issue_tracker.issue, 172 )) 173 174 self.assertEqual(len(group.get().anomalies), 4) 175 self.assertEqual(group.get().status, alert_group.AlertGroup.Status.triaged) 176 for a in added: 177 self.assertIn(a, group.get().anomalies) 178 self.assertEqual(group.get().bug.bug_id, 179 self._issue_tracker.add_comment_args[0]) 180 self.assertIn('Added 2 regressions to the group', 181 self._issue_tracker.add_comment_args[1]) 182 self.assertIn('4 regressions in test_suite', 183 self._issue_tracker.add_comment_kwargs['summary']) 184 self.assertIn('sheriff', 185 self._issue_tracker.add_comment_kwargs['summary']) 186 self.assertFalse(self._issue_tracker.add_comment_kwargs['send_email']) 187 188 def testAddAnomalies_GroupTriaged_IssueClosed(self): 189 anomalies = [self._AddAnomaly(), self._AddAnomaly()] 190 added = [self._AddAnomaly(), self._AddAnomaly()] 191 group = self._AddAlertGroup( 192 anomalies[0], 193 issue=self._issue_tracker.issue, 194 anomalies=anomalies, 195 status=alert_group.AlertGroup.Status.closed, 196 ) 197 self._issue_tracker.issue.update({ 198 'state': 199 'closed', 200 'comments': [{ 201 'id': 1, 202 'author': _SERVICE_ACCOUNT_EMAIL, 203 'updates': { 204 'status': 'WontFix' 205 }, 206 }], 207 }) 208 self._sheriff_config.patterns = { 209 '*': [ 210 subscription.Subscription(name='sheriff', auto_triage_enable=True) 211 ], 212 } 213 w = alert_group_workflow.AlertGroupWorkflow( 214 group.get(), 215 sheriff_config=self._sheriff_config, 216 issue_tracker=self._issue_tracker, 217 service_account=self._service_account, 218 ) 219 w.Process( 220 update=alert_group_workflow.AlertGroupWorkflow.GroupUpdate( 221 now=datetime.datetime.utcnow(), 222 anomalies=ndb.get_multi(anomalies + added), 223 issue=self._issue_tracker.issue, 224 )) 225 226 self.assertEqual(len(group.get().anomalies), 4) 227 self.assertEqual('closed', self._issue_tracker.issue.get('state')) 228 for a in added: 229 self.assertIn(a, group.get().anomalies) 230 self.assertEqual(group.get().bug.bug_id, 231 self._issue_tracker.add_comment_args[0]) 232 self.assertIn('Added 2 regressions to the group', 233 self._issue_tracker.add_comment_args[1]) 234 self.assertIn('4 regressions in test_suite', 235 self._issue_tracker.add_comment_kwargs['summary']) 236 self.assertIn('sheriff', 237 self._issue_tracker.add_comment_kwargs['summary']) 238 self.assertFalse(self._issue_tracker.add_comment_kwargs['send_email']) 239 240 def testAddAnomalies_GroupTriaged_IssueClosed_AutoBisect(self): 241 anomalies = [self._AddAnomaly(), self._AddAnomaly()] 242 added = [self._AddAnomaly(), self._AddAnomaly()] 243 group = self._AddAlertGroup( 244 anomalies[0], 245 issue=self._issue_tracker.issue, 246 anomalies=anomalies, 247 status=alert_group.AlertGroup.Status.closed, 248 ) 249 self._issue_tracker.issue.update({ 250 'state': 251 'closed', 252 'comments': [{ 253 'id': 1, 254 'author': _SERVICE_ACCOUNT_EMAIL, 255 'updates': { 256 'status': 'WontFix' 257 }, 258 }], 259 }) 260 self._sheriff_config.patterns = { 261 '*': [ 262 subscription.Subscription( 263 name='sheriff', 264 auto_triage_enable=True, 265 auto_bisect_enable=True) 266 ], 267 } 268 w = alert_group_workflow.AlertGroupWorkflow( 269 group.get(), 270 sheriff_config=self._sheriff_config, 271 issue_tracker=self._issue_tracker, 272 service_account=self._service_account, 273 ) 274 w.Process( 275 update=alert_group_workflow.AlertGroupWorkflow.GroupUpdate( 276 now=datetime.datetime.utcnow(), 277 anomalies=ndb.get_multi(anomalies + added), 278 issue=self._issue_tracker.issue, 279 )) 280 281 self.assertEqual(len(group.get().anomalies), 4) 282 self.assertEqual('open', self._issue_tracker.issue.get('state')) 283 for a in added: 284 self.assertIn(a, group.get().anomalies) 285 self.assertEqual(group.get().bug.bug_id, 286 self._issue_tracker.add_comment_args[0]) 287 self.assertIn('Added 2 regressions to the group', 288 self._issue_tracker.add_comment_args[1]) 289 self.assertFalse(self._issue_tracker.add_comment_kwargs['send_email']) 290 291 def testUpdate_GroupTriaged_IssueClosed(self): 292 anomalies = [self._AddAnomaly(), self._AddAnomaly()] 293 group = self._AddAlertGroup( 294 anomalies[0], 295 issue=self._issue_tracker.issue, 296 status=alert_group.AlertGroup.Status.triaged, 297 ) 298 self._issue_tracker.issue.update({ 299 'state': 300 'closed', 301 'comments': [{ 302 'id': 1, 303 'author': _SERVICE_ACCOUNT_EMAIL, 304 'updates': { 305 'status': 'WontFix' 306 }, 307 }], 308 }) 309 self._sheriff_config.patterns = { 310 '*': [ 311 subscription.Subscription(name='sheriff', auto_triage_enable=True) 312 ], 313 } 314 w = alert_group_workflow.AlertGroupWorkflow( 315 group.get(), 316 sheriff_config=self._sheriff_config, 317 issue_tracker=self._issue_tracker, 318 service_account=self._service_account, 319 ) 320 w.Process( 321 update=alert_group_workflow.AlertGroupWorkflow.GroupUpdate( 322 now=datetime.datetime.utcnow(), 323 anomalies=ndb.get_multi(anomalies), 324 issue=self._issue_tracker.issue, 325 )) 326 self.assertEqual(group.get().status, alert_group.AlertGroup.Status.closed) 327 328 def testAddAnomalies_GroupTriaged_IssueClosed_Manual(self): 329 anomalies = [self._AddAnomaly(), self._AddAnomaly()] 330 added = [self._AddAnomaly(), self._AddAnomaly()] 331 group = self._AddAlertGroup( 332 anomalies[0], 333 issue=self._issue_tracker.issue, 334 anomalies=anomalies, 335 status=alert_group.AlertGroup.Status.closed, 336 ) 337 self._issue_tracker.issue.update({ 338 'state': 339 'closed', 340 'comments': [{ 341 'id': 2, 342 'author': "sheriff@chromium.org", 343 'updates': { 344 'status': 'WontFix' 345 }, 346 }, { 347 'id': 1, 348 'author': _SERVICE_ACCOUNT_EMAIL, 349 'updates': { 350 'status': 'WontFix' 351 }, 352 }], 353 }) 354 self._sheriff_config.patterns = { 355 '*': [ 356 subscription.Subscription( 357 name='sheriff', 358 auto_triage_enable=True, 359 auto_bisect_enable=True) 360 ], 361 } 362 w = alert_group_workflow.AlertGroupWorkflow( 363 group.get(), 364 sheriff_config=self._sheriff_config, 365 issue_tracker=self._issue_tracker, 366 service_account=self._service_account, 367 ) 368 w.Process( 369 update=alert_group_workflow.AlertGroupWorkflow.GroupUpdate( 370 now=datetime.datetime.utcnow(), 371 anomalies=ndb.get_multi(anomalies + added), 372 issue=self._issue_tracker.issue, 373 )) 374 375 self.assertEqual(len(group.get().anomalies), 4) 376 self.assertEqual('closed', self._issue_tracker.issue.get('state')) 377 for a in added: 378 self.assertIn(a, group.get().anomalies) 379 self.assertEqual(group.get().bug.bug_id, 380 self._issue_tracker.add_comment_args[0]) 381 self.assertIn('Added 2 regressions to the group', 382 self._issue_tracker.add_comment_args[1]) 383 self.assertFalse(self._issue_tracker.add_comment_kwargs['send_email']) 384 385 def testUpdate_GroupTriaged_IssueClosed_AllTriaged(self): 386 anomalies = [ 387 self._AddAnomaly(recovered=True), 388 self._AddAnomaly(recovered=True) 389 ] 390 group = self._AddAlertGroup( 391 anomalies[0], 392 issue=self._issue_tracker.issue, 393 anomalies=anomalies, 394 status=alert_group.AlertGroup.Status.triaged, 395 ) 396 self._issue_tracker.issue.update({ 397 'state': 398 'closed', 399 'comments': [{ 400 'id': 1, 401 'author': _SERVICE_ACCOUNT_EMAIL, 402 'updates': { 403 'status': 'WontFix' 404 }, 405 }], 406 }) 407 self._sheriff_config.patterns = { 408 '*': [ 409 subscription.Subscription(name='sheriff', auto_triage_enable=True) 410 ], 411 } 412 w = alert_group_workflow.AlertGroupWorkflow( 413 group.get(), 414 sheriff_config=self._sheriff_config, 415 issue_tracker=self._issue_tracker, 416 service_account=self._service_account, 417 ) 418 w.Process( 419 update=alert_group_workflow.AlertGroupWorkflow.GroupUpdate( 420 now=datetime.datetime.utcnow(), 421 anomalies=ndb.get_multi(anomalies), 422 issue=self._issue_tracker.issue, 423 )) 424 self.assertEqual(group.get().status, alert_group.AlertGroup.Status.closed) 425 self.assertIsNone(self._issue_tracker.add_comment_args) 426 427 def testAddAnomalies_GroupTriaged_CommentsNone(self): 428 anomalies = [self._AddAnomaly(), self._AddAnomaly()] 429 added = [self._AddAnomaly(), self._AddAnomaly()] 430 group = self._AddAlertGroup( 431 anomalies[0], 432 issue=self._issue_tracker.issue, 433 anomalies=anomalies, 434 status=alert_group.AlertGroup.Status.closed, 435 ) 436 self._issue_tracker.issue.update({ 437 'state': 'closed', 438 'comments': None, 439 }) 440 self._sheriff_config.patterns = { 441 '*': [ 442 subscription.Subscription( 443 name='sheriff', 444 auto_triage_enable=True, 445 auto_bisect_enable=True) 446 ], 447 } 448 w = alert_group_workflow.AlertGroupWorkflow( 449 group.get(), 450 sheriff_config=self._sheriff_config, 451 issue_tracker=self._issue_tracker, 452 service_account=self._service_account, 453 ) 454 w.Process( 455 update=alert_group_workflow.AlertGroupWorkflow.GroupUpdate( 456 now=datetime.datetime.utcnow(), 457 anomalies=ndb.get_multi(anomalies + added), 458 issue=self._issue_tracker.issue, 459 )) 460 461 self.assertEqual(len(group.get().anomalies), 4) 462 self.assertEqual('closed', self._issue_tracker.issue.get('state')) 463 for a in added: 464 self.assertIn(a, group.get().anomalies) 465 self.assertEqual(group.get().bug.bug_id, 466 self._issue_tracker.add_comment_args[0]) 467 self.assertIn('Added 2 regressions to the group', 468 self._issue_tracker.add_comment_args[1]) 469 self.assertFalse(self._issue_tracker.add_comment_kwargs['send_email']) 470 471 def testUpdate_GroupClosed_IssueOpen(self): 472 anomalies = [self._AddAnomaly(), self._AddAnomaly()] 473 group = self._AddAlertGroup( 474 anomalies[0], 475 issue=self._issue_tracker.issue, 476 status=alert_group.AlertGroup.Status.closed, 477 ) 478 self._issue_tracker.issue.update({ 479 'state': 'open', 480 }) 481 self._sheriff_config.patterns = { 482 '*': [ 483 subscription.Subscription(name='sheriff', auto_triage_enable=True) 484 ], 485 } 486 w = alert_group_workflow.AlertGroupWorkflow( 487 group.get(), 488 sheriff_config=self._sheriff_config, 489 issue_tracker=self._issue_tracker, 490 ) 491 w.Process( 492 update=alert_group_workflow.AlertGroupWorkflow.GroupUpdate( 493 now=datetime.datetime.utcnow(), 494 anomalies=ndb.get_multi(anomalies), 495 issue=self._issue_tracker.issue, 496 )) 497 498 self.assertEqual(group.get().status, alert_group.AlertGroup.Status.triaged) 499 500 def testUpdate_GroupTriaged_AlertsAllRecovered(self): 501 anomalies = [ 502 self._AddAnomaly(recovered=True), 503 self._AddAnomaly(recovered=True), 504 ] 505 group = self._AddAlertGroup( 506 anomalies[0], 507 issue=self._issue_tracker.issue, 508 status=alert_group.AlertGroup.Status.triaged, 509 ) 510 self._issue_tracker.issue.update({ 511 'state': 'open', 512 }) 513 self._sheriff_config.patterns = { 514 '*': [ 515 subscription.Subscription(name='sheriff', auto_triage_enable=True) 516 ], 517 } 518 w = alert_group_workflow.AlertGroupWorkflow( 519 group.get(), 520 sheriff_config=self._sheriff_config, 521 issue_tracker=self._issue_tracker, 522 ) 523 w.Process( 524 update=alert_group_workflow.AlertGroupWorkflow.GroupUpdate( 525 now=datetime.datetime.utcnow(), 526 anomalies=ndb.get_multi(anomalies), 527 issue=self._issue_tracker.issue, 528 )) 529 530 self.assertEqual('closed', self._issue_tracker.issue.get('state')) 531 532 def testUpdate_GroupTriaged_AlertsPartRecovered(self): 533 anomalies = [self._AddAnomaly(recovered=True), self._AddAnomaly()] 534 group = self._AddAlertGroup( 535 anomalies[0], 536 issue=self._issue_tracker.issue, 537 status=alert_group.AlertGroup.Status.triaged, 538 ) 539 self._issue_tracker.issue.update({ 540 'state': 'open', 541 }) 542 self._sheriff_config.patterns = { 543 '*': [ 544 subscription.Subscription(name='sheriff', auto_triage_enable=True) 545 ], 546 } 547 w = alert_group_workflow.AlertGroupWorkflow( 548 group.get(), 549 sheriff_config=self._sheriff_config, 550 issue_tracker=self._issue_tracker, 551 ) 552 w.Process( 553 update=alert_group_workflow.AlertGroupWorkflow.GroupUpdate( 554 now=datetime.datetime.utcnow(), 555 anomalies=ndb.get_multi(anomalies), 556 issue=self._issue_tracker.issue, 557 )) 558 559 self.assertEqual('open', self._issue_tracker.issue.get('state')) 560 561 def testTriage_GroupUntriaged(self): 562 anomalies = [self._AddAnomaly(), self._AddAnomaly()] 563 group = self._AddAlertGroup( 564 anomalies[0], 565 status=alert_group.AlertGroup.Status.untriaged, 566 ) 567 self._sheriff_config.patterns = { 568 '*': [ 569 subscription.Subscription(name='sheriff', auto_triage_enable=True) 570 ], 571 } 572 w = alert_group_workflow.AlertGroupWorkflow( 573 group.get(), 574 sheriff_config=self._sheriff_config, 575 issue_tracker=self._issue_tracker, 576 revision_info=self._revision_info, 577 config=alert_group_workflow.AlertGroupWorkflow.Config( 578 active_window=datetime.timedelta(days=7), 579 triage_delay=datetime.timedelta(hours=0), 580 ), 581 ) 582 w.Process( 583 update=alert_group_workflow.AlertGroupWorkflow.GroupUpdate( 584 now=datetime.datetime.utcnow(), 585 anomalies=ndb.get_multi(anomalies), 586 issue=None, 587 )) 588 self.assertIn('2 regressions', self._issue_tracker.new_bug_args[0]) 589 self.assertIn( 590 'Chromium Commit Position: http://test-results.appspot.com/revision_range?start=0&end=100', 591 self._issue_tracker.new_bug_args[1]) 592 593 def testTriage_GroupUntriaged_MultiSubscriptions(self): 594 anomalies = [self._AddAnomaly(), self._AddAnomaly()] 595 group = self._AddAlertGroup( 596 anomalies[0], 597 status=alert_group.AlertGroup.Status.untriaged, 598 ) 599 self._sheriff_config.patterns = { 600 '*': [ 601 subscription.Subscription(name='sheriff'), 602 subscription.Subscription( 603 name='sheriff_not_bind', auto_triage_enable=True) 604 ], 605 } 606 w = alert_group_workflow.AlertGroupWorkflow( 607 group.get(), 608 sheriff_config=self._sheriff_config, 609 issue_tracker=self._issue_tracker, 610 revision_info=self._revision_info, 611 config=alert_group_workflow.AlertGroupWorkflow.Config( 612 active_window=datetime.timedelta(days=7), 613 triage_delay=datetime.timedelta(hours=0), 614 ), 615 ) 616 w.Process( 617 update=alert_group_workflow.AlertGroupWorkflow.GroupUpdate( 618 now=datetime.datetime.utcnow(), 619 anomalies=ndb.get_multi(anomalies), 620 issue=None, 621 )) 622 self.assertIsNone(self._issue_tracker.new_bug_args) 623 624 def testTriage_GroupUntriaged_NonChromiumProject(self): 625 anomalies = [self._AddAnomaly()] 626 # TODO(dberris): Figure out a way to not have to hack the fake service to 627 # seed it with the correct issue in the correct project. 628 self._issue_tracker.issues[( 629 'v8', self._issue_tracker.bug_id)] = self._issue_tracker.issues[( 630 'chromium', self._issue_tracker.bug_id)] 631 del self._issue_tracker.issues[('chromium', self._issue_tracker.bug_id)] 632 self._issue_tracker.issues[('v8', self._issue_tracker.bug_id)].update({ 633 'projectId': 'v8', 634 }) 635 group = self._AddAlertGroup( 636 anomalies[0], 637 status=alert_group.AlertGroup.Status.untriaged, 638 project_id='v8') 639 self._sheriff_config.patterns = { 640 '*': [ 641 subscription.Subscription( 642 name='sheriff', 643 auto_triage_enable=True, 644 monorail_project_id='v8') 645 ], 646 } 647 self.assertEqual(group.get().project_id, 'v8') 648 w = alert_group_workflow.AlertGroupWorkflow( 649 group.get(), 650 sheriff_config=self._sheriff_config, 651 issue_tracker=self._issue_tracker, 652 revision_info=self._revision_info, 653 config=alert_group_workflow.AlertGroupWorkflow.Config( 654 active_window=datetime.timedelta(days=7), 655 triage_delay=datetime.timedelta(hours=0), 656 )) 657 w.Process( 658 update=alert_group_workflow.AlertGroupWorkflow.GroupUpdate( 659 now=datetime.datetime.utcnow(), 660 anomalies=ndb.get_multi(anomalies), 661 issue=None)) 662 self.assertEqual(group.get().bug.project, 'v8') 663 self.assertEqual(anomalies[0].get().project_id, 'v8') 664 665 def testTriage_GroupUntriaged_MultipleRange(self): 666 anomalies = [ 667 self._AddAnomaly(median_before_anomaly=0.2, start_revision=10), 668 self._AddAnomaly(median_before_anomaly=0.1) 669 ] 670 group = self._AddAlertGroup( 671 anomalies[0], 672 status=alert_group.AlertGroup.Status.untriaged, 673 ) 674 self._sheriff_config.patterns = { 675 '*': [ 676 subscription.Subscription(name='sheriff', auto_triage_enable=True) 677 ], 678 } 679 w = alert_group_workflow.AlertGroupWorkflow( 680 group.get(), 681 sheriff_config=self._sheriff_config, 682 issue_tracker=self._issue_tracker, 683 revision_info=self._revision_info, 684 config=alert_group_workflow.AlertGroupWorkflow.Config( 685 active_window=datetime.timedelta(days=7), 686 triage_delay=datetime.timedelta(hours=0), 687 ), 688 ) 689 w.Process( 690 update=alert_group_workflow.AlertGroupWorkflow.GroupUpdate( 691 now=datetime.datetime.utcnow(), 692 anomalies=ndb.get_multi(anomalies), 693 issue=None, 694 )) 695 self.assertIn('2 regressions', self._issue_tracker.new_bug_args[0]) 696 self.assertIn( 697 'Chromium Commit Position: http://test-results.appspot.com/revision_range?start=0&end=100', 698 self._issue_tracker.new_bug_args[1]) 699 700 def testTriage_GroupUntriaged_InfAnomaly(self): 701 anomalies = [self._AddAnomaly(median_before_anomaly=0), self._AddAnomaly()] 702 group = self._AddAlertGroup( 703 anomalies[0], 704 status=alert_group.AlertGroup.Status.untriaged, 705 ) 706 self._sheriff_config.patterns = { 707 '*': [ 708 subscription.Subscription(name='sheriff', auto_triage_enable=True) 709 ], 710 } 711 w = alert_group_workflow.AlertGroupWorkflow( 712 group.get(), 713 sheriff_config=self._sheriff_config, 714 issue_tracker=self._issue_tracker, 715 revision_info=self._revision_info, 716 config=alert_group_workflow.AlertGroupWorkflow.Config( 717 active_window=datetime.timedelta(days=7), 718 triage_delay=datetime.timedelta(hours=0), 719 ), 720 ) 721 w.Process( 722 update=alert_group_workflow.AlertGroupWorkflow.GroupUpdate( 723 now=datetime.datetime.utcnow(), 724 anomalies=ndb.get_multi(anomalies), 725 issue=None, 726 )) 727 self.assertIn('inf', self._issue_tracker.new_bug_args[1]) 728 729 def testTriage_GroupTriaged_InfAnomaly(self): 730 anomalies = [self._AddAnomaly(median_before_anomaly=0), self._AddAnomaly()] 731 group = self._AddAlertGroup( 732 anomalies[0], 733 issue=self._issue_tracker.issue, 734 status=alert_group.AlertGroup.Status.triaged, 735 ) 736 self._sheriff_config.patterns = { 737 '*': [ 738 subscription.Subscription(name='sheriff', auto_triage_enable=True) 739 ], 740 } 741 w = alert_group_workflow.AlertGroupWorkflow( 742 group.get(), 743 sheriff_config=self._sheriff_config, 744 issue_tracker=self._issue_tracker, 745 ) 746 w.Process( 747 update=alert_group_workflow.AlertGroupWorkflow.GroupUpdate( 748 now=datetime.datetime.utcnow(), 749 anomalies=ndb.get_multi(anomalies), 750 issue=self._issue_tracker.issue, 751 )) 752 self.assertIn('inf', self._issue_tracker.add_comment_args[1]) 753 self.assertFalse(self._issue_tracker.add_comment_kwargs['send_email']) 754 755 def testArchive_GroupUntriaged(self): 756 anomalies = [self._AddAnomaly(), self._AddAnomaly()] 757 group = self._AddAlertGroup( 758 anomalies[0], 759 anomalies=anomalies, 760 status=alert_group.AlertGroup.Status.untriaged, 761 ) 762 self._sheriff_config.patterns = { 763 '*': [subscription.Subscription(name='sheriff')], 764 } 765 w = alert_group_workflow.AlertGroupWorkflow( 766 group.get(), 767 sheriff_config=self._sheriff_config, 768 issue_tracker=self._issue_tracker, 769 config=alert_group_workflow.AlertGroupWorkflow.Config( 770 active_window=datetime.timedelta(days=0), 771 triage_delay=datetime.timedelta(hours=0), 772 ), 773 ) 774 w.Process( 775 update=alert_group_workflow.AlertGroupWorkflow.GroupUpdate( 776 now=datetime.datetime.utcnow(), 777 anomalies=ndb.get_multi(anomalies), 778 issue=None, 779 )) 780 self.assertEqual(False, group.get().active) 781 782 def testArchive_GroupTriaged(self): 783 anomalies = [self._AddAnomaly(), self._AddAnomaly()] 784 group = self._AddAlertGroup( 785 anomalies[0], 786 anomalies=anomalies, 787 issue=self._issue_tracker.issue, 788 status=alert_group.AlertGroup.Status.triaged, 789 ) 790 self._issue_tracker.issue.update({ 791 'state': 'open', 792 }) 793 self._sheriff_config.patterns = { 794 '*': [ 795 subscription.Subscription(name='sheriff', auto_triage_enable=True) 796 ], 797 } 798 w = alert_group_workflow.AlertGroupWorkflow( 799 group.get(), 800 sheriff_config=self._sheriff_config, 801 issue_tracker=self._issue_tracker, 802 config=alert_group_workflow.AlertGroupWorkflow.Config( 803 active_window=datetime.timedelta(days=0), 804 triage_delay=datetime.timedelta(hours=0), 805 ), 806 ) 807 w.Process( 808 update=alert_group_workflow.AlertGroupWorkflow.GroupUpdate( 809 now=datetime.datetime.utcnow(), 810 anomalies=ndb.get_multi(anomalies), 811 issue=self._issue_tracker.issue, 812 )) 813 self.assertEqual(True, group.get().active) 814 815 def testBisect_GroupTriaged(self): 816 anomalies = [ 817 self._AddAnomaly(median_before_anomaly=0.2), 818 self._AddAnomaly(median_before_anomaly=0.1), 819 ] 820 group = self._AddAlertGroup( 821 anomalies[0], 822 issue=self._issue_tracker.issue, 823 status=alert_group.AlertGroup.Status.triaged, 824 ) 825 self._issue_tracker.issue.update({ 826 'state': 'open', 827 }) 828 self._sheriff_config.patterns = { 829 '*': [ 830 subscription.Subscription( 831 name='sheriff', 832 auto_triage_enable=True, 833 auto_bisect_enable=True) 834 ], 835 } 836 w = alert_group_workflow.AlertGroupWorkflow( 837 group.get(), 838 sheriff_config=self._sheriff_config, 839 issue_tracker=self._issue_tracker, 840 pinpoint=self._pinpoint, 841 crrev=self._crrev, 842 ) 843 w.Process( 844 update=alert_group_workflow.AlertGroupWorkflow.GroupUpdate( 845 now=datetime.datetime.utcnow(), 846 anomalies=ndb.get_multi(anomalies), 847 issue=self._issue_tracker.issue, 848 )) 849 tags = json.loads(self._pinpoint.new_job_request['tags']) 850 self.assertEqual(anomalies[1].urlsafe(), tags['alert']) 851 852 # Tags must be a dict of key/value string pairs. 853 for k, v in tags.items(): 854 self.assertIsInstance(k, basestring) 855 self.assertIsInstance(v, basestring) 856 857 self.assertEqual(['123456'], group.get().bisection_ids) 858 self.assertEqual(['Chromeperf-Auto-Bisected'], 859 self._issue_tracker.add_comment_kwargs['labels']) 860 861 def testBisect_GroupTriaged_MultiSubscriptions(self): 862 anomalies = [ 863 self._AddAnomaly(median_before_anomaly=0.2), 864 self._AddAnomaly(median_before_anomaly=0.1), 865 ] 866 group = self._AddAlertGroup( 867 anomalies[0], 868 issue=self._issue_tracker.issue, 869 status=alert_group.AlertGroup.Status.triaged, 870 ) 871 self._issue_tracker.issue.update({ 872 'state': 'open', 873 }) 874 self._sheriff_config.patterns = { 875 '*': [ 876 subscription.Subscription(name='sheriff'), 877 subscription.Subscription( 878 name='sheriff_not_bind', 879 auto_triage_enable=True, 880 auto_bisect_enable=True) 881 ], 882 } 883 w = alert_group_workflow.AlertGroupWorkflow( 884 group.get(), 885 sheriff_config=self._sheriff_config, 886 issue_tracker=self._issue_tracker, 887 pinpoint=self._pinpoint, 888 crrev=self._crrev, 889 ) 890 w.Process( 891 update=alert_group_workflow.AlertGroupWorkflow.GroupUpdate( 892 now=datetime.datetime.utcnow(), 893 anomalies=ndb.get_multi(anomalies), 894 issue=self._issue_tracker.issue, 895 )) 896 self.assertIsNone(self._pinpoint.new_job_request) 897 898 def testBisect_GroupBisected(self): 899 anomalies = [self._AddAnomaly(), self._AddAnomaly()] 900 group = self._AddAlertGroup( 901 anomalies[0], 902 issue=self._issue_tracker.issue, 903 status=alert_group.AlertGroup.Status.bisected, 904 ) 905 self._issue_tracker.issue.update({ 906 'state': 'open', 907 }) 908 self._sheriff_config.patterns = { 909 '*': [ 910 subscription.Subscription( 911 name='sheriff', 912 auto_triage_enable=True, 913 auto_bisect_enable=True) 914 ], 915 } 916 w = alert_group_workflow.AlertGroupWorkflow( 917 group.get(), 918 sheriff_config=self._sheriff_config, 919 issue_tracker=self._issue_tracker, 920 pinpoint=self._pinpoint, 921 crrev=self._crrev, 922 ) 923 w.Process( 924 update=alert_group_workflow.AlertGroupWorkflow.GroupUpdate( 925 now=datetime.datetime.utcnow(), 926 anomalies=ndb.get_multi(anomalies), 927 issue=self._issue_tracker.issue, 928 )) 929 self.assertIsNone(self._pinpoint.new_job_request) 930 931 def testBisect_GroupTriaged_NoRecovered(self): 932 anomalies = [ 933 self._AddAnomaly( 934 median_before_anomaly=0.1, median_after_anomaly=1.0, 935 recovered=True), 936 self._AddAnomaly(median_before_anomaly=0.2, median_after_anomaly=1.0), 937 ] 938 group = self._AddAlertGroup( 939 anomalies[1], 940 issue=self._issue_tracker.issue, 941 status=alert_group.AlertGroup.Status.triaged, 942 anomalies=anomalies, 943 ) 944 self._issue_tracker.issue.update({ 945 'state': 'open', 946 }) 947 self._sheriff_config.patterns = { 948 '*': [ 949 subscription.Subscription( 950 name='sheriff', 951 auto_triage_enable=True, 952 auto_bisect_enable=True) 953 ], 954 } 955 w = alert_group_workflow.AlertGroupWorkflow( 956 group.get(), 957 sheriff_config=self._sheriff_config, 958 issue_tracker=self._issue_tracker, 959 pinpoint=self._pinpoint, 960 crrev=self._crrev, 961 ) 962 w.Process( 963 update=alert_group_workflow.AlertGroupWorkflow.GroupUpdate( 964 now=datetime.datetime.utcnow(), 965 anomalies=ndb.get_multi(anomalies), 966 issue=self._issue_tracker.issue, 967 )) 968 self.assertIsNotNone(self._pinpoint.new_job_request) 969 self.assertEqual(group.get().status, alert_group.AlertGroup.Status.bisected) 970 971 # Check that we bisected the anomaly that is not recovered. 972 recovered_anomaly = anomalies[0].get() 973 bisected_anomaly = anomalies[1].get() 974 self.assertNotEqual(recovered_anomaly.pinpoint_bisects, ['123456']) 975 self.assertEqual(bisected_anomaly.pinpoint_bisects, ['123456']) 976 977 def testBisect_GroupTriaged_NoIgnored(self): 978 anomalies = [ 979 # This anomaly is manually ignored. 980 self._AddAnomaly( 981 median_before_anomaly=0.1, median_after_anomaly=1.0, bug_id=-2), 982 self._AddAnomaly( 983 median_before_anomaly=0.2, 984 median_after_anomaly=1.0, 985 start_revision=20), 986 ] 987 group = self._AddAlertGroup( 988 anomalies[1], 989 issue=self._issue_tracker.issue, 990 status=alert_group.AlertGroup.Status.triaged, 991 anomalies=anomalies, 992 ) 993 self._issue_tracker.issue.update({ 994 'state': 'open', 995 }) 996 self._sheriff_config.patterns = { 997 '*': [ 998 subscription.Subscription( 999 name='sheriff', 1000 auto_triage_enable=True, 1001 auto_bisect_enable=True) 1002 ], 1003 } 1004 w = alert_group_workflow.AlertGroupWorkflow( 1005 group.get(), 1006 sheriff_config=self._sheriff_config, 1007 issue_tracker=self._issue_tracker, 1008 pinpoint=self._pinpoint, 1009 crrev=self._crrev, 1010 ) 1011 w.Process( 1012 update=alert_group_workflow.AlertGroupWorkflow.GroupUpdate( 1013 now=datetime.datetime.utcnow(), 1014 anomalies=ndb.get_multi(anomalies), 1015 issue=self._issue_tracker.issue, 1016 )) 1017 self.assertIsNotNone(self._pinpoint.new_job_request) 1018 self.assertEqual(self._pinpoint.new_job_request['bug_id'], 12345) 1019 self.assertEqual(group.get().status, alert_group.AlertGroup.Status.bisected) 1020 1021 # Check that we bisected the anomaly that is not ignored. 1022 ignored_anomaly = anomalies[0].get() 1023 bisected_anomaly = anomalies[1].get() 1024 self.assertNotEqual(ignored_anomaly.pinpoint_bisects, ['123456']) 1025 self.assertEqual(bisected_anomaly.pinpoint_bisects, ['123456']) 1026 1027 def testBisect_GroupTriaged_AlertWithBug(self): 1028 anomalies = [ 1029 self._AddAnomaly(median_before_anomaly=0.2), 1030 self._AddAnomaly( 1031 median_before_anomaly=0.1, 1032 bug_id=12340, 1033 project_id='v8', 1034 ), 1035 ] 1036 group = self._AddAlertGroup( 1037 anomalies[0], 1038 issue=self._issue_tracker.issue, 1039 status=alert_group.AlertGroup.Status.triaged, 1040 ) 1041 self._issue_tracker.issue.update({ 1042 'state': 'open', 1043 }) 1044 self._sheriff_config.patterns = { 1045 '*': [ 1046 subscription.Subscription( 1047 name='sheriff', 1048 auto_triage_enable=True, 1049 auto_bisect_enable=True) 1050 ], 1051 } 1052 w = alert_group_workflow.AlertGroupWorkflow( 1053 group.get(), 1054 sheriff_config=self._sheriff_config, 1055 issue_tracker=self._issue_tracker, 1056 pinpoint=self._pinpoint, 1057 crrev=self._crrev, 1058 ) 1059 w.Process( 1060 update=alert_group_workflow.AlertGroupWorkflow.GroupUpdate( 1061 now=datetime.datetime.utcnow(), 1062 anomalies=ndb.get_multi(anomalies), 1063 issue=self._issue_tracker.issue, 1064 )) 1065 self.assertEqual(self._issue_tracker.bug_id, 1066 self._pinpoint.new_job_request['bug_id']) 1067 self.assertEqual('chromium', self._pinpoint.new_job_request['project']) 1068 self.assertEqual(['123456'], group.get().bisection_ids) 1069 1070 def testBisect_GroupTriaged_MultiBot(self): 1071 anomalies = [ 1072 self._AddAnomaly( 1073 test='master/bot1/test_suite/measurement/test_case1', 1074 median_before_anomaly=0.3, 1075 ), 1076 self._AddAnomaly( 1077 test='master/bot1/test_suite/measurement/test_case2', 1078 median_before_anomaly=0.2, 1079 ), 1080 self._AddAnomaly( 1081 test='master/bot2/test_suite/measurement/test_case2', 1082 median_before_anomaly=0.1, 1083 ), 1084 ] 1085 group = self._AddAlertGroup( 1086 anomalies[0], 1087 issue=self._issue_tracker.issue, 1088 status=alert_group.AlertGroup.Status.triaged, 1089 ) 1090 self._issue_tracker.issue.update({ 1091 'state': 'open', 1092 }) 1093 self._sheriff_config.patterns = { 1094 '*': [ 1095 subscription.Subscription( 1096 name='sheriff', 1097 auto_triage_enable=True, 1098 auto_bisect_enable=True) 1099 ], 1100 } 1101 w = alert_group_workflow.AlertGroupWorkflow( 1102 group.get(), 1103 sheriff_config=self._sheriff_config, 1104 issue_tracker=self._issue_tracker, 1105 pinpoint=self._pinpoint, 1106 crrev=self._crrev, 1107 ) 1108 w.Process( 1109 update=alert_group_workflow.AlertGroupWorkflow.GroupUpdate( 1110 now=datetime.datetime.utcnow(), 1111 anomalies=ndb.get_multi(anomalies), 1112 issue=self._issue_tracker.issue, 1113 )) 1114 self.assertEqual( 1115 anomalies[1].urlsafe(), 1116 json.loads(self._pinpoint.new_job_request['tags'])['alert']) 1117 self.assertEqual(['123456'], group.get().bisection_ids) 1118 1119 def testBisect_GroupTriaged_MultiBot_PartInf(self): 1120 anomalies = [ 1121 self._AddAnomaly( 1122 test='master/bot1/test_suite/measurement/test_case1', 1123 median_before_anomaly=0.0, 1124 ), 1125 self._AddAnomaly( 1126 test='master/bot1/test_suite/measurement/test_case2', 1127 median_before_anomaly=0.2, 1128 ), 1129 self._AddAnomaly( 1130 test='master/bot2/test_suite/measurement/test_case2', 1131 median_before_anomaly=0.1, 1132 ), 1133 ] 1134 group = self._AddAlertGroup( 1135 anomalies[0], 1136 issue=self._issue_tracker.issue, 1137 status=alert_group.AlertGroup.Status.triaged, 1138 ) 1139 self._issue_tracker.issue.update({ 1140 'state': 'open', 1141 }) 1142 self._sheriff_config.patterns = { 1143 '*': [ 1144 subscription.Subscription( 1145 name='sheriff', 1146 auto_triage_enable=True, 1147 auto_bisect_enable=True) 1148 ], 1149 } 1150 w = alert_group_workflow.AlertGroupWorkflow( 1151 group.get(), 1152 sheriff_config=self._sheriff_config, 1153 issue_tracker=self._issue_tracker, 1154 pinpoint=self._pinpoint, 1155 crrev=self._crrev, 1156 ) 1157 w.Process( 1158 update=alert_group_workflow.AlertGroupWorkflow.GroupUpdate( 1159 now=datetime.datetime.utcnow(), 1160 anomalies=ndb.get_multi(anomalies), 1161 issue=self._issue_tracker.issue, 1162 )) 1163 self.assertEqual( 1164 anomalies[1].urlsafe(), 1165 json.loads(self._pinpoint.new_job_request['tags'])['alert']) 1166 self.assertEqual(['123456'], group.get().bisection_ids) 1167 1168 def testBisect_GroupTriaged_MultiBot_AllInf(self): 1169 anomalies = [ 1170 self._AddAnomaly( 1171 test='master/bot1/test_suite/measurement/test_case1', 1172 median_before_anomaly=0.0, 1173 median_after_anomaly=1.0, 1174 ), 1175 self._AddAnomaly( 1176 test='master/bot1/test_suite/measurement/test_case2', 1177 median_before_anomaly=0.0, 1178 median_after_anomaly=2.0, 1179 ), 1180 self._AddAnomaly( 1181 test='master/bot2/test_suite/measurement/test_case2', 1182 median_before_anomaly=0.1, 1183 ), 1184 ] 1185 group = self._AddAlertGroup( 1186 anomalies[0], 1187 issue=self._issue_tracker.issue, 1188 status=alert_group.AlertGroup.Status.triaged, 1189 ) 1190 self._issue_tracker.issue.update({ 1191 'state': 'open', 1192 }) 1193 self._sheriff_config.patterns = { 1194 '*': [ 1195 subscription.Subscription( 1196 name='sheriff', 1197 auto_triage_enable=True, 1198 auto_bisect_enable=True) 1199 ], 1200 } 1201 w = alert_group_workflow.AlertGroupWorkflow( 1202 group.get(), 1203 sheriff_config=self._sheriff_config, 1204 issue_tracker=self._issue_tracker, 1205 pinpoint=self._pinpoint, 1206 crrev=self._crrev, 1207 ) 1208 w.Process( 1209 update=alert_group_workflow.AlertGroupWorkflow.GroupUpdate( 1210 now=datetime.datetime.utcnow(), 1211 anomalies=ndb.get_multi(anomalies), 1212 issue=self._issue_tracker.issue, 1213 )) 1214 self.assertEqual( 1215 anomalies[1].urlsafe(), 1216 json.loads(self._pinpoint.new_job_request['tags'])['alert']) 1217 self.assertEqual(['123456'], group.get().bisection_ids) 1218 1219 def testBisect_GroupTriaged_AlertBisected(self): 1220 anomalies = [ 1221 self._AddAnomaly( 1222 test='master/bot1/test_suite/measurement/test_case1', 1223 pinpoint_bisects=['abcdefg'], 1224 median_before_anomaly=0.2, 1225 ), 1226 self._AddAnomaly( 1227 test='master/bot1/test_suite/measurement/test_case2', 1228 pinpoint_bisects=['abcdef'], 1229 median_before_anomaly=0.1, 1230 ), 1231 ] 1232 group = self._AddAlertGroup( 1233 anomalies[0], 1234 issue=self._issue_tracker.issue, 1235 status=alert_group.AlertGroup.Status.triaged, 1236 bisection_ids=['abcdef'], 1237 ) 1238 self._issue_tracker.issue.update({ 1239 'state': 'open', 1240 }) 1241 self._sheriff_config.patterns = { 1242 '*': [ 1243 subscription.Subscription( 1244 name='sheriff', 1245 auto_triage_enable=True, 1246 auto_bisect_enable=True) 1247 ], 1248 } 1249 w = alert_group_workflow.AlertGroupWorkflow( 1250 group.get(), 1251 sheriff_config=self._sheriff_config, 1252 issue_tracker=self._issue_tracker, 1253 pinpoint=self._pinpoint, 1254 crrev=self._crrev, 1255 ) 1256 w.Process( 1257 update=alert_group_workflow.AlertGroupWorkflow.GroupUpdate( 1258 now=datetime.datetime.utcnow(), 1259 anomalies=ndb.get_multi(anomalies), 1260 issue=self._issue_tracker.issue, 1261 )) 1262 self.assertEqual( 1263 anomalies[0].urlsafe(), 1264 json.loads(self._pinpoint.new_job_request['tags'])['alert']) 1265 self.assertItemsEqual(['abcdef', '123456'], group.get().bisection_ids) 1266 1267 def testBisect_GroupTriaged_CrrevFailed(self): 1268 anomalies = [self._AddAnomaly(), self._AddAnomaly()] 1269 group = self._AddAlertGroup( 1270 anomalies[0], 1271 issue=self._issue_tracker.issue, 1272 status=alert_group.AlertGroup.Status.triaged, 1273 ) 1274 self._issue_tracker.issue.update({ 1275 'state': 'open', 1276 }) 1277 self._crrev.SetFailure() 1278 self._sheriff_config.patterns = { 1279 '*': [ 1280 subscription.Subscription( 1281 name='sheriff', 1282 auto_triage_enable=True, 1283 auto_bisect_enable=True) 1284 ], 1285 } 1286 w = alert_group_workflow.AlertGroupWorkflow( 1287 group.get(), 1288 sheriff_config=self._sheriff_config, 1289 issue_tracker=self._issue_tracker, 1290 pinpoint=self._pinpoint, 1291 crrev=self._crrev, 1292 ) 1293 w.Process( 1294 update=alert_group_workflow.AlertGroupWorkflow.GroupUpdate( 1295 now=datetime.datetime.utcnow(), 1296 anomalies=ndb.get_multi(anomalies), 1297 issue=self._issue_tracker.issue, 1298 )) 1299 self.assertEqual(alert_group.AlertGroup.Status.bisected, group.get().status) 1300 self.assertEqual([], group.get().bisection_ids) 1301 self.assertEqual(['Chromeperf-Auto-NeedsAttention'], 1302 self._issue_tracker.add_comment_kwargs['labels']) 1303 1304 def testBisect_GroupTriaged_PinpointFailed(self): 1305 anomalies = [self._AddAnomaly(), self._AddAnomaly()] 1306 group = self._AddAlertGroup( 1307 anomalies[0], 1308 issue=self._issue_tracker.issue, 1309 status=alert_group.AlertGroup.Status.triaged, 1310 ) 1311 self._issue_tracker.issue.update({ 1312 'state': 'open', 1313 }) 1314 self._pinpoint.SetFailure() 1315 self._sheriff_config.patterns = { 1316 '*': [ 1317 subscription.Subscription( 1318 name='sheriff', 1319 auto_triage_enable=True, 1320 auto_bisect_enable=True) 1321 ], 1322 } 1323 w = alert_group_workflow.AlertGroupWorkflow( 1324 group.get(), 1325 sheriff_config=self._sheriff_config, 1326 issue_tracker=self._issue_tracker, 1327 pinpoint=self._pinpoint, 1328 crrev=self._crrev, 1329 ) 1330 w.Process( 1331 update=alert_group_workflow.AlertGroupWorkflow.GroupUpdate( 1332 now=datetime.datetime.utcnow(), 1333 anomalies=ndb.get_multi(anomalies), 1334 issue=self._issue_tracker.issue, 1335 )) 1336 self.assertEqual(alert_group.AlertGroup.Status.bisected, group.get().status) 1337 self.assertEqual([], group.get().bisection_ids) 1338 self.assertEqual(['Chromeperf-Auto-NeedsAttention'], 1339 self._issue_tracker.add_comment_kwargs['labels']) 1340 1341 def testBisect_SingleCL(self): 1342 anomalies = [ 1343 self._AddAnomaly( 1344 # Current implementation requires that a revision string is between 1345 # 5 and 7 digits long. 1346 start_revision=11111, 1347 end_revision=11111, 1348 test='ChromiumPerf/some-bot/some-benchmark/some-metric/some-story') 1349 ] 1350 group = self._AddAlertGroup( 1351 anomalies[0], 1352 issue=self._issue_tracker.issue, 1353 status=alert_group.AlertGroup.Status.triaged) 1354 self._sheriff_config.patterns = { 1355 '*': [ 1356 subscription.Subscription( 1357 name='sheriff', 1358 auto_triage_enable=True, 1359 auto_bisect_enable=True) 1360 ] 1361 } 1362 # Here we are simulating that a gitiles service will respond to a specific 1363 # repository URL (the format is not important) and can map a commit (40 1364 # hexadecimal characters) to some commit information. 1365 self._gitiles._repo_commit_list.update({ 1366 'git://chromium': { 1367 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa': { 1368 'author': { 1369 'email': 'author@chromium.org', 1370 }, 1371 'message': 'This is some commit.\n\nWith some details.', 1372 } 1373 } 1374 }) 1375 1376 # We are also seeding some repository information to let us set which 1377 # repository URL is being used to look up data from a gitiles service. 1378 namespaced_stored_object.Set('repositories', { 1379 'chromium': { 1380 'repository_url': 'git://chromium' 1381 }, 1382 }) 1383 1384 # Current implementation requires that a git hash is 40 characters of 1385 # hexadecimal digits. 1386 self._crrev.SetSuccess('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa') 1387 w = alert_group_workflow.AlertGroupWorkflow( 1388 group.get(), 1389 sheriff_config=self._sheriff_config, 1390 issue_tracker=self._issue_tracker, 1391 pinpoint=self._pinpoint, 1392 crrev=self._crrev, 1393 gitiles=self._gitiles) 1394 w.Process( 1395 update=alert_group_workflow.AlertGroupWorkflow.GroupUpdate( 1396 now=datetime.datetime.utcnow(), 1397 anomalies=ndb.get_multi(anomalies), 1398 issue=self._issue_tracker.issue)) 1399 self.assertEqual(alert_group.AlertGroup.Status.bisected, group.get().status) 1400 self.assertEqual([], group.get().bisection_ids) 1401 self.assertEqual(['Chromeperf-Auto-Assigned'], 1402 self._issue_tracker.add_comment_kwargs['labels']) 1403 self.assertIn(('Assigning to author@chromium.org because this is the ' 1404 'only CL in range:'), 1405 self._issue_tracker.add_comment_args[1]) 1406 1407 def testBisect_ExplicitOptOut(self): 1408 anomalies = [self._AddAnomaly(), self._AddAnomaly()] 1409 group = self._AddAlertGroup( 1410 anomalies[0], 1411 issue=self._issue_tracker.issue, 1412 status=alert_group.AlertGroup.Status.triaged, 1413 ) 1414 self._issue_tracker.issue.update({ 1415 'state': 1416 'open', 1417 'labels': 1418 self._issue_tracker.issue.get('labels') + 1419 ['Chromeperf-Auto-BisectOptOut'] 1420 }) 1421 self._sheriff_config.patterns = { 1422 '*': [ 1423 subscription.Subscription( 1424 name='sheriff', 1425 auto_triage_enable=True, 1426 auto_bisect_enable=True) 1427 ], 1428 } 1429 w = alert_group_workflow.AlertGroupWorkflow( 1430 group.get(), 1431 sheriff_config=self._sheriff_config, 1432 issue_tracker=self._issue_tracker, 1433 pinpoint=self._pinpoint, 1434 crrev=self._crrev, 1435 ) 1436 self.assertIn('Chromeperf-Auto-BisectOptOut', 1437 self._issue_tracker.issue.get('labels')) 1438 w.Process( 1439 update=alert_group_workflow.AlertGroupWorkflow.GroupUpdate( 1440 now=datetime.datetime.utcnow(), 1441 anomalies=ndb.get_multi(anomalies), 1442 issue=self._issue_tracker.issue, 1443 )) 1444 self.assertIsNone(self._pinpoint.new_job_request) 1445