Zuul status page: Redesign and fix bugs
status.html: - Added eventqueue-length status (was already present in production but not committed here yet). - HTML5 markup. - Remove unused jquery-visibility.min.js and jquery-graphite.js. status.js: - Clean up (various js best practices and consistent coding style) - Use empty() instead of html(''). - Use text() for text instead of html(). html() will trigger the parser where text will simply create a text node with the string literal, much faster, safer and semantically correct. - Fix implied global variable leak 'result'. - Fix reference error that crashes/freezes the page Property data.trigger_event_queue and data.trigger_event_queue can be undefined, in which case data.trigger_event_queue.length causes an uncaught TypeError to be thrown. - Use a closure instead of polluting global scope. - Rewrite object oriented. - Added 'demo' feature for easy local testing. Downstream commits at https://gerrit.wikimedia.org/r/#/q/project:integration/docroot+topic:zuul-js+branch:master+owner:Krinkle+is:merged,n,z Change-Id: Iddd4e2787f2e2eb27bf428f733fbb8b4a9d162d5 Reviewed-on: https://review.openstack.org/26416 Reviewed-by: James E. Blair <corvus@inaugust.com> Reviewed-by: Clark Boylan <clark.boylan@gmail.com> Reviewed-by: Jeremy Stanley <fungi@yuggoth.org> Approved: James E. Blair <corvus@inaugust.com> Tested-by: Jenkins
This commit is contained in:
parent
80edd5a8fa
commit
51516cd2f3
|
@ -1,87 +0,0 @@
|
|||
<!--
|
||||
Copyright 2013 OpenStack Foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
not use this file except in compliance with the License. You may obtain
|
||||
a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
License for the specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:py="http://genshi.edgewall.org/"
|
||||
lang="en">
|
||||
<head>
|
||||
<style type="text/css">
|
||||
#pipeline-container {
|
||||
margin: 0 auto;
|
||||
}
|
||||
.change {
|
||||
border: 1px solid;
|
||||
margin-top: 10px;
|
||||
padding: 2px;
|
||||
}
|
||||
.change > .header {
|
||||
background: #cccccc;
|
||||
color: black;
|
||||
margin: -2px -2px 2px -2px;
|
||||
padding: 4px;
|
||||
}
|
||||
.change > .header > .changeid {
|
||||
float: right;
|
||||
}
|
||||
.job {
|
||||
display: block;
|
||||
}
|
||||
.pipeline {
|
||||
float: left;
|
||||
width: 25em;
|
||||
padding: 4px;
|
||||
}
|
||||
.pipeline > .header {
|
||||
background: #0000cc;
|
||||
color: white;
|
||||
}
|
||||
.arrow {
|
||||
text-align: center;
|
||||
font-size: 16pt;
|
||||
line-height: 1.0;
|
||||
}
|
||||
.result_success {
|
||||
color: #007f00;
|
||||
}
|
||||
.result_failure {
|
||||
color: #cf2f19;
|
||||
}
|
||||
.result_unstable {
|
||||
color: #e39f00;
|
||||
}
|
||||
</style>
|
||||
|
||||
<title>Zuul Status</title>
|
||||
|
||||
<script type="text/javascript" src="jquery.min.js"></script>
|
||||
<script type="text/javascript" src="jquery-visibility.min.js"></script>
|
||||
<script type="text/javascript" src="jquery-graphite.js"></script>
|
||||
<script type="text/javascript" src="status.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1> Zuul Status </h1>
|
||||
|
||||
<div id="message-container">
|
||||
<p id="message"/>
|
||||
</div>
|
||||
|
||||
<div id="pipeline-container">
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
152
etc/status.js
152
etc/status.js
|
@ -1,152 +0,0 @@
|
|||
// Copyright 2012 OpenStack Foundation
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
window.zuul_enable_status_updates = true;
|
||||
|
||||
function format_pipeline(data) {
|
||||
var html = '<div class="pipeline"><h3 class="subhead">'+
|
||||
data['name']+'</h3>';
|
||||
if (data['description'] != null) {
|
||||
html += '<p>'+data['description']+'</p>';
|
||||
}
|
||||
|
||||
$.each(data['change_queues'], function(change_queue_i, change_queue) {
|
||||
$.each(change_queue['heads'], function(head_i, head) {
|
||||
if (data['change_queues'].length > 1 && head_i == 0) {
|
||||
html += '<div> Change queue: ';
|
||||
|
||||
var name = change_queue['name'];
|
||||
html += '<a title="' + name + '">';
|
||||
if (name.length > 32) {
|
||||
name = name.substr(0,32) + '...';
|
||||
}
|
||||
html += name + '</a></div>'
|
||||
}
|
||||
$.each(head, function(change_i, change) {
|
||||
if (change_i > 0) {
|
||||
html += '<div class="arrow">↑</div>'
|
||||
}
|
||||
html += format_change(change);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
html += '</div>';
|
||||
return html;
|
||||
}
|
||||
|
||||
function format_change(change) {
|
||||
var html = '<div class="change"><div class="header">';
|
||||
|
||||
html += '<span class="project">'+change['project']+'</span>';
|
||||
var id = change['id'];
|
||||
var url = change['url'];
|
||||
if (id.length == 40) {
|
||||
id = id.substr(0,7);
|
||||
}
|
||||
html += '<span class="changeid">';
|
||||
if (url != null) {
|
||||
html += '<a href="'+url+'">';
|
||||
}
|
||||
html += id;
|
||||
if (url != null) {
|
||||
html += '</a>';
|
||||
}
|
||||
html += '</span></div><div class="jobs">';
|
||||
|
||||
$.each(change['jobs'], function(i, job) {
|
||||
result = job['result'];
|
||||
var result_class = "result";
|
||||
if (result == null) {
|
||||
if (job['url'] != null) {
|
||||
result = 'in progress';
|
||||
} else {
|
||||
result = 'queued';
|
||||
}
|
||||
} else if (result == 'SUCCESS') {
|
||||
result_class += " result_success";
|
||||
} else if (result == 'FAILURE') {
|
||||
result_class += " result_failure";
|
||||
} else if (result == 'LOST') {
|
||||
result_class += " result_unstable";
|
||||
} else if (result == 'UNSTABLE') {
|
||||
result_class += " result_unstable";
|
||||
}
|
||||
html += '<span class="job">';
|
||||
if (job['url'] != null) {
|
||||
html += '<a href="'+job['url']+'">';
|
||||
}
|
||||
html += job['name'];
|
||||
if (job['url'] != null) {
|
||||
html += '</a>';
|
||||
}
|
||||
html += ': <span class="'+result_class+'">'+result+'</span>';
|
||||
if (job['voting'] == false) {
|
||||
html += ' (non-voting)';
|
||||
}
|
||||
html += '</span>';
|
||||
});
|
||||
|
||||
html += '</div></div>';
|
||||
return html;
|
||||
}
|
||||
|
||||
function update_timeout() {
|
||||
if (!window.zuul_enable_status_updates) {
|
||||
setTimeout(update_timeout, 5000);
|
||||
return;
|
||||
}
|
||||
|
||||
update();
|
||||
|
||||
setTimeout(update_timeout, 5000);
|
||||
}
|
||||
|
||||
function update() {
|
||||
var html = '';
|
||||
|
||||
$.getJSON('/status.json', function(data) {
|
||||
if ('message' in data) {
|
||||
$("#message-container").attr('class', 'topMessage');
|
||||
$("#message").html(data['message']);
|
||||
} else {
|
||||
$("#message-container").removeClass('topMessage');
|
||||
$("#message").html('');
|
||||
}
|
||||
|
||||
html += '<br style="clear:both"/>';
|
||||
|
||||
$.each(data['pipelines'], function(i, pipeline) {
|
||||
html = html + format_pipeline(pipeline);
|
||||
});
|
||||
|
||||
html += '<br style="clear:both"/>';
|
||||
$("#pipeline-container").html(html);
|
||||
});
|
||||
}
|
||||
|
||||
$(function() {
|
||||
update_timeout();
|
||||
|
||||
$(document).on({
|
||||
'show.visibility': function() {
|
||||
window.zuul_enable_status_updates = true;
|
||||
update();
|
||||
},
|
||||
'hide.visibility': function() {
|
||||
window.zuul_enable_status_updates = false;
|
||||
}
|
||||
});
|
||||
|
||||
});
|
|
@ -0,0 +1,3 @@
|
|||
public_html/jquery.min.js
|
||||
public_html/jquery-visibility.min.js
|
||||
public_html/bootstrap
|
|
@ -0,0 +1,27 @@
|
|||
Zuul Status
|
||||
====
|
||||
|
||||
Zuul Status is a web portal for a Zuul server.
|
||||
|
||||
Set up
|
||||
------------
|
||||
|
||||
The markup generated by the javascript is fairly generic so it should be easy
|
||||
to drop into an existing portal. All it needs is
|
||||
``<div id="id="zuul-container"></div>``.
|
||||
|
||||
Having said that, the markup is optimised for Twitter Bootstrap, though it in
|
||||
no way depends on Boostrap and any element using a bootstrap class has a
|
||||
``zuul-`` prefixed class alongside it.
|
||||
|
||||
The script depends on jQuery (tested with version 1.8 and 1.9).
|
||||
|
||||
The script optimises updates by stopping when the page is not visible.
|
||||
This is done by listerning to ``show`` and ``hide`` events emitted by the
|
||||
Page Visibility plugin for jQuery. If you don't want to load this plugin you
|
||||
can undo undo this optimisation by removing the 9 lines using this on the
|
||||
bottom of ``app.js``
|
||||
|
||||
To automatically fetch the latest versions of jQuery, the Page Visibility
|
||||
plugin and Twitter Boostrap, run the ``fetch-dependencies.sh`` script.
|
||||
The default ``index.html`` references these.
|
|
@ -0,0 +1,9 @@
|
|||
#!/bin/bash
|
||||
BASE_DIR=$(cd $(dirname $0); pwd)
|
||||
echo "Destination: $BASE_DIR/public_html"
|
||||
echo "Fetching jquery.min.js..."
|
||||
curl --silent http://code.jquery.com/jquery.min.js > $BASE_DIR/public_html/jquery.min.js
|
||||
echo "Fetching jquery-visibility.min.js..."
|
||||
curl --silent https://raw.github.com/mathiasbynens/jquery-visibility/master/jquery-visibility.min.js > $BASE_DIR/public_html/jquery-visibility.min.js
|
||||
echo "Fetching bootstrap..."
|
||||
curl --silent http://twitter.github.io/bootstrap/assets/bootstrap.zip > bootstrap.zip && unzip -q -o bootstrap.zip -d $BASE_DIR/public_html/ && rm bootstrap.zip
|
|
@ -0,0 +1,241 @@
|
|||
// Client script for Zuul status page
|
||||
//
|
||||
// Copyright 2012 OpenStack Foundation
|
||||
// Copyright 2013 Timo Tijhof
|
||||
// Copyright 2013 Wikimedia Foundation
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
(function ($) {
|
||||
var $container, $msg, $msgWrap, $indicator, $queueInfo, $queueEventsNum, $queueResultsNum, $pipelines,
|
||||
prevHtml, xhr, zuul, $jq,
|
||||
demo = location.search.match(/[?&]demo=([^?&]*)/),
|
||||
source = demo ?
|
||||
'./status-' + (demo[1] || 'basic') + '.json-sample' :
|
||||
'/zuul/status.json';
|
||||
|
||||
zuul = {
|
||||
enabled: true,
|
||||
|
||||
schedule: function () {
|
||||
if (!zuul.enabled) {
|
||||
setTimeout(zuul.schedule, 5000);
|
||||
return;
|
||||
}
|
||||
zuul.update().complete(function () {
|
||||
setTimeout(zuul.schedule, 5000);
|
||||
});
|
||||
},
|
||||
|
||||
/** @return {jQuery.Promise} */
|
||||
update: function () {
|
||||
// Cancel the previous update if it hasn't completed yet.
|
||||
if (xhr) {
|
||||
xhr.abort();
|
||||
}
|
||||
|
||||
zuul.emit('update-start');
|
||||
|
||||
xhr = $.ajax({
|
||||
url: source,
|
||||
dataType: 'json',
|
||||
cache: false
|
||||
})
|
||||
.done(function (data) {
|
||||
var html = '';
|
||||
data = data || {};
|
||||
|
||||
if ('message' in data) {
|
||||
$msg.html(data.message);
|
||||
$msgWrap.removeClass('zuul-msg-wrap-off');
|
||||
} else {
|
||||
$msg.empty();
|
||||
$msgWrap.addClass('zuul-msg-wrap-off');
|
||||
}
|
||||
|
||||
$.each(data.pipelines, function (i, pipeline) {
|
||||
html += zuul.format.pipeline(pipeline);
|
||||
});
|
||||
|
||||
// Only re-parse the DOM if we have to
|
||||
if (html !== prevHtml) {
|
||||
prevHtml = html;
|
||||
$pipelines.html(html);
|
||||
}
|
||||
|
||||
$queueEventsNum.text(
|
||||
data.trigger_event_queue ? data.trigger_event_queue.length : '0'
|
||||
);
|
||||
$queueResultsNum.text(
|
||||
data.result_event_queue ? data.result_event_queue.length : '0'
|
||||
);
|
||||
})
|
||||
.fail(function (err, jqXHR, errMsg) {
|
||||
$msg.text(source + ': ' + errMsg).show();
|
||||
$msgWrap.removeClass('zuul-msg-wrap-off');
|
||||
})
|
||||
.complete(function () {
|
||||
xhr = undefined;
|
||||
zuul.emit('update-end');
|
||||
});
|
||||
|
||||
return xhr;
|
||||
},
|
||||
|
||||
format: {
|
||||
change: function (change) {
|
||||
var html = '<div class="well well-small zuul-change"><ul class="nav nav-list">',
|
||||
id = change.id,
|
||||
url = change.url;
|
||||
|
||||
html += '<li class="nav-header">' + change.project;
|
||||
if (id.length === 40) {
|
||||
id = id.substr(0, 7);
|
||||
}
|
||||
html += ' <span class="zuul-change-id">';
|
||||
if (url !== null) {
|
||||
html += '<a href="' + url + '">';
|
||||
}
|
||||
html += id;
|
||||
if (url !== null) {
|
||||
html += '</a>';
|
||||
}
|
||||
html += '</span></li>';
|
||||
|
||||
$.each(change.jobs, function (i, job) {
|
||||
var result = job.result ? job.result.toLowerCase() : null,
|
||||
resultClass = 'zuul-result label';
|
||||
if (result === null) {
|
||||
result = job.url ? 'in progress' : 'queued';
|
||||
}
|
||||
switch (result) {
|
||||
case 'success':
|
||||
resultClass += ' label-success';
|
||||
break;
|
||||
case 'failure':
|
||||
resultClass += ' label-important';
|
||||
break;
|
||||
case 'lost':
|
||||
case 'unstable':
|
||||
resultClass += ' label-warning';
|
||||
break;
|
||||
}
|
||||
html += '<li class="zuul-change-job">';
|
||||
html += job.url !== null ?
|
||||
'<a href="' + job.url + '" class="zuul-change-job-link">' :
|
||||
'<span class="zuul-change-job-link">';
|
||||
html += job.name;
|
||||
html += ' <span class="' + resultClass + '">' + result + '</span>';
|
||||
if (job.voting === false) {
|
||||
html += ' <span class="muted">(non-voting)</span>';
|
||||
}
|
||||
html += job.url !== null ? '</a>' : '</span>';
|
||||
html += '</li>';
|
||||
});
|
||||
|
||||
html += '</ul></div>';
|
||||
return html;
|
||||
},
|
||||
|
||||
pipeline: function (pipeline) {
|
||||
var html = '<div class="zuul-pipeline span4"><h3>' +
|
||||
pipeline.name + '</h3>';
|
||||
if (typeof pipeline.description === 'string') {
|
||||
html += '<p><small>' + pipeline.description + '</small></p>';
|
||||
}
|
||||
|
||||
$.each(pipeline.change_queues, function (queueNum, changeQueue) {
|
||||
$.each(changeQueue.heads, function (headNum, changes) {
|
||||
if (pipeline.change_queues.length > 1 && headNum === 0) {
|
||||
var name = changeQueue.name;
|
||||
html += '<p>Queue: <abbr title="' + name + '">';
|
||||
if (name.length > 32) {
|
||||
name = name.substr(0, 32) + '...';
|
||||
}
|
||||
html += name + '</abbr></p>';
|
||||
}
|
||||
$.each(changes, function (changeNum, change) {
|
||||
// If there are multiple changes in the same head it means they're connected
|
||||
if (changeNum > 0) {
|
||||
html += '<div class="zuul-change-arrow">↑</div>';
|
||||
}
|
||||
html += zuul.format.change(change);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
html += '</div>';
|
||||
return html;
|
||||
}
|
||||
},
|
||||
|
||||
emit: function () {
|
||||
$jq.trigger.apply($jq, arguments);
|
||||
return this;
|
||||
},
|
||||
on: function () {
|
||||
$jq.on.apply($jq, arguments);
|
||||
return this;
|
||||
},
|
||||
one: function () {
|
||||
$jq.one.apply($jq, arguments);
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
$jq = $(zuul);
|
||||
|
||||
$jq.on('update-start', function () {
|
||||
$container.addClass('zuul-container-loading');
|
||||
$indicator.addClass('zuul-spinner-on');
|
||||
});
|
||||
|
||||
$jq.on('update-end', function () {
|
||||
$container.removeClass('zuul-container-loading');
|
||||
setTimeout(function () {
|
||||
$indicator.removeClass('zuul-spinner-on');
|
||||
}, 550);
|
||||
});
|
||||
|
||||
$jq.one('update-end', function () {
|
||||
// Do this asynchronous so that if the first update adds a message, it will not animate
|
||||
// while we fade in the content. Instead it simply appears with the rest of the content.
|
||||
setTimeout(function () {
|
||||
$container.addClass('zuul-container-ready'); // Fades in the content
|
||||
});
|
||||
});
|
||||
|
||||
$(function ($) {
|
||||
$msg = $('<div class="zuul-msg alert alert-error"></div>');
|
||||
$msgWrap = $msg.wrap('<div class="zuul-msg-wrap zuul-msg-wrap-off"></div>').parent();
|
||||
$indicator = $('<span class="btn pull-right zuul-spinner">updating <i class="icon-refresh"></i></span>');
|
||||
$queueInfo = $('<p>Queue lengths: <span>0</span> events, <span>0</span> results.</p>');
|
||||
$queueEventsNum = $queueInfo.find('span').eq(0);
|
||||
$queueResultsNum = $queueEventsNum.next();
|
||||
$pipelines = $('<div class="row"></div>');
|
||||
|
||||
$container = $('#zuul-container').append($msgWrap, $indicator, $queueInfo, $pipelines);
|
||||
|
||||
zuul.schedule();
|
||||
|
||||
$(document).on({
|
||||
'show.visibility': function () {
|
||||
zuul.enabled = true;
|
||||
zuul.update();
|
||||
},
|
||||
'hide.visibility': function () {
|
||||
zuul.enabled = false;
|
||||
}
|
||||
});
|
||||
});
|
||||
}(jQuery));
|
|
@ -0,0 +1,141 @@
|
|||
<!--
|
||||
Copyright 2013 OpenStack Foundation
|
||||
Copyright 2013 Timo Tijhof
|
||||
Copyright 2013 Wikimedia Foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
not use this file except in compliance with the License. You may obtain
|
||||
a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
License for the specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
<!DOCTYPE html>
|
||||
<html dir="ltr" lang="en">
|
||||
<head>
|
||||
<title>Zuul Status</title>
|
||||
<link rel="stylesheet" href="bootstrap/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="bootstrap/css/bootstrap-responsive.min.css">
|
||||
<style>
|
||||
.zuul-container {
|
||||
transition-property: opacity, background-color;
|
||||
transition-duration: 1s;
|
||||
transition-timing-function: ease-in-out;
|
||||
clear: both;
|
||||
opacity: 0;
|
||||
cursor: progress;
|
||||
min-height: 400px;
|
||||
background-color: #f8ffaa;
|
||||
}
|
||||
|
||||
.zuul-container-ready {
|
||||
opacity: 1;
|
||||
cursor: auto;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.zuul-spinner,
|
||||
.zuul-spinner:hover {
|
||||
opacity: 0;
|
||||
transition: opacity 3s ease-out;
|
||||
cursor: default;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.zuul-spinner-on,
|
||||
.zuul-spinner-on:hover {
|
||||
opacity: 1;
|
||||
transition-duration: 0.4s;
|
||||
cursor: progress;
|
||||
}
|
||||
|
||||
.zuul-change-arrow {
|
||||
text-align: center;
|
||||
font-size: 16pt;
|
||||
line-height: 1.0;
|
||||
}
|
||||
|
||||
.zuul-change-id {
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
.zuul-change-job a {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.zuul-result {
|
||||
text-shadow: none;
|
||||
font-weight: normal;
|
||||
background-color: #E9E9E9;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.zuul-result.label-success {
|
||||
background-color: #CDF0CD;
|
||||
color: #468847;
|
||||
}
|
||||
|
||||
.zuul-result.label-important {
|
||||
background-color: #F1DBDA;
|
||||
color: #B94A48;
|
||||
}
|
||||
|
||||
.zuul-result.label-warning {
|
||||
background-color: #F3E6D4;
|
||||
color: #F89406;
|
||||
}
|
||||
|
||||
.zuul-msg-wrap {
|
||||
max-height: 150px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.zuul-container-ready .zuul-msg-wrap {
|
||||
transition: max-height 1s ease-in;
|
||||
}
|
||||
|
||||
.zuul-msg-wrap-off {
|
||||
max-height: 0;
|
||||
}
|
||||
|
||||
.zuul-msg p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Styles for Bootstrap only
|
||||
* (remove when not using Bootstrap)
|
||||
*/
|
||||
|
||||
.zuul-change-id {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.zuul-change-job-link {
|
||||
overflow: auto;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.zuul-result {
|
||||
float: right;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>Zuul Status</h1>
|
||||
<p>Real-time status monitor of Zuul, the pipeline manager between Gerrit and Jenkins.</p>
|
||||
|
||||
<div class="zuul-container" id="zuul-container"></div>
|
||||
</div>
|
||||
<script src="jquery.min.js"></script>
|
||||
<script src="jquery-visibility.min.js"></script>
|
||||
<script src="app.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,176 @@
|
|||
{
|
||||
"message": "Example error message",
|
||||
"pipelines": [
|
||||
{
|
||||
"name": "test",
|
||||
"description": "Lint and unit tests",
|
||||
"change_queues": [
|
||||
{
|
||||
"name": "some-jobs@worker301.ci-example.org",
|
||||
"heads": [
|
||||
[
|
||||
{
|
||||
"id": "10101,1",
|
||||
"url": "#!/review.example.org/r/10101",
|
||||
"project": "openstack/infra/zuul",
|
||||
"jobs": [
|
||||
{
|
||||
"name": "zuul-merge",
|
||||
"url": "#!/jenkins.example.org/job/zuul-merge/201",
|
||||
"result": "SUCCESS",
|
||||
"voting": true
|
||||
},
|
||||
{
|
||||
"name": "zuul-lint",
|
||||
"url": "#!/jenkins.example.org/job/zuul-lint/201",
|
||||
"result": "SUCCESS",
|
||||
"voting": true
|
||||
},
|
||||
{
|
||||
"name": "zuul-test",
|
||||
"url": "#!/jenkins.example.org/job/zuul-test/201",
|
||||
"result": "SUCCESS",
|
||||
"voting": true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"id": "10103,1",
|
||||
"url": "#!/review.example.org/r/10103",
|
||||
"project": "google/gerrit",
|
||||
"jobs": [
|
||||
{
|
||||
"name": "gerrit-merge",
|
||||
"url": "#!/jenkins.example.org/job/gerrit-merge/203",
|
||||
"result": "SUCCESS",
|
||||
"voting": false
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "other-jobs@worker301.ci-example.org",
|
||||
"heads": [
|
||||
[
|
||||
{
|
||||
"id": "10102,1",
|
||||
"url": "#!/review.example.org/r/10102",
|
||||
"project": "google/gerrit",
|
||||
"jobs": [
|
||||
{
|
||||
"name": "gerrit-merge",
|
||||
"url": "#!/jenkins.example.org/job/gerrit-merge/202",
|
||||
"result": "UNSTABLE",
|
||||
"voting": false
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"id": "10104,1",
|
||||
"url": "#!/review.example.org/r/10104",
|
||||
"project": "openstack/infra/zuul",
|
||||
"jobs": [
|
||||
{
|
||||
"name": "zuul-merge",
|
||||
"url": "#!/jenkins.example.org/job/zuul-merge/204",
|
||||
"result": "SUCCESS",
|
||||
"voting": true
|
||||
},
|
||||
{
|
||||
"name": "zuul-lint",
|
||||
"url": "#!/jenkins.example.org/job/zuul-lint/204",
|
||||
"result": "FAILURE",
|
||||
"voting": true
|
||||
},
|
||||
{
|
||||
"name": "zuul-test",
|
||||
"url": "#!/jenkins.example.org/job/zuul-test/204",
|
||||
"result": null,
|
||||
"voting": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "gate-and-submit",
|
||||
"change_queues": []
|
||||
},
|
||||
{
|
||||
"name": "postmerge",
|
||||
"change_queues": [
|
||||
{
|
||||
"name": "some-jobs@worker301.ci-example.org",
|
||||
"heads": [
|
||||
[
|
||||
{
|
||||
"id": "7f1d65cb0f663c907698f915da01c008c7ef4748",
|
||||
"url": "#!/review.example.org/r/10100",
|
||||
"project": "openstack/infra/zuul",
|
||||
"jobs": [
|
||||
{
|
||||
"name": "zuul-lint",
|
||||
"url": "#!/jenkins.example.org/job/zuul-lint/200",
|
||||
"result": "SUCCESS",
|
||||
"voting": true
|
||||
},
|
||||
{
|
||||
"name": "zuul-test",
|
||||
"url": "#!/jenkins.example.org/job/zuul-test/200",
|
||||
"result": "FAILURE",
|
||||
"voting": true
|
||||
},
|
||||
{
|
||||
"name": "zuul-regression-python2",
|
||||
"url": "#!/jenkins.example.org/job/zuul-regression-python2/200",
|
||||
"result": "SUCCESS",
|
||||
"voting": true
|
||||
},
|
||||
{
|
||||
"name": "zuul-regression-python3",
|
||||
"url": "#!/jenkins.example.org/job/zuul-regression-python3/200",
|
||||
"result": "FAILURE",
|
||||
"voting": true
|
||||
},
|
||||
{
|
||||
"name": "zuul-performance-python2",
|
||||
"url": null,
|
||||
"result": null,
|
||||
"voting": true
|
||||
},
|
||||
{
|
||||
"name": "zuul-performance-python3",
|
||||
"url": null,
|
||||
"result": null,
|
||||
"voting": true
|
||||
},
|
||||
{
|
||||
"name": "zuul-docs-publish",
|
||||
"url": null,
|
||||
"result": null,
|
||||
"voting": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"trigger_event_queue": {
|
||||
"length": 0
|
||||
},
|
||||
"result_event_queue": {
|
||||
"length": 0
|
||||
}
|
||||
}
|
|
@ -0,0 +1,310 @@
|
|||
{
|
||||
"pipelines": [
|
||||
{
|
||||
"name": "check",
|
||||
"description": "Newly uploaded patchsets enter this pipeline to receive an initial +/-1 Verified vote from Jenkins.",
|
||||
"change_queues": [
|
||||
{
|
||||
"heads": [],
|
||||
"name": "stackforge/tripleo-image-elements"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Changes that have been approved by core developers are enqueued in order in this pipeline, and .",
|
||||
"change_queues": [
|
||||
{
|
||||
"heads": [],
|
||||
"name": "openstack-detackforge/reddwarf-integration"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "stackforge/moniker"
|
||||
},
|
||||
{
|
||||
"heads": [
|
||||
[
|
||||
{
|
||||
"url": "https://review.openstack.org/26292",
|
||||
"project": "openstack/quantum",
|
||||
"jobs": [
|
||||
{
|
||||
"url": "https://jenkins.openstack.org/job/gate-quantum-docs/5501/consoleFull",
|
||||
"voting": true,
|
||||
"result": "SUCCESS",
|
||||
"name": "gate-quantum-docs"
|
||||
},
|
||||
{
|
||||
"url": "https://jenkins.openstack.org/job/gate-quantum-pep8/6254/consoleFull",
|
||||
"voting": true,
|
||||
"result": "SUCCESS",
|
||||
"name": "gate-quantum-pep8"
|
||||
},
|
||||
{
|
||||
"url": "https://jenkins.openstack.org/job/gate-quantum-python26/5876/",
|
||||
"voting": true,
|
||||
"result": null,
|
||||
"name": "gate-quantum-python26"
|
||||
},
|
||||
{
|
||||
"url": "https://jenkins.openstack.org/job/gate-quantum-python27/5887/",
|
||||
"voting": true,
|
||||
"result": null,
|
||||
"name": "gate-quantum-python27"
|
||||
},
|
||||
{
|
||||
"url": "https://jenkins.openstack.org/job/gate-tempest-devstack-vm-quantum/17548/",
|
||||
"voting": true,
|
||||
"result": null,
|
||||
"name": "gate-tempest-devstack-vm-quantum"
|
||||
}
|
||||
],
|
||||
"id": "26292,1"
|
||||
}
|
||||
]
|
||||
],
|
||||
"name": "openstack-dev/devstack, openstack-infra/devstack-gate, openstack/cinder, openstack/glance, openstack/horizon, openstack/keystone, openstack/nova, openstack/python-cinderclient, openstack/python-glanceclient, openstack/python-keystoneclient, openstack/python-novaclient, openstack/python-quantumclient, openstack/quantum, openstack/swift, openstack/tempest, z/tempest"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "openstack/ceilometer"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "stackforge/puppet-openstack"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "stackforge/puppet-cinder"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "stackforge/marconi"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "openstack-infra/config"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "stackforge/tripleo-image-elements"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "stackforge/kwapi"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "stackforge/python-reddwarfclient"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "stackforge/python-savannaclient"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "stackforge/python-monikerclient"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "stackforge/packstack"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "openstack/oslo.config"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "openstack-infra/jenkins-job-builder"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "stackforge/puppet-horizon"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "openstack/heat-cfntools"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "openstack/oslo-incubator"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "stackforge/os-config-applier"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "openstack/requirements"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "stackforge/puppet-glance"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "openstack-infra/gearman-plugin"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "stackforge/puppet-keystone"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "stackforge/puppet-nova"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "stackforge/climate"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "openstack/python-swiftclient"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "openstack/python-ceilometerclient"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "openstack-infra/git-review"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "stackforge/bufunfa"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "stackforge/puppet-swift"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "openstack-infra/statusbot"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "openstack/openstack-planet"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "openstack/python-openstackclient"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "stackforge/diskimage-builder"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "openstack-infra/gerritlib"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "openstack-infra/zuul"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "stackforge/reddwarf"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "openstack-dev/hacking"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "openstack/python-heatclient"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "stackforge/python-libraclient"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "openstack-infra/reviewday"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "openstack-infra/jeepyb"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "openstack/heat"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "stackforge/libra"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "openstack-infra/gerrit"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "stackforge/healthnmon"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "openstack-infra/gerritbot"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "openstack-dev/pbr"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "stackforge/savanna"
|
||||
},
|
||||
{
|
||||
"heads": [],
|
||||
"name": "openstack/openstack-manuals"
|
||||
}
|
||||
],
|
||||
"name": "gate"
|
||||
},
|
||||
{
|
||||
"description": "This pipeline runs jobs that operate after each change is merged.",
|
||||
"change_queues": [
|
||||
{
|
||||
"heads": [],
|
||||
"name": "openstack-dev/hacking, openstack-dev/openstack-qa, openstack-dev/pbr, openstack-infra/config, openstack-infra/gearman-plugin, openstack-infra/gerrit, openstack-infra/gerritbot, openstack-infra/git-review, openstack-infra/jenkins-job-builder, openstack-infra/nose-html-output, openstack-infra/reviewday, openstack-infra/statusbot, openstack-infra/zuul, openstack/api-site, openstack/ceilometer, openstack/cinder, openstack/compute-api, openstack/glance, openstack/heat, openstack/heat-cfntools, openstack/horizon, openstack/identity-api, openstack/image-api, openstack/keystone, openstack/netconn-api, openstack/nova, openstack/object-api, openstack/openstack-manuals, openstack/oslo-incubator, openstack/oslo.config, openstack/python-ceilometerclient, openstack/python-cinderclient, openstack/python-glanceclient, openstack/python-heatclient, openstack/python-keystoneclient, openstack/python-novaclient, openstack/python-openstackclient, openstack/python-quantumclient, openstack/python-swiftclient, openstack/quantum, openstack/requirements, openstack/swift, openstack/volume-api, stackforge/bufunfa, stackforge/diskimage-builder, stackforge/moniker, stackforge/os-config-applier, stackforge/python-monikerclient, stackforge/python-savannaclient, stackforge/reddwarf, stackforge/savanna, stackforge/tripleo-image-elements"
|
||||
}
|
||||
],
|
||||
"name": "post"
|
||||
},
|
||||
{
|
||||
"description": "This pipeline runs jobs on projects in response to pre-release tags.",
|
||||
"change_queues": [
|
||||
{
|
||||
"heads": [],
|
||||
"name": "openstack-dev/hacking, openstack-dev/pbr, openstack-infra/gerritbot, openstack-infra/gerritlib, openstack-infra/git-review, openstack-infra/jeepyb, openstack-infra/jenkins-job-builder, openstack-infra/nose-html-output, openstack-infra/reviewday, openstack-infra/statusbot, openstack-infra/zuul, openstack/ceilometer, openstack/cinder, openstack/glance, openstack/heat, openstack/heat-cfntools, openstack/horizon, openstack/keystone, openstack/nova, openstack/oslo.config, openstack/python-ceilometerclient, openstack/python-cinderclient, openstack/python-glanceclient, openstack/python-heatclient, openstack/python-keystoneclient, openstack/python-novaclient, openstack/python-openstackclient, openstack/python-quantumclient, openstack/python-swiftclient, openstack/quantum, openstack/swift, stackforge/moniker, stackforge/python-monikerclient, stackforge/python-reddwarfclient, stackforge/python-savannaclient, stackforge/savanna"
|
||||
}
|
||||
],
|
||||
"name": "pre-release"
|
||||
},
|
||||
{
|
||||
"description": "When a commit is tagged as a release, this pipeline runs jobs that publish archives and documentation.",
|
||||
"change_queues": [
|
||||
{
|
||||
"heads": [],
|
||||
"name": "openstack-dev/hacking, openstack-dev/openstack-qa, openstack-dev/pbr, openstack-infra/gerritbot, openstack-infra/gerritlib, openstack-infra/git-review, openstack-infra/jeepyb, openstack-infra/jenkins-job-builder, openstack-infra/nose-html-output, openstack-infra/reviewday, openstack-infra/statusbot, openstack-infra/zuul, openstack/ceilometer, openstack/cinder, openstack/glance, openstack/heat, openstack/heat-cfntools, openstack/horizon, openstack/keystone, openstack/nova, openstack/oslo-incubator, openstack/oslo.config, openstack/python-ceilometerclient, openstack/python-cinderclient, openstack/python-glanceclient, openstack/python-heatclient, openstack/python-keystoneclient, openstack/python-novaclient, openstack/python-openstackclient, openstack/python-quantumclient, openstack/python-swiftclient, openstack/quantum, openstack/swift, stackforge/moniker, stackforge/python-monikerclient, stackforge/python-reddwarfclient, stackforge/python-savannaclient, stackforge/savanna"
|
||||
}
|
||||
],
|
||||
"name": "release"
|
||||
},
|
||||
{
|
||||
"description": "This pipeline is used for silently testing new jobs.",
|
||||
"change_queues": [
|
||||
{
|
||||
"heads": [],
|
||||
"name": ""
|
||||
}
|
||||
],
|
||||
"name": "silent"
|
||||
}
|
||||
],
|
||||
"trigger_event_queue": {
|
||||
"length": 0
|
||||
},
|
||||
"result_event_queue": {
|
||||
"length": 0
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue