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

Unified Diff: Tools/GardeningServer/ui/ct-failure-analyzer.html

Issue 498523002: [Sheriff-o-matic] Use likely_revisions instead of first_failing/last_passing (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: sort git hashes Created 6 years, 4 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: Tools/GardeningServer/ui/ct-failure-analyzer.html
diff --git a/Tools/GardeningServer/ui/ct-failure-analyzer.html b/Tools/GardeningServer/ui/ct-failure-analyzer.html
index 6add6dbcb15c47f896dd72073ffbd70747809292..0d0996796d774d10f0ddb3f2697bbd67e599e160 100644
--- a/Tools/GardeningServer/ui/ct-failure-analyzer.html
+++ b/Tools/GardeningServer/ui/ct-failure-analyzer.html
@@ -35,34 +35,58 @@ found in the LICENSE file.
],
},
- _failureListComparator: function(tree, a, b) {
+ _failureByTreeListComparator: function(tree, a, b) {
if (tree === undefined)
tree = 'chromium';
- var rev_a = a.failures[0].firstFailingRevisions;
- var rev_b = b.failures[0].firstFailingRevisions;
-
- // Handle missing revision.
- if (!rev_a) {
- if (!rev_b) {
+ if (!a.revisions || !a.revisions.length) {
+ if (!a.revisions || !b.revisions.length)
return 0;
- }
return -1;
- } else if (!rev_b) {
+ } else if (!b.revisions || !b.revisions.length) {
return 1;
}
- // Prioritize the tree's revision.
- if (rev_a[tree] != rev_b[tree])
- return rev_b[tree] - rev_a[tree];
-
- // Compare other revisions in alphabetical order.
- var keys = Object.keys(rev_a).sort();
- for (var i = 0; i < keys.length; i++) {
- if (rev_a[keys[i]] != rev_b[keys[i]])
- return rev_b[keys[i]] - rev_a[keys[i]];
+ // At this point |a.revisions| and |b.revisions| are sorted lists of
ojan 2014/08/23 01:23:06 It turns out that we'll be able to keep using git
Mathieu 2014/08/24 23:42:11 No problem. Are you fine with this implementation
ojan 2014/08/25 03:54:13 I'd rather use the old implementation. It's consid
Mathieu 2014/08/25 13:03:22 Much of my rewrite was because the old arguments w
+ // revisions of the form '<tree>:<revision>', where <tree> is not
+ // necessarily |tree|. Get the latest revision, and favor those related
+ // to |tree|.
+ var _getLatestRevisionForTree = function(revisions) {
ojan 2014/08/23 01:23:06 This should have a FIXME to sort by timestamp of t
Mathieu 2014/08/24 23:42:11 Done.
+ var i = 0;
+ var rev = revisions[revisions.length - 1 - i];
+ while (rev.lastIndexOf(tree, 0) !== 0) {
+ i++;
+ rev = revisions[revisions.length - 1 - i];
+ }
+ return rev;
+ };
+ var rev_a = _getLatestRevisionForTree(a.revisions, tree);
+ var rev_b = _getLatestRevisionForTree(b.revisions, tree);
+
+ // Extract the <tree> and <revision> parts.
+ var a_split = rev_a.split(':');
+ var a_tree = a_split[0];
+ var a_id = a_split[1];
+
+ var b_split = rev_b.split(':');
+ var b_tree = b_split[0];
+ var b_id = b_split[1];
+
+ // If trees mismatch, favor the one matching with |tree|. If none equal
+ // |tree|, b is favored.
+ if (a_tree != b_tree)
+ return b_tree == tree ? 1 : -1;
+
+ if (rev_a == rev_b) {
+ // In case of tree-revision equality, try a fallback.
+ var a_last = a.revisions.last();
+ var b_last = b.revisions.last();
+ if (a_last == b_last)
+ return 0;
+ return a_last < b_last ? 1 : -1;
}
- return 0;
+
+ return b_id == a_id ? 0 : (b_id > a_id) ? 1 : -1;
},
update: function() {
@@ -73,11 +97,13 @@ found in the LICENSE file.
this.builderLatestRevisions = new CTBuilderRevisions(data.latest_builder_info['chromium.webkit']);
this.failures = {};
this.lastUpdateDate = new Date(data.date * 1000);
- data.range_groups.forEach(function(group) {
- this._processFailuresForGroup(group, data.alerts, annotations);
+ // Update |failures| with the appropriate CTFailureGroup's for each tree.
+ data.range_groups.forEach(function(range_group) {
+ this._processFailuresForRangeGroup(range_group, data.alerts, annotations);
}.bind(this));
+ // Sort failure groups so that newer failures are shown at the top of the UI.
Object.keys(this.failures, function (tree, failuresByTree) {
- this.failures[tree].sort(this._failureListComparator.bind(this, tree));
+ this.failures[tree].sort(this._failureByTreeListComparator.bind(this, tree));
}.bind(this));
}.bind(this));
}.bind(this));
@@ -95,9 +121,7 @@ found in the LICENSE file.
return 0;
},
- _processFailuresForGroup: function(group, failures, annotations) {
- var failuresByReason = {};
-
+ _processFailuresForRangeGroup: function(range_group, alerts, annotations) {
ojan 2014/08/23 01:23:05 s/range_group/rangeGroup/
Mathieu 2014/08/24 23:42:11 Done.
var masterToTree = {};
Object.keys(this._trees, function(tree, masters) {
masters.forEach(function(master) {
@@ -105,8 +129,13 @@ found in the LICENSE file.
});
});
- group.failure_keys.forEach(function(failure_key) {
- var failure = failures.find(function(item) { return item.key == failure_key; });
+ // A range_group may be related to multiple alerts (via |failure_keys|). Categorize
+ // these failures by reason (cause of failure), so that they can be grouped in the UI
+ // (via a CTFailureGroup). Failures will be grouped in |failuresByReason|.
+ var failuresByReason = {};
+ range_group.failure_keys.forEach(function(failure_key) {
+ var failure = alerts.find(function(item) { return item.key == failure_key; });
+ // Establish the key to uniquely identify a failure by reason.
var reason, failureType;
if (failure.reason) {
// FIXME: Store the actual failure type in a different field instead of smashing it into the reason.
@@ -123,7 +152,12 @@ found in the LICENSE file.
reason: reason,
});
+ // Get the actual tree on which this failure occurred ('blink', 'chromium')
ojan 2014/08/23 01:23:06 IMO, this is pretty clear. No need to give comment
Mathieu 2014/08/24 23:42:11 Sorry, I was annotating as I went along.
var tree = masterToTree[failure.master_url];
+ if (!tree) {
+ // FIXME: No tree corresponding to master URL!
ojan 2014/08/23 01:23:05 FIXMEs should state what to fix. Something like...
Mathieu 2014/08/24 23:42:11 Done.
+ return;
ojan 2014/08/23 01:23:05 We don't actually want to early return here. We'll
Mathieu 2014/08/24 23:42:11 Nah, it just didn't seem clean to be using |tree|
ojan 2014/08/25 03:54:13 Yeah. Long-term, the right thing here is to grab t
+ }
// FIXME: Use a model class instead of a dumb object.
if (!failuresByReason[failureKey])
@@ -140,13 +174,19 @@ found in the LICENSE file.
};
}.bind(this));
+ // Skip further processing if no failures were collected (e.g. the tree
ojan 2014/08/23 01:23:05 Ditto: This is clearly what the next line of code
Mathieu 2014/08/24 23:42:11 Done.
+ // was unknown).
+ if (!Object.keys(failuresByReason).length)
+ return;
+
var groupedFailures = {};
Object.keys(failuresByReason, function(failureKey, resultsByTree) {
var failure = JSON.parse(failureKey);
Object.keys(resultsByTree, function(tree, resultsByBuilder) {
if (!groupedFailures[tree])
groupedFailures[tree] = [];
- groupedFailures[tree].push(new CTFailure(failure.step, failure.reason, resultsByBuilder, group.merged_first_failing, group.merged_last_passing));
+ groupedFailures[tree].push(
+ new CTFailure(failure.step, failure.reason, resultsByBuilder));
})
});
@@ -156,8 +196,10 @@ found in the LICENSE file.
if (!this.failures[tree])
this.failures[tree] = [];
// FIXME: Need a better identifier for a failure group;
- var key = group.sort_key;
- this.failures[tree].push(new CTFailureGroup(key, failures, annotations[key]));
+ var key = range_group.sort_key;
+ this.failures[tree].push(
+ new CTFailureGroup(key, failures, range_group.likely_revisions,
+ annotations[key]));
}.bind(this));
},
});

Powered by Google App Engine
This is Rietveld 408576698