117 lines
4.0 KiB
Python
117 lines
4.0 KiB
Python
|
#!/usr/bin/env python
|
||
|
#-*- coding: utf-8 -*-
|
||
|
# Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||
|
#
|
||
|
# Use of this source code is governed by a BSD-style license
|
||
|
# that can be found in the LICENSE file in the root of the source
|
||
|
# tree. An additional intellectual property rights grant can be found
|
||
|
# in the file PATENTS. All contributing project authors may
|
||
|
# be found in the AUTHORS file in the root of the source tree.
|
||
|
|
||
|
"""Loads build status data for the dashboard."""
|
||
|
|
||
|
__author__ = 'phoglund@webrtc.org (Patrik Höglund)'
|
||
|
|
||
|
from google.appengine.ext import db
|
||
|
|
||
|
|
||
|
def _all_ok(statuses):
|
||
|
return filter(lambda status: status != "OK", statuses) == []
|
||
|
|
||
|
|
||
|
def _get_first_entry(iterable):
|
||
|
if not iterable:
|
||
|
return None
|
||
|
for item in iterable:
|
||
|
return item
|
||
|
|
||
|
|
||
|
class BuildStatusLoader:
|
||
|
""" Loads various build status data from the database."""
|
||
|
|
||
|
def load_build_status_data(self):
|
||
|
"""Returns the latest conclusive build status for each bot.
|
||
|
|
||
|
The statuses OK or failed are considered to be conclusive.
|
||
|
|
||
|
The two most recent revisions are considered. The set of bots returned
|
||
|
will therefore be the bots that were reported the two most recent
|
||
|
revisions. This script will therefore adapt automatically to any changes
|
||
|
in the set of available bots.
|
||
|
|
||
|
Returns:
|
||
|
A list of BuildStatusData entities with one entity per bot.
|
||
|
"""
|
||
|
|
||
|
build_status_entries = db.GqlQuery('SELECT * '
|
||
|
'FROM BuildStatusData '
|
||
|
'ORDER BY revision DESC ')
|
||
|
|
||
|
bots_to_latest_conclusive_entry = dict()
|
||
|
for entry in build_status_entries:
|
||
|
if entry.status == "building":
|
||
|
# The 'building' status it not conclusive, so discard this entry and
|
||
|
# pick up the entry for this bot on the next revision instead. That
|
||
|
# entry is guaranteed to have a status != 'building' since a bot cannot
|
||
|
# be building two revisions simultaneously.
|
||
|
continue
|
||
|
if bots_to_latest_conclusive_entry.has_key(entry.bot_name):
|
||
|
# We've already determined this bot's status.
|
||
|
continue
|
||
|
|
||
|
bots_to_latest_conclusive_entry[entry.bot_name] = entry
|
||
|
|
||
|
return bots_to_latest_conclusive_entry.values()
|
||
|
|
||
|
def load_last_modified_at(self):
|
||
|
build_status_root = db.GqlQuery('SELECT * '
|
||
|
'FROM BuildStatusRoot').get()
|
||
|
if not build_status_root:
|
||
|
# Operating on completely empty database
|
||
|
return None
|
||
|
|
||
|
return build_status_root.last_updated_at
|
||
|
|
||
|
def compute_lkgr(self):
|
||
|
""" Finds the most recent revision for which all bots are green.
|
||
|
|
||
|
Returns:
|
||
|
The last known good revision (as an integer) or None if there
|
||
|
is no green revision in the database.
|
||
|
|
||
|
Implementation note: The data store fetches stuff as we go, so we won't
|
||
|
read in the whole status table unless the LKGR is right at the end or
|
||
|
we don't have a LKGR.
|
||
|
"""
|
||
|
build_status_entries = db.GqlQuery('SELECT * '
|
||
|
'FROM BuildStatusData '
|
||
|
'ORDER BY revision DESC ')
|
||
|
|
||
|
first_entry = _get_first_entry(build_status_entries)
|
||
|
if first_entry is None:
|
||
|
# No entries => no LKGR
|
||
|
return None
|
||
|
|
||
|
current_lkgr = first_entry.revision
|
||
|
statuses_for_current_lkgr = [first_entry.status]
|
||
|
|
||
|
for entry in build_status_entries:
|
||
|
if current_lkgr == entry.revision:
|
||
|
statuses_for_current_lkgr.append(entry.status)
|
||
|
else:
|
||
|
# Starting on new revision, check previous revision.
|
||
|
if _all_ok(statuses_for_current_lkgr):
|
||
|
# All bots are green; LKGR found.
|
||
|
return current_lkgr
|
||
|
else:
|
||
|
# Not all bots are green, so start over on the next revision.
|
||
|
current_lkgr = entry.revision
|
||
|
statuses_for_current_lkgr = [entry.status]
|
||
|
|
||
|
if _all_ok(statuses_for_current_lkgr):
|
||
|
# There was only one revision and it was OK.
|
||
|
return current_lkgr
|
||
|
|
||
|
# There is no all-green revision in the database.
|
||
|
return None
|