Add tree control feature to auto-roll script.
authormachenbach@chromium.org <machenbach@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 15 Jan 2014 15:55:23 +0000 (15:55 +0000)
committermachenbach@chromium.org <machenbach@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 15 Jan 2014 15:55:23 +0000 (15:55 +0000)
This CL enables the auto-roll script to close and reopen the tree when pushing.

Modifies an auto-roll test so that the push-to-trunk part is executed in order to test the new tree control feature.

BUG=
R=ulan@chromium.org

Review URL: https://codereview.chromium.org/130403006

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18622 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

tools/push-to-trunk/auto_roll.py
tools/push-to-trunk/common_includes.py
tools/push-to-trunk/test_scripts.py

index 3ba4481534f7903ef848cf36a30b5472a261f9e8..94fd7b4c97eab30c1d96918752e2441cd59a3d07 100755 (executable)
@@ -31,6 +31,7 @@ import optparse
 import os
 import re
 import sys
+import urllib
 
 from common_includes import *
 
@@ -47,6 +48,7 @@ class AutoRollOptions(CommonOptions):
   def __init__(self, options):
     super(AutoRollOptions, self).__init__(options)
     self.requires_editor = False
+    self.status_password = options.status_password
 
 
 class Preparation(Step):
@@ -78,6 +80,7 @@ class CheckTreeStatus(Step):
     message = json.loads(status_json)["message"]
     if re.search(r"nopush|no push", message, flags=re.I):
       self.Die("Push to trunk disabled by tree state: %s" % message)
+    self.Persist("tree_message", message)
 
 
 class FetchLatestRevision(Step):
@@ -121,18 +124,36 @@ class FetchLKGR(Step):
 class PushToTrunk(Step):
   MESSAGE = "Pushing to trunk if possible."
 
+  def PushTreeStatus(self, message):
+    if not self._options.status_password:
+      print "Skipping tree status update without password file."
+      return
+    params = {
+      "message": message,
+      "username": "v8-auto-roll@chromium.org",
+      "password": FileToText(self._options.status_password).strip(),
+    }
+    params = urllib.urlencode(params)
+    print "Pushing tree status: '%s'" % message
+    self.ReadURL("https://v8-status.appspot.com/status", params,
+                 wait_plan=[5, 20])
+
   def RunStep(self):
     self.RestoreIfUnset("latest")
     self.RestoreIfUnset("lkgr")
+    self.RestoreIfUnset("tree_message")
     latest = int(self._state["latest"])
     lkgr = int(self._state["lkgr"])
     if latest == lkgr:
       print "ToT (r%d) is clean. Pushing to trunk." % latest
+      self.PushTreeStatus("Tree is closed (preparing to push)")
+
       # TODO(machenbach): Call push to trunk script.
       # TODO(machenbach): Update the script before calling it.
       # self._side_effect_handler.Command(
       #     "tools/push-to-trunk/push-to-trunk.py",
       #     "-f -c %s -r %s" % (self._options.c, self._options.r))
+      self.PushTreeStatus(self._state["tree_message"])
     else:
       print("ToT (r%d) is ahead of the LKGR (r%d). Skipping push to trunk."
             % (latest, lkgr))
@@ -163,6 +184,8 @@ def BuildOptions():
   result.add_option("-s", "--step", dest="s",
                     help="Specify the step where to start work. Default: 0.",
                     default=0, type="int")
+  result.add_option("--status-password",
+                    help="A file with the password to the status app.")
   return result
 
 
index b4501136fb966d7b69b62a03ed63bbb15d9ab439..a6096486a6642718baf6b41d44129b362b223c87 100644 (file)
@@ -195,9 +195,9 @@ class SideEffectHandler(object):
   def ReadLine(self):
     return sys.stdin.readline().strip()
 
-  def ReadURL(self, url):
+  def ReadURL(self, url, params=None):
     # pylint: disable=E1121
-    url_fh = urllib2.urlopen(url, None, 60)
+    url_fh = urllib2.urlopen(url, params, 60)
     try:
       return url_fh.read()
     finally:
