display zuul in gerrit change

This brings over a short summary of current zuul status for gerrit
changes. It is displayed above the test results table. And updates
every 10 seconds. If there are no outstanding changes in zuul, this
will hide the table where it's displayed.

This can be made more network efficient once
Ib8d80530cc99c222226f73046c17ab0bbf6e080b lands, however, it works
pretty quick in it's current format.

Co-Authored-By: Joshua Hesketh <josh@nitrotech.org>
Change-Id: Ice735926204d8cb972b68078e7ee23e56dce0b93
This commit is contained in:
Joshua Hesketh 2014-11-27 14:36:13 +11:00
parent e28b838c29
commit 0118d2b4b5

View File

@ -14,7 +14,7 @@
// under the License.
// this regex matches the hash part of review pages
var hashRegex = /^\#\/c\/[\/\d]+$/;
var hashRegex = /^\#\/c\/([\d]+)(\/([\/\d+])?)?$/;
// this regex matches CI comments
var ciRegex = /^(.* CI|Jenkins)$/;
// this regex matches "Patch set #"
@ -26,6 +26,46 @@ var trustedCIRegex = /^(OpenStack CI|Jenkins)$/;
// this regex matches the pipeline markup
var pipelineNameRegex = /Build \w+ \((\w+) pipeline\)/;
// The url to full status information on running jobs
var zuulStatusURL = 'http://status.openstack.org/zuul';
// The json URL to check for running jobs
var zuulStatusJSON = 'http://zuul.openstack.org/status.json';
function format_time(ms, words) {
if (ms == null) {
return "unknown";
}
var seconds = (+ms)/1000;
var minutes = Math.floor(seconds/60);
var hours = Math.floor(minutes/60);
seconds = Math.floor(seconds % 60);
minutes = Math.floor(minutes % 60);
r = '';
if (words) {
if (hours) {
r += hours;
r += ' hr ';
}
r += minutes + ' min';
} else {
if (hours < 10) r += '0';
r += hours + ':';
if (minutes < 10) r += '0';
r += minutes + ':';
if (seconds < 10) r += '0';
r += seconds;
}
return r;
}
var ci_parse_psnum = function($panel) {
var match = psRegex.exec($panel.html());
if (match !== null) {
return parseInt(match[2]);
}
return 0;
};
var ci_parse_is_merge_conflict = function($panel) {
return (mergeFailedRegex.exec($panel.html()) !== null);
};
@ -180,6 +220,7 @@ var ci_prepare_results_table = function() {
table = document.createElement("table");
$(table).addClass("test_result_table");
$(table).addClass("infoTable").css({"margin-top":"1em", "margin-bottom":"1em"});
var approval_table = $("div.approvalTable");
if (approval_table.length) {
var outer_table = document.createElement("table");
@ -293,11 +334,116 @@ var ci_page_loaded = function() {
if (!showOrHide) {
ci_hide_ci_comments(comments);
}
ci_zuul_for_change(comments);
} else {
$("#toggleci").hide();
}
};
var ci_current_change = function() {
var change = hashRegex.exec(window.location.hash);
if (change.length > 1) {
return change[1];
}
return null;
};
// recursively find the zuul status change, will be much more
// efficient once zuul supports since json status.
var ci_find_zuul_status = function (data, change_psnum) {
var objects = [];
for (var i in data) {
if (!data.hasOwnProperty(i)) continue;
if (typeof data[i] == 'object') {
objects = objects.concat(ci_find_zuul_status(data[i],
change_psnum));
} else if (i == 'id' && data.id == change_psnum) {
objects.push(data);
}
}
return objects;
};
var ci_zuul_all_status = function(jobs) {
var status = "passing";
for (var i = 0; i < jobs.length; i++) {
if (jobs[i].result && jobs[i].result != "SUCCESS") {
status = "failing";
break;
}
}
return status;
};
var ci_zuul_display_status = function(status) {
var zuul_table = $("table.zuul_result_table")[0];
if (!zuul_table) {
var test_results = $("table.test_result_table")[0];
zuul_table = document.createElement("table");
$(zuul_table).addClass("zuul_result_table");
$(zuul_table).addClass("infoTable").css({"margin-bottom":"1em"});
if (test_results) {
$(test_results).prepend(zuul_table);
}
}
$(zuul_table).empty();
$(zuul_table).show();
$(zuul_table).append("<tr><td class='header'>Review currently being tested (<a href='" + zuulStatusURL + "'>full status</a>)</td></tr>");
for (var i = 0; i < status.length; i++) {
var item = status[i];
var pipeline = item.jobs[0].pipeline;
var passing = (item.failing_reasons && item.failing_reasons.length > 0) ? "failing" : "passing";
var timeleft = item.remaining_time;
var row = "<tr><td>";
if (pipeline != null) {
row += pipeline + " pipeline: " + passing;
row += " (" + format_time(timeleft, false) + " left)";
} else {
row += "in between pipelines, status should update shortly";
}
row += "</td></tr>";
$(zuul_table).append(row);
}
};
var ci_zuul_clear_status = function () {
var zuul_table = $("table.zuul_result_table")[0];
if (zuul_table) {
$(zuul_table).hide();
}
};
var ci_zuul_process_changes = function(data, change_psnum) {
var zuul_status = ci_find_zuul_status(data, change_psnum);
if (zuul_status.length) {
ci_zuul_display_status(zuul_status);
} else {
ci_zuul_clear_status();
}
};
var ci_zuul_inner_loop = function(change_psnum) {
var current = ci_current_change();
if (current && change_psnum.indexOf(current) != 0) {
// window url is dead
return;
}
$.getJSON(zuulStatusJSON, function(data) {
ci_zuul_process_changes(data, change_psnum);
});
setTimeout(function() {ci_zuul_inner_loop(change_psnum);}, 10000);
};
var ci_zuul_for_change = function(comments) {
if (!comments) {
comments = ci_parse_comments();
}
var change = ci_current_change();
var psnum = ci_latest_patchset(comments);
var change_psnum = change + "," + psnum;
ci_zuul_inner_loop(change_psnum);
};
window.onload = function() {
var input = document.createElement("input");