1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
7 var lkgrURL = 'http://chromium-status.appspot.com/lkgr';
9 // Interval at which to reload the non-CL bot status.
10 var botStatusRefreshIntervalInMs = 60 * 1000;
11 // Interval at which to check for LKGR updates.
12 var lkgrRefreshIntervalInMs = 60 * 1000;
14 function getClassForTryJobResult(result) {
15 // Some win bots seem to report a null result while building.
17 result = buildbot.RUNNING;
19 switch (parseInt(result)) {
20 case buildbot.RUNNING:
23 case buildbot.SUCCESS:
26 case buildbot.WARNINGS:
29 case buildbot.FAILURE:
32 case buildbot.SKIPPED:
35 case buildbot.EXCEPTION:
41 case buildbot.NOT_STARTED:
47 // Remove try jobs that have been supplanted by newer runs.
48 function filterOldTryJobs(tryJobs) {
50 tryJobs.forEach(function(tryJob) {
51 if (!latest[tryJob.builder] ||
52 latest[tryJob.builder].buildnumber < tryJob.buildnumber)
53 latest[tryJob.builder] = tryJob;
57 tryJobs.forEach(function(tryJob) {
58 if (tryJob.buildnumber == latest[tryJob.builder].buildnumber)
65 function createTryJobAnchorTitle(tryJob, fullTryJob) {
66 var title = tryJob.builder;
72 if (fullTryJob.currentStep)
73 stepText.push("running " + fullTryJob.currentStep.name);
75 if (fullTryJob.results == buildbot.FAILURE && fullTryJob.text) {
76 stepText.push(fullTryJob.text.join(" "));
78 // Sometimes a step can fail without setting the try job text. Look
79 // through all the steps to identify if this is the case.
81 fullTryJob.steps.forEach(function(step) {
82 if (step.results[0] == buildbot.FAILURE)
83 text.push(step.results[1][0]);
86 if (text.length > 0) {
87 text.unshift("failure");
88 stepText.push(text.join(" "));
92 if (stepText.length > 0)
93 title += ": " + stepText.join("; ");
98 function createPatchsetStatusElement(patchset) {
99 var table = document.createElement("div");
100 table.className = "issue-status";
102 var tryJobs = filterOldTryJobs(patchset.try_job_results);
103 tryJobs.forEach(function(tryJob) {
104 var key = tryJob.builder + "-" + tryJob.buildnumber;
105 var fullTryJob = patchset.full_try_job_results &&
106 patchset.full_try_job_results[key];
108 var tryJobAnchor = document.createElement("a");
109 tryJobAnchor.textContent = " ";
110 tryJobAnchor.title = createTryJobAnchorTitle(tryJob, fullTryJob);
111 tryJobAnchor.className = "issue-status-build " +
112 getClassForTryJobResult(tryJob.result);
113 tryJobAnchor.target = "_blank";
114 tryJobAnchor.href = tryJob.url;
115 table.appendChild(tryJobAnchor);
121 function getLastFullPatchsetWithTryJobs(issue) {
122 var index = issue.patchsets.length - 1;
123 var fullPatchsets = issue.full_patchsets;
126 !fullPatchsets[issue.patchsets[index]] ||
127 !fullPatchsets[issue.patchsets[index]].try_job_results ||
128 fullPatchsets[issue.patchsets[index]].try_job_results.length == 0)) {
132 return index >= 0 ? fullPatchsets[issue.patchsets[index]] : null;
135 function createTryStatusRow(issue) {
136 var table = document.getElementById("status-table");
138 // Order by decreasing issue number.
140 document.getElementsByClassName("trunk-status-row")[0].rowIndex;
141 while (position > 0 &&
142 parseInt(issue.issue) >
143 parseInt(table.rows[position - 1].getAttribute("data-issue"))) {
147 var row = table.insertRow(position);
148 row.setAttribute("data-issue", issue.issue);
153 function updateIssueDisplay(issue) {
154 var codereviewBaseURL = "https://codereview.chromium.org";
156 var lastFullPatchset = getLastFullPatchsetWithTryJobs(issue);
158 var row = document.querySelector("*[data-issue='" + issue.issue + "']");
159 if (!lastFullPatchset) {
161 row.parentNode.removeChild(row);
166 row = createTryStatusRow(issue);
168 var label = row.childNodes[0] || row.insertCell(-1);
169 var status = row.childNodes[1] || row.insertCell(-1);
171 label.className = "status-label";
172 var clAnchor = label.childNodes[0] ||
173 label.appendChild(document.createElement("a"));
174 clAnchor.textContent = "CL " + issue.issue;
175 clAnchor.href = codereviewBaseURL + "/" + issue.issue;
176 clAnchor.title = issue.subject;
177 if (lastFullPatchset && lastFullPatchset.message)
178 clAnchor.title += " | " + lastFullPatchset.message;
179 clAnchor.target = "_blank";
181 var statusElement = createPatchsetStatusElement(lastFullPatchset);
182 if (status.childElementCount < 1)
183 status.appendChild(statusElement);
185 status.replaceChild(statusElement, status.firstChild);
188 function removeIssueDisplay(issueNumber) {
189 var row = document.querySelector("*[data-issue='" + issueNumber + "']");
190 row.parentNode.removeChild(row);
193 function addTryStatusRows() {
194 buildbot.getActiveIssues().forEach(updateIssueDisplay);
197 function updateLKGR(lkgr) {
198 var link = document.getElementById('link_lkgr');
199 link.textContent = 'LKGR (' + lkgr + ')';
202 function addBotStatusRow(bot, className) {
203 var table = document.getElementById("status-table");
205 var baseURL = "http://build.chromium.org/p/chromium" +
206 (bot.id != "" ? "." + bot.id : "");
207 var consoleURL = baseURL + "/console";
208 var statusURL = baseURL + "/horizontal_one_box_per_builder";
210 var row = table.insertRow(-1);
211 row.className = "trunk-status-row " + className;
212 var label = row.insertCell(-1);
213 label.className = "status-label";
214 var labelAnchor = document.createElement("a");
215 labelAnchor.href = consoleURL;
216 labelAnchor.target = "_blank";
217 labelAnchor.id = "link_" + bot.id;
218 labelAnchor.textContent = bot.label;
219 label.appendChild(labelAnchor);
221 var status = row.insertCell(-1);
222 status.className = "trunk-status-cell";
223 var statusIframe = document.createElement("iframe");
224 statusIframe.scrolling = "no";
225 statusIframe.src = statusURL;
226 status.appendChild(statusIframe);
229 function addBotStatusRows() {
231 {id: "", label: "Chromium"},
232 {id: "win", label: "Win"},
233 {id: "mac", label: "Mac"},
234 {id: "linux", label: "Linux"},
235 {id: "chromiumos", label: "ChromiumOS"},
236 {id: "chrome", label: "Official"},
237 {id: "memory", label: "Memory"}
241 {id: "lkgr", label: "LKGR"},
242 {id: "perf", label: "Perf"},
243 {id: "memory.fyi", label: "Memory FYI"},
244 {id: "gpu", label: "GPU"},
245 {id: "gpu.fyi", label: "GPU FYI"}
248 closerBots.forEach(function(bot) {
249 addBotStatusRow(bot, "closer-status-row");
252 otherBots.forEach(function(bot) {
253 addBotStatusRow(bot, "other-status-row");
257 function fillStatusTable() {
263 buildbot.requestURL(lkgrURL, "text", updateLKGR);
266 buildbot.getActiveIssues().setEventCallback(function(request) {
267 // NOTE(wittman): It doesn't appear that we can reliably detect closing of
268 // the popup and remove the event callback, so ensure the popup window is
269 // displayed before processing the event.
270 if (!chrome.extension.getViews({type: "popup"}))
273 switch (request.event) {
276 updateIssueDisplay(buildbot.getActiveIssues().getIssue(request.issue));
280 removeIssueDisplay(request.issue);
285 setInterval(function() {
286 buildbot.requestURL(lkgrURL, "text", updateLKGR);
287 }, lkgrRefreshIntervalInMs);
289 setInterval(function() {
290 var botStatusElements =
291 document.getElementsByClassName("trunk-status-iframe");
292 for (var i = 0; i < botStatusElements.length; i++)
293 // Force a reload of the iframe in a way that doesn't cause cross-domain
294 // policy violations.
295 botStatusElements.item(i).src = botStatusElements.item(i).src;
296 }, botStatusRefreshIntervalInMs);