OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 """Script that reads omahaproxy and gsutil to determine version of SDK to put | 6 """Script that reads omahaproxy and gsutil to determine version of SDK to put |
7 in manifest. | 7 in manifest. |
8 """ | 8 """ |
9 | 9 |
10 # pylint is convinced the email module is missing attributes | 10 # pylint is convinced the email module is missing attributes |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
160 stdin: If src is '-', this is used as the stdin to give to gsutil. The | 160 stdin: If src is '-', this is used as the stdin to give to gsutil. The |
161 effect is that text in stdin is copied to |dest|.""" | 161 effect is that text in stdin is copied to |dest|.""" |
162 raise NotImplementedError() | 162 raise NotImplementedError() |
163 | 163 |
164 def Print(self, *args): | 164 def Print(self, *args): |
165 """Print a message.""" | 165 """Print a message.""" |
166 raise NotImplementedError() | 166 raise NotImplementedError() |
167 | 167 |
168 | 168 |
169 class RealDelegate(Delegate): | 169 class RealDelegate(Delegate): |
170 def __init__(self, dryrun=False, gsutil=None): | 170 def __init__(self, dryrun=False, gsutil=None, verbose=False): |
171 super(RealDelegate, self).__init__() | 171 super(RealDelegate, self).__init__() |
172 self.dryrun = dryrun | 172 self.dryrun = dryrun |
| 173 self.verbose = verbose |
173 if gsutil: | 174 if gsutil: |
174 self.gsutil = gsutil | 175 self.gsutil = gsutil |
175 else: | 176 else: |
176 self.gsutil = buildbot_common.GetGsutil() | 177 self.gsutil = buildbot_common.GetGsutil() |
177 | 178 |
178 def GetRepoManifest(self): | 179 def GetRepoManifest(self): |
179 """See Delegate.GetRepoManifest""" | 180 """See Delegate.GetRepoManifest""" |
180 with open(REPO_MANIFEST, 'r') as sdk_stream: | 181 with open(REPO_MANIFEST, 'r') as sdk_stream: |
181 sdk_json_string = sdk_stream.read() | 182 sdk_json_string = sdk_stream.read() |
182 | 183 |
183 manifest = manifest_util.SDKManifest() | 184 manifest = manifest_util.SDKManifest() |
184 manifest.LoadDataFromString(sdk_json_string) | 185 manifest.LoadDataFromString(sdk_json_string, add_missing_info=True) |
185 return manifest | 186 return manifest |
186 | 187 |
187 def GetHistory(self): | 188 def GetHistory(self): |
188 """See Delegate.GetHistory""" | 189 """See Delegate.GetHistory""" |
189 url_stream = urllib2.urlopen('https://omahaproxy.appspot.com/history') | 190 url_stream = urllib2.urlopen('https://omahaproxy.appspot.com/history') |
190 return [(platform, channel, version, date) | 191 return [(platform, channel, version, date) |
191 for platform, channel, version, date in csv.reader(url_stream)] | 192 for platform, channel, version, date in csv.reader(url_stream)] |
192 | 193 |
193 def GetTrunkRevision(self, version): | 194 def GetTrunkRevision(self, version): |
194 """See Delegate.GetTrunkRevision""" | 195 """See Delegate.GetTrunkRevision""" |
(...skipping 10 matching lines...) Expand all Loading... |
205 # filter out empty lines | 206 # filter out empty lines |
206 return filter(None, stdout.split('\n')) | 207 return filter(None, stdout.split('\n')) |
207 | 208 |
208 def GsUtil_cat(self, url): | 209 def GsUtil_cat(self, url): |
209 """See Delegate.GsUtil_cat""" | 210 """See Delegate.GsUtil_cat""" |
210 return self._RunGsUtil(None, 'cat', url) | 211 return self._RunGsUtil(None, 'cat', url) |
211 | 212 |
212 def GsUtil_cp(self, src, dest, stdin=None): | 213 def GsUtil_cp(self, src, dest, stdin=None): |
213 """See Delegate.GsUtil_cp""" | 214 """See Delegate.GsUtil_cp""" |
214 if self.dryrun: | 215 if self.dryrun: |
| 216 self.Trace("Skipping upload: %s -> %s" % (src, dest)) |
215 return | 217 return |
216 | 218 |
217 # -p ensures we keep permissions when copying "in-the-cloud". | 219 # -p ensures we keep permissions when copying "in-the-cloud". |
218 return self._RunGsUtil(stdin, 'cp', '-p', '-a', 'public-read', src, dest) | 220 return self._RunGsUtil(stdin, 'cp', '-p', '-a', 'public-read', src, dest) |
219 | 221 |
220 def Print(self, *args): | 222 def Print(self, *args): |
221 sys.stdout.write(' '.join(map(str, args)) + '\n') | 223 sys.stdout.write(' '.join(map(str, args)) + '\n') |
222 | 224 |
| 225 def Trace(self, *args): |
| 226 if self.verbose: |
| 227 self.Print(*args) |
| 228 |
223 def _RunGsUtil(self, stdin, *args): | 229 def _RunGsUtil(self, stdin, *args): |
224 """Run gsutil as a subprocess. | 230 """Run gsutil as a subprocess. |
225 | 231 |
226 Args: | 232 Args: |
227 stdin: If non-None, used as input to the process. | 233 stdin: If non-None, used as input to the process. |
228 *args: Arguments to pass to gsutil. The first argument should be an | 234 *args: Arguments to pass to gsutil. The first argument should be an |
229 operation such as ls, cp or cat. | 235 operation such as ls, cp or cat. |
230 Returns: | 236 Returns: |
231 The stdout from the process.""" | 237 The stdout from the process.""" |
232 cmd = [self.gsutil] + list(args) | 238 cmd = [self.gsutil] + list(args) |
| 239 self.Trace("Running: %s" % str(cmd)) |
233 if stdin: | 240 if stdin: |
234 stdin_pipe = subprocess.PIPE | 241 stdin_pipe = subprocess.PIPE |
235 else: | 242 else: |
236 stdin_pipe = None | 243 stdin_pipe = None |
237 | 244 |
238 process = subprocess.Popen(cmd, stdin=stdin_pipe, stdout=subprocess.PIPE, | 245 try: |
239 stderr=subprocess.PIPE) | 246 process = subprocess.Popen(cmd, stdin=stdin_pipe, stdout=subprocess.PIPE, |
240 stdout, stderr = process.communicate(stdin) | 247 stderr=subprocess.PIPE) |
| 248 stdout, stderr = process.communicate(stdin) |
| 249 except OSError as e: |
| 250 raise manifest_util.Error("Unable to run '%s': %s" % (cmd[0], str(e))) |
241 | 251 |
242 if process.returncode != 0: | 252 if process.returncode: |
243 sys.stderr.write(stderr) | 253 sys.stderr.write(stderr) |
244 raise subprocess.CalledProcessError(process.returncode, ' '.join(cmd)) | 254 raise subprocess.CalledProcessError(process.returncode, ' '.join(cmd)) |
245 return stdout | 255 return stdout |
246 | 256 |
247 | 257 |
248 class VersionFinder(object): | 258 class VersionFinder(object): |
249 """Finds a version of a pepper bundle that all desired platforms share.""" | 259 """Finds a version of a pepper bundle that all desired platforms share.""" |
250 def __init__(self, delegate): | 260 def __init__(self, delegate): |
251 self.delegate = delegate | 261 self.delegate = delegate |
252 self.history = delegate.GetHistory() | 262 self.history = delegate.GetHistory() |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
511 | 521 |
512 def _UploadManifest(self, manifest): | 522 def _UploadManifest(self, manifest): |
513 """Upload a serialized manifest_util.SDKManifest object. | 523 """Upload a serialized manifest_util.SDKManifest object. |
514 | 524 |
515 Upload one copy to gs://<BUCKET_PATH>/naclsdk_manifest2.json, and a copy to | 525 Upload one copy to gs://<BUCKET_PATH>/naclsdk_manifest2.json, and a copy to |
516 gs://<BUCKET_PATH>/manifest_backups/naclsdk_manifest2.<TIMESTAMP>.json. | 526 gs://<BUCKET_PATH>/manifest_backups/naclsdk_manifest2.<TIMESTAMP>.json. |
517 | 527 |
518 Args: | 528 Args: |
519 manifest: The new manifest to upload. | 529 manifest: The new manifest to upload. |
520 """ | 530 """ |
| 531 if self.delegate.dryrun: |
| 532 name = MANIFEST_BASENAME + ".new" |
| 533 self.delegate.Print("Writing new manifest: %s" % name) |
| 534 with open(name, 'w') as f: |
| 535 f.write(manifest.GetDataAsString()) |
| 536 stdout = self.delegate.GsUtil_cat(GS_SDK_MANIFEST) |
| 537 |
| 538 online = MANIFEST_BASENAME + ".online" |
| 539 self.delegate.Print("Writing online manifest: %s" % online) |
| 540 with open(online, 'w') as f: |
| 541 f.write(stdout) |
| 542 os.system('diff -u %s %s' % (online, name)) |
| 543 |
521 timestamp_manifest_path = GS_MANIFEST_BACKUP_DIR + \ | 544 timestamp_manifest_path = GS_MANIFEST_BACKUP_DIR + \ |
522 GetTimestampManifestName() | 545 GetTimestampManifestName() |
523 self.delegate.GsUtil_cp('-', timestamp_manifest_path, | 546 self.delegate.GsUtil_cp('-', timestamp_manifest_path, |
524 stdin=manifest.GetDataAsString()) | 547 stdin=manifest.GetDataAsString()) |
525 | 548 |
526 # copy from timestampped copy over the official manifest. | 549 # copy from timestampped copy over the official manifest. |
527 self.delegate.GsUtil_cp(timestamp_manifest_path, GS_SDK_MANIFEST) | 550 self.delegate.GsUtil_cp(timestamp_manifest_path, GS_SDK_MANIFEST) |
528 | 551 |
529 | 552 |
530 def Run(delegate, platforms): | 553 def Run(delegate, platforms): |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
590 self.written.write(s) | 613 self.written.write(s) |
591 if self.passthrough: | 614 if self.passthrough: |
592 self.passthrough.write(s) | 615 self.passthrough.write(s) |
593 | 616 |
594 def getvalue(self): | 617 def getvalue(self): |
595 return self.written.getvalue() | 618 return self.written.getvalue() |
596 | 619 |
597 | 620 |
598 def main(args): | 621 def main(args): |
599 parser = optparse.OptionParser() | 622 parser = optparse.OptionParser() |
600 parser.add_option('--gsutil', help='path to gsutil', dest='gsutil', | 623 parser.add_option('--gsutil', help='path to gsutil.') |
601 default=None) | 624 parser.add_option('-d', '--debug', help='run in debug mode.', |
602 parser.add_option('--mailfrom', help='email address of sender', | 625 action='store_true') |
603 dest='mailfrom', default=None) | 626 parser.add_option('--mailfrom', help='email address of sender.') |
604 parser.add_option('--mailto', help='send error mails to...', dest='mailto', | 627 parser.add_option('--mailto', help='send error mails to...', action='append') |
605 default=[], action='append') | 628 parser.add_option('-n', '--dryrun', help="don't upload the manifest.", |
606 parser.add_option('--dryrun', help='don\'t upload the manifest.', | 629 action='store_true') |
607 dest='dryrun', action='store_true', default=False) | 630 parser.add_option('-v', '--verbose', help='print more diagnotic messages.', |
| 631 action='store_true') |
608 options, args = parser.parse_args(args[1:]) | 632 options, args = parser.parse_args(args[1:]) |
609 | 633 |
610 if (options.mailfrom is None) != (not options.mailto): | 634 if (options.mailfrom is None) != (not options.mailto): |
611 options.mailfrom = None | 635 options.mailfrom = None |
612 options.mailto = None | 636 options.mailto = None |
613 sys.stderr.write('warning: Disabling email, one of --mailto or --mailfrom ' | 637 sys.stderr.write('warning: Disabling email, one of --mailto or --mailfrom ' |
614 'was missing.\n') | 638 'was missing.\n') |
615 | 639 |
616 if options.mailfrom and options.mailto: | 640 if options.mailfrom and options.mailto: |
617 # Capture stderr so it can be emailed, if necessary. | 641 # Capture stderr so it can be emailed, if necessary. |
618 sys.stderr = CapturedFile(sys.stderr) | 642 sys.stderr = CapturedFile(sys.stderr) |
619 | 643 |
620 try: | 644 try: |
621 delegate = RealDelegate(dryrun=options.dryrun, gsutil=options.gsutil) | 645 try: |
622 Run(delegate, ('mac', 'win', 'linux')) | 646 delegate = RealDelegate(options.dryrun, options.gsutil, options.verbose) |
623 except Exception: | 647 Run(delegate, ('mac', 'win', 'linux')) |
624 if options.mailfrom and options.mailto: | 648 except Exception: |
625 traceback.print_exc() | 649 if options.mailfrom and options.mailto: |
626 scriptname = os.path.basename(sys.argv[0]) | 650 traceback.print_exc() |
627 subject = '[%s] Failed to update manifest' % (scriptname,) | 651 scriptname = os.path.basename(sys.argv[0]) |
628 text = '%s failed.\n\nSTDERR:\n%s\n' % (scriptname, sys.stderr.getvalue()) | 652 subject = '[%s] Failed to update manifest' % (scriptname,) |
629 SendMail(options.mailfrom, options.mailto, subject, text) | 653 text = '%s failed.\n\nSTDERR:\n%s\n' % (scriptname, |
630 sys.exit(1) | 654 sys.stderr.getvalue()) |
631 else: | 655 SendMail(options.mailfrom, options.mailto, subject, text) |
| 656 sys.exit(1) |
| 657 else: |
| 658 raise |
| 659 except manifest_util.Error as e: |
| 660 if options.debug: |
632 raise | 661 raise |
| 662 print e |
| 663 sys.exit(1) |
633 | 664 |
634 | 665 |
635 if __name__ == '__main__': | 666 if __name__ == '__main__': |
636 sys.exit(main(sys.argv)) | 667 sys.exit(main(sys.argv)) |
OLD | NEW |