Index: appengine/findit/waterfall/build_failure_analysis.py |
diff --git a/appengine/findit/waterfall/build_failure_analysis.py b/appengine/findit/waterfall/build_failure_analysis.py |
index d1ecd1bf369682b301b13b498fd59ef72ad08c68..142a1c89a9ca24e55bbfad6b5a20f98285d05fbd 100644 |
--- a/appengine/findit/waterfall/build_failure_analysis.py |
+++ b/appengine/findit/waterfall/build_failure_analysis.py |
@@ -159,6 +159,15 @@ class _Justification(object): |
self._hints[hint] += score |
self._score += score |
+ def AddDEPSRoll(self, dep_path, dep_repo_url, dep_new_revision, |
+ dep_old_revision, file_path_in_log, score): |
+ url_to_changes_in_roll = '%s/+log/%s..%s?pretty=fuller' % ( |
+ dep_repo_url, dep_old_revision[:12], dep_new_revision[:12]) |
+ hint = ('Rolled %s with changes %s (and %s was in log)' % ( |
+ dep_path, url_to_changes_in_roll, file_path_in_log)) |
+ self._hints[hint] = score |
+ self._score += score |
+ |
def ToDict(self): |
return { |
'score': self._score, |
@@ -234,13 +243,15 @@ def _CheckFile(touched_file, |
score, |
file_name_occurrences.get(file_name)) |
-def _CheckFiles(failure_signal, change_log): |
+ |
+def _CheckFiles(failure_signal, change_log, deps_info): |
"""Check files in the given change log of a CL against the failure signal. |
Args: |
failure_signal (FailureSignal): The failure signal of a failed step or test. |
change_log (dict): The change log of a CL as returned by |
common.change_log.ChangeLog.ToDict(). |
+ deps_info (dict): Output of pipeline ExtractDEPSInfoPipeline. |
Returns: |
A dict as returned by _Justification.ToDict() if the CL is suspected for the |
@@ -262,26 +273,35 @@ def _CheckFiles(failure_signal, change_log): |
justification = _Justification() |
for file_path_in_log, _ in failure_signal.files.iteritems(): |
- # TODO(stgao): remove this hack when DEPS parsing is supported. |
- if file_path_in_log.startswith('src/'): |
- file_path_in_log = file_path_in_log[4:] |
+ # Strip src/ from file path to make all files relative to the chromium root |
+ # directory. |
+ file_path_in_log = file_path_in_log.lstrip('src/') |
for touched_file in change_log['touched_files']: |
_CheckFile( |
touched_file, file_path_in_log, justification, file_name_occurrences) |
+ for roll in deps_info.get('deps_rolls', {}).get(change_log['revision'], []): |
+ dep_path = roll['path'].lstrip('src/') |
+ if file_path_in_log.startswith(dep_path): |
+ justification.AddDEPSRoll( |
+ dep_path, roll['repo_url'], roll['new_revision'], |
+ roll['old_revision'], file_path_in_log[len(dep_path):], 2) |
+ |
if not justification.score: |
return None |
else: |
return justification.ToDict() |
-def AnalyzeBuildFailure(failure_info, change_logs, failure_signals): |
+def AnalyzeBuildFailure( |
+ failure_info, change_logs, deps_info, failure_signals): |
"""Analyze the given failure signals, and figure out culprit CLs. |
Args: |
failure_info (dict): Output of pipeline DetectFirstFailurePipeline. |
change_logs (dict): Output of pipeline PullChangelogPipeline. |
+ deps_info (dict): Output of pipeline ExtractDEPSInfoPipeline. |
failure_signals (dict): Output of pipeline ExtractSignalPipeline. |
Returns: |
@@ -355,7 +375,8 @@ def AnalyzeBuildFailure(failure_info, change_logs, failure_signals): |
while build_number <= failed_build_number: |
for revision in builds[str(build_number)]['blame_list']: |
- justification_dict = _CheckFiles(failure_signal, change_logs[revision]) |
+ justification_dict = _CheckFiles( |
+ failure_signal, change_logs[revision], deps_info) |
if not justification_dict: |
continue |