fetch partial builder status from the cq master
This CL causes the CQ master to fetch not only the final build status,
but also the partial 'unittest' statuses.
BUG=chromium:310668
TEST=Unit tests pass.
Change-Id: I171e62d23a3bed9cec54b7d69659dd4effa7d0d6
Reviewed-on: https://chromium-review.googlesource.com/174433
Reviewed-by: Aviv Keshet <akeshet@chromium.org>
Tested-by: Aviv Keshet <akeshet@chromium.org>
Commit-Queue: Aviv Keshet <akeshet@chromium.org>
diff --git a/buildbot/cbuildbot_stages.py b/buildbot/cbuildbot_stages.py
index 1ac99f0..6a63cc1 100644
--- a/buildbot/cbuildbot_stages.py
+++ b/buildbot/cbuildbot_stages.py
@@ -1212,7 +1212,7 @@
super(LKGMCandidateSyncCompletionStage, self).__init__(*args, **kwargs)
self._slave_statuses = {}
- def _FetchSlaveStatuses(self):
+ def _FetchSlaveStatuses(self, step_name=None, wait_for_status=True):
"""Fetch and return build status for this build and any of its slaves."""
if self._options.debug:
# In debug mode, nothing is uploaded to Google Storage, so we bypass
@@ -1223,18 +1223,23 @@
elif not self._build_config['master']:
# Slaves only need to look at their own status.
return ManifestVersionedSyncStage.manifest_manager.GetBuildersStatus(
- [self._bot_id])
+ [self._bot_id], step_name=step_name,
+ wait_for_status=wait_for_status)
else:
builders = self._GetSlavesForMaster(self._build_config)
manager = ManifestVersionedSyncStage.manifest_manager
sub_manager = LKGMCandidateSyncStage.sub_manager
if sub_manager:
public_builders = [b['name'] for b in builders if not b['internal']]
- statuses = sub_manager.GetBuildersStatus(public_builders)
+ statuses = sub_manager.GetBuildersStatus(public_builders,
+ step_name=step_name, wait_for_status=wait_for_status)
private_builders = [b['name'] for b in builders if b['internal']]
- statuses.update(manager.GetBuildersStatus(private_builders))
+ statuses.update(manager.GetBuildersStatus(private_builders,
+ step_name=step_name, wait_for_status=wait_for_status))
else:
- statuses = manager.GetBuildersStatus([b['name'] for b in builders])
+ statuses = manager.GetBuildersStatus([b['name'] for b in builders],
+ step_name=step_name,
+ wait_for_status=wait_for_status)
return statuses
def _AbortCQHWTests(self):
@@ -1301,6 +1306,14 @@
self._AbortCQHWTests()
statuses = self._FetchSlaveStatuses()
+
+ # disable the unused-variable warning
+ # pylint: disable-msg=W0612
+ unittest_statuses = self._FetchSlaveStatuses(step_name='unittest',
+ wait_for_status=False)
+ # TODO: Handle the case where statuses shows full build failures, but
+ # unittest_statuses shows that all slave builder unit tests passed.
+ # In this case, submit and uprev the non-unit-test CLs only.
self._slave_statuses = statuses
failing_build_dict, inflight_build_dict = {}, {}
for builder, status in statuses.iteritems():
diff --git a/buildbot/lkgm_manager.py b/buildbot/lkgm_manager.py
index 064f9dd..dea8673 100755
--- a/buildbot/lkgm_manager.py
+++ b/buildbot/lkgm_manager.py
@@ -156,7 +156,11 @@
self.rel_working_dir = self.LKGM_SUBDIR
def _RunLambdaWithTimeout(self, function_to_run, use_long_timeout=False):
- """Runs function_to_run until it returns a value or timeout is reached."""
+ """Runs function_to_run until it returns a value or timeout is reached.
+
+ Returns:
+ The value returned by the final call to function_to_run.
+ """
function_success = False
start_time = time.time()
max_timeout = self.MAX_TIMEOUT_SECONDS
@@ -380,22 +384,32 @@
else:
return None
- def GetBuildersStatus(self, builders_array):
+ def GetBuildersStatus(self, builders_array, step_name=None,
+ wait_for_status=True):
"""Returns a build-names->status dictionary of build statuses.
Args:
builders_array: A list of the names of the builders to check.
+ step_name: The step name to get a partial builder status for.
+ Defaults to None, in which case the full builder
+ status is fetched.
+ wait_for_status: Defaults to True, in which case the call will
+ wait until status files appear (with a default
+ timeout). If False, will not wait for files to
+ appear.
"""
builders_completed = set()
builder_statuses = {}
def _CheckStatusOfBuildersArray():
- """Helper function that iterates through current statuses."""
+ """Helper function that iterates through current statuses.
+ """
for b in builders_array:
cached_status = builder_statuses.get(b)
if not cached_status or not cached_status.Completed():
logging.debug("Checking for builder %s's status", b)
- builder_status = self.GetBuildStatus(b, self.current_version)
+ builder_status = self.GetBuildStatus(b, self.current_version,
+ step_name=step_name)
builder_statuses[b] = builder_status
if builder_status is None:
logging.warn('No status found for builder %s.', b)
@@ -414,10 +428,14 @@
return 'Builds completed.'
# Check for build completion until all builders report in.
- builds_succeeded = self._RunLambdaWithTimeout(_CheckStatusOfBuildersArray,
- use_long_timeout=True)
+ if wait_for_status:
+ builds_succeeded = self._RunLambdaWithTimeout(_CheckStatusOfBuildersArray,
+ use_long_timeout=True)
+ else:
+ builds_succeeded = _CheckStatusOfBuildersArray()
+
if not builds_succeeded:
- logging.error('Not all builds finished before MAX_TIMEOUT reached.')
+ logging.error('Not all build statuses available or MAX_TIMEOUT reached.')
return builder_statuses
diff --git a/buildbot/lkgm_manager_unittest.py b/buildbot/lkgm_manager_unittest.py
index 0cf69fe..eba376b 100755
--- a/buildbot/lkgm_manager_unittest.py
+++ b/buildbot/lkgm_manager_unittest.py
@@ -341,12 +341,13 @@
osutils.Touch(manifest)
return manifest, dir_pfx
- def _GetBuildersStatus(self, builders, status_runs):
+ def _GetBuildersStatus(self, builders, status_runs, step_name=None):
"""Test a call to LKGMManager.GetBuildersStatus.
Args:
builders: List of builders to get status for.
status_runs: List of expected (builder, status) tuples.
+ step_name: Builder step to test getting status for. Default: None
"""
self.mox.StubOutWithMock(lkgm_manager.LKGMManager, 'GetBuildStatus')
for builder, status in status_runs:
@@ -355,7 +356,7 @@
if status is not None:
status = manifest_version.BuilderStatus(status, None)
lkgm_manager.LKGMManager.GetBuildStatus(
- builder, mox.IgnoreArg()).AndReturn(status)
+ builder, mox.IgnoreArg(), step_name=step_name).AndReturn(status)
self.mox.ReplayAll()
statuses = self.manager.GetBuildersStatus(builders)
diff --git a/buildbot/manifest_version.py b/buildbot/manifest_version.py
index a66dbfb..9d85221 100644
--- a/buildbot/manifest_version.py
+++ b/buildbot/manifest_version.py
@@ -535,7 +535,8 @@
return self._latest_status and self._latest_status.Failed()
@staticmethod
- def GetBuildStatus(builder, version, retries=NUM_RETRIES):
+ def GetBuildStatus(builder, version, retries=NUM_RETRIES,
+ step_name=None):
"""Returns a BuilderStatus instance for the given the builder.
Args:
@@ -547,7 +548,7 @@
A BuilderStatus instance containing the builder status and any optional
message associated with the status passed by the builder.
"""
- url = BuildSpecsManager._GetStatusUrl(builder, version)
+ url = BuildSpecsManager._GetStatusUrl(builder, version, step_name)
ctx = gs.GSContext(retries=retries)
try:
output = ctx.Cat(url).output