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 |