2 * Copyright (C) 2013-2015 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 Buildbot = function(baseURL, queuesInfo, options)
28 BaseObject.call(this);
30 console.assert(baseURL);
31 console.assert(queuesInfo);
33 this.baseURL = baseURL;
34 this.queuesInfo = queuesInfo;
37 this._normalizeQueuesInfo();
39 // We regard _needsAuthentication as a hint whether this Buildbot requires authentication so that we can show
40 // an appropriate initial status message (say, an "unauthorized" status if the Buildbot requires authentication)
41 // for its associated queues before we make the actual HTTP request for the status of each queue.
42 this._needsAuthentication = typeof options === "object" && options.needsAuthentication === true;
43 this._authenticationStatus = Buildbot.AuthenticationStatus.Unauthenticated;
45 for (var id in queuesInfo) {
46 if (queuesInfo[id].combinedQueues) {
47 for (var combinedQueueID in queuesInfo[id].combinedQueues)
48 this.queues[combinedQueueID] = new BuildbotQueue(this, combinedQueueID, queuesInfo[id].combinedQueues[combinedQueueID]);
50 this.queues[id] = new BuildbotQueue(this, id, queuesInfo[id]);
54 BaseObject.addConstructorFunctions(Buildbot);
56 Buildbot.AuthenticationStatus = {
57 Unauthenticated: "unauthenticated",
58 Authenticated: "authenticated",
59 InvalidCredentials: "invalid-credentials"
62 Buildbot.UpdateReason = {
63 Reauthenticate: "reauthenticate"
66 // Ordered importance.
67 Buildbot.TestCategory = {
72 // Ordered importance.
73 Buildbot.BuildArchitecture = {
74 Universal: "universal",
75 SixtyFourBit: "sixty-four-bit",
76 ThirtyTwoBit: "thirty-two-bit"
79 Buildbot.prototype = {
80 constructor: Buildbot,
81 __proto__: BaseObject.prototype,
83 get needsAuthentication()
85 return this._needsAuthentication;
88 get authenticationStatus()
90 return this._authenticationStatus;
95 return this._authenticationStatus === Buildbot.AuthenticationStatus.Authenticated;
98 set isAuthenticated(value)
100 this._authenticationStatus = value ? Buildbot.AuthenticationStatus.Authenticated : Buildbot.AuthenticationStatus.InvalidCredentials;
103 _normalizeQueueInfo: function(queueInfo)
105 if (!queueInfo.combinedQueues)
106 queueInfo.branches = queueInfo.branches || this.defaultBranches;
107 queueInfo.debug = queueInfo.debug || false;
108 queueInfo.builder = queueInfo.builder || false;
109 queueInfo.tester = queueInfo.tester || false;
110 queueInfo.performance = queueInfo.performance || false;
111 queueInfo.staticAnalyzer = queueInfo.staticAnalyzer || false;
112 queueInfo.leaks = queueInfo.leaks || false;
113 queueInfo.architecture = queueInfo.architecture || null;
114 queueInfo.testCategory = queueInfo.testCategory || null;
115 queueInfo.heading = queueInfo.heading || null;
116 queueInfo.crashesOnly = queueInfo.crashesOnly || false;
119 _normalizeQueuesInfo: function()
121 for (queueName in this.queuesInfo) {
122 var queueInfo = this.queuesInfo[queueName];
123 this._normalizeQueueInfo(queueInfo);
124 if (queueInfo.combinedQueues) {
125 for (combinedQueueName in queueInfo.combinedQueues) {
126 queueInfo.combinedQueues[combinedQueueName].platform = queueInfo.platform;
127 this._normalizeQueueInfo(queueInfo.combinedQueues[combinedQueueName]);
133 updateQueues: function(updateReason)
135 var shouldReauthenticate = updateReason === Buildbot.UpdateReason.Reauthenticate;
136 if (shouldReauthenticate) {
137 var savedAuthenticationStatus = this._authenticationStatus;
138 this._authenticationStatus = Buildbot.AuthenticationStatus.Unauthenticated;
140 for (var id in this.queues)
141 this.queues[id].update();
142 if (shouldReauthenticate) {
143 // Assert status wasn't changed synchronously. Otherwise, we will override it (below).
144 console.assert(this._authenticationStatus === Buildbot.AuthenticationStatus.Unauthenticated);
145 this._authenticationStatus = savedAuthenticationStatus;
149 buildPageURLForIteration: function(iteration)
151 return this.baseURL + "builders/" + encodeURIComponent(iteration.queue.id) + "/builds/" + iteration.id;
154 layoutTestResultsDirectoryURLForIteration: function(iteration)
156 var underscoreSeparatedRevisions = "r";
157 sortDictionariesByOrder(Dashboard.Repository).forEach(function(repository) {
158 if (iteration.revision[repository.name]) {
159 if (underscoreSeparatedRevisions.length > 1)
160 underscoreSeparatedRevisions += "_";
161 underscoreSeparatedRevisions += iteration.revision[repository.name];
164 return this.baseURL + "results/" + encodeURIComponent(iteration.queue.id) + "/" + encodeURIComponent(underscoreSeparatedRevisions + " (" + iteration.id + ")");
167 layoutTestResultsURLForIteration: function(iteration)
169 return this.layoutTestResultsDirectoryURLForIteration(iteration) + "/results.html";
172 layoutTestFullResultsURLForIteration: function(iteration)
174 return this.layoutTestResultsDirectoryURLForIteration(iteration) + "/full_results.json";
177 layoutTestCrashLogURLForIteration: function(iteration, testPath)
179 var path = testPath.replace(/^(.*)\.(?:.*)$/, "$1-crash-log.txt");
180 return this.layoutTestResultsDirectoryURLForIteration(iteration) + "/" + path;
183 layoutTestStderrURLForIteration: function(iteration, testPath)
185 var path = testPath.replace(/^(.*)\.(?:.*)$/, "$1-stderr.txt");
186 return this.layoutTestResultsDirectoryURLForIteration(iteration) + "/" + path;
189 layoutTestDiffURLForIteration: function(iteration, testPath)
191 var path = testPath.replace(/^(.*)\.(?:.*)$/, "$1-diff.txt");
192 return this.layoutTestResultsDirectoryURLForIteration(iteration) + "/" + path;
195 layoutTestPrettyDiffURLForIteration: function(iteration, testPath)
197 // pretty-patch may not be available, caller should check JSON results for has_pretty_patch attribute.
198 var path = testPath.replace(/^(.*)\.(?:.*)$/, "$1-pretty-diff.html");
199 return this.layoutTestResultsDirectoryURLForIteration(iteration) + "/" + path;
202 layoutTestImagesURLForIteration: function(iteration, testPath)
204 var path = testPath.replace(/^(.*)\.(?:.*)$/, "$1-diffs.html");
205 return this.layoutTestResultsDirectoryURLForIteration(iteration) + "/" + path;
208 layoutTestImageDiffURLForIteration: function(iteration, testPath)
210 var path = testPath.replace(/^(.*)\.(?:.*)$/, "$1-diff.png");
211 return this.layoutTestResultsDirectoryURLForIteration(iteration) + "/" + path;