Changeset 52641 in webkit


Ignore:
Timestamp:
Dec 29, 2009 8:47:56 PM (14 years ago)
Author:
eric@webkit.org
Message:

2009-12-29 Eric Seidel <eric@webkit.org>

Reviewed by Adam Barth.

Need a script to assign bugs with r+ patches to committers for landing
https://bugs.webkit.org/show_bug.cgi?id=33009

This is just one more small tool to help in the fight against our
ever-growing list of to-be-committed patches.

  • Scripts/modules/bugzilla.py:
    • Rename assign_to_email to assigned_to_email (typo).
    • Add assigned_to_email() method on Bug.
    • Add reassign_bug method.
    • Add Bugzilla.unassigned_email, eventually should move to some webkit_config.py module.
  • Scripts/modules/bugzilla_unittest.py:
    • Update test after assigned_to_email rename.
  • Scripts/modules/commands/commandtest.py:
    • Call bind_to_tool to that self.tool works in Command testing.
  • Scripts/modules/commands/download.py:
    • Move AbstractDeclarativeCommmand multicommandtool.py, it should be part of Command.
  • Scripts/modules/commands/queries_unittest.py:
    • One of the test patches is now posted by "eric@webkit.org" which is a committer.
    • Eventually we'll mock out CommitterList and be able to better control what's a committer and what's not.
  • Scripts/modules/commands/upload.py:
    • Add new assign-to-committer command.
  • Scripts/modules/commands/upload_unittest.py:
    • Add basic assign-to-committer test.
  • Scripts/modules/committers.py:
    • Add bugzilla_email() accessor.
  • Scripts/modules/committers_unittest.py:
    • Test our assumption that bugzilla_email is the first email.
  • Scripts/modules/mock_bugzillatool.py:
    • Add _id_to_object_dictionary for generating bug_cache from list of bugs.
    • Remove unused fetch_attachments_from_bug.
    • Add fetch_bug support and a bug_cache.
  • Scripts/modules/multicommandtool.py:
    • Move AbstractDeclarativeCommmand here from download.py
