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 22 matching lines...) Expand all Loading... |
33 "https://build.chromium.org/p/chromium.chromiumos", | 33 "https://build.chromium.org/p/chromium.chromiumos", |
34 "https://build.chromium.org/p/chromium.gpu", | 34 "https://build.chromium.org/p/chromium.gpu", |
35 "https://build.chromium.org/p/chromium.linux", | 35 "https://build.chromium.org/p/chromium.linux", |
36 "https://build.chromium.org/p/chromium.mac", | 36 "https://build.chromium.org/p/chromium.mac", |
37 "https://build.chromium.org/p/chromium.memory", | 37 "https://build.chromium.org/p/chromium.memory", |
38 "https://build.chromium.org/p/chromium.win" | 38 "https://build.chromium.org/p/chromium.win" |
39 ], | 39 ], |
40 }; | 40 }; |
41 } | 41 } |
42 | 42 |
| 43 (function() { |
| 44 'use strict'; |
| 45 |
43 // FIXME: This could potentially move onto CTSheriffFailureGroupData as it isn't
relevant to | 46 // FIXME: This could potentially move onto CTSheriffFailureGroupData as it isn't
relevant to |
44 // trooper failures. | 47 // trooper failures. |
45 // Reverse sorting order, if a > b, return a negative number. | 48 // Reverse sorting order, if a > b, return a negative number. |
46 CTFailures.prototype._failureByTreeListComparator = function(tree, a, b) { | 49 CTFailures.prototype._failureByTreeListComparator = function(tree, a, b) { |
47 if (tree === undefined) | 50 if (tree === undefined) |
48 tree = 'chromium'; | 51 tree = 'chromium'; |
49 | 52 |
50 var rev_a = a.data.commitList.revisions; | 53 var rev_a = a.data.commitList.revisions; |
51 var rev_b = b.data.commitList.revisions; | 54 var rev_b = b.data.commitList.revisions; |
52 | 55 |
(...skipping 21 matching lines...) Expand all Loading... |
74 var b_list = rev_b[keys[i]]; | 77 var b_list = rev_b[keys[i]]; |
75 if (!b_list) | 78 if (!b_list) |
76 return -1; | 79 return -1; |
77 | 80 |
78 if (a_list.last() != b_list.last()) | 81 if (a_list.last() != b_list.last()) |
79 return b_list.last() - a_list.last(); | 82 return b_list.last() - a_list.last(); |
80 } | 83 } |
81 return 0; | 84 return 0; |
82 }; | 85 }; |
83 | 86 |
| 87 // Updates the format of the alerts array to be easier to parse. |
| 88 CTFailures.prototype._mungeAlerts = function(alerts) { |
| 89 var masterToTree = {}; |
| 90 Object.keys(this._trees, function(tree, masters) { |
| 91 masters.forEach(function(master) { |
| 92 masterToTree[master] = tree; |
| 93 }); |
| 94 }); |
| 95 |
| 96 alerts.forEach(function(failure) { |
| 97 // FIXME: Have the server store the actual failure type in a different |
| 98 // field instead of smashing it into the reason. |
| 99 if (failure.failureType) { |
| 100 // The server has been fixed. |
| 101 } else { |
| 102 if (failure.reason) { |
| 103 var parts = failure.reason.split(':'); |
| 104 failure.reason = parts[0]; |
| 105 failure.failureType = parts[1] || 'FAIL'; |
| 106 } else { |
| 107 failure.failureType = 'UNKNOWN'; |
| 108 } |
| 109 } |
| 110 |
| 111 // FIXME: Figure out what tree masters that aren't in masterToTree |
| 112 // we should have. |
| 113 failure.tree = masterToTree[failure.master_url]; |
| 114 }); |
| 115 }; |
| 116 |
84 CTFailures.prototype.update = function() { | 117 CTFailures.prototype.update = function() { |
85 var annotationPromise = CTFailureGroup.fetchAnnotations(); | 118 var annotationPromise = CTFailureGroup.fetchAnnotations(); |
86 return Promise.all([annotationPromise, net.json('http://sheriff-o-matic.appspo
t.com/alerts'), | 119 return Promise.all([annotationPromise, net.json('http://sheriff-o-matic.appspo
t.com/alerts'), |
87 net.json('http://trooper-o-matic.appspot.com/alerts')]).then(function(data
_array) { | 120 net.json('http://trooper-o-matic.appspot.com/alerts')]).then(function(data
_array) { |
88 var annotations = data_array[0]; | 121 var annotations = data_array[0]; |
89 var sheriff_data = data_array[1]; | 122 var sheriff_data = data_array[1]; |
90 var trooper_data = data_array[2]; | 123 var trooper_data = data_array[2]; |
91 | 124 |
92 // FIXME: Don't special-case the blink master. | 125 // FIXME: Don't special-case the blink master. |
93 this.builderLatestRevisions = new CTBuilderRevisions(sheriff_data.latest_bui
lder_info['chromium.webkit']); | 126 this.builderLatestRevisions = new CTBuilderRevisions(sheriff_data.latest_bui
lder_info['chromium.webkit']); |
94 var newFailures = {}; | 127 var newFailures = {}; |
95 this.lastUpdateDate = new Date(sheriff_data.date * 1000); | 128 this.lastUpdateDate = new Date(sheriff_data.date * 1000); |
| 129 this._mungeAlerts(sheriff_data.alerts); |
| 130 // FIXME: Change builder_alerts to expose the alerts as a map instead of an
array. |
| 131 var alertsByKey = {} |
| 132 sheriff_data.alerts.forEach(function(alert) { |
| 133 alertsByKey[alert.key] = alert; |
| 134 }); |
96 // Update |failures| with the appropriate CTFailureGroup's for each | 135 // Update |failures| with the appropriate CTFailureGroup's for each |
97 // tree. | 136 // tree. |
98 sheriff_data.range_groups.forEach(function(rangeGroup) { | 137 sheriff_data.range_groups.forEach(function(rangeGroup) { |
99 this._processFailuresForRangeGroup(newFailures, rangeGroup, sheriff_data.a
lerts, annotations); | 138 this._processFailuresForRangeGroup(newFailures, rangeGroup, alertsByKey, a
nnotations); |
100 }.bind(this)); | 139 }.bind(this)); |
101 // Sort failure groups so that newer failures are shown at the top | 140 // Sort failure groups so that newer failures are shown at the top |
102 // of the UI. | 141 // of the UI. |
103 Object.keys(newFailures, function (tree, failuresByTree) { | 142 Object.keys(newFailures, function (tree, failuresByTree) { |
104 failuresByTree.sort(this._failureByTreeListComparator.bind(this, tree)); | 143 failuresByTree.sort(this._failureByTreeListComparator.bind(this, tree)); |
105 }.bind(this)); | 144 }.bind(this)); |
106 this.failures = updateUtil.updateLeft(this.failures, newFailures); | 145 this.failures = updateUtil.updateLeft(this.failures, newFailures); |
107 this._processTrooperFailures(trooper_data); | 146 this._processTrooperFailures(trooper_data); |
108 }.bind(this)); | 147 }.bind(this)); |
109 }; | 148 }; |
(...skipping 16 matching lines...) Expand all Loading... |
126 Object.keys(failuresByTree, function(tree, failure) { | 165 Object.keys(failuresByTree, function(tree, failure) { |
127 if (failure.should_alert) { | 166 if (failure.should_alert) { |
128 trooper_failures.push(new CTFailureGroup('', | 167 trooper_failures.push(new CTFailureGroup('', |
129 new CTTrooperFailureGroupData(failure.details, failure.url, failure,
failureType, tree))); | 168 new CTTrooperFailureGroupData(failure.details, failure.url, failure,
failureType, tree))); |
130 } | 169 } |
131 }); | 170 }); |
132 }); | 171 }); |
133 this.failures['trooper'] = trooper_failures; | 172 this.failures['trooper'] = trooper_failures; |
134 }; | 173 }; |
135 | 174 |
136 CTFailures.prototype._processFailuresForRangeGroup = function(newFailures, range
Group, alerts, annotations) { | 175 CTFailures.prototype._groupFailuresByTreeAndReason = function(failures, annotati
ons) { |
137 var masterToTree = {}; | 176 var failuresByTree = {}; |
138 Object.keys(this._trees, function(tree, masters) { | 177 failures.forEach(function(failure) { |
139 masters.forEach(function(master) { | |
140 masterToTree[master] = tree; | |
141 }); | |
142 }); | |
143 | |
144 // A rangeGroup may be related to multiple alerts (via |failure_keys|). Catego
rize | |
145 // these failures by reason (cause of failure), so that they can be grouped in
the UI | |
146 // (via a CTFailureGroup). Failures will be grouped in |failuresByReason|. | |
147 var failuresByReason = {}; | |
148 rangeGroup.failure_keys.forEach(function(failure_key) { | |
149 var failure = alerts.find(function(item) { return item.key == failure_key; }
); | |
150 // Establish the key to uniquely identify a failure by reason. | 178 // Establish the key to uniquely identify a failure by reason. |
151 var reason, failureType; | |
152 if (failure.reason) { | |
153 // FIXME: Store the actual failure type in a different field instead of sm
ashing it into the reason. | |
154 var parts = failure.reason.split(':'); | |
155 reason = parts[0]; | |
156 failureType = parts[1] || 'FAIL'; | |
157 } else { | |
158 reason = null; | |
159 failureType = 'UNKNOWN'; | |
160 } | |
161 | |
162 var failureKey = CTFailure.createKey(failure); | 179 var failureKey = CTFailure.createKey(failure); |
163 | 180 |
164 var reasonKey = JSON.stringify({ | 181 var reasonKey = JSON.stringify({ |
165 step: failure.step_name, | 182 step: failure.step_name, |
166 reason: reason, | 183 reason: failure.reason, |
167 }); | 184 }); |
168 | 185 |
169 // FIXME: Figure out what tree masters that aren't in masterToTree | |
170 // we should have. | |
171 var tree = masterToTree[failure.master_url]; | |
172 | |
173 // FIXME: Use a model class instead of a dumb object. | 186 // FIXME: Use a model class instead of a dumb object. |
174 if (!failuresByReason[reasonKey]) | 187 if (!failuresByTree[failure.tree]) |
175 failuresByReason[reasonKey] = {}; | 188 failuresByTree[failure.tree] = {}; |
176 if (!failuresByReason[reasonKey][tree]) | 189 if (!failuresByTree[failure.tree][reasonKey]) |
177 failuresByReason[reasonKey][tree] = {}; | 190 failuresByTree[failure.tree][reasonKey] = {}; |
178 failuresByReason[reasonKey][tree][failure.builder_name] = { | 191 failuresByTree[failure.tree][reasonKey][failure.builder_name] = { |
179 key: failureKey, | 192 key: failureKey, |
180 // FIXME: Rename to failureType. | 193 // FIXME: Rename to failureType. |
181 actual: failureType, | 194 actual: failure.failureType, |
182 lastFailingBuild: failure.last_failing_build, | 195 lastFailingBuild: failure.last_failing_build, |
183 earliestFailingBuild: failure.failing_build, | 196 earliestFailingBuild: failure.failing_build, |
184 masterUrl: failure.master_url, | 197 masterUrl: failure.master_url, |
185 failingBuildCount: failure.failing_build_count, | 198 failingBuildCount: failure.failing_build_count, |
186 annotation: annotations[failureKey], | 199 annotation: annotations[failureKey], |
187 }; | 200 }; |
188 }.bind(this)); | 201 }); |
| 202 return failuresByTree |
| 203 }; |
189 | 204 |
190 if (!Object.keys(failuresByReason).length) | 205 CTFailures.prototype._processFailuresForRangeGroup = function(newFailures, range
Group, alerts, annotations) { |
| 206 // A rangeGroup may be related to multiple alerts (via |failure_keys|). Catego
rize |
| 207 // these failures by reason (cause of failure), so that they can be grouped in
the UI |
| 208 // (via a CTFailureGroup). |
| 209 var failures = rangeGroup.failure_keys.map(function(failure_key) { |
| 210 return alerts[failure_key]; |
| 211 }); |
| 212 var failuresByTree = this._groupFailuresByTreeAndReason(failures, annotations)
; |
| 213 |
| 214 if (Object.isEmpty(failuresByTree)) |
191 return; | 215 return; |
192 | 216 |
193 // Maps a tree id to a list of CTFailures in that tree. | 217 Object.keys(failuresByTree, function(tree, resultsByReason) { |
194 var groupedFailures = {}; | 218 var treeFailures = []; |
195 Object.keys(failuresByReason, function(reasonKey, resultsByTree) { | 219 Object.keys(resultsByReason, function(reasonKey, resultsByBuilder) { |
196 var failure = JSON.parse(reasonKey); | 220 var failure = JSON.parse(reasonKey); |
197 Object.keys(resultsByTree, function(tree, resultsByBuilder) { | 221 treeFailures.push( |
198 if (!groupedFailures[tree]) | |
199 groupedFailures[tree] = []; | |
200 groupedFailures[tree].push( | |
201 new CTFailure(failure.step, failure.reason, resultsByBuilder)); | 222 new CTFailure(failure.step, failure.reason, resultsByBuilder)); |
202 }) | 223 }) |
203 }); | 224 treeFailures.sort(this._failureComparator); |
204 | |
205 Object.keys(groupedFailures, function(tree, failures) { | |
206 failures.sort(this._failureComparator); | |
207 | 225 |
208 if (!newFailures[tree]) | 226 if (!newFailures[tree]) |
209 newFailures[tree] = []; | 227 newFailures[tree] = []; |
210 var commitList = new CTCommitList(this.commitLog, rangeGroup.likely_revision
s); | 228 var commitList = new CTCommitList(this.commitLog, rangeGroup.likely_revision
s); |
211 newFailures[tree].push(new CTFailureGroup(rangeGroup.sort_key, new CTSheriff
FailureGroupData(failures, commitList))); | 229 newFailures[tree].push(new CTFailureGroup(rangeGroup.sort_key, new CTSheriff
FailureGroupData(treeFailures, commitList))); |
212 }.bind(this)); | 230 }.bind(this)); |
213 }; | 231 }; |
214 | 232 |
| 233 })(); |
215 </script> | 234 </script> |
OLD | NEW |