Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 <!-- | 1 <!-- |
| 2 Copyright 2014 The Chromium Authors. All rights reserved. | 2 Copyright 2014 The Chromium Authors. All rights reserved. |
| 3 Use of this source code is governed by a BSD-style license that can be | 3 Use of this source code is governed by a BSD-style license that can be |
| 4 found in the LICENSE file. | 4 found in the LICENSE file. |
| 5 --> | 5 --> |
| 6 | 6 |
| 7 <link rel="import" href="../lib/net.html"> | 7 <link rel="import" href="../lib/net.html"> |
| 8 <link rel="import" href="../lib/update-util.html"> | 8 <link rel="import" href="../lib/update-util.html"> |
| 9 <link rel="import" href="ct-builder-revisions.html"> | 9 <link rel="import" href="ct-builder-revisions.html"> |
| 10 <link rel="import" href="ct-failure.html"> | 10 <link rel="import" href="ct-failure.html"> |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 31 "https://build.chromium.org/p/chromium.chromiumos", | 31 "https://build.chromium.org/p/chromium.chromiumos", |
| 32 "https://build.chromium.org/p/chromium.gpu", | 32 "https://build.chromium.org/p/chromium.gpu", |
| 33 "https://build.chromium.org/p/chromium.linux", | 33 "https://build.chromium.org/p/chromium.linux", |
| 34 "https://build.chromium.org/p/chromium.mac", | 34 "https://build.chromium.org/p/chromium.mac", |
| 35 "https://build.chromium.org/p/chromium.memory", | 35 "https://build.chromium.org/p/chromium.memory", |
| 36 "https://build.chromium.org/p/chromium.win" | 36 "https://build.chromium.org/p/chromium.win" |
| 37 ], | 37 ], |
| 38 }; | 38 }; |
| 39 } | 39 } |
| 40 | 40 |
| 41 (function() { | |
| 42 'use strict'; | |
| 43 | |
| 41 // Reverse sorting order, if a > b, return a negative number. | 44 // Reverse sorting order, if a > b, return a negative number. |
| 42 CTFailures.prototype._failureByTreeListComparator = function(tree, a, b) { | 45 CTFailures.prototype._failureByTreeListComparator = function(tree, a, b) { |
| 43 if (tree === undefined) | 46 if (tree === undefined) |
| 44 tree = 'chromium'; | 47 tree = 'chromium'; |
| 45 | 48 |
| 46 var rev_a = a.commitList.revisions; | 49 var rev_a = a.commitList.revisions; |
| 47 var rev_b = b.commitList.revisions; | 50 var rev_b = b.commitList.revisions; |
| 48 | 51 |
| 49 if (!rev_a || !Object.keys(rev_a).length) { | 52 if (!rev_a || !Object.keys(rev_a).length) { |
| 50 if (!rev_b || !Object.keys(rev_b).length) | 53 if (!rev_b || !Object.keys(rev_b).length) |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 70 var b_list = rev_b[keys[i]]; | 73 var b_list = rev_b[keys[i]]; |
| 71 if (!b_list) | 74 if (!b_list) |
| 72 return -1; | 75 return -1; |
| 73 | 76 |
| 74 if (a_list.last() != b_list.last()) | 77 if (a_list.last() != b_list.last()) |
| 75 return b_list.last() - a_list.last(); | 78 return b_list.last() - a_list.last(); |
| 76 } | 79 } |
| 77 return 0; | 80 return 0; |
| 78 }; | 81 }; |
| 79 | 82 |
| 83 // Updates the format of the alerts array to be easier to parse. | |
| 84 CTFailures.prototype._mungeAlerts = function(alerts) { | |
|
ojan
2014/09/05 00:56:42
Mind writing basic unit tests for this function? I
Jeffrey Yasskin
2014/09/09 01:00:32
Done.
| |
| 85 var masterToTree = {}; | |
| 86 Object.keys(this._trees, function(tree, masters) { | |
| 87 masters.forEach(function(master) { | |
| 88 masterToTree[master] = tree; | |
| 89 }); | |
| 90 }); | |
| 91 | |
| 92 alerts.forEach(function(failure) { | |
| 93 // FIXME: Have the server store the actual failure type in a different | |
| 94 // field instead of smashing it into the reason. | |
| 95 if (failure.failureType) { | |
| 96 // The server has been fixed. | |
|
ojan
2014/09/05 00:56:42
<3
| |
| 97 } else { | |
| 98 if (failure.reason) { | |
| 99 var parts = failure.reason.split(':'); | |
| 100 failure.reason = parts[0]; | |
| 101 failure.failureType = parts[1] || 'FAIL'; | |
| 102 } else { | |
| 103 failure.failureType = 'UNKNOWN'; | |
| 104 } | |
| 105 } | |
| 106 | |
| 107 // FIXME: Figure out what tree masters that aren't in masterToTree | |
| 108 // we should have. | |
| 109 failure.tree = masterToTree[failure.master_url]; | |
| 110 }); | |
| 111 }; | |
| 112 | |
| 80 CTFailures.prototype.update = function() { | 113 CTFailures.prototype.update = function() { |
| 81 var annotationPromise = CTFailureGroup.fetchAnnotations(); | 114 var annotationPromise = CTFailureGroup.fetchAnnotations(); |
| 82 | 115 |
| 83 return net.json('http://sheriff-o-matic.appspot.com/alerts').then(function(dat a) { | 116 return net.json('http://sheriff-o-matic.appspot.com/alerts').then(function(dat a) { |
| 84 return annotationPromise.then(function(annotations) { | 117 return annotationPromise.then(function(annotations) { |
| 85 // FIXME: Don't special-case the blink master. | 118 // FIXME: Don't special-case the blink master. |
| 86 this.builderLatestRevisions = new CTBuilderRevisions(data.latest_builder_i nfo['chromium.webkit']); | 119 this.builderLatestRevisions = new CTBuilderRevisions(data.latest_builder_i nfo['chromium.webkit']); |
| 87 var newFailures = {}; | 120 var newFailures = {}; |
| 88 this.lastUpdateDate = new Date(data.date * 1000); | 121 this.lastUpdateDate = new Date(data.date * 1000); |
| 122 this._mungeAlerts(data.alerts); | |
| 123 var alertsByKey = {} | |
|
ojan
2014/09/05 00:56:42
Add a FIXME to change builder_alerts to just have
Jeffrey Yasskin
2014/09/09 01:00:33
Done.
| |
| 124 data.alerts.forEach(function(alert) { | |
| 125 alertsByKey[alert.key] = alert; | |
| 126 }); | |
| 89 // Update |failures| with the appropriate CTFailureGroup's for each | 127 // Update |failures| with the appropriate CTFailureGroup's for each |
| 90 // tree. | 128 // tree. |
| 91 data.range_groups.forEach(function(rangeGroup) { | 129 data.range_groups.forEach(function(rangeGroup) { |
| 92 this._processFailuresForRangeGroup(newFailures, rangeGroup, data.alerts, annotations); | 130 this._processFailuresForRangeGroup(newFailures, rangeGroup, alertsByKey, annotations); |
| 93 }.bind(this)); | 131 }.bind(this)); |
| 94 // Sort failure groups so that newer failures are shown at the top | 132 // Sort failure groups so that newer failures are shown at the top |
| 95 // of the UI. | 133 // of the UI. |
| 96 Object.keys(newFailures, function (tree, failuresByTree) { | 134 Object.keys(newFailures, function (tree, failuresByTree) { |
| 97 failuresByTree.sort(this._failureByTreeListComparator.bind(this, tree)); | 135 failuresByTree.sort(this._failureByTreeListComparator.bind(this, tree)); |
| 98 }.bind(this)); | 136 }.bind(this)); |
| 99 this.failures = updateUtil.updateLeft(this.failures, newFailures); | 137 this.failures = updateUtil.updateLeft(this.failures, newFailures); |
| 100 }.bind(this)); | 138 }.bind(this)); |
| 101 }.bind(this)); | 139 }.bind(this)); |
| 102 }; | 140 }; |
| 103 | 141 |
| 104 CTFailures.prototype._failureComparator = function(a, b) { | 142 CTFailures.prototype._failureComparator = function(a, b) { |
| 105 if (a.step > b.step) | 143 if (a.step > b.step) |
| 106 return 1; | 144 return 1; |
| 107 if (a.step < b.step) | 145 if (a.step < b.step) |
| 108 return -1 | 146 return -1 |
| 109 if (a.testName > b.testName) | 147 if (a.testName > b.testName) |
| 110 return 1; | 148 return 1; |
| 111 if (a.testName < b.testName) | 149 if (a.testName < b.testName) |
| 112 return -1 | 150 return -1 |
| 113 return 0; | 151 return 0; |
| 114 }; | 152 }; |
| 115 | 153 |
| 116 CTFailures.prototype._processFailuresForRangeGroup = function(newFailures, range Group, alerts, annotations) { | 154 function groupFailuresByTreeAndReason(failures, annotations) { |
|
ojan
2014/09/05 00:56:42
Ditto. You'll need to make this a function on CTFa
Jeffrey Yasskin
2014/09/09 01:00:32
To do the refactoring that Elliott asked for in ht
Jeffrey Yasskin
2014/09/09 01:00:33
Tested.
| |
| 117 var masterToTree = {}; | 155 var failuresByTree = {}; |
| 118 Object.keys(this._trees, function(tree, masters) { | 156 failures.forEach(function(failure) { |
| 119 masters.forEach(function(master) { | |
| 120 masterToTree[master] = tree; | |
| 121 }); | |
| 122 }); | |
| 123 | |
| 124 // A rangeGroup may be related to multiple alerts (via |failure_keys|). Catego rize | |
| 125 // these failures by reason (cause of failure), so that they can be grouped in the UI | |
| 126 // (via a CTFailureGroup). Failures will be grouped in |failuresByReason|. | |
| 127 var failuresByReason = {}; | |
| 128 rangeGroup.failure_keys.forEach(function(failure_key) { | |
| 129 var failure = alerts.find(function(item) { return item.key == failure_key; } ); | |
| 130 // Establish the key to uniquely identify a failure by reason. | 157 // Establish the key to uniquely identify a failure by reason. |
| 131 var reason, failureType; | |
| 132 if (failure.reason) { | |
| 133 // FIXME: Store the actual failure type in a different field instead of sm ashing it into the reason. | |
| 134 var parts = failure.reason.split(':'); | |
| 135 reason = parts[0]; | |
| 136 failureType = parts[1] || 'FAIL'; | |
| 137 } else { | |
| 138 reason = null; | |
| 139 failureType = 'UNKNOWN'; | |
| 140 } | |
| 141 | |
| 142 var failureKey = CTFailure.createKey(failure); | 158 var failureKey = CTFailure.createKey(failure); |
| 143 | 159 |
| 144 var reasonKey = JSON.stringify({ | 160 var reasonKey = JSON.stringify({ |
| 145 step: failure.step_name, | 161 step: failure.step_name, |
| 146 reason: reason, | 162 reason: failure.reason, |
| 147 }); | 163 }); |
| 148 | 164 |
| 149 // FIXME: Figure out what tree masters that aren't in masterToTree | |
| 150 // we should have. | |
| 151 var tree = masterToTree[failure.master_url]; | |
| 152 | |
| 153 // FIXME: Use a model class instead of a dumb object. | 165 // FIXME: Use a model class instead of a dumb object. |
| 154 if (!failuresByReason[reasonKey]) | 166 if (!failuresByTree[failure.tree]) |
| 155 failuresByReason[reasonKey] = {}; | 167 failuresByTree[failure.tree] = {}; |
| 156 if (!failuresByReason[reasonKey][tree]) | 168 if (!failuresByTree[failure.tree][reasonKey]) |
| 157 failuresByReason[reasonKey][tree] = {}; | 169 failuresByTree[failure.tree][reasonKey] = {}; |
| 158 failuresByReason[reasonKey][tree][failure.builder_name] = { | 170 failuresByTree[failure.tree][reasonKey][failure.builder_name] = { |
| 159 key: failureKey, | 171 key: failureKey, |
| 160 // FIXME: Rename to failureType. | 172 // FIXME: Rename to failureType. |
| 161 actual: failureType, | 173 actual: failure.failureType, |
| 162 lastFailingBuild: failure.last_failing_build, | 174 lastFailingBuild: failure.last_failing_build, |
| 163 earliestFailingBuild: failure.failing_build, | 175 earliestFailingBuild: failure.failing_build, |
| 164 masterUrl: failure.master_url, | 176 masterUrl: failure.master_url, |
| 165 failingBuildCount: failure.failing_build_count, | 177 failingBuildCount: failure.failing_build_count, |
| 166 annotation: annotations[failureKey], | 178 annotation: annotations[failureKey], |
| 167 }; | 179 }; |
| 168 }.bind(this)); | 180 }); |
| 181 return failuresByTree | |
| 182 }; | |
| 169 | 183 |
| 170 if (!Object.keys(failuresByReason).length) | 184 CTFailures.prototype._processFailuresForRangeGroup = function(newFailures, range Group, alerts, annotations) { |
| 185 // A rangeGroup may be related to multiple alerts (via |failure_keys|). Catego rize | |
| 186 // these failures by reason (cause of failure), so that they can be grouped in the UI | |
| 187 // (via a CTFailureGroup). | |
| 188 var failures = rangeGroup.failure_keys.map(function(failure_key) { | |
| 189 return alerts[failure_key]; | |
| 190 }); | |
| 191 var failuresByTree = groupFailuresByTreeAndReason(failures, annotations); | |
| 192 | |
| 193 if (Object.isEmpty(failuresByTree)) | |
| 171 return; | 194 return; |
| 172 | 195 |
| 173 // Maps a tree id to a list of CTFailures in that tree. | 196 Object.keys(failuresByTree, function(tree, resultsByReason) { |
| 174 var groupedFailures = {}; | 197 var treeFailures = []; |
| 175 Object.keys(failuresByReason, function(reasonKey, resultsByTree) { | 198 Object.keys(resultsByReason, function(reasonKey, resultsByBuilder) { |
| 176 var failure = JSON.parse(reasonKey); | 199 var failure = JSON.parse(reasonKey); |
| 177 Object.keys(resultsByTree, function(tree, resultsByBuilder) { | 200 treeFailures.push( |
| 178 if (!groupedFailures[tree]) | |
| 179 groupedFailures[tree] = []; | |
| 180 groupedFailures[tree].push( | |
| 181 new CTFailure(failure.step, failure.reason, resultsByBuilder)); | 201 new CTFailure(failure.step, failure.reason, resultsByBuilder)); |
| 182 }) | 202 }) |
| 183 }); | 203 treeFailures.sort(this._failureComparator); |
| 184 | |
| 185 Object.keys(groupedFailures, function(tree, failures) { | |
| 186 failures.sort(this._failureComparator); | |
| 187 | 204 |
| 188 if (!newFailures[tree]) | 205 if (!newFailures[tree]) |
| 189 newFailures[tree] = []; | 206 newFailures[tree] = []; |
| 190 var commitList = new CTCommitList(this.commitLog, rangeGroup.likely_revision s); | 207 var commitList = new CTCommitList(this.commitLog, rangeGroup.likely_revision s); |
| 191 newFailures[tree].push(new CTFailureGroup(rangeGroup.sort_key, failures, com mitList)); | 208 newFailures[tree].push(new CTFailureGroup(rangeGroup.sort_key, treeFailures, commitList)); |
| 192 }.bind(this)); | 209 }.bind(this)); |
| 193 }; | 210 }; |
| 194 | 211 |
| 212 })(); | |
| 195 </script> | 213 </script> |
| OLD | NEW |