| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright 2013 the V8 project authors. All rights reserved. | 2 # Copyright 2013 the V8 project authors. All rights reserved. |
| 3 # Redistribution and use in source and binary forms, with or without | 3 # Redistribution and use in source and binary forms, with or without |
| 4 # modification, are permitted provided that the following conditions are | 4 # modification, are permitted provided that the following conditions are |
| 5 # met: | 5 # met: |
| 6 # | 6 # |
| 7 # * Redistributions of source code must retain the above copyright | 7 # * Redistributions of source code must retain the above copyright |
| 8 # notice, this list of conditions and the following disclaimer. | 8 # notice, this list of conditions and the following disclaimer. |
| 9 # * Redistributions in binary form must reproduce the above | 9 # * Redistributions in binary form must reproduce the above |
| 10 # copyright notice, this list of conditions and the following | 10 # copyright notice, this list of conditions and the following |
| (...skipping 13 matching lines...) Expand all Loading... |
| 24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 28 | 28 |
| 29 import json | 29 import json |
| 30 import optparse | 30 import optparse |
| 31 import os | 31 import os |
| 32 import re | 32 import re |
| 33 import sys | 33 import sys |
| 34 import urllib |
| 34 | 35 |
| 35 from common_includes import * | 36 from common_includes import * |
| 36 | 37 |
| 37 SETTINGS_LOCATION = "SETTINGS_LOCATION" | 38 SETTINGS_LOCATION = "SETTINGS_LOCATION" |
| 38 | 39 |
| 39 CONFIG = { | 40 CONFIG = { |
| 40 PERSISTFILE_BASENAME: "/tmp/v8-auto-roll-tempfile", | 41 PERSISTFILE_BASENAME: "/tmp/v8-auto-roll-tempfile", |
| 41 DOT_GIT_LOCATION: ".git", | 42 DOT_GIT_LOCATION: ".git", |
| 42 SETTINGS_LOCATION: "~/.auto-roll", | 43 SETTINGS_LOCATION: "~/.auto-roll", |
| 43 } | 44 } |
| 44 | 45 |
| 45 | 46 |
| 46 class AutoRollOptions(CommonOptions): | 47 class AutoRollOptions(CommonOptions): |
| 47 def __init__(self, options): | 48 def __init__(self, options): |
| 48 super(AutoRollOptions, self).__init__(options) | 49 super(AutoRollOptions, self).__init__(options) |
| 49 self.requires_editor = False | 50 self.requires_editor = False |
| 51 self.status_password = options.status_password |
| 50 | 52 |
| 51 | 53 |
| 52 class Preparation(Step): | 54 class Preparation(Step): |
| 53 MESSAGE = "Preparation." | 55 MESSAGE = "Preparation." |
| 54 | 56 |
| 55 def RunStep(self): | 57 def RunStep(self): |
| 56 self.InitialEnvironmentChecks() | 58 self.InitialEnvironmentChecks() |
| 57 self.CommonPrepare() | 59 self.CommonPrepare() |
| 58 | 60 |
| 59 | 61 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 71 | 73 |
| 72 class CheckTreeStatus(Step): | 74 class CheckTreeStatus(Step): |
| 73 MESSAGE = "Checking v8 tree status message." | 75 MESSAGE = "Checking v8 tree status message." |
| 74 | 76 |
| 75 def RunStep(self): | 77 def RunStep(self): |
| 76 status_url = "https://v8-status.appspot.com/current?format=json" | 78 status_url = "https://v8-status.appspot.com/current?format=json" |
| 77 status_json = self.ReadURL(status_url, wait_plan=[5, 20, 300, 300]) | 79 status_json = self.ReadURL(status_url, wait_plan=[5, 20, 300, 300]) |
| 78 message = json.loads(status_json)["message"] | 80 message = json.loads(status_json)["message"] |
| 79 if re.search(r"nopush|no push", message, flags=re.I): | 81 if re.search(r"nopush|no push", message, flags=re.I): |
| 80 self.Die("Push to trunk disabled by tree state: %s" % message) | 82 self.Die("Push to trunk disabled by tree state: %s" % message) |
| 83 self.Persist("tree_message", message) |
| 81 | 84 |
| 82 | 85 |
| 83 class FetchLatestRevision(Step): | 86 class FetchLatestRevision(Step): |
| 84 MESSAGE = "Fetching latest V8 revision." | 87 MESSAGE = "Fetching latest V8 revision." |
| 85 | 88 |
| 86 def RunStep(self): | 89 def RunStep(self): |
| 87 log = self.Git("svn log -1 --oneline").strip() | 90 log = self.Git("svn log -1 --oneline").strip() |
| 88 match = re.match(r"^r(\d+) ", log) | 91 match = re.match(r"^r(\d+) ", log) |
| 89 if not match: | 92 if not match: |
| 90 self.Die("Could not extract current svn revision from log.") | 93 self.Die("Could not extract current svn revision from log.") |
| (...skipping 23 matching lines...) Expand all Loading... |
| 114 | 117 |
| 115 def RunStep(self): | 118 def RunStep(self): |
| 116 lkgr_url = "https://v8-status.appspot.com/lkgr" | 119 lkgr_url = "https://v8-status.appspot.com/lkgr" |
| 117 # Retry several times since app engine might have issues. | 120 # Retry several times since app engine might have issues. |
| 118 self.Persist("lkgr", self.ReadURL(lkgr_url, wait_plan=[5, 20, 300, 300])) | 121 self.Persist("lkgr", self.ReadURL(lkgr_url, wait_plan=[5, 20, 300, 300])) |
| 119 | 122 |
| 120 | 123 |
| 121 class PushToTrunk(Step): | 124 class PushToTrunk(Step): |
| 122 MESSAGE = "Pushing to trunk if possible." | 125 MESSAGE = "Pushing to trunk if possible." |
| 123 | 126 |
| 127 def PushTreeStatus(self, message): |
| 128 if not self._options.status_password: |
| 129 print "Skipping tree status update without password file." |
| 130 return |
| 131 params = { |
| 132 "message": message, |
| 133 "username": "v8-auto-roll@chromium.org", |
| 134 "password": FileToText(self._options.status_password).strip(), |
| 135 } |
| 136 params = urllib.urlencode(params) |
| 137 print "Pushing tree status: '%s'" % message |
| 138 self.ReadURL("https://v8-status.appspot.com/status", params, |
| 139 wait_plan=[5, 20]) |
| 140 |
| 124 def RunStep(self): | 141 def RunStep(self): |
| 125 self.RestoreIfUnset("latest") | 142 self.RestoreIfUnset("latest") |
| 126 self.RestoreIfUnset("lkgr") | 143 self.RestoreIfUnset("lkgr") |
| 144 self.RestoreIfUnset("tree_message") |
| 127 latest = int(self._state["latest"]) | 145 latest = int(self._state["latest"]) |
| 128 lkgr = int(self._state["lkgr"]) | 146 lkgr = int(self._state["lkgr"]) |
| 129 if latest == lkgr: | 147 if latest == lkgr: |
| 130 print "ToT (r%d) is clean. Pushing to trunk." % latest | 148 print "ToT (r%d) is clean. Pushing to trunk." % latest |
| 149 self.PushTreeStatus("Tree is closed (preparing to push)") |
| 150 |
| 131 # TODO(machenbach): Call push to trunk script. | 151 # TODO(machenbach): Call push to trunk script. |
| 132 # TODO(machenbach): Update the script before calling it. | 152 # TODO(machenbach): Update the script before calling it. |
| 133 # self._side_effect_handler.Command( | 153 # self._side_effect_handler.Command( |
| 134 # "tools/push-to-trunk/push-to-trunk.py", | 154 # "tools/push-to-trunk/push-to-trunk.py", |
| 135 # "-f -c %s -r %s" % (self._options.c, self._options.r)) | 155 # "-f -c %s -r %s" % (self._options.c, self._options.r)) |
| 156 self.PushTreeStatus(self._state["tree_message"]) |
| 136 else: | 157 else: |
| 137 print("ToT (r%d) is ahead of the LKGR (r%d). Skipping push to trunk." | 158 print("ToT (r%d) is ahead of the LKGR (r%d). Skipping push to trunk." |
| 138 % (latest, lkgr)) | 159 % (latest, lkgr)) |
| 139 | 160 |
| 140 | 161 |
| 141 def RunAutoRoll(config, | 162 def RunAutoRoll(config, |
| 142 options, | 163 options, |
| 143 side_effect_handler=DEFAULT_SIDE_EFFECT_HANDLER): | 164 side_effect_handler=DEFAULT_SIDE_EFFECT_HANDLER): |
| 144 step_classes = [ | 165 step_classes = [ |
| 145 Preparation, | 166 Preparation, |
| (...skipping 10 matching lines...) Expand all Loading... |
| 156 def BuildOptions(): | 177 def BuildOptions(): |
| 157 result = optparse.OptionParser() | 178 result = optparse.OptionParser() |
| 158 result.add_option("-c", "--chromium", dest="c", | 179 result.add_option("-c", "--chromium", dest="c", |
| 159 help=("Specify the path to your Chromium src/ " | 180 help=("Specify the path to your Chromium src/ " |
| 160 "directory to automate the V8 roll.")) | 181 "directory to automate the V8 roll.")) |
| 161 result.add_option("-r", "--reviewer", dest="r", | 182 result.add_option("-r", "--reviewer", dest="r", |
| 162 help=("Specify the account name to be used for reviews.")) | 183 help=("Specify the account name to be used for reviews.")) |
| 163 result.add_option("-s", "--step", dest="s", | 184 result.add_option("-s", "--step", dest="s", |
| 164 help="Specify the step where to start work. Default: 0.", | 185 help="Specify the step where to start work. Default: 0.", |
| 165 default=0, type="int") | 186 default=0, type="int") |
| 187 result.add_option("--status-password", |
| 188 help="A file with the password to the status app.") |
| 166 return result | 189 return result |
| 167 | 190 |
| 168 | 191 |
| 169 def Main(): | 192 def Main(): |
| 170 parser = BuildOptions() | 193 parser = BuildOptions() |
| 171 (options, args) = parser.parse_args() | 194 (options, args) = parser.parse_args() |
| 172 if not options.c or not options.r: | 195 if not options.c or not options.r: |
| 173 print "You need to specify the chromium src location and a reviewer." | 196 print "You need to specify the chromium src location and a reviewer." |
| 174 parser.print_help() | 197 parser.print_help() |
| 175 return 1 | 198 return 1 |
| 176 RunAutoRoll(CONFIG, AutoRollOptions(options)) | 199 RunAutoRoll(CONFIG, AutoRollOptions(options)) |
| 177 | 200 |
| 178 if __name__ == "__main__": | 201 if __name__ == "__main__": |
| 179 sys.exit(Main()) | 202 sys.exit(Main()) |
| OLD | NEW |