Chromium Code Reviews| Index: gce/checker.py |
| diff --git a/gce/checker.py b/gce/checker.py |
| new file mode 100755 |
| index 0000000000000000000000000000000000000000..c981ed61e5fd816a377bb78cbc7f1c26643d3358 |
| --- /dev/null |
| +++ b/gce/checker.py |
| @@ -0,0 +1,115 @@ |
| +#!/usr/bin/python |
| +# Copyright (c) 2016 The Chromium Authors. All rights reserved. |
| +# Use of this source code is governed by a BSD-style license that can be |
| +# found in the LICENSE file. |
| + |
| +from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer |
| +import logging |
| +import logging.handlers |
| +from os import path |
| +import subprocess |
| +import sys |
| +import threading |
| +import time |
| +import urllib2 |
| + |
| +import uploader_mail |
| + |
| +# How many seconds to wait after a cycle. |
| +CYCLE_DELAY = 1800 |
| + |
| +# Verifies a commit this long ago has been uploaded to devtools-frontend appspot |
| +CHECKER_DELAY = "12 hours" |
| + |
| +CYCLES_PER_24_HOURS = (86400 / CYCLE_DELAY) |
| + |
| +CHECKER_PATH = path.join(path.dirname(path.abspath(__file__)), '..', '..') |
| +CHROMIUM_CHECKOUT_PATH = path.join(CHECKER_PATH, 'src') |
| +LOG_PATH = path.join(CHECKER_PATH, 'logs', 'checker.log') |
| + |
| +consecutive_success = 0 |
| + |
| +def main(): |
| + logfile = init_logger() |
| + start_uptime_check_server() |
| + while True: |
| + logfile.doRollover() |
| + logging.info('Starting iteration cycle') |
| + call(['git', 'pull', 'origin', 'master']) |
| + yesterday_commit_hash = call(['git', 'rev-list', '-n1', '--before={}'.format(CHECKER_DELAY), '--first-parent', 'HEAD']) |
| + check_commit(yesterday_commit_hash.strip()) |
| + logging.info('Finished iteration cycle') |
| + time.sleep(CYCLE_DELAY) |
| + |
| +def init_logger(): |
| + logger = logging.getLogger() |
| + logger.setLevel(logging.INFO) |
| + |
| + console = logging.StreamHandler() |
| + console.setLevel(logging.INFO) |
| + logger.addHandler(console) |
| + |
| + logfile = logging.handlers.RotatingFileHandler(LOG_PATH, backupCount=30) |
| + logfile.setLevel(logging.INFO) |
| + logger.addHandler(logfile) |
| + |
| + formatter = logging.Formatter('%(asctime)s:%(message)s', |
| + datefmt='%Y-%m-%d %H:%M:%S') |
| + console.setFormatter(formatter) |
| + logfile.setFormatter(formatter) |
| + return logfile |
| + |
| +def check_commit(commit_hash): |
| + global consecutive_success |
|
dgozman
2016/09/22 16:42:54
Why this? Ain't consecutive_success already visibl
chenwilliam
2016/09/22 20:25:53
It's visible but consecutive_success += 1 causes t
|
| + url = 'https://chrome-devtools-frontend.appspot.com/serve_file/@{}/inspector.html'.format(commit_hash) |
| + request = urllib2.Request(url) |
| + try: |
| + response = urllib2.urlopen(request) |
| + summary = format_summary('Success', commit_hash, response.getcode()) |
| + logging.info(summary) |
| + # Send an email on first success after start-up or getting an error |
| + if consecutive_success == 0: |
| + send_email(subject=summary, body='Response body:\n' + response.read()) |
| + consecutive_success += 1 |
| + if consecutive_success >= CYCLES_PER_24_HOURS: |
| + send_email(subject=summary, body='Response body:\n' +response.read()) |
| + consecutive_success = 0 |
| + except urllib2.HTTPError as error: |
| + summary = format_summary('Error', commit_hash, error.code) |
| + logging.info(summary) |
| + send_email(subject=summary, body='Error message:\n' + error.reason) |
| + consecutive_success = 0 |
| + |
| +def send_email(subject, body): |
| + mail_config = uploader_mail.ParseMailConfig(call( |
| + ['gsutil', 'cat', 'gs://chrome-devtools-frontend/mail_config'], log_output=False)) |
| + uploader_mail.SendMail(mail_config, subject, body) |
| + logging.info('Sent email with subject: {} and body: {}'.format(subject, body)) |
| + |
| +def call(args, log_output=True, cwd=CHROMIUM_CHECKOUT_PATH): |
| + process = subprocess.Popen(args, stdout=subprocess.PIPE, |
| + stderr=subprocess.STDOUT, cwd=cwd) |
| + out, err = process.communicate() |
| + if process.returncode != 0: |
| + logging.info('Error {} from {}'.format(process.returncode, args)) |
| + if log_output: |
| + logging.info(out) |
| + return out |
| + |
| +def format_summary(status, commit_hash, status_code): |
| + return '[devtools-frontend-checker] {} for commit {} - HTTP status {}'.format( |
| + status, commit_hash, status_code) |
| + |
| +def start_uptime_check_server(): |
| + class Handler(BaseHTTPRequestHandler): |
| + def do_GET(self): |
| + self.send_response(200) |
| + self.send_header('Content-Type', 'text/html') |
| + self.end_headers() |
| + server = HTTPServer(('', 80), Handler) |
| + thread = threading.Thread(target=server.serve_forever) |
| + thread.daemon = True |
| + thread.start() |
| + |
| +if __name__ == '__main__': |
| + sys.exit(main()) |