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 |