@@ -303,9 +303,9 @@ class Step(object):
       return self._side_effect_handler.Command(os.environ["EDITOR"], args,
                                                pipe=False)
 
-  def ReadURL(self, url, retry_on=None, wait_plan=None):
+  def ReadURL(self, url, params=None, retry_on=None, wait_plan=None):
     wait_plan = wait_plan or [3, 60, 600]
-    cmd = lambda: self._side_effect_handler.ReadURL(url)
+    cmd = lambda: self._side_effect_handler.ReadURL(url, params)
     return self.Retry(cmd, retry_on, wait_plan)
 
   def GetDate(self):
index 9ef57578750f5a59261f407a65724789baf975d7..56b44a6e4844a059dc41ec9d38cb172f15a02e6c 100644 (file)
@@ -58,7 +58,8 @@ TEST_CONFIG = {
 }
 
 
-def MakeOptions(s=0, l=None, f=False, m=True, r=None, c=None):
+def MakeOptions(s=0, l=None, f=False, m=True, r=None, c=None,
+                status_password=None):
   """Convenience wrapper."""
   class Options(object):
       pass
@@ -69,6 +70,7 @@ def MakeOptions(s=0, l=None, f=False, m=True, r=None, c=None):
   options.m = m
   options.r = r
   options.c = c
+  options.status_password = status_password
   return options
 
 
@@ -304,8 +306,11 @@ class ScriptTest(unittest.TestCase):
   def ReadLine(self):
     return self._rl_mock.Call()
 
-  def ReadURL(self, url):
-    return self._url_mock.Call(url)
+  def ReadURL(self, url, params):
+    if params is not None:
+      return self._url_mock.Call(url, params)
+    else:
+      return self._url_mock.Call(url)
 
   def Sleep(self, seconds):
     pass
@@ -748,6 +753,8 @@ Performance and stability improvements on all platforms."""
     self.assertRaises(Exception, self.MakeStep(CheckLastPush, state=state).Run)
 
   def testAutoRoll(self):
+    status_password = self.MakeEmptyTempFile()
+    TextToFile("PW", status_password)
     TEST_CONFIG[DOT_GIT_LOCATION] = self.MakeEmptyTempFile()
     TEST_CONFIG[SETTINGS_LOCATION] = "~/.doesnotexist"
 
@@ -756,20 +763,28 @@ Performance and stability improvements on all platforms."""
        "{\"message\": \"Tree is throttled\"}"],
       ["https://v8-status.appspot.com/lkgr", Exception("Network problem")],
       ["https://v8-status.appspot.com/lkgr", "100"],
+      ["https://v8-status.appspot.com/status",
+       ("username=v8-auto-roll%40chromium.org&"
+        "message=Tree+is+closed+%28preparing+to+push%29&password=PW"),
+       ""],
+      ["https://v8-status.appspot.com/status",
+       ("username=v8-auto-roll%40chromium.org&"
+        "message=Tree+is+throttled&password=PW"), ""],
     ])
 
     self.ExpectGit([
       ["status -s -uno", ""],
       ["status -s -b -uno", "## some_branch\n"],
       ["svn fetch", ""],
-      ["svn log -1 --oneline", "r101 | Text"],
+      ["svn log -1 --oneline", "r100 | Text"],
       ["svn log -1 --oneline ChangeLog", "r65 | Prepare push to trunk..."],
     ])
 
-    auto_roll.RunAutoRoll(TEST_CONFIG, AutoRollOptions(MakeOptions()), self)
+    auto_roll.RunAutoRoll(TEST_CONFIG, AutoRollOptions(
+        MakeOptions(status_password=status_password)), self)
 
     self.assertEquals("100", self.MakeStep().Restore("lkgr"))
-    self.assertEquals("101", self.MakeStep().Restore("latest"))
+    self.assertEquals("100", self.MakeStep().Restore("latest"))
 
   def testAutoRollStoppedBySettings(self):
     TEST_CONFIG[DOT_GIT_LOCATION] = self.MakeEmptyTempFile()