blob: 4ea026e255e4d1845f13d067ca3095f6d494d447 [file] [log] [blame]
# Copyright 2017 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Routes for CL exonerator."""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import httplib
import sys
from chromite.lib import cidb
from chromite.lib import parallel
from chromite.lib import cros_logging as logging
import flask
import config
import debug_routes
import flex_ts_mon.setup
from exonerator import cidblib
from exonerator import gerrit_cq
from exonerator import gerrit_precq
from exonerator import innocent_cls_cq
from exonerator import innocent_cls_precq
from exonerator import weekend
app = flask.Flask(__name__)
config = config.Config()
# TODO(phobbs) make this higher at night / weekend
PRE_CQ_TYPE = 'pre-cq'
CQ_TYPE = 'cq'
# This must be done at the top level because gunicorn and nginx does not run us
# as __main__
def Hello():
"""Placeholder route"""
return 'hello world'
# Ideally this would be a POST, but Appengine cron only makes GET requests.
def ExonerateCQ():
"""Exonerates innocent CLs which were kicked out."""
if not _RequestIsFromAppEngineCron():
conn = cidb.CIDBConnection(
config.cidb_cred_dir, for_service=config.is_service)
all_exonerated = []
for batch in innocent_cls_cq.NewInnocentCLs(conn, limit=_CQ_BUILD_LIMIT):
all_exonerated.extend(_ExonerateBatch(conn, batch, CQ_TYPE))
return flask.jsonify(exonerated=all_exonerated)
def ExoneratePreCQ():
"""Exonerates innocent CLs which were kicked out."""
if not _RequestIsFromAppEngineCron():
# Blunt force disable for PreCQ exonerator
conn = cidb.CIDBConnection(
config.cidb_cred_dir, for_service=config.is_service)
all_exonerated = []
on_peak = not weekend.HaveUnlimitedResources()
for batch in innocent_cls_precq.NewInnocentCLs(conn, on_peak=on_peak):
all_exonerated.extend(_ExonerateBatch(conn, batch, PRE_CQ_TYPE))
return flask.jsonify(exonerated=all_exonerated)
def _ExonerateBatch(conn, batch, exoneration_type):
"""Exonerates a batch of changes, then inserts CLActions.
conn: The CIDBConnection to use
batch: A List[exonerator.gerrit_cq.ChangeWithBuild] of changes to exonerate.
exoneration_type: A string in ('cq', 'pre-cq')
exonerate_f = {
'cq': gerrit_cq.MaybeExonerate,
'pre-cq': gerrit_precq.MaybeExonerate,
exonerated_flags = parallel.RunTasksInProcessPool(
[[change, build_id] for change, build_id in batch])
exonerated_changes = []
for change, exonerated in zip(batch, exonerated_flags):
if exonerated:
if exonerated_changes:
conn, exonerated_changes, exoneration_type)
return exonerated_changes
def _RequestIsFromAppEngineCron():
"""Returns whether the request came from Appengine's cron service.
for more details.
return flask.request.headers.get(APPENGINE_CRON_HEADER) == 'true'
_METRICS_DEBUG_FILE = '/tmp/metrics-debug.log' if config.debug else None
def SetupWorkerMetrics():
"""Sets up the metrics sending thread.
This must happen post-fork, or else the gunicorn workers will all use the
same hostname and task_num arguments, causing conflicts when they flush
if __name__ == '__main__':
print('Run the app locally with '
'"gunicorn -c -b :8080 main:app"', file=sys.stderr)