Please clarify "pending" reporting at build.webkit.org/dashboard
[WebKit-https.git] / Tools / BuildSlaveSupport / build.webkit.org-config / public_html / dashboard / Scripts / BuildbotQueueView.js
1 /*
2  * Copyright (C) 2013 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 BuildbotQueueView = function(debugQueues, releaseQueues)
27 {
28     BaseObject.call(this);
29
30     this.releaseQueues = releaseQueues || [];
31     this.debugQueues = debugQueues || [];
32
33     this.element = document.createElement("div");
34     this.element.classList.add("queue-view");
35     this.element.__queueView = this;
36
37     this.releaseQueues.forEach(function(queue) {
38         if (this.platform && this.platform != queue.platform)
39             throw "A buildbot view may not contain queues for multiple platforms."
40         else
41             this.platform = queue.platform;
42         queue.addEventListener(BuildbotQueue.Event.IterationsAdded, this._queueIterationsAdded, this);
43     }.bind(this));
44
45     this.debugQueues.forEach(function(queue) {
46         if (this.platform && this.platform != queue.platform)
47             throw "A buildbot view may not contain queues for multiple platforms."
48         else
49             this.platform = queue.platform;
50         queue.addEventListener(BuildbotQueue.Event.IterationsAdded, this._queueIterationsAdded, this);
51     }.bind(this));
52
53     webkitTrac.addEventListener(Trac.Event.NewCommitsRecorded, this._newCommitsRecorded, this);
54     if (typeof internalTrac != "undefined")
55         internalTrac.addEventListener(Trac.Event.NewCommitsRecorded, this._newCommitsRecorded, this);
56
57     this.updateTimer = null;
58     this._updateHiddenState();
59     settings.addSettingListener("hiddenPlatforms", this._updateHiddenState.bind(this));
60 };
61
62 BaseObject.addConstructorFunctions(BuildbotQueueView);
63
64 BuildbotQueueView.UpdateInterval = 45000; // 45 seconds
65 BuildbotQueueView.UpdateSoonTimeout = 1000; // 1 second
66
67 BuildbotQueueView.prototype = {
68     constructor: BuildbotQueueView,
69     __proto__: BaseObject.prototype,
70
71     updateSoon: function()
72     {
73         if (this._updateTimeout)
74             return;
75         this._updateTimeout = setTimeout(this.update.bind(this), BuildbotQueueView.UpdateSoonTimeout);
76     },
77
78     update: function()
79     {
80         if (this._updateTimeout) {
81             clearTimeout(this._updateTimeout);
82             delete this._updateTimeout;
83         }
84
85         // Implemented by subclasses.
86     },
87
88     _appendPendingRevisionCount: function(queue)
89     {
90         for (var i = 0; i < queue.iterations.length; ++i) {
91             var iteration = queue.iterations[i];
92             if (!iteration.loaded || !iteration.finished)
93                 continue;
94
95             var latestRecordedOpenSourceRevisionNumber = webkitTrac.latestRecordedRevisionNumber;
96             if (!latestRecordedOpenSourceRevisionNumber)
97                 return;
98
99             var openSourceRevisionsBehind = latestRecordedOpenSourceRevisionNumber - iteration.openSourceRevision;
100             if (openSourceRevisionsBehind < 0)
101                 openSourceRevisionsBehind = 0;
102
103             if (iteration.internalRevision) {
104                 var latestRecordedInternalRevisionNumber = internalTrac.latestRecordedRevisionNumber;
105                 if (!latestRecordedInternalRevisionNumber)
106                     return;
107
108                 var internalRevisionsBehind = latestRecordedInternalRevisionNumber - iteration.internalRevision;
109                 if (internalRevisionsBehind < 0)
110                     internalRevisionsBehind = 0;
111                 if (openSourceRevisionsBehind || internalRevisionsBehind) {
112                     var message = openSourceRevisionsBehind + " \uff0b " + internalRevisionsBehind + " revisions behind";
113                     var status = new StatusLineView(message, StatusLineView.Status.NoBubble);
114                     this.element.appendChild(status.element);
115                 }
116             } else if (openSourceRevisionsBehind) {
117                 var message = openSourceRevisionsBehind + " " + (openSourceRevisionsBehind === 1 ? "revision behind" : "revisions behind");
118                 var status = new StatusLineView(message, StatusLineView.Status.NoBubble);
119                 this.element.appendChild(status.element);
120             }
121
122             return;
123         }
124     },
125
126     revisionLinksForIteration: function(iteration)
127     {
128         function linkForRevision(revision, trac)
129         {
130             var linkElement = document.createElement("a");
131             linkElement.href = trac.revisionURL(revision);
132             linkElement.target = "_blank";
133             linkElement.textContent = "r" + revision;
134             linkElement.classList.add("selectable");
135
136             return linkElement;
137         }
138
139         console.assert(iteration.openSourceRevision);
140         var openSourceLink = linkForRevision(iteration.openSourceRevision, webkitTrac);
141
142         if (!iteration.internalRevision)
143             return openSourceLink;
144
145         var internalLink = linkForRevision(iteration.internalRevision, internalTrac);
146
147         var fragment = document.createDocumentFragment();
148         fragment.appendChild(openSourceLink);
149         fragment.appendChild(document.createTextNode(" \uff0b "));
150         fragment.appendChild(internalLink);
151         return fragment;
152     },
153
154     _updateHiddenState: function()
155     {
156         var hiddenPlatforms = settings.getObject("hiddenPlatforms");
157         var wasHidden = !this.updateTimer;
158         var isHidden = hiddenPlatforms && hiddenPlatforms.contains(this.platform);
159
160         if (wasHidden && !isHidden)
161             this.updateTimer = setInterval(this._updateQueues.bind(this), BuildbotQueueView.UpdateInterval);
162         else if (!wasHidden && isHidden) {
163             clearInterval(this.updateTimer);
164             this.updateTimer = null;
165         }
166     },
167
168     _updateQueues: function()
169     {
170         this.releaseQueues.forEach(function(queue) { queue.update(); });
171         this.debugQueues.forEach(function(queue) { queue.update(); });
172     },
173
174     _queueIterationsAdded: function(event)
175     {
176         this.updateSoon();
177
178         event.data.addedIterations.forEach(function(iteration) {
179             iteration.addEventListener(BuildbotIteration.Event.Updated, this._iterationUpdated, this);
180         }.bind(this));
181     },
182
183     _iterationUpdated: function(event)
184     {
185         this.updateSoon();
186     },
187     
188     _newCommitsRecorded: function(event)
189     {
190         this.updateSoon();
191     }
192 };