blob: 04d2317cbcad0ea1f62d2fd9492ef2f2adb549f9 [file] [log] [blame]
#!/usr/bin/python
# Copyright 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
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:
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())