From 0118d2b4b53cea2641c123a57c14bf8276237f09 Mon Sep 17 00:00:00 2001 From: Joshua Hesketh Date: Thu, 27 Nov 2014 14:36:13 +1100 Subject: [PATCH] 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 Change-Id: Ice735926204d8cb972b68078e7ee23e56dce0b93 --- .../openstack_project/files/gerrit/hideci.js | 148 +++++++++++++++++- 1 file changed, 147 insertions(+), 1 deletion(-) diff --git a/modules/openstack_project/files/gerrit/hideci.js b/modules/openstack_project/files/gerrit/hideci.js index 2affea8f93..8e3a46651a 100644 --- a/modules/openstack_project/files/gerrit/hideci.js +++ b/modules/openstack_project/files/gerrit/hideci.js @@ -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("Review currently being tested (full status)"); + 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 = ""; + if (pipeline != null) { + row += pipeline + " pipeline: " + passing; + row += " (" + format_time(timeleft, false) + " left)"; + } else { + row += "in between pipelines, status should update shortly"; + } + row += ""; + + $(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");