Title: [91240] trunk/Tools
Revision
91240
Author
[email protected]
Date
2011-07-19 00:37:01 -0700 (Tue, 19 Jul 2011)

Log Message

garden-o-matic should live update as conditions change on the buildbot
https://bugs.webkit.org/show_bug.cgi?id=64646

Reviewed by Eric Seidel.

This patch causes the garden-o-matic display to update every 10 minutes
to show the latest failures.  This patch required a moderately large
refactoring of main.js to make the display incremental instead of
all-at-once.

* Scripts/webkitpy/tool/servers/data/gardeningserver/base.js:
* Scripts/webkitpy/tool/servers/data/gardeningserver/main.css:
* Scripts/webkitpy/tool/servers/data/gardeningserver/main.js:
* Scripts/webkitpy/tool/servers/data/gardeningserver/ui.js:

Modified Paths

Diff

Modified: trunk/Tools/ChangeLog (91239 => 91240)


--- trunk/Tools/ChangeLog	2011-07-19 05:33:10 UTC (rev 91239)
+++ trunk/Tools/ChangeLog	2011-07-19 07:37:01 UTC (rev 91240)
@@ -1,3 +1,20 @@
+2011-07-19  Adam Barth  <[email protected]>
+
+        garden-o-matic should live update as conditions change on the buildbot
+        https://bugs.webkit.org/show_bug.cgi?id=64646
+
+        Reviewed by Eric Seidel.
+
+        This patch causes the garden-o-matic display to update every 10 minutes
+        to show the latest failures.  This patch required a moderately large
+        refactoring of main.js to make the display incremental instead of
+        all-at-once.
+
+        * Scripts/webkitpy/tool/servers/data/gardeningserver/base.js:
+        * Scripts/webkitpy/tool/servers/data/gardeningserver/main.css:
+        * Scripts/webkitpy/tool/servers/data/gardeningserver/main.js:
+        * Scripts/webkitpy/tool/servers/data/gardeningserver/ui.js:
+
 2011-07-18  Tab Atkins  <[email protected]>
 
         Tab Atkins is not in committers.py (as a non-committer)

Modified: trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/base.js (91239 => 91240)


--- trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/base.js	2011-07-19 05:33:10 UTC (rev 91239)
+++ trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/base.js	2011-07-19 07:37:01 UTC (rev 91240)
@@ -97,4 +97,18 @@
     });
 };
 
+base.RequestTracker = function(requestsInFlight, callback, args)
+{
+    this.m_requestsInFlight = requestsInFlight;
+    this.m_callback = callback;
+    this.m_args = args || [];
+};
+
+base.RequestTracker.prototype.requestComplete = function()
+{
+    --this.m_requestsInFlight;
+    if (!this.m_requestsInFlight)
+        this.m_callback.apply(null, this.m_args);
+};
+
 })();

Modified: trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/base_unittests.js (91239 => 91240)


--- trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/base_unittests.js	2011-07-19 05:33:10 UTC (rev 91239)
+++ trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/base_unittests.js	2011-07-19 07:37:01 UTC (rev 91240)
@@ -48,6 +48,30 @@
     deepEqual(base.keys({"a": 1, "b": { "c" : 1}}), ["a", "b"]);
 });
 