Location:
trunk/WebKitTools
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebKitTools/ChangeLog

    r52640 r52641  
     12009-12-29  Eric Seidel  <eric@webkit.org>
     2
     3        Reviewed by Adam Barth.
     4
     5        Need a script to assign bugs with r+ patches to committers for landing
     6        https://bugs.webkit.org/show_bug.cgi?id=33009
     7
     8        This is just one more small tool to help in the fight against our
     9        ever-growing list of to-be-committed patches.
     10
     11        * Scripts/modules/bugzilla.py:
     12         - Rename assign_to_email to assigned_to_email (typo).
     13         - Add assigned_to_email() method on Bug.
     14         - Add reassign_bug method.
     15         - Add Bugzilla.unassigned_email, eventually should move to some webkit_config.py module.
     16        * Scripts/modules/bugzilla_unittest.py:
     17         - Update test after assigned_to_email rename.
     18        * Scripts/modules/commands/commandtest.py:
     19         - Call bind_to_tool to that self.tool works in Command testing.
     20        * Scripts/modules/commands/download.py:
     21         - Move AbstractDeclarativeCommmand multicommandtool.py, it should be part of Command.
     22        * Scripts/modules/commands/queries_unittest.py:
     23         - One of the test patches is now posted by "eric@webkit.org" which is a committer.
     24         - Eventually we'll mock out CommitterList and be able to better control what's a committer and what's not.
     25        * Scripts/modules/commands/upload.py:
     26         - Add new assign-to-committer command.
     27        * Scripts/modules/commands/upload_unittest.py:
     28         - Add basic assign-to-committer test.
     29        * Scripts/modules/committers.py:
     30         - Add bugzilla_email() accessor.
     31        * Scripts/modules/committers_unittest.py:
     32         - Test our assumption that bugzilla_email is the first email.
     33        * Scripts/modules/mock_bugzillatool.py:
     34         - Add _id_to_object_dictionary for generating bug_cache from list of bugs.
     35         - Remove unused fetch_attachments_from_bug.
     36         - Add fetch_bug support and a bug_cache.
     37        * Scripts/modules/multicommandtool.py:
     38         - Move AbstractDeclarativeCommmand here from download.py
     39
    1402009-12-29  Adam Barth  <abarth@webkit.org>
    241
  • trunk/WebKitTools/Scripts/modules/bugzilla.py

    r52628 r52641  
    7070        self.bug_dictionary = bug_dictionary
    7171
     72    def assigned_to_email(self):
     73        return self.bug_dictionary["assigned_to_email"]
     74
    7275    # Rarely do we actually want obsolete attachments
    7376    def attachments(self, include_obsolete=False):
     
    9497        self.committers = committers
    9598
    96     # Defaults (until we support better option parsing):
     99    # FIXME: Much of this should go into some sort of config module:
    97100    bug_server_host = "bugs.webkit.org"
    98101    bug_server_regex = "https?://%s/" % re.sub('\.', '\\.', bug_server_host)
    99102    bug_server_url = "https://%s/" % bug_server_host
     103    unassigned_email = "webkit-unassigned@lists.webkit.org"
    100104
    101105    def bug_url_for_bug_id(self, bug_id, xml=False):
     
    139143        bug["title"] = unicode(soup.find("short_desc").string)
    140144        bug["reporter_email"] = str(soup.find("reporter").string)
    141         bug["assign_to_email"] = str(soup.find("assigned_to").string)
     145        bug["assigned_to_email"] = str(soup.find("assigned_to").string)
    142146        bug["cc_emails"] = [str(element.string) for element in soup.findAll('cc')]
    143147        bug["attachments"] = [self._parse_attachment_element(element, bug["id"]) for element in soup.findAll('attachment')]
     
    517521        self.browser.submit()
    518522
     523    def reassign_bug(self, bug_id, assignee, comment_text=None):
     524        self.authenticate()
     525
     526        log("Assigning bug %s to %s" % (bug_id, assignee))
     527        if self.dryrun:
     528            log(comment_text)
     529            return
     530
     531        self.browser.open(self.bug_url_for_bug_id(bug_id))
     532        self.browser.select_form(name="changeform")
     533        if comment_text:
     534            log(comment_text)
     535            self.browser["comment"] = comment_text
     536        self.browser["assigned_to"] = assignee
     537        self.browser.submit()
     538
    519539    def reopen_bug(self, bug_id, comment_text):
    520540        self.authenticate()
  • trunk/WebKitTools/Scripts/modules/bugzilla_unittest.py

    r52628 r52641  
    175175        "cc_emails" : ["foo@bar.com", "example@example.com"],
    176176        "reporter_email" : "eric@webkit.org",
    177         "assign_to_email" : "webkit-unassigned@lists.webkit.org",
     177        "assigned_to_email" : "webkit-unassigned@lists.webkit.org",
    178178        "attachments" : [{
    179179            'name': u'Patch',
  • trunk/WebKitTools/Scripts/modules/commands/commandtest.py

    r52239 r52641  
    3535class CommandsTest(unittest.TestCase):
    3636    def assert_execute_outputs(self, command, args, expected_stdout="", expected_stderr="", options=Mock(), tool=MockBugzillaTool()):
     37        command.bind_to_tool(tool)
    3738        OutputCapture().assert_outputs(self, command.execute, [options, args, tool], expected_stdout=expected_stdout, expected_stderr=expected_stderr)
  • trunk/WebKitTools/Scripts/modules/commands/download.py

    r52628 r52641  
    4141from modules.grammar import pluralize
    4242from modules.logging import error, log
    43 from modules.multicommandtool import Command
     43from modules.multicommandtool import AbstractDeclarativeCommmand, Command
    4444from modules.stepsequence import StepSequence
    45 
    46 
    47 # FIXME: Move this to a more general location.
    48 class AbstractDeclarativeCommmand(Command):
    49     help_text = None
    50     argument_names = None
    51     def __init__(self, options):
    52         Command.__init__(self, self.help_text, self.argument_names, options)
    5345
    5446
  • trunk/WebKitTools/Scripts/modules/commands/queries_unittest.py

    r51959 r52641  
    4545
    4646    def test_patches_to_commit_queue(self):
    47         expected_stdout = "http://example.com/197&action=edit\nhttp://example.com/128&action=edit\n"
    48         expected_stderr = ""
     47        expected_stdout = "http://example.com/197&action=edit\n"
     48        expected_stderr = "128 committer = \"Eric Seidel\" <eric@webkit.org>\n"
    4949        options = Mock()
    5050        options.bugs = False
  • trunk/WebKitTools/Scripts/modules/commands/upload.py

    r52628 r52641  
    4040from modules.commands.download import AbstractSequencedCommmand
    4141from modules.comments import bug_comment_from_svn_revision
     42from modules.committers import CommitterList
    4243from modules.grammar import pluralize
    4344from modules.logging import error, log
    44 from modules.multicommandtool import Command
     45from modules.multicommandtool import Command, AbstractDeclarativeCommmand
    4546
    4647# FIXME: Requires unit test.
     
    5354        os.chdir(tool.scm().checkout_root)
    5455        print "%s" % tool.scm().commit_message_for_this_commit().message()
     56
     57
     58class AssignToCommitter(AbstractDeclarativeCommmand):
     59    name = "assign-to-committer"
     60    help_text = "Assign bug to whoever attached the most recent r+'d patch"
     61
     62    def _assign_bug_to_last_patch_attacher(self, bug_id):
     63        committers = CommitterList()
     64        bug = self.tool.bugs.fetch_bug(bug_id)
     65        assigned_to_email = bug.assigned_to_email()
     66        if assigned_to_email != self.tool.bugs.unassigned_email:
     67            log("Bug %s is already assigned to %s (%s)." % (bug_id, assigned_to_email, committers.committer_by_email(assigned_to_email)))
     68            return
     69
     70        # FIXME: This should call a reviewed_patches() method on bug instead of re-fetching.
     71        reviewed_patches = self.tool.bugs.fetch_reviewed_patches_from_bug(bug_id)
     72        if not reviewed_patches:
     73            log("Bug %s has no non-obsolete patches, ignoring." % bug_id)
     74            return
     75        latest_patch = reviewed_patches[-1]
     76        attacher_email = latest_patch["attacher_email"]
     77        committer = committers.committer_by_email(attacher_email)
     78        if not committer:
     79            log("Attacher %s is not a committer.  Bug %s likely needs commit-queue+." % (attacher_email, bug_id))
     80            return
     81
     82        reassign_message = "Attachment %s was posted by a committer and has review+, assigning to %s for commit." % (latest_patch["id"], committer.full_name)
     83        self.tool.bugs.reassign_bug(bug_id, committer.bugzilla_email(), reassign_message)
     84
     85    def execute(self, options, args, tool):
     86        for bug_id in tool.bugs.fetch_bug_ids_from_needs_commit_list():
     87            self._assign_bug_to_last_patch_attacher(bug_id)
    5588
    5689
  • trunk/WebKitTools/Scripts/modules/commands/upload_unittest.py

    r52600 r52641  
    3131from modules.commands.commandtest import CommandsTest
    3232from modules.commands.upload import *
     33from modules.mock_bugzillatool import MockBugzillaTool
    3334
    3435class UploadCommandsTest(CommandsTest):
     36    def test_assign_to_committer(self):
     37        tool = MockBugzillaTool()
     38        expected_stderr = "Bug 75 is already assigned to foo@foo.com (None).\nBug 76 has no non-obsolete patches, ignoring.\n"
     39        self.assert_execute_outputs(AssignToCommitter(), [], expected_stderr=expected_stderr, tool=tool)
     40        tool.bugs.reassign_bug.assert_called_with(42, "eric@webkit.org", "Attachment 128 was posted by a committer and has review+, assigning to Eric Seidel for commit.")
     41
    3542    def test_obsolete_attachments(self):
    3643        expected_stderr = "Obsoleting 2 old patches on bug 42\n"
  • trunk/WebKitTools/Scripts/modules/committers.py

    r52604 r52641  
    3737            self.emails = email_or_emails
    3838        self.can_review = False
     39
     40    # FIXME: We're assuming the first email is a valid bugzilla email, which might not be right.
     41    def bugzilla_email(self):
     42        return self.emails[0]
    3943
    4044    def __str__(self):
  • trunk/WebKitTools/Scripts/modules/committers_unittest.py

    r50505 r52641  
    4444        self.assertEqual(committer_list.reviewer_by_email('so_two@gmail.com'), reviewer)
    4545
     46        # Test that the first email is assumed to be the Bugzilla email address (for now)
     47        self.assertEqual(committer_list.committer_by_email('two@rad.com').bugzilla_email(), 'two@test.com')
     48
    4649        # Test that a known committer is not returned during reviewer lookup
    4750        self.assertEqual(committer_list.reviewer_by_email('one@test.com'), None)
  • trunk/WebKitTools/Scripts/modules/mock_bugzillatool.py

    r52599 r52641  
    3131from modules.mock import Mock
    3232from modules.scm import CommitMessage
    33 
     33from modules.bugzilla import Bug
     34
     35def _id_to_object_dictionary(objects):
     36    dictionary = {}
     37    for thing in objects:
     38        dictionary[thing["id"]] = thing
     39    return dictionary
    3440
    3541class MockBugzilla(Mock):
     
    4854        "is_obsolete" : False,
    4955        "reviewer" : "Reviewer2",
    50         "attacher_email" : "Contributer2",
     56        "attacher_email" : "eric@webkit.org",
    5157    }
    5258    bug_server_url = "http://example.com"
     59    unassigned_email = "unassigned@example.com"
    5360
    5461    def fetch_bug_ids_from_commit_queue(self):
     
    6067    def fetch_patches_from_commit_queue(self, reject_invalid_patches=False):
    6168        return [self.patch1, self.patch2]
     69
     70    def fetch_bug_ids_from_needs_commit_list(self):
     71        return [42, 75, 76]
     72
     73    bug1 = {
     74        "id" : 42,
     75        "assigned_to_email" : unassigned_email,
     76        "attachments" : [patch1, patch2],
     77    }
     78    bug2 = {
     79        "id" : 75,
     80        "assigned_to_email" : "foo@foo.com",
     81        "attachments" : [],
     82    }
     83    bug3 = {
     84        "id" : 76,
     85        "assigned_to_email" : unassigned_email,
     86        "attachments" : [],
     87    }
     88
     89    bug_cache = _id_to_object_dictionary([bug1, bug2, bug3])
     90
     91    def fetch_bug(self, bug_id):
     92        return Bug(self.bug_cache.get(bug_id))
    6293
    6394    def fetch_patches_from_pending_commit_list(self):
     
    6899            return [self.patch1, self.patch2]
    69100        return []
    70 
    71     def fetch_attachments_from_bug(self, bug_id):
    72         if bug_id == 42:
    73             return [self.patch1, self.patch2]
    74         return None
    75101
    76102    def fetch_patches_from_bug(self, bug_id):
  • trunk/WebKitTools/Scripts/modules/multicommandtool.py

    r52543 r52641  
    3939from modules.logging import log
    4040
     41
    4142class Command(object):
    4243    name = None
     
    126127        return self.check_arguments_and_execute(options, args)
    127128
     129
     130# FIXME: This should just be rolled into Command.  help_text and argument_names do not need to be instance variables.
     131class AbstractDeclarativeCommmand(Command):
     132    help_text = None
     133    argument_names = None
     134    def __init__(self, options=None):
     135        Command.__init__(self, self.help_text, self.argument_names, options)
     136
     137
    128138class HelpPrintingOptionParser(OptionParser):
    129139    def __init__(self, epilog_method=None, *args, **kwargs):
Note: See TracChangeset for help on using the changeset viewer.