From 8400d7a1842930987bfad5255570d11fe1c4553c Mon Sep 17 00:00:00 2001 From: Sean Dague Date: Fri, 1 May 2015 08:35:26 -0400 Subject: [PATCH] Revert "Revert zuul status in gerrit" This reverts commit ff6d73b989c57db79bb53e82f814d651945c3ac6. This brings back zuul inline status which is further optimized in follow on patches. We do this in phases because it's a lot easier to review that way. It also introduces zuul_inline global control variable, so we can land this turned off, and enable in the debugger to verify it's doing the correct thing. Change-Id: If951a4a05a7dfef7a6d0c8e15ed263ff0523165e --- .../openstack_project/files/gerrit/hideci.js | 152 ++++++++++++++++++ 1 file changed, 152 insertions(+) diff --git a/modules/openstack_project/files/gerrit/hideci.js b/modules/openstack_project/files/gerrit/hideci.js index 25ee0e0867..4634ca9d5e 100644 --- a/modules/openstack_project/files/gerrit/hideci.js +++ b/modules/openstack_project/files/gerrit/hideci.js @@ -25,10 +25,18 @@ var mergeFailedRegex = /Merge Failed\./; 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 = 'https://zuul.openstack.org/status.json'; // This is a variable to determine if we're in debugging mode, which // lets you globally set it to see what's going on in the flow. var hideci_debug = false; +// This is a variable to enable zuul integration, we default it off so +// that it creates no additional load, and that it's easy to turn off +// the feature. +var zuul_inline = false; /** dbg(...) - prints a list of items out to the javascript @@ -44,6 +52,42 @@ function dbg () { } } + +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); }; @@ -199,6 +243,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"); @@ -313,11 +358,118 @@ var ci_page_loaded = function() { if (!showOrHide) { ci_hide_ci_comments(comments); } + if (zuul_inline === true) { + 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");