+test("RequestTracker", 3, function() {
+    var ready = false;
+    var tracker = new base.RequestTracker(1, function() {
+        ok(ready);
+    });
+    ready = true;
+    tracker.requestComplete();
+    ready = false;
+
+    tracker = new base.RequestTracker(2, function(parameter) {
+        ok(ready);
+        equals(parameter, 'argument');
+    }, ['argument']);
+    tracker.requestComplete();
+    ready = true;
+    tracker.requestComplete();
+    ready = false;
+
+    tracker = new base.RequestTracker(0, function() {
+        ok(false);
+    });
+    tracker.requestComplete();
+});
+
 test("filterTree", 2, function() {
     var tree = {
         'path': {

Modified: trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/main.css (91239 => 91240)


--- trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/main.css	2011-07-19 05:33:10 UTC (rev 91239)
+++ trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/main.css	2011-07-19 07:37:01 UTC (rev 91240)
@@ -87,6 +87,10 @@
     padding: 4px;
 }
 
+.results-summary tbody tr {
+    display: none;
+}
+
 .results-summary ul {
     margin: 0px;
     padding: 0px;
@@ -159,13 +163,8 @@
     border-radius: 4px;
 }
 
-.results-summary .test[data-new-test="true"] .what a[draggable]::before {
-    content: '(new)';
-    margin: 0 3px;
-}
-
 /* If we've only seen a given test failure once, we dim it so as not to distract the gardener. */
-.results-summary .test[data-failure-count="1"][data-new-test="false"] {
+.results-summary .test[data-failure-count="1"] {
     -webkit-transition: 1s opacity;
     opacity: 0.5;
 }

Modified: trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/main.js (91239 => 91240)


--- trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/main.js	2011-07-19 05:33:10 UTC (rev 91239)
+++ trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/main.js	2011-07-19 07:37:01 UTC (rev 91240)
@@ -47,52 +47,103 @@
     $('#favicon').attr('href', faviconURL);
 }
 
-function showResults(onsuccess)
+function togglePartyTime(hasFailures)
 {
+    if (!hasFailures) {
+        $('.results').text('No failures. Party time!');
+        var partyTime = $('<div class="partytime"><img src=""
+        $('.results').append(partyTime);
+        partyTime.fadeIn(1200).delay(7000).fadeOut();
+        return;
+    }
+    $('.results').empty();
+}
+
+function ensureResultsSummaryContainer()
+{
+    var container = $('.results-summary');
+    if (container.length)
+        return container;
+    container = ui.regressionsContainer();
+    $('.results').append(container);
+    return container;
+}
+
+function detachRepairedTestsAndPrepareTestMap(unexpectedFailures)
+{
+    var testMap = {};
+
+    $('.test').each(function() {
+        var testSummary = $(this);
+        var testName = testSummary.attr(config.kTestNameAttr);
+        if (!(testName in unexpectedFailures))
+            testSummary.slideUp(function() { testSummary.detach(); });
+        else
+            testMap[testName] = testSummary;
+    });
+
+    return testMap;
+}
+
+function prepareTestSummary(testName, resultNodesByBuilder, callback)
+{
+    var testSummary = ui.summarizeTest(testName, resultNodesByBuilder);
+    var builderNameList = base.keys(resultNodesByBuilder);
+
+    results.unifyRegressionRanges(builderNameList, testName, function(oldestFailingRevision, newestPassingRevision) {
+        $('.when', testSummary).append(ui.summarizeRegressionRange(oldestFailingRevision, newestPassingRevision));
+    });
+
+    results.countFailureOccurances(builderNameList, testName, function(failureCount) {
+        $(testSummary).attr(config.kFailureCountAttr, failureCount);
+        $('.how-many', testSummary).text(ui.failureCount(failureCount));
+    });
+
+    callback(testSummary);
+}
+
+function updateResultsSummary(callback)
+{
     results.fetchResultsByBuilder(config.kBuilders, function(resultsByBuilder) {
         var unexpectedFailures = results.unexpectedFailuresByTest(resultsByBuilder);
         var hasFailures = !$.isEmptyObject(unexpectedFailures)
-        if (!hasFailures) {
-            $('.results').text('No failures. Party time!');
-            var partyTime = $('<div class="partytime"><img src=""
-            $('.results').append(partyTime);
-            partyTime.fadeIn(1200).delay(7000).fadeOut();
-        } else {
-            var regressions = ui.regressionsContainer();
 
-            $.each(unexpectedFailures, function(testName, resultNodesByBuilder) {
-                var testSummary = ui.summarizeTest(testName, resultNodesByBuilder);
-                $('tbody', regressions).append(testSummary);
+        togglePartyTime(hasFailures);
+        setIconState(hasFailures);
 
-                var builderNameList = base.keys(resultNodesByBuilder);
-                results.unifyRegressionRanges(builderNameList, testName, function(oldestFailingRevision, newestPassingRevision) {
-                    $('.when', testSummary).append(ui.summarizeRegressionRange(oldestFailingRevision, newestPassingRevision));
-                    if (!newestPassingRevision)
-                        return;
-                    checkout.existsAtRevision(checkout.subversionURLForTest(testName), newestPassingRevision, function(testExistedBeforeFailure) {
-                        $(testSummary).attr('data-new-test', !testExistedBeforeFailure);
-                    });
-                });
-                results.countFailureOccurances(builderNameList, testName, function(failureCount) {
-                    $(testSummary).attr(config.kFailureCountAttr, failureCount);
-                    $('.how-many', testSummary).text(ui.failureCount(failureCount));
-                });
+        var container = ensureResultsSummaryContainer();
+        var testMap = detachRepairedTestsAndPrepareTestMap(unexpectedFailures);
+
+        var newTestSummaries = $();
+        var requestTracker = new base.RequestTracker(base.keys(unexpectedFailures).length, function() {
+            newTestSummaries.fadeIn();
+            callback()
+        });
+
+        $.each(unexpectedFailures, function(testName, resultNodesByBuilder) {
+            prepareTestSummary(testName, resultNodesByBuilder, function(testSummary) {
+                var existingElement = testMap[testName];
+                if (existingElement) {
+                    existingElement.replaceWith(testSummary);
+                    requestTracker.requestComplete();
+                    return;
+                }
+                $('tbody', container).append(testSummary);
+                newTestSummaries = newTestSummaries.add(testSummary);
+                requestTracker.requestComplete();
             });
-            $('.results').append(regressions);
-        }
-        setIconState(hasFailures);
-        onsuccess();
+        });
     });
 }
 
 function showResultsDetail()
 {
-    var testBlock = $(this).parents('.test');
+    var testSummary = $(this).parents('.test');
     var builderName = $(this).attr(config.kBuilderNameAttr);
-    var testName = $('.what', testBlock).text();
+    var testName = testSummary.attr(config.kTestNameAttr);
 
     // FIXME: It's lame that we have two different representations of multiple failure types.
-    var failureTypes = testBlock.attr(config.kFailureTypesAttr);
+    var failureTypes = testSummary.attr(config.kFailureTypesAttr);
     var failureTypeList = failureTypes.split(' ');
 
     var content = $('.results-detail .content');
@@ -166,6 +217,8 @@
 
 function update()
 {
+    displayOnButterbar('Loading...');
+    updateResultsSummary(dismissButterbar);
     checkBuilderStatuses();
 }
 
@@ -174,9 +227,6 @@
 $('.results-detail .actions .rebaseline').live('click', rebaselineResults);
 
 $(document).ready(function() {
-    showResults(function() {
-        $('.butterbar').fadeOut();
-    });
     g_updateTimerId = window.setInterval(update, config.kUpdateFrequency);
     update();
 });

Modified: trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/results.js (91239 => 91240)


--- trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/results.js	2011-07-19 05:33:10 UTC (rev 91239)
+++ trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/results.js	2011-07-19 07:37:01 UTC (rev 91240)
@@ -177,7 +177,7 @@
 // FIXME: Consider using setTimeout to make this method always asynchronous.
 ResultsCache.prototype.get = function(key, callback)
 {
-    if (key in this._cache) {
+    if (this._cache[key]) {
         callback(this._cache[key]);
         return;
     }

Modified: trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/ui.js (91239 => 91240)


--- trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/ui.js	2011-07-19 05:33:10 UTC (rev 91239)
+++ trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/ui.js	2011-07-19 07:37:01 UTC (rev 91240)
@@ -54,6 +54,7 @@
           '<td class="how-many"></td>' +
         '</tr>');
     $('.what a', block).text(testName).attr('href', ui.urlForTest(testName)).attr('class', unexpectedResults.join(' '));
+    block.attr(config.kTestNameAttr, testName);
     block.attr(config.kFailureTypesAttr, unexpectedResults);
 
     var where = $('.where', block);
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to