| {%- block doctype -%} |
| <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" |
| "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
| {% endblock %} |
| <!-- Copied and modified from: |
| http://src.chromium.org/viewvc/chrome/trunk/tools/build/third_party/buildbot_8_4p1/buildbot/status/web/templates/layout.html?revision=89637&content-type=text/plain |
| --> |
| <html xmlns="http://www.w3.org/1999/xhtml"> |
| <head> |
| {% block head %} |
| <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> |
| {% if metatags %} |
| {{ metatags }} |
| {% endif %} |
| <title>{{ pageTitle|e }}</title> |
| <link rel="stylesheet" href="{{ stylesheet }}" type="text/css" /> |
| <link rel="alternate" type="application/rss+xml" title="RSS" href="{{ path_to_root }}rss"> |
| <script type="text/javascript"> |
| "use strict"; |
| |
| // Revision of the buildbot code on the build master. |
| var javascript_revision = "{{ master_revision }}"; |
| |
| // Ports used to access the buildbot webstatus pages. |
| var internalPort = "{{ internal_port }}"; |
| var externalPort = "{{ external_port }}"; |
| |
| // JSON data URL. |
| var tree_status_appspot_url = "{{ tree_status_baseurl }}"; |
| |
| // Per-builder status messages. |
| var builder_statuses = {}; |
| |
| // How often, in milliseconds, to refresh the page. |
| var refreshInterval = {{ refresh or default_refresh }} * 1000; |
| var refreshTimer = null; |
| |
| // Number of times a page reload has been cancelled due to activity on the page. |
| var cancelledReloads = 0; |
| |
| // Maximum number of cancelled reloads before forcing a reload. |
| var maxCancelledReloads = 10; |
| |
| // Variables passed in the URL. |
| var urlVars = {}; |
| |
| // Categories of builders, and whether each category should be displayed. |
| var allCategories = { |
| {% for r in all_categories %} |
| "{{ r }}": true, |
| {% endfor %} |
| }; |
| |
| // Subcategories of builders, and whether each category should be displayed. |
| var allSubcategories = { |
| {% for subcategory in all_subcategories %} |
| "{{ subcategory }}": true, |
| {% endfor %} |
| }; |
| |
| // Subcategories listed by which category they fall under. |
| var subcategoriesByCategory = { |
| {% for category in subcategories_by_category %} |
| "{{ category }}": [ |
| {% for subcategory in subcategories_by_category[category] %} |
| "{{ subcategory }}", |
| {% endfor %} |
| ], |
| {% endfor %} |
| } |
| |
| function addLinks(text) { |
| // Linkify arbitrary URLs. |
| var new_text = ""; |
| if (text && text.indexOf("<a href=") == -1) { |
| new_text = text.replace( |
| /(https?:\/\/.+?)(\s|\t|<|\n|\r|$)/g, '<a href="$1" target="_blank">$1</a>$2'); |
| } |
| |
| // Linkify instances of "skia:123". |
| var re = new RegExp("skia:[0-9]+"); |
| var found_bugs = new_text.match(/skia:[0-9]+/g); |
| if (found_bugs) { |
| for (var i = 0; i < found_bugs.length; ++i) { |
| var found_bug = found_bugs[i]; |
| var bug_number = found_bug.split(":")[1]; |
| var bug_link = '<a href="https://code.google.com/p/skia/issues/detail?id=' + bug_number + '" target="_blank">' + found_bug + '</a>'; |
| new_text = new_text.replace(found_bug, bug_link); |
| } |
| } |
| return new_text; |
| } |
| |
| // Switch to a new host/port. |
| function setHostAndPort(host, port) { |
| var current_host = window.location.host.split(":"); |
| if (!host) { |
| host = current_host[0]; |
| } |
| if (!port) { |
| port = current_host[1]; |
| } |
| window.location.host = host + ":" + port; |
| } |
| |
| // Parse the variables in the URL and return a key/value dictionary. |
| function parseArgs() |
| { |
| var args = {}; |
| var dict = window.location.search.slice(1).split('&'); |
| for(var i = 0; i < dict.length; i++) { |
| var split = dict[i].split('='); |
| var key = split[0]; |
| var value = split[1]; |
| if (args[key]) { |
| if (Object.prototype.toString.call(args[key]) == "[object Array]") { |
| args[key].push(value); |
| } else { |
| args[key] = [args[key], value]; |
| } |
| } else if (key != "") { |
| args[key] = value; |
| } |
| } |
| return args; |
| } |
| |
| // If the currently running revision of this page differs from that of the |
| // build master, reload the whole page instead of just the JSON data. |
| function doReload() { |
| // Get the master's code revision. |
| loadJSONP("/json/master_revision", |
| gotMasterRevision, |
| null); |
| } |
| |
| // Callback function for doReload. |
| function gotMasterRevision(data) { |
| if (data["master_checkedout_revision"] != javascript_revision) { |
| // Force a reload of the page if the master has a new revision. |
| location.reload(true); |
| } else { |
| loadAllData(); |
| } |
| } |
| |
| // Reload the page, if the user isn't actively interacting with it. |
| function reloadPage() { |
| var reloadIsAllowed = true; |
| |
| // Don't allow reload if a build box is open. |
| var buildBox = document.getElementById("divBox"); |
| if (buildBox && buildBox.style.display != "none") { |
| console.log("divBox is displaying (" + buildBox.style.display + ")."); |
| reloadIsAllowed = false; |
| } |
| |
| if (reloadIsAllowed) { |
| doReload(); |
| } else if (cancelledReloads >= maxCancelledReloads) { |
| console.log("Forcing a reload because the number of " + |
| "previously-cancelled reloads exceeded " + |
| maxCancelledReloads + "."); |
| doReload(); |
| } else { |
| console.log("Not reloading page because the user is interacting with it."); |
| cancelledReloads++; |
| refreshTimer = setTimeout(reloadPage, refreshInterval); |
| } |
| } |
| |
| // Return the name of a non-anonymous function. |
| function getFunctionName(func) { |
| var name = func.toString(); |
| name = name.substr("function ".length); |
| name = name.substr(0, name.indexOf("(")); |
| return name; |
| } |
| |
| // Use JSONP to retrieve data from the given URL. There are a few possible |
| // outcomes: |
| // 1. The server returns valid JSONP. In this case, the provided callback |
| // will be called with the data as the parameter. |
| // 2. The server returns an error code (eg. if the requested URL isn't |
| // valid). In this case, the provided errback will be called. |
| // 3. The server returns a success code but the response does not contain |
| // valid JSONP. In this case, the callback cannot be called, since that |
| // call is part of the JSONP response. Additionally, the errback will |
| // not fire, since there is no way to dynamically insert a try/catch |
| // around the response content, and the script tag's onError handler |
| // only fires if the script could not be obtained from the server. |
| // |
| // Note: callback must NOT be an anonymous function. |
| // |
| function loadJSONP(url, callback, errback) { |
| var script = document.createElement("script"); |
| var src = appendParamToURL(url, "callback", getFunctionName(callback)); |
| script.setAttribute("src", src); |
| script.onError = errback |
| document.getElementsByTagName("head")[0].appendChild(script); |
| } |
| |
| // Use an XmlHttpRequest to retrieve data from the given URL. |
| function loadXML(url, callback) { |
| var req = new XMLHttpRequest(); |
| req.open("GET", url, true); |
| req.onreadystatechange = function() { |
| if (req.readyState == 4) { callback(req.responseText); } |
| }; |
| req.send(); |
| } |
| |
| // Set the tree status. |
| function setTreeStatus(data) { |
| var tree_status_div = document.getElementById("tree_status_div"); |
| if (tree_status_div) { |
| tree_status_div.className = "status-message " + data["general_state"]; |
| } |
| var tree_status_message = document.getElementById("tree_status_message"); |
| if (tree_status_message) { |
| tree_status_message.innerHTML = data["message"]; |
| } |
| } |
| |
| // Set the current sheriff. |
| function setSheriff(data) { |
| var sheriff_div = document.getElementById("sheriff_div"); |
| if (sheriff_div) { |
| sheriff_div.innerHTML = "Sheriff: " + data["username"]; |
| } |
| } |
| |
| // Set builder statuses. |
| function setBuilderStatuses(data) { |
| // Set the global builder status variable. |
| builder_statuses = data; |
| |
| // Mark builders who have comments. |
| for (var builder_name in data) { |
| // Builder column headers. |
| var comment_indicator = document.getElementById("commentIndicator_" + builder_name); |
| if (comment_indicator) { |
| comment_indicator.className += " BuilderHasComment"; |
| } |
| |
| // Summary boxes for all masters. |
| var summary_box = document.getElementById("summaryBox_" + builder_name); |
| if (summary_box) { |
| summary_box.className += " BuilderHasComment"; |
| } |
| } |
| |
| // Optionally display the builder status message on the page. |
| var display_comment_elems = document.getElementsByClassName("DisplayBuilderComment"); |
| for (var i = 0; i < display_comment_elems.length; ++i) { |
| var display_comment = display_comment_elems[i]; |
| display_comment.innerHTML = ""; |
| var builder_name = display_comment.id.slice("displayBuilderComment_".length); |
| buildComment(builder_name, display_comment); |
| if (builder_statuses[builder_name]) { |
| display_comment.className += " BuilderHasComment"; |
| } |
| } |
| |
| // Rebuild the console table, if applicable. |
| if (typeof buildConsoleTable == "function") { |
| buildConsoleTable(); |
| } |
| } |
| |
| // Function to call on page load. Reloads the page with appropriate options |
| // if they are not already set. |
| function init() { |
| var host = window.location.host; |
| var checkedRadio; |
| if (host.indexOf(internalPort, host.length - internalPort.length) !== -1) { |
| checkedRadio = document.getElementById("radio_internal"); |
| } else if (host.indexOf(externalPort, host.length - externalPort.length) !== -1) { |
| checkedRadio = document.getElementById("radio_external"); |
| } |
| if (checkedRadio) { |
| checkedRadio.checked = true; |
| } |
| |
| urlVars = parseArgs(); |
| if (urlVars["hideCategories"]) { |
| var categoryList = urlVars["hideCategories"].split(","); |
| for (var i = 0; i < categoryList.length; ++i) { |
| var name = categoryList[i]; |
| allCategories[name] = false; |
| var chkbox = document.getElementById("chkbox_category_" + name); |
| if (chkbox) { |
| chkbox.checked = false; |
| } |
| } |
| } |
| if (urlVars["hideSubcategories"]) { |
| var subcategoryList = urlVars["hideSubcategories"].split(","); |
| for (var i = 0; i < subcategoryList.length; ++i) { |
| var name = subcategoryList[i]; |
| allSubcategories[name] = false; |
| var chkbox = document.getElementById("chkbox_subcategory_" + name); |
| if (chkbox) { |
| chkbox.checked = false; |
| } |
| } |
| } |
| loadAllData(); |
| } |
| |
| // Display the most recent build for each builder on the given master. |
| function setLatestBuildsForMaster(master, master_builder_url, builders) { |
| var master_data_row = document.getElementById("results_summary_" + master); |
| if (!master_data_row) { |
| return; |
| } |
| // Clear any old results, up to the first cell which is the label. |
| while (master_data_row.cells.length > 1) { |
| master_data_row.deleteCell(-1); |
| } |
| // Add the new results. |
| for (var builder_index = 0; builder_index < builders.length; ++builder_index) { |
| var cell = master_data_row.insertCell(-1); |
| cell.className = "mini-box"; |
| cell.style.padding = "0px"; |
| cell.style.verticalAlign = "bottom"; |
| var builder_name = builders[builder_index].name; |
| cell.id = "summaryBox_" + builder_name |
| var outcome = builders[builder_index].outcome; |
| if (!outcome) { |
| outcome = "offline"; |
| } |
| var link = document.createElement("a"); |
| link.href = master_builder_url + builder_name; |
| link.title = builder_name; |
| link.target = "_blank"; |
| link.innerHTML = " "; |
| cell.style.width = "10px"; |
| link.style.width = "100%"; |
| link.style.height = "100%"; |
| link.className = outcome; |
| link.style.margin = "0px"; |
| link.style.padding = "0px"; |
| |
| // Decorate the result summary box if there's a comment for the builder. |
| if (builder_statuses[builder_name]) { |
| cell.className += " BuilderHasComment"; |
| } |
| |
| cell.appendChild(link); |
| } |
| } |
| |
| // Callback functions for individual masters. |
| {% for master in masters %} |
| {% if not (not is_internal_view and master['name'] == 'PrivateSkia') %} |
| function setLatestBuildsFor{{ master['name'] }}(data) { |
| setLatestBuildsForMaster("{{ master['name'] }}", |
| "http://{{ master['host'] }}:{{ master['internal_port'] if is_internal_view else master['external_port'] }}/waterfall?show=", |
| data['builders']); |
| } |
| {% endif %} |
| {% endfor %} |
| |
| // Callback function for AutoRoll bot status. |
| function gotARBStatus(data) { |
| var arb_status_div = document.getElementById("arb_status_div"); |
| if (arb_status_div) { |
| arb_status_div.innerHTML = "AutoRoll Status: " + addLinks(data); |
| } |
| } |
| |
| // Load JSON data from various places. |
| function loadAllData() { |
| // Tree status. |
| loadJSONP(tree_status_appspot_url + "/banner-status?format=json", |
| setTreeStatus, |
| function() { |
| setTreeStatus({ |
| "general_state": "", |
| "message": "Failed to load tree status.", |
| }); |
| }); |
| |
| // Current sheriff. |
| loadJSONP(tree_status_appspot_url + "/current-sheriff", |
| setSheriff, |
| function() { setSheriff({"username": "unknown"}); }); |
| |
| // Builder statuses. |
| loadJSONP(tree_status_appspot_url + "/builder-status/get_builder_statuses", |
| setBuilderStatuses); |
| |
| // Last build result for each builder on each master. |
| var master_json_url = ""; |
| {% for master in masters %} |
| {% if not (not is_internal_view and master['name'] == 'PrivateSkia') %} |
| master_json_url = "http://{{ master['host'] }}:{{ master['internal_port'] if is_internal_view else master['external_port'] }}/json/builder_statuses"; |
| loadJSONP(master_json_url, setLatestBuildsFor{{ master['name'] }}); |
| {% endif %} |
| {% endfor %} |
| |
| // AutoRoll bot status. |
| loadXML("http://chromium-skia-gm.storage.googleapis.com/arb_status.html", gotARBStatus); |
| |
| // Set the reload timer. |
| refreshTimer = setTimeout(reloadPage, refreshInterval); |
| |
| // Load the console data, if applicable. |
| if (typeof loadConsoleData == "function") { |
| loadConsoleData(); |
| } |
| } |
| |
| // Get the comment text for a given builder. |
| function buildComment(builder_name, container) { |
| var file_bug_link = document.createElement("a"); |
| file_bug_link.href = "http://code.google.com/p/skia/issues/entry?labels=BreakingTheBuildbots,Type-Defect,Priority-Medium&summary=" + builder_name; |
| file_bug_link.target = "_blank"; |
| file_bug_link.appendChild(document.createTextNode("file bug")); |
| |
| var edit_status_url = tree_status_appspot_url + "/builder-status/?selected_builder_name=" + builder_name; |
| var edit_status_link = document.createElement("a"); |
| edit_status_link.href = edit_status_url; |
| edit_status_link.target = "_blank"; |
| |
| var builder_para = document.createElement("p"); |
| builder_para.style.fontWeight = "bold"; |
| builder_para.style.lineHeight = "105%"; |
| builder_para.appendChild(document.createTextNode(builder_name)); |
| container.appendChild(builder_para); |
| |
| var comment_para = document.createElement("p"); |
| |
| var comment = null; |
| if (builder_statuses[builder_name]) { |
| comment = builder_statuses[builder_name]["message"]; |
| } |
| if (comment) { |
| comment_para.appendChild(document.createTextNode(comment)); |
| comment_para.innerHTML = addLinks(comment_para.innerHTML); |
| edit_status_link.appendChild(document.createTextNode("edit")); |
| } else { |
| edit_status_link.appendChild(document.createTextNode("add comment")); |
| } |
| container.appendChild(comment_para); |
| |
| var links_para = document.createElement("p"); |
| links_para.appendChild(document.createTextNode("(")); |
| links_para.appendChild(edit_status_link); |
| links_para.appendChild(document.createTextNode(" or ")); |
| links_para.appendChild(file_bug_link); |
| links_para.appendChild(document.createTextNode(")")); |
| container.appendChild(links_para); |
| } |
| |
| // Display a builder tooltip. |
| function showBuilderTooltip(builder_name, event) { |
| var tooltipbox = document.getElementById('builderTooltip'); |
| if (tooltipbox) { |
| var cursorPosTop = (window.event ? window.event.clientY : event.pageY) |
| var cursorPosLeft = (window.event ? window.event.clientX : event.pageX) |
| |
| cursorPosTop = cursorPosTop + document.body.scrollTop + 5; |
| cursorPosLeft = cursorPosLeft + document.body.scrollLeft; |
| |
| tooltipbox.innerHTML = ""; |
| buildComment(builder_name, tooltipbox); |
| tooltipbox.style.top = parseInt(cursorPosTop) + 'px'; |
| tooltipbox.style.left = parseInt(cursorPosLeft) + 'px'; |
| tooltipbox.style.display = "block"; |
| } |
| } |
| |
| // Hide the builder tooltip. |
| function hideBuilderTooltip(event) { |
| var tooltipbox = document.getElementById('builderTooltip'); |
| if (tooltipbox) { |
| // Only hide the tooltip if the mouse is outside the tooltip area. |
| var cursorPosTop = (window.event ? window.event.clientY : event.pageY) |
| var cursorPosLeft = (window.event ? window.event.clientX : event.pageX) |
| cursorPosTop = cursorPosTop + document.body.scrollTop; |
| cursorPosLeft = cursorPosLeft + document.body.scrollLeft; |
| |
| var top = parseInt(tooltipbox.style.top.replace("px", "")); |
| var left = parseInt(tooltipbox.style.left.replace("px", "")); |
| var bottom = top + parseInt(tooltipbox.offsetHeight); |
| var right = left + parseInt(tooltipbox.offsetWidth); |
| |
| if (cursorPosTop < top - 5 || cursorPosTop > bottom || |
| cursorPosLeft < left || cursorPosLeft > right) { |
| tooltipbox.style.display = "none"; |
| } |
| } |
| } |
| |
| // Helper function used by refreshCategories which loops through an array of |
| // elements and shows or hides them as indicated. |
| function showOrHideElements(elems, shouldDisplay) { |
| for (var i = 0; i < elems.length; ++i) { |
| elems[i].style.display = shouldDisplay ? "table-cell" : "none"; |
| } |
| } |
| |
| // Update the display based on the selected set of categories and |
| // subcategories. |
| function refreshCategories() { |
| for (var category in allCategories) { |
| // Show or hide each subcategory. |
| var colSpan = 0; |
| for (var i = 0; i < subcategoriesByCategory[category].length; ++i) { |
| var subcategory = subcategoriesByCategory[category][i]; |
| var className = "category_" + category + "_subcategory_" + subcategory; |
| var elemsToChange = document.getElementsByClassName(className); |
| // Only display a subcategory if its category is also displaying. |
| var shouldDisplay = allCategories[category] && allSubcategories[subcategory] |
| showOrHideElements(elemsToChange, shouldDisplay); |
| if (shouldDisplay) { |
| colSpan++; |
| } |
| } |
| |
| // Show or hide the category label. |
| var elemsToChange = document.getElementsByClassName("category_" + category); |
| var shouldDisplay = allCategories[category] && colSpan > 0; |
| showOrHideElements(elemsToChange, shouldDisplay); |
| |
| // Fix the colSpan of the category header. |
| var header = document.getElementById("category_header_" + category); |
| if (header) { |
| header.colSpan = colSpan; |
| } |
| } |
| } |
| |
| // Adds the key/value parameter pair to the given URL. |
| function appendParamToURL(url, key, value) { |
| if (url.indexOf("?") == "-1") { |
| url += "?"; |
| } else { |
| url += "&"; |
| } |
| url += key + "=" + value; |
| return url; |
| } |
| |
| // Build a URL using the previous URL parameters and the category and |
| // subcategory lists. |
| function buildURL() { |
| var newLocation = location.protocol + "//" + location.host + location.pathname; |
| var firstVar = true; |
| for (var urlVar in urlVars) { |
| if (urlVar != "hideCategories" && urlVar != "hideSubcategories") { |
| if (Object.prototype.toString.call(urlVars[urlVar]) == "[object Array]") { |
| for (var i = 0; i < urlVars[urlVar].length; ++i) { |
| newLocation = appendParamToURL(newLocation, urlVar, urlVars[urlVar][i]); |
| } |
| } else { |
| newLocation = appendParamToURL(newLocation, urlVar, urlVars[urlVar]); |
| } |
| } |
| } |
| |
| // Add hidden categories to the URL. |
| var hiddenCategories = "" |
| for (var category in allCategories) { |
| if (!allCategories[category]) { |
| if (hiddenCategories == "") { |
| hiddenCategories = category; |
| } else { |
| hiddenCategories += "," + category; |
| } |
| } |
| } |
| if (hiddenCategories != "") { |
| newLocation = appendParamToURL(newLocation, "hideCategories", hiddenCategories); |
| } |
| |
| // Add hidden subcategories to the URL. |
| var hiddenSubcategories = "" |
| for (var subcategory in allSubcategories) { |
| if (!allSubcategories[subcategory]) { |
| if (hiddenSubcategories == "") { |
| hiddenSubcategories = subcategory; |
| } else { |
| hiddenSubcategories += "," + subcategory; |
| } |
| } |
| } |
| if (hiddenSubcategories != "") { |
| newLocation = appendParamToURL(newLocation, "hideSubcategories", hiddenSubcategories); |
| } |
| |
| return newLocation; |
| } |
| |
| // Callback function for when a category or subcategory checkbox is clicked. |
| function checkboxClicked(id) { |
| var chkbox = document.getElementById(id); |
| var toChange = id.substring("chkbox_".length).split("_"); |
| if (toChange[0] == "category") { |
| allCategories[toChange[1]] = chkbox.checked; |
| } else if (toChange[0] == "subcategory") { |
| allSubcategories[toChange[1]] = chkbox.checked; |
| } |
| window.history.replaceState("", "Checked box", buildURL()); |
| |
| // Rebuild the console table, if applicable, or fall back on attempting to |
| // hide the correct categories and subcategories. |
| if (typeof buildConsoleTable == "function") { |
| buildConsoleTable(); |
| } else { |
| refreshCategories(); |
| } |
| } |
| |
| // Callback function to adjust the reload time. |
| function setReload(textBox) { |
| var regex = /^\d+$/; |
| if (regex.test(textBox.value)) { |
| refreshInterval = textBox.value * 1000; |
| urlVars["reload"] = textBox.value; |
| window.history.replaceState("", "Changed refresh", buildURL()); |
| clearTimeout(refreshTimer); |
| refreshTimer = setTimeout(reloadPage, refreshInterval); |
| } |
| } |
| </script> |
| {% endblock %} |
| </head> |
| <body class="interface"> |
| {% block header -%} |
| <div id="skia_header" style="top:5px;"> |
| <a href="{{ tree_status_baseurl }}" target="_blank" style="text-decoration:inherit;"> |
| <div id="tree_status_div" width="100%" height="50" class="status-message"> |
| <span id="tree_status_message"></span> |
| <div id="sheriff_div" class="sheriff-message"></div> |
| <div id="arb_status_div" class="arb-status"></div> |
| </div> |
| </a> |
| <div id="container" style="float: left; width: 100%;"> |
| <div style="float:left; width:25%;"> |
| <form name="unused" action="javascript:void(0);"> |
| <input type="radio" name="internal_external" value="external" id="radio_external" onClick="setHostAndPort(null, '{{ external_port }}');">External View<br> |
| <input type="radio" name="internal_external" value="internal" id="radio_internal" onClick="setHostAndPort(null, '{{ internal_port }}');">Internal View |
| <br/><nobr>Refresh (seconds): <input type="text" name="reload_time" value="{{ refresh or default_refresh }}" onChange="setReload(this)" style="width: 50px;" maxlength="4" /></nobr> |
| <div> |
| {% if master_launch_datetime %} |
| <br/> |
| master launched at {{ master_launch_datetime.strftime('%Y-%m-%d %H:%M:%S UTC') }} |
| |
| <br/> |
| <span title="master_running_revision: git hash of code at which the buildbot master was launched"> |
| <u>master_running_revision</u> |
| </span> is |
| <a href="https://skia.googlesource.com/buildbot.git/+/{{ master_running_revision }}"> |
| {{ master_running_revision|truncate(8, True, "") }} |
| </a> |
| |
| <br/> |
| <span title="master_revision: git hash of code currently checked out on master"> |
| <u>master_revision</u> |
| </span> is |
| <a href="https://skia.googlesource.com/buildbot.git/+/{{ master_revision }}"> |
| {{ master_revision|truncate(8, True, "") }} |
| </a> |
| {% endif %} |
| </div> |
| </form> |
| </div> |
| |
| <div id="links" style="float:right; width:25%;"> |
| <div style="float:right; width: 195px;"><ul style="margin: 0px 0px 0px 25px; padding:0;"><li><a href="https://sites.google.com/site/skiadocs/developer-documentation/the-skia-buildbots/1-overview" target="_blank">Full Skia documentation</a><br/></li></ul></div> |
| <div style="float:right; width: 195px;"><ul style="margin: 0px 0px 0px 25px; padding:0;"><li><a href="{{ tree_status_baseurl }}" target="_blank">Skia Tree Status Manager</a><br/></li></ul></div> |
| <div style="float:right; width: 195px;"><ul style="margin: 0px 0px 0px 25px; padding:0;"><li><a href="https://code.google.com/p/skia/issues/list?can=2&q=label%3ABreakingTheBuildbots" target="_blank">Current build-breaking bugs</a><br/></li></ul></div> |
| <div style="float:right; width: 195px;"><ul style="margin: 0px 0px 0px 25px; padding:0;"><li><a href="http://go/skpdash" target="_blank">Bench Dashboard Internal</a><br/></li></ul></div> |
| <div style="float:right; width: 195px;"><ul style="margin: 0px 0px 0px 25px; padding:0;"><li><a href="bug_graphs.html" target="_blank">Open Bugs Graph</a><br/></li></ul></div> |
| <div style="float:right; width: 195px;"><ul style="margin: 0px 0px 0px 25px; padding:0;"><li><a href="https://storage.cloud.google.com/chromium-skia-gm/static_analyzers/clang_static_analyzer/index.html" target="_blank">Clang Static Analyzer</a><br/></li></ul></div> |
| <div style="float:right; width: 195px;"><ul style="margin: 0px 0px 0px 25px; padding:0;"><li><a href="buildbots_self_analysis.html" target="_blank">Buildbot Self-Dashboard</a><br/></li></ul></div> |
| <div style="float:right; width: 195px;"><ul style="margin: 0px 0px 0px 25px; padding:0;"><li><a href="buildslave_idle.html" target="_blank">Buildslave Idle Time Analysis</a><br/></li></ul></div> |
| <div style="float:right; width: 195px;"><ul style="margin: 0px 0px 0px 25px; padding:0;"><li><a href="https://skia-tree-status.appspot.com/sheriff" target="_blank">Sheriff Schedule</a><br/></li></ul></div> |
| <div style="float:right; width: 195px;"><ul style="margin: 0px 0px 0px 25px; padding:0;"><li><a href="https://skia-tree-status.appspot.com/skia-telemetry/lua_script" target="_blank">Run Lua Scripts on SKP Repo</a><br/></li></ul></div> |
| <div style="float:right; width: 195px;"><ul style="margin: 0px 0px 0px 25px; padding:0;"><li><a href="https://skia-tree-status.appspot.com/skia-telemetry/skia_try" target="_blank">Run Patches on SKP Repo</a><br/></li></ul></div> |
| <div style="float:right; width: 195px;"><ul style="margin: 0px 0px 0px 25px; padding:0;"><li><a href="http://skia-tree-status.appspot.com/redirect/rebaseline-server/static/view.html#/view.html?resultsToLoad=/results/failures" target="_blank">Recent GM Failures</a><br/></li></ul></div> |
| <div style="float:right; width: 195px;"><ul style="margin: 0px 0px 0px 25px; padding:0;"><li><a href="http://chromium-skia-gm.commondatastorage.googleapis.com/depsroll.html" target="_blank">Current DEPS roll attempt</a><br/></li></ul></div> |
| </div> |
| |
| <div style="text-align:center; width: 50%; margin-left: 25%; margin-right: 25%"> |
| <div id="heading" style="font-size:3.5em; text-align:center;">Skia Buildbots ({{ active_master_name }})</div> |
| <div> |
| <p> |
| Skia Build Masters: |
| <table> |
| <tr id="results_summary_client_skia"> |
| <td style="text-align: right"><a href="http://build.chromium.org/p/client.skia/console">client.skia</a></td> |
| <td colspan="1000"><iframe width="100%" height="20" frameborder="0" scrolling="no" src="http://build.chromium.org/p/client.skia/horizontal_one_box_per_builder"></iframe></td> |
| </tr> |
| {% for master in masters %} |
| {% if not (not is_internal_view and master['name'] == 'PrivateSkia') %} |
| <tr id="results_summary_{{ master['name'] }}"> |
| <td style="text-align: right"><a href="http://{{ master['host'] }}:{{ master['internal_port'] if is_internal_view else master['external_port'] }}/console">{{ master['name'] }}</a></td> |
| </tr> |
| {% endif %} |
| {% endfor %} |
| </table> |
| </div> |
| </p> |
| </div> |
| </div> |
| |
| <div class="header"> |
| <a href="{{ path_to_root or '.' }}">Home</a> - |
| <a href="{{ path_to_root }}waterfall">Waterfall</a> |
| <a href="{{ path_to_root }}console">Console</a> |
| <a href="{{ path_to_root }}builders">Builders</a> |
| <a href="{{ path_to_root }}buildslaves">Buildslaves</a> - |
| <a href="{{ path_to_root }}failures">Currently Failing</a> - |
| <a href="{{ path_to_root }}trybots">Trybot Waterfall</a> - |
| <a href="{{ path_to_root }}json/help">JSON API</a> - |
| <a href="{{ path_to_root }}about">About</a> |
| </div> |
| </div> |
| {% endblock %} |
| |
| {%- block barecontent -%} |
| |
| <div class="content"> |
| {%- block content -%} |
| {%- endblock -%} |
| </div> |
| {%- endblock -%} |
| |
| {%- block footer -%} |
| <div class="footer" style="clear:both"> |
| <hr/> |
| <a href="http://buildbot.net/">BuildBot</a> ({{version}}) |
| {% if title -%} |
| working for the |
| {%- if title_url -%} |
| <a href="{{ title_url }}">{{ title }}</a> |
| {%- else -%} |
| {{ title }} |
| {%- endif -%} |
| project. |
| {%- endif -%} |
| <br/> |
| Page built: <b>{{ time }}</b> ({{ tz }}) |
| </div> |
| {% endblock -%} |
| <div id="builderTooltip" class="BuilderTooltip RoundedRect" style="display: none;" onmouseout="hideBuilderTooltip(event)"></div> |
| <script language="JavaScript"> |
| init(); |
| </script> |
| </body> |
| </html> |