WebKitTools/Scripts/webkitpy/tool/commands/sheriffbot.py
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     1 # Copyright (c) 2009 Google Inc. All rights reserved.
       
     2 #
       
     3 # Redistribution and use in source and binary forms, with or without
       
     4 # modification, are permitted provided that the following conditions are
       
     5 # met:
       
     6 # 
       
     7 #     * Redistributions of source code must retain the above copyright
       
     8 # notice, this list of conditions and the following disclaimer.
       
     9 #     * Redistributions in binary form must reproduce the above
       
    10 # copyright notice, this list of conditions and the following disclaimer
       
    11 # in the documentation and/or other materials provided with the
       
    12 # distribution.
       
    13 #     * Neither the name of Google Inc. nor the names of its
       
    14 # contributors may be used to endorse or promote products derived from
       
    15 # this software without specific prior written permission.
       
    16 # 
       
    17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
       
    18 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
       
    19 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
       
    20 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
       
    21 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
       
    22 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
       
    23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
       
    24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
       
    25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
       
    26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
       
    27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
       
    28 
       
    29 import os
       
    30 
       
    31 from webkitpy.common.system.deprecated_logging import log
       
    32 from webkitpy.common.config.ports import WebKitPort
       
    33 from webkitpy.tool.bot.sheriff import Sheriff
       
    34 from webkitpy.tool.bot.sheriffircbot import SheriffIRCBot
       
    35 from webkitpy.tool.commands.queues import AbstractQueue
       
    36 from webkitpy.tool.commands.stepsequence import StepSequenceErrorHandler
       
    37 
       
    38 
       
    39 class SheriffBot(AbstractQueue, StepSequenceErrorHandler):
       
    40     name = "sheriff-bot"
       
    41     watchers = AbstractQueue.watchers + [
       
    42         "abarth@webkit.org",
       
    43         "eric@webkit.org",
       
    44     ]
       
    45 
       
    46     def _update(self):
       
    47         self.run_webkit_patch(["update", "--force-clean", "--quiet"])
       
    48 
       
    49     # AbstractQueue methods
       
    50 
       
    51     def begin_work_queue(self):
       
    52         AbstractQueue.begin_work_queue(self)
       
    53         self._sheriff = Sheriff(self.tool, self)
       
    54         self._irc_bot = SheriffIRCBot(self.tool, self._sheriff)
       
    55         self.tool.ensure_irc_connected(self._irc_bot.irc_delegate())
       
    56 
       
    57     def work_item_log_path(self, new_failures):
       
    58         return os.path.join("%s-logs" % self.name, "%s.log" % new_failures.keys()[0])
       
    59 
       
    60     def _new_failures(self, revisions_causing_failures, old_failing_svn_revisions):
       
    61         # We ignore failures that might have been caused by svn_revisions that
       
    62         # we've already complained about.  This is conservative in the sense
       
    63         # that we might be ignoring some new failures, but our experience has
       
    64         # been that skipping this check causes a lot of spam for builders that
       
    65         # take a long time to cycle.
       
    66         old_failing_builder_names = []
       
    67         for svn_revision in old_failing_svn_revisions:
       
    68             old_failing_builder_names.extend(
       
    69                 [builder.name() for builder in revisions_causing_failures[svn_revision]])
       
    70 
       
    71         new_failures = {}
       
    72         for svn_revision, builders in revisions_causing_failures.items():
       
    73             if svn_revision in old_failing_svn_revisions:
       
    74                 # FIXME: We should re-process the work item after some time delay.
       
    75                 # https://bugs.webkit.org/show_bug.cgi?id=36581
       
    76                 continue
       
    77             new_builders = [builder for builder in builders
       
    78                             if builder.name() not in old_failing_builder_names]
       
    79             if new_builders:
       
    80                 new_failures[svn_revision] = new_builders
       
    81 
       
    82         return new_failures
       
    83 
       
    84     def next_work_item(self):
       
    85         self._irc_bot.process_pending_messages()
       
    86         self._update()
       
    87 
       
    88         # We do one read from buildbot to ensure a consistent view.
       
    89         revisions_causing_failures = self.tool.buildbot.revisions_causing_failures()
       
    90 
       
    91         # Similarly, we read once from our the status_server.
       
    92         old_failing_svn_revisions = []
       
    93         for svn_revision in revisions_causing_failures.keys():
       
    94             if self.tool.status_server.svn_revision(svn_revision):
       
    95                 old_failing_svn_revisions.append(svn_revision)
       
    96 
       
    97         new_failures = self._new_failures(revisions_causing_failures,
       
    98                                           old_failing_svn_revisions)
       
    99 
       
   100         self._sheriff.provoke_flaky_builders(revisions_causing_failures)
       
   101         return new_failures
       
   102 
       
   103     def should_proceed_with_work_item(self, new_failures):
       
   104         # Currently, we don't have any reasons not to proceed with work items.
       
   105         return True
       
   106 
       
   107     def process_work_item(self, new_failures):
       
   108         blame_list = new_failures.keys()
       
   109         for svn_revision, builders in new_failures.items():
       
   110             try:
       
   111                 commit_info = self.tool.checkout().commit_info_for_revision(svn_revision)
       
   112                 if not commit_info:
       
   113                     print "FAILED to fetch CommitInfo for r%s, likely missing ChangeLog" % revision
       
   114                     continue
       
   115                 self._sheriff.post_irc_warning(commit_info, builders)
       
   116                 self._sheriff.post_blame_comment_on_bug(commit_info,
       
   117                                                         builders,
       
   118                                                         blame_list)
       
   119                 self._sheriff.post_automatic_rollout_patch(commit_info,
       
   120                                                            builders)
       
   121             finally:
       
   122                 for builder in builders:
       
   123                     self.tool.status_server.update_svn_revision(svn_revision,
       
   124                                                                 builder.name())
       
   125         return True
       
   126 
       
   127     def handle_unexpected_error(self, new_failures, message):
       
   128         log(message)
       
   129 
       
   130     # StepSequenceErrorHandler methods
       
   131 
       
   132     @classmethod
       
   133     def handle_script_error(cls, tool, state, script_error):
       
   134         # Ideally we would post some information to IRC about what went wrong
       
   135         # here, but we don't have the IRC password in the child process.
       
   136         pass