Changeset 91240 in webkit


Ignore:
Timestamp:
Jul 19, 2011 12:37:01 AM (13 years ago)
Author:
abarth@webkit.org
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:
Location:
trunk/Tools
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/Tools/ChangeLog

    r91233 r91240  
     12011-07-19  Adam Barth  <abarth@webkit.org>
     2
     3        garden-o-matic should live update as conditions change on the buildbot
     4        https://bugs.webkit.org/show_bug.cgi?id=64646
     5
     6        Reviewed by Eric Seidel.
     7
     8        This patch causes the garden-o-matic display to update every 10 minutes
     9        to show the latest failures.  This patch required a moderately large
     10        refactoring of main.js to make the display incremental instead of
     11        all-at-once.
     12
     13        * Scripts/webkitpy/tool/servers/data/gardeningserver/base.js:
     14        * Scripts/webkitpy/tool/servers/data/gardeningserver/main.css:
     15        * Scripts/webkitpy/tool/servers/data/gardeningserver/main.js:
     16        * Scripts/webkitpy/tool/servers/data/gardeningserver/ui.js:
     17
    1182011-07-18  Tab Atkins  <jackalmage@gmail.com>
    219
  • trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/base.js

    r90866 r91240  
    9898};
    9999
     100base.RequestTracker = function(requestsInFlight, callback, args)
     101{
     102    this.m_requestsInFlight = requestsInFlight;
     103    this.m_callback = callback;
     104    this.m_args = args || [];
     105};
     106
     107base.RequestTracker.prototype.requestComplete = function()
     108{
     109    --this.m_requestsInFlight;
     110    if (!this.m_requestsInFlight)
     111        this.m_callback.apply(null, this.m_args);
     112};
     113
    100114})();
  • trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/base_unittests.js

    r90880 r91240  
    4949});
    5050
     51test("RequestTracker", 3, function() {
     52    var ready = false;
     53    var tracker = new base.RequestTracker(1, function() {
     54        ok(ready);
     55    });
     56    ready = true;
     57    tracker.requestComplete();
     58    ready = false;
     59
     60    tracker = new base.RequestTracker(2, function(parameter) {
     61        ok(ready);
     62        equals(parameter, 'argument');
     63    }, ['argument']);
     64    tracker.requestComplete();
     65    ready = true;
     66    tracker.requestComplete();
     67    ready = false;
     68
     69    tracker = new base.RequestTracker(0, function() {
     70        ok(false);
     71    });
     72    tracker.requestComplete();
     73});
     74
    5175test("filterTree", 2, function() {
    5276    var tree = {
  • trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/main.css

    r91197 r91240  
    8888}
    8989
     90.results-summary tbody tr {
     91    display: none;
     92}
     93
    9094.results-summary ul {
    9195    margin: 0px;
     
    160164}
    161165
    162 .results-summary .test[data-new-test="true"] .what a[draggable]::before {
    163     content: '(new)';
    164     margin: 0 3px;
    165 }
    166 
    167166/* If we've only seen a given test failure once, we dim it so as not to distract the gardener. */
    168 .results-summary .test[data-failure-count="1"][data-new-test="false"] {
     167.results-summary .test[data-failure-count="1"] {
    169168    -webkit-transition: 1s opacity;
    170169    opacity: 0.5;
  • trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/main.js

    r91197 r91240  
    4848}
    4949
    50 function showResults(onsuccess)
     50function togglePartyTime(hasFailures)
     51{
     52    if (!hasFailures) {
     53        $('.results').text('No failures. Party time!');
     54        var partyTime = $('<div class="partytime"><img src="partytime.gif"></div>');
     55        $('.results').append(partyTime);
     56        partyTime.fadeIn(1200).delay(7000).fadeOut();
     57        return;
     58    }
     59    $('.results').empty();
     60}
     61
     62function ensureResultsSummaryContainer()
     63{
     64    var container = $('.results-summary');
     65    if (container.length)
     66        return container;
     67    container = ui.regressionsContainer();
     68    $('.results').append(container);
     69    return container;
     70}
     71
     72function detachRepairedTestsAndPrepareTestMap(unexpectedFailures)
     73{
     74    var testMap = {};
     75
     76    $('.test').each(function() {
     77        var testSummary = $(this);
     78        var testName = testSummary.attr(config.kTestNameAttr);
     79        if (!(testName in unexpectedFailures))
     80            testSummary.slideUp(function() { testSummary.detach(); });
     81        else
     82            testMap[testName] = testSummary;
     83    });
     84
     85    return testMap;
     86}
     87
     88function prepareTestSummary(testName, resultNodesByBuilder, callback)
     89{
     90    var testSummary = ui.summarizeTest(testName, resultNodesByBuilder);
     91    var builderNameList = base.keys(resultNodesByBuilder);
     92
     93    results.unifyRegressionRanges(builderNameList, testName, function(oldestFailingRevision, newestPassingRevision) {
     94        $('.when', testSummary).append(ui.summarizeRegressionRange(oldestFailingRevision, newestPassingRevision));
     95    });
     96
     97    results.countFailureOccurances(builderNameList, testName, function(failureCount) {
     98        $(testSummary).attr(config.kFailureCountAttr, failureCount);
     99        $('.how-many', testSummary).text(ui.failureCount(failureCount));
     100    });
     101
     102    callback(testSummary);
     103}
     104
     105function updateResultsSummary(callback)
    51106{
    52107    results.fetchResultsByBuilder(config.kBuilders, function(resultsByBuilder) {
    53108        var unexpectedFailures = results.unexpectedFailuresByTest(resultsByBuilder);
    54109        var hasFailures = !$.isEmptyObject(unexpectedFailures)
    55         if (!hasFailures) {
    56             $('.results').text('No failures. Party time!');
    57             var partyTime = $('<div class="partytime"><img src="partytime.gif"></div>');
    58             $('.results').append(partyTime);
    59             partyTime.fadeIn(1200).delay(7000).fadeOut();
    60         } else {
    61             var regressions = ui.regressionsContainer();
    62 
    63             $.each(unexpectedFailures, function(testName, resultNodesByBuilder) {
    64                 var testSummary = ui.summarizeTest(testName, resultNodesByBuilder);
    65                 $('tbody', regressions).append(testSummary);
    66 
    67                 var builderNameList = base.keys(resultNodesByBuilder);
    68                 results.unifyRegressionRanges(builderNameList, testName, function(oldestFailingRevision, newestPassingRevision) {
    69                     $('.when', testSummary).append(ui.summarizeRegressionRange(oldestFailingRevision, newestPassingRevision));
    70                     if (!newestPassingRevision)
    71                         return;
    72                     checkout.existsAtRevision(checkout.subversionURLForTest(testName), newestPassingRevision, function(testExistedBeforeFailure) {
    73                         $(testSummary).attr('data-new-test', !testExistedBeforeFailure);
    74                     });
    75                 });
    76                 results.countFailureOccurances(builderNameList, testName, function(failureCount) {
    77                     $(testSummary).attr(config.kFailureCountAttr, failureCount);
    78                     $('.how-many', testSummary).text(ui.failureCount(failureCount));
    79                 });
     110
     111        togglePartyTime(hasFailures);
     112        setIconState(hasFailures);
     113
     114        var container = ensureResultsSummaryContainer();
     115        var testMap = detachRepairedTestsAndPrepareTestMap(unexpectedFailures);
     116
     117        var newTestSummaries = $();
     118        var requestTracker = new base.RequestTracker(base.keys(unexpectedFailures).length, function() {
     119            newTestSummaries.fadeIn();
     120            callback()
     121        });
     122
     123        $.each(unexpectedFailures, function(testName, resultNodesByBuilder) {
     124            prepareTestSummary(testName, resultNodesByBuilder, function(testSummary) {
     125                var existingElement = testMap[testName];
     126                if (existingElement) {
     127                    existingElement.replaceWith(testSummary);
     128                    requestTracker.requestComplete();
     129                    return;
     130                }
     131                $('tbody', container).append(testSummary);
     132                newTestSummaries = newTestSummaries.add(testSummary);
     133                requestTracker.requestComplete();
    80134            });
    81             $('.results').append(regressions);
    82         }
    83         setIconState(hasFailures);
    84         onsuccess();
     135        });
    85136    });
    86137}
     
    88139function showResultsDetail()
    89140{
    90     var testBlock = $(this).parents('.test');
     141    var testSummary = $(this).parents('.test');
    91142    var builderName = $(this).attr(config.kBuilderNameAttr);
    92     var testName = $('.what', testBlock).text();
     143    var testName = testSummary.attr(config.kTestNameAttr);
    93144
    94145    // FIXME: It's lame that we have two different representations of multiple failure types.
    95     var failureTypes = testBlock.attr(config.kFailureTypesAttr);
     146    var failureTypes = testSummary.attr(config.kFailureTypesAttr);
    96147    var failureTypeList = failureTypes.split(' ');
    97148
     
    167218function update()
    168219{
     220    displayOnButterbar('Loading...');
     221    updateResultsSummary(dismissButterbar);
    169222    checkBuilderStatuses();
    170223}
     
    175228
    176229$(document).ready(function() {
    177     showResults(function() {
    178         $('.butterbar').fadeOut();
    179     });
    180230    g_updateTimerId = window.setInterval(update, config.kUpdateFrequency);
    181231    update();
  • trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/results.js

    r91196 r91240  
    178178ResultsCache.prototype.get = function(key, callback)
    179179{
    180     if (key in this._cache) {
     180    if (this._cache[key]) {
    181181        callback(this._cache[key]);
    182182        return;
  • trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/ui.js

    r91197 r91240  
    5555        '</tr>');
    5656    $('.what a', block).text(testName).attr('href', ui.urlForTest(testName)).attr('class', unexpectedResults.join(' '));
     57    block.attr(config.kTestNameAttr, testName);
    5758    block.attr(config.kFailureTypesAttr, unexpectedResults);
    5859
Note: See TracChangeset for help on using the changeset viewer.