blob: 3afe19d180134747c268aa00c94907da4108a5bf [file] [log] [blame]
# Copyright 2016 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.
"""Module for tracking relevant changes (i.e. CLs) to validate."""
from __future__ import print_function
from chromite.lib import clactions
from chromite.lib import constants
class RelevantChanges(object):
"""Class that quries and tracks relevant changes."""
@classmethod
def _GetSlaveMappingAndCLActions(cls, master_build_id, db, config, changes,
slave_buildbucket_ids):
"""Query CIDB to for slaves and CL actions.
Args:
master_build_id: Build id of this master build.
db: Instance of cidb.CIDBConnection.
config: Instance of config_lib.BuildConfig of this build.
changes: A list of GerritPatch instances to examine.
slave_buildbucket_ids: A list of buildbucket_ids (strings) of slave builds
scheduled by Buildbucket.
Returns:
A tuple of (config_map, action_history), where the config_map
is a dictionary mapping build_id to config name for all slaves
in this run plus the master, and action_history is a list of all
CL actions associated with |changes|.
"""
assert db, 'No database connection to use.'
slave_list = db.GetSlaveStatuses(
master_build_id, buildbucket_ids=slave_buildbucket_ids)
# TODO(akeshet): We are getting the full action history for all changes that
# were in this CQ run. It would make more sense to only get the actions from
# build_ids of this master and its slaves.
action_history = db.GetActionsForChanges(changes)
config_map = dict()
for d in slave_list:
config_map[d['id']] = d['build_config']
# TODO(akeshet): We are giving special treatment to the CQ master, which
# makes this logic CQ specific. We only use this logic in the CQ anyway at
# the moment, but may need to reconsider if we need to generalize to other
# master-slave builds.
assert config.name == constants.CQ_MASTER
config_map[master_build_id] = constants.CQ_MASTER
return config_map, action_history
@classmethod
def GetRelevantChangesForSlaves(cls, master_build_id, db, config, changes,
no_stat, slave_buildbucket_ids):
"""Compile a set of relevant changes for each slave.
Args:
master_build_id: Build id of this master build.
db: Instance of cidb.CIDBConnection.
config: Instance of config_lib.BuildConfig of this build.
changes: A list of GerritPatch instances to examine.
no_stat: Set of builder names of slave builders that had status None.
slave_buildbucket_ids: A list of buildbucket_ids (strings) of slave builds
scheduled by Buildbucket.
Returns:
A dictionary mapping a slave config name to a set of relevant changes
(as GerritPatch instances).
"""
# Retrieve the slaves and clactions from CIDB.
config_map, action_history = cls._GetSlaveMappingAndCLActions(
master_build_id, db, config, changes, slave_buildbucket_ids)
changes_by_build_id = clactions.GetRelevantChangesForBuilds(
changes, action_history, config_map.keys())
# Convert index from build_ids to config names.
changes_by_config = dict()
for k, v in changes_by_build_id.iteritems():
changes_by_config[config_map[k]] = v
for config in no_stat:
# If a slave is in |no_stat|, it means that the slave never
# finished applying the changes in the sync stage. Hence the CL
# pickup actions for this slave may be
# inaccurate. Conservatively assume all changes are relevant.
changes_by_config[config] = set(changes)
return changes_by_config