2 * Copyright (C) 2013 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
26 BuildbotBuilderQueueView = function(queues)
28 BuildbotQueueView.call(this, queues);
30 function filterQueues(architecture, debug, queue)
32 return queue.architecture === architecture && queue.debug === debug;
35 this.universalReleaseQueues = this.queues.filter(filterQueues.bind(this, Buildbot.BuildArchitecture.Universal, false));
36 this.sixtyFourBitReleaseQueues = this.queues.filter(filterQueues.bind(this, Buildbot.BuildArchitecture.SixtyFourBit, false));
37 this.thirtyTwoBitReleaseQueues = this.queues.filter(filterQueues.bind(this, Buildbot.BuildArchitecture.ThirtyTwoBit, false));
39 this.universalDebugQueues = this.queues.filter(filterQueues.bind(this, Buildbot.BuildArchitecture.Universal, true));
40 this.sixtyFourBitDebugQueues = this.queues.filter(filterQueues.bind(this, Buildbot.BuildArchitecture.SixtyFourBit, true));
41 this.thirtyTwoBitDebugQueues = this.queues.filter(filterQueues.bind(this, Buildbot.BuildArchitecture.ThirtyTwoBit, true));
43 this.hasMultipleReleaseBuilds = this.universalReleaseQueues.length + this.sixtyFourBitReleaseQueues.length + this.thirtyTwoBitReleaseQueues.length > 1;
44 this.hasMultipleDebugBuilds = this.universalDebugQueues.length + this.sixtyFourBitDebugQueues.length + this.thirtyTwoBitDebugQueues.length > 1;
49 BaseObject.addConstructorFunctions(BuildbotBuilderQueueView);
51 BuildbotBuilderQueueView.prototype = {
52 constructor: BuildbotBuilderQueueView,
53 __proto__: BuildbotQueueView.prototype,
57 BuildbotQueueView.prototype.update.call(this);
59 this.element.removeChildren();
61 function appendBuilderQueueStatus(queue)
63 if (queue.buildbot.needsAuthentication && !queue.buildbot.isAuthenticated) {
64 this._appendUnauthorizedLineView(queue);
68 this._appendPendingRevisionCount(queue);
70 var firstRecentUnsuccessfulIteration = queue.firstRecentUnsuccessfulIteration;
71 var mostRecentFinishedIteration = queue.mostRecentFinishedIteration;
72 var mostRecentSuccessfulIteration = queue.mostRecentSuccessfulIteration;
74 if (firstRecentUnsuccessfulIteration && firstRecentUnsuccessfulIteration.loaded
75 && mostRecentFinishedIteration && mostRecentFinishedIteration.loaded) {
76 console.assert(!mostRecentFinishedIteration.successful);
77 var message = this.revisionContentForIteration(mostRecentFinishedIteration, mostRecentFinishedIteration.productive ? mostRecentSuccessfulIteration : null);
78 if (mostRecentFinishedIteration.failed && mostRecentFinishedIteration.productive) {
79 // Assume it was a build step that failed, and link directly to output.
80 var url = mostRecentFinishedIteration.failureLogURL("build log");
82 url = mostRecentFinishedIteration.failureLogURL("stdio");
83 var status = StatusLineView.Status.Bad;
85 var status = StatusLineView.Status.Danger;
87 // Show a popover when the URL is not a main build page one, because there are usually multiple logs, and it's good to provide a choice.
88 var needsPopover = !!url;
90 // Some other step failed, link to main buildbot page for the iteration.
92 url = queue.buildbot.buildPageURLForIteration(mostRecentFinishedIteration);
93 var status = new StatusLineView(message, status, mostRecentFinishedIteration.text, null, url);
94 this.element.appendChild(status.element);
97 new PopoverTracker(status.statusBubbleElement, this._presentPopoverFailureLogs.bind(this), mostRecentFinishedIteration);
100 if (mostRecentSuccessfulIteration && mostRecentSuccessfulIteration.loaded) {
101 var message = this.revisionContentForIteration(mostRecentSuccessfulIteration);
102 var url = queue.buildbot.buildPageURLForIteration(mostRecentSuccessfulIteration);
103 var status = new StatusLineView(message, StatusLineView.Status.Good, firstRecentUnsuccessfulIteration ? "last successful build" : "latest build", null, url);
104 this.element.appendChild(status.element);
106 var status = new StatusLineView("unknown", StatusLineView.Status.Neutral, firstRecentUnsuccessfulIteration ? "last successful build" : "latest build");
107 this.element.appendChild(status.element);
109 if (firstRecentUnsuccessfulIteration) {
110 // We have a failed iteration but no successful. It might be further back in time.
111 queue.loadMoreHistoricalIterations();
116 this.appendBuildStyle.call(this, this.universalReleaseQueues, this.hasMultipleReleaseBuilds ? "Release (Universal)" : "Release", appendBuilderQueueStatus);
117 this.appendBuildStyle.call(this, this.sixtyFourBitReleaseQueues, this.hasMultipleReleaseBuilds ? "Release (64-bit)" : "Release", appendBuilderQueueStatus);
118 this.appendBuildStyle.call(this, this.thirtyTwoBitReleaseQueues, this.hasMultipleReleaseBuilds ? "Release (32-bit)" : "Release", appendBuilderQueueStatus);
120 this.appendBuildStyle.call(this, this.universalDebugQueues, this.hasMultipleDebugBuilds ? "Debug (Universal)" : "Debug", appendBuilderQueueStatus);
121 this.appendBuildStyle.call(this, this.sixtyFourBitDebugQueues, this.hasMultipleDebugBuilds ? "Debug (64-bit)" : "Debug", appendBuilderQueueStatus);
122 this.appendBuildStyle.call(this, this.thirtyTwoBitDebugQueues, this.hasMultipleDebugBuilds ? "Debug (32-bit)" : "Debug", appendBuilderQueueStatus);
125 _presentPopoverFailureLogs: function(element, popover, iteration)
127 var content = document.createElement("div");
128 content.className = "build-logs-popover";
130 function addLog(name, url) {
131 var line = document.createElement("a");
132 line.className = "build-log-link";
134 line.textContent = name;
135 line.target = "_blank";
136 content.appendChild(line);
139 this._addIterationHeadingToPopover(iteration, content);
140 this._addDividerToPopover(content);
142 var logsHeadingLine = document.createElement("div");
143 logsHeadingLine.className = "build-logs-heading";
144 logsHeadingLine.textContent = iteration.firstFailedStepName + " failed";
145 content.appendChild(logsHeadingLine);
147 for (var i = 0, end = iteration.failureLogs.length; i < end; ++i)
148 addLog(iteration.failureLogs[i][0], iteration.failureLogs[i][1]);
150 var rect = Dashboard.Rect.rectFromClientRect(element.getBoundingClientRect());
151 popover.content = content;
152 popover.present(rect, [Dashboard.RectEdge.MIN_Y, Dashboard.RectEdge.MAX_Y, Dashboard.RectEdge.MAX_X, Dashboard.RectEdge.MIN_X]);