| Index: Tools/GardeningServer/model/ct-failures.html
|
| diff --git a/Tools/GardeningServer/model/ct-failures.html b/Tools/GardeningServer/model/ct-failures.html
|
| index 4343c577e14ee0d64c7e99344f5a81a7170cadce..e2fcd46ce7e48125e83b0757b1897939b51b9036 100644
|
| --- a/Tools/GardeningServer/model/ct-failures.html
|
| +++ b/Tools/GardeningServer/model/ct-failures.html
|
| @@ -40,6 +40,9 @@ function CTFailures(commitLog) {
|
| };
|
| }
|
|
|
| +(function() {
|
| +'use strict';
|
| +
|
| // FIXME: This could potentially move onto CTSheriffFailureGroupData as it isn't relevant to
|
| // trooper failures.
|
| // Reverse sorting order, if a > b, return a negative number.
|
| @@ -81,6 +84,36 @@ CTFailures.prototype._failureByTreeListComparator = function(tree, a, b) {
|
| return 0;
|
| };
|
|
|
| +// Updates the format of the alerts array to be easier to parse.
|
| +CTFailures.prototype._mungeAlerts = function(alerts) {
|
| + var masterToTree = {};
|
| + Object.keys(this._trees, function(tree, masters) {
|
| + masters.forEach(function(master) {
|
| + masterToTree[master] = tree;
|
| + });
|
| + });
|
| +
|
| + alerts.forEach(function(failure) {
|
| + // FIXME: Have the server store the actual failure type in a different
|
| + // field instead of smashing it into the reason.
|
| + if (failure.failureType) {
|
| + // The server has been fixed.
|
| + } else {
|
| + if (failure.reason) {
|
| + var parts = failure.reason.split(':');
|
| + failure.reason = parts[0];
|
| + failure.failureType = parts[1] || 'FAIL';
|
| + } else {
|
| + failure.failureType = 'UNKNOWN';
|
| + }
|
| + }
|
| +
|
| + // FIXME: Figure out what tree masters that aren't in masterToTree
|
| + // we should have.
|
| + failure.tree = masterToTree[failure.master_url];
|
| + });
|
| +};
|
| +
|
| CTFailures.prototype.update = function() {
|
| var annotationPromise = CTFailureGroup.fetchAnnotations();
|
| return Promise.all([annotationPromise, net.json('http://sheriff-o-matic.appspot.com/alerts'),
|
| @@ -93,10 +126,16 @@ CTFailures.prototype.update = function() {
|
| this.builderLatestRevisions = new CTBuilderRevisions(sheriff_data.latest_builder_info['chromium.webkit']);
|
| var newFailures = {};
|
| this.lastUpdateDate = new Date(sheriff_data.date * 1000);
|
| + this._mungeAlerts(sheriff_data.alerts);
|
| + // FIXME: Change builder_alerts to expose the alerts as a map instead of an array.
|
| + var alertsByKey = {}
|
| + sheriff_data.alerts.forEach(function(alert) {
|
| + alertsByKey[alert.key] = alert;
|
| + });
|
| // Update |failures| with the appropriate CTFailureGroup's for each
|
| // tree.
|
| sheriff_data.range_groups.forEach(function(rangeGroup) {
|
| - this._processFailuresForRangeGroup(newFailures, rangeGroup, sheriff_data.alerts, annotations);
|
| + this._processFailuresForRangeGroup(newFailures, rangeGroup, alertsByKey, annotations);
|
| }.bind(this));
|
| // Sort failure groups so that newer failures are shown at the top
|
| // of the UI.
|
| @@ -133,83 +172,63 @@ CTFailures.prototype._processTrooperFailures = function(data) {
|
| this.failures['trooper'] = trooper_failures;
|
| };
|
|
|
| -CTFailures.prototype._processFailuresForRangeGroup = function(newFailures, rangeGroup, alerts, annotations) {
|
| - var masterToTree = {};
|
| - Object.keys(this._trees, function(tree, masters) {
|
| - masters.forEach(function(master) {
|
| - masterToTree[master] = tree;
|
| - });
|
| - });
|
| -
|
| - // A rangeGroup 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 = {};
|
| - rangeGroup.failure_keys.forEach(function(failure_key) {
|
| - var failure = alerts.find(function(item) { return item.key == failure_key; });
|
| +CTFailures.prototype._groupFailuresByTreeAndReason = function(failures, annotations) {
|
| + var failuresByTree = {};
|
| + failures.forEach(function(failure) {
|
| // 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.
|
| - var parts = failure.reason.split(':');
|
| - reason = parts[0];
|
| - failureType = parts[1] || 'FAIL';
|
| - } else {
|
| - reason = null;
|
| - failureType = 'UNKNOWN';
|
| - }
|
| -
|
| var failureKey = CTFailure.createKey(failure);
|
|
|
| var reasonKey = JSON.stringify({
|
| step: failure.step_name,
|
| - reason: reason,
|
| + reason: failure.reason,
|
| });
|
|
|
| - // FIXME: Figure out what tree masters that aren't in masterToTree
|
| - // we should have.
|
| - var tree = masterToTree[failure.master_url];
|
| -
|
| // FIXME: Use a model class instead of a dumb object.
|
| - if (!failuresByReason[reasonKey])
|
| - failuresByReason[reasonKey] = {};
|
| - if (!failuresByReason[reasonKey][tree])
|
| - failuresByReason[reasonKey][tree] = {};
|
| - failuresByReason[reasonKey][tree][failure.builder_name] = {
|
| + if (!failuresByTree[failure.tree])
|
| + failuresByTree[failure.tree] = {};
|
| + if (!failuresByTree[failure.tree][reasonKey])
|
| + failuresByTree[failure.tree][reasonKey] = {};
|
| + failuresByTree[failure.tree][reasonKey][failure.builder_name] = {
|
| key: failureKey,
|
| // FIXME: Rename to failureType.
|
| - actual: failureType,
|
| + actual: failure.failureType,
|
| lastFailingBuild: failure.last_failing_build,
|
| earliestFailingBuild: failure.failing_build,
|
| masterUrl: failure.master_url,
|
| failingBuildCount: failure.failing_build_count,
|
| annotation: annotations[failureKey],
|
| };
|
| - }.bind(this));
|
| + });
|
| + return failuresByTree
|
| +};
|
|
|
| - if (!Object.keys(failuresByReason).length)
|
| +CTFailures.prototype._processFailuresForRangeGroup = function(newFailures, rangeGroup, alerts, annotations) {
|
| + // A rangeGroup 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).
|
| + var failures = rangeGroup.failure_keys.map(function(failure_key) {
|
| + return alerts[failure_key];
|
| + });
|
| + var failuresByTree = this._groupFailuresByTreeAndReason(failures, annotations);
|
| +
|
| + if (Object.isEmpty(failuresByTree))
|
| return;
|
|
|
| - // Maps a tree id to a list of CTFailures in that tree.
|
| - var groupedFailures = {};
|
| - Object.keys(failuresByReason, function(reasonKey, resultsByTree) {
|
| - var failure = JSON.parse(reasonKey);
|
| - Object.keys(resultsByTree, function(tree, resultsByBuilder) {
|
| - if (!groupedFailures[tree])
|
| - groupedFailures[tree] = [];
|
| - groupedFailures[tree].push(
|
| + Object.keys(failuresByTree, function(tree, resultsByReason) {
|
| + var treeFailures = [];
|
| + Object.keys(resultsByReason, function(reasonKey, resultsByBuilder) {
|
| + var failure = JSON.parse(reasonKey);
|
| + treeFailures.push(
|
| new CTFailure(failure.step, failure.reason, resultsByBuilder));
|
| })
|
| - });
|
| -
|
| - Object.keys(groupedFailures, function(tree, failures) {
|
| - failures.sort(this._failureComparator);
|
| + treeFailures.sort(this._failureComparator);
|
|
|
| if (!newFailures[tree])
|
| newFailures[tree] = [];
|
| var commitList = new CTCommitList(this.commitLog, rangeGroup.likely_revisions);
|
| - newFailures[tree].push(new CTFailureGroup(rangeGroup.sort_key, new CTSheriffFailureGroupData(failures, commitList)));
|
| + newFailures[tree].push(new CTFailureGroup(rangeGroup.sort_key, new CTSheriffFailureGroupData(treeFailures, commitList)));
|
| }.bind(this));
|
| };
|
|
|
| +})();
|
| </script>
|
|
|