Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1103)

Unified Diff: scripts/slave/recipe_modules/auto_bisect/bisector.py

Issue 1339613005: Refactoring scripts that wait for buildbot jobs to complete. (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/build.git@hax
Patch Set: . Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: scripts/slave/recipe_modules/auto_bisect/bisector.py
diff --git a/scripts/slave/recipe_modules/auto_bisect/bisector.py b/scripts/slave/recipe_modules/auto_bisect/bisector.py
index 13636398fe4bf3ae8d6dfe1148b8d057fb1b85cf..521e8cce43722212024ff55d3b8078a642768201 100644
--- a/scripts/slave/recipe_modules/auto_bisect/bisector.py
+++ b/scripts/slave/recipe_modules/auto_bisect/bisector.py
@@ -453,46 +453,61 @@ class Bisector(object):
A revision is considered to make progress when a build file is uploaded to
the appropriate bucket, or when buildbot test job is complete.
"""
- gsutil_path = self.api.m.gsutil.get_gsutil_path()
- name = 'Waiting for revision ' + revision_list[0].revision_string
- if len(revision_list) > 1:
- name += ' and %d other revision(s).' % (len(revision_list) - 1)
+
+ revision_mapping = {}
+ gs_jobs = []
+ buildbot_jobs = []
+
+ for revision in revision_list:
+ url = revision.get_next_url()
+ buildbot_job = revision.get_buildbot_locator()
+ if url:
+ gs_jobs.append({'type': 'gs', 'location': url})
+ revision_mapping[url] = revision
+ if buildbot_job:
+ buildbot_job['type'] = 'buildbot'
prasadv 2015/09/17 22:33:34 Just curious, why 'type' is not added in get_build
RobertoCN 2015/09/19 00:32:54 Because the 'type': 'gs' is just 2 lines above. Bu
+ buildbot_jobs.append(buildbot_job)
+ revision_mapping[buildbot_job['job_name']] = revision
+
+ jobs_config = {'jobs': buildbot_jobs + gs_jobs}
+
script = self.api.resource('wait_for_any.py')
- args_list = [gsutil_path]
- url_mapping = {r.get_next_url(): r for r in revision_list}
- bb_locator_mapping = {r.get_buildbot_locator(): r for r in revision_list}
- bb_locator_list = bb_locator_mapping.keys()
- url_list = url_mapping.keys()
- args_list += [url for url in url_list if url and url is not None]
- args_list += [entry for entry in bb_locator_list
- if entry and entry is not None]
- args_list.append(
- '--timeout=%d' % (
- self.get_build_timeout_minutes() * 60))
+ args_list = [self.api.m.gsutil.get_gsutil_path()] if gs_jobs else []
+
try:
+ step_name = 'Waiting for revision ' + revision_list[0].revision_string
+ if len(revision_list) > 1:
+ step_name += ' and %d other revision(s).' % (len(revision_list) - 1)
step_result = self.api.m.python(
- str(name),
+ str(step_name),
script,
args_list,
- stdout=self.api.m.raw_io.output())
+ stdout=self.api.m.json.output(),
+ stdin=self.api.m.json.input(jobs_config))
except self.api.m.step.StepFailure: # pragma: no cover
# StepFailure is interpreted as a timeout.
for revision in revision_list:
revision.status = revision_state.RevisionState.FAILED
return None
prasadv 2015/09/17 22:33:34 When this happens what should be the behavior of w
RobertoCN 2015/09/19 00:32:54 Changed it so that we keep the step red and procee
RobertoCN 2015/09/19 00:32:54 If wait_for_any.py errors out, all revisions will
- step_output = step_result.stdout or 'Build finished: Unknown'
- for line in step_output.splitlines():
- if line.startswith('Build finished: '):
- finished_url = line[len('Build finished: '):].strip()
- return url_mapping.get(finished_url)
- if line.startswith('Failed build url: '): # pragma: no cover
- url = line[len('Failed build url: '):].strip()
- step_result.presentation.links['Failed build'] = url
prasadv 2015/09/17 22:33:34 This is missing.
RobertoCN 2015/09/19 00:32:54 Done.
- if line.startswith('Build failed: '): # pragma: no cover
- failed_build_locator = line[len('Build failed: '):].strip()
- failed_build = bb_locator_mapping.get(failed_build_locator)
- failed_build.status = revision_state.RevisionState.FAILED
- return failed_build
+ if not step_result.stdout:
+ return None
+ step_results = step_result.stdout
+ failed_jobs = step_results.get('failed', [])
+ completed_jobs = step_results.get('completed', [])
+ assert failed_jobs or completed_jobs
+ # Marked all failed builds as failed
+ for job in failed_jobs:
+ last_failed_revision = revision_mapping[str(job.get(
+ 'location', job.get('job_name')))]
+ last_failed_revision.status = revision_state.RevisionState.FAILED
+
+ # Return a completed job if availavle
+ for job in completed_jobs:
+ return revision_mapping[str(job.get(
+ 'location', job.get('job_name')))]
+
+ # Or return any of the failed revisions
+ return last_failed_revision
def wait_for_any(self, revision_list):
"""Waits for any of the revisions in the list to finish its job(s)."""
@@ -560,11 +575,6 @@ class Bisector(object):
# Reasonable fallback
return 'linux_perf_tester'
- def get_build_timeout_minutes(self):
- if 'win' in self.get_perf_tester_name():
- return 4 * 60
- return 2 * 60
-
def get_builder_bot_for_this_platform(self):
# TODO(prasadv): We should refactor these codes to remove hard coded values.
bot_name = self.get_perf_tester_name()

Powered by Google App Engine
This is Rietveld 408576698