forked from matt-catalyst/websockets-dashboard
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #56 from srynot4sale/jenkins
plugins/jenkins: Initial version
- Loading branch information
Showing
3 changed files
with
346 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
plugins.jenkins = { | ||
|
||
html: null, | ||
|
||
start: function() { | ||
html = ('<div class="plugin" id="jenkins"><h1>Jenkins Builds</h1><div class="fader"></div><ol></ol></div>'); | ||
$('div#body').append(html); | ||
}, | ||
|
||
queue: 0, | ||
|
||
receiveData: function(data) { | ||
|
||
// Check for a single message (is not array?) | ||
if (!$.isArray(data)) { | ||
data = [data]; | ||
} | ||
|
||
var container = $('div#jenkins ol'); | ||
|
||
// Save old queue count for comparison later | ||
var oldqueue = this.queue; | ||
this.queue = 0; | ||
|
||
for (c in data) { | ||
var content = data[c]; | ||
|
||
if (content == 1) { | ||
// Ignore (this is a placeholder) | ||
continue; | ||
} | ||
|
||
var id = 'build-'+content.id; | ||
var status = content.status; | ||
var statusclass = 'status-'+status; | ||
var name = content.name; | ||
var duration = content.duration; | ||
var href = content.href; | ||
|
||
if (status == 'RUNNING') { | ||
duration = status; | ||
|
||
// Update queue count (only running jobs have a queue property) | ||
this.queue = content.queue; | ||
} | ||
|
||
var link = $('<a>').attr('href', href).html(name); | ||
var dur = $('<span class="duration">').html(duration); | ||
|
||
var node = $('<li data-sort="'+content.sort+'">').attr('id', id).attr('class', statusclass).data('buildid', content.id).data('sort', content.sort); | ||
node.html(link).append(dur); | ||
node.hide(); | ||
|
||
// Check if this is an update (as the previous build already exists) | ||
var exists = $('li#'+id, container); | ||
if (exists.length) { | ||
if (exists.attr('class') !== statusclass || status == 'RUNNING') { | ||
console.log('replace'); | ||
exists.replaceWith(node); | ||
node.show(); | ||
} | ||
else { | ||
console.log('no change'); | ||
} | ||
|
||
continue; | ||
} | ||
|
||
// Find the next highest build time and add after that | ||
var buildsort = content.sort; | ||
var next = null; | ||
var nextid = null; | ||
$('li', container).each(function() { | ||
var check = $(this).data('sort'); | ||
if (check > buildsort) { | ||
if (next) { | ||
if (next > check) { | ||
next = check; | ||
nextid = $(this).data('buildid'); | ||
} | ||
} else { | ||
next = check; | ||
nextid = $(this).data('buildid'); | ||
} | ||
} | ||
}); | ||
|
||
if (next) { | ||
// If found next highest, append after | ||
$('li#build-'+nextid, container).after(node); | ||
} else { | ||
// Otherwise is highest, add to top | ||
container.prepend(node); | ||
} | ||
|
||
node.fadeIn(1000); | ||
} | ||
|
||
if ($('li', container).length > 30) { | ||
$('li:last', container).slideUp().remove(); | ||
} | ||
|
||
// If queue length has changed, update it | ||
if (oldqueue != this.queue) { | ||
console.log('Update queue'); | ||
|
||
// Update queue | ||
var qcontainer = $('div#jenkins h1 span.queue'); | ||
if (!qcontainer.length) { | ||
qcontainer = $('<span class="queue"></span>'); | ||
$('div#jenkins h1').append(qcontainer); | ||
} | ||
|
||
if (this.queue == 0) { | ||
qcontainer.text(''); | ||
} else if (this.queue == 1) { | ||
qcontainer.text('['+this.queue+' build in queue]'); | ||
} else { | ||
qcontainer.text('['+this.queue+' builds in queue]'); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
div#jenkins li.urgent a { | ||
color: #f00; | ||
} | ||
|
||
.dashboard-fullscreen div#jenkins { | ||
font-size: 32px; | ||
} | ||
|
||
div#jenkins h1 span.queue { | ||
margin-left: 2em; | ||
display: inline-block; | ||
color: #fff; | ||
} | ||
|
||
.dashboard-fullscreen div#jenkins > ol > li { | ||
padding-bottom: 10px; | ||
padding-top: 10px; | ||
} | ||
|
||
div#jenkins li.new span.status { | ||
color: #f90; | ||
} | ||
|
||
div#jenkins li { | ||
padding: 2px 0; | ||
border-bottom: 1px solid #999; | ||
overflow: auto; | ||
font-size: 110%; | ||
margin-bottom: 1px; | ||
} | ||
|
||
div#jenkins li a { | ||
color: #fff; | ||
padding: 3px 0; | ||
display: inline-block; | ||
/** text-shadow: 0 0 0.1em #fff; **/ | ||
} | ||
|
||
div#jenkins li span.duration { | ||
float: right; | ||
background-color: #fff; | ||
color: #333; | ||
padding: 5px; | ||
width: 20%; | ||
text-align: center; | ||
} | ||
/** | ||
div#jenkins li.status-RUNNING { | ||
border: 3px solid #fff; | ||
} | ||
div#jenkins li.status-ABORTED { | ||
background-color: #666; | ||
} | ||
div#jenkins li.status-FAILURE { | ||
background-color: #f00; | ||
} | ||
div#jenkins li.status-SUCCESS { | ||
background-color: #0f0; | ||
} | ||
div#jenkins li.status-SUCCESS a { | ||
color: #333; | ||
text-shadow: none; | ||
} | ||
**/ | ||
|
||
div#jenkins li.status-RUNNING { | ||
/** border: 3px solid #666;**/ | ||
} | ||
|
||
div#jenkins li.status-ABORTED span.duration { | ||
background-color: #666; | ||
color: #fff; | ||
} | ||
|
||
div#jenkins li.status-FAILURE span.duration { | ||
background-color: #f00; | ||
color: #fff; | ||
} | ||
|
||
div#jenkins li.status-SUCCESS span.duration { | ||
background-color: #0f0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
import ConfigParser | ||
import json | ||
import logging | ||
import os | ||
import requests | ||
import time | ||
import urllib | ||
|
||
import jenkinsapi | ||
from jenkinsapi.jenkins import Jenkins | ||
|
||
CONFIG = {} | ||
|
||
def setup_config(): | ||
global CONFIG | ||
|
||
# Load global config file | ||
path = os.path.join(os.path.dirname(__file__), '../../config.ini') | ||
con = ConfigParser.ConfigParser() | ||
con.readfp(open(path)) | ||
|
||
host = con.get('general', 'host') | ||
port = con.get('general', 'port') | ||
CONFIG['host'] = '%s:%s' % (host, port) | ||
|
||
# Load module config file | ||
path = os.path.join(os.path.dirname(__file__), 'config.ini') | ||
con = ConfigParser.ConfigParser() | ||
con.readfp(open(path)) | ||
|
||
CONFIG['jenkins'] = con.get('jenkins', 'host') | ||
|
||
|
||
# Generic push to dashboard function | ||
def dashboard_push_data(plugin, data, multiple = False): | ||
global CONFIG | ||
|
||
d = [] | ||
if multiple: | ||
d.append(('multiple', 1)) | ||
for item in data: | ||
j = json.dumps(item) | ||
d.append(('data', j)) | ||
else: | ||
j = json.dumps(data) | ||
d.append(('data', j)) | ||
|
||
r = requests.post('http://%s/update/%s?%s' % (CONFIG['host'], plugin, urllib.urlencode(d))) | ||
|
||
|
||
|
||
# Main code | ||
def main(): | ||
global CONFIG | ||
setup_config() | ||
|
||
server = Jenkins(CONFIG['jenkins']) | ||
|
||
#print(dir(j['moodle'])) | ||
|
||
jobs = ['moodle', 'totara'] | ||
|
||
# Run forever | ||
while 1: | ||
|
||
try: | ||
queueitems = [] | ||
for jobname in jobs: | ||
job = server[jobname] | ||
|
||
# Get queue length | ||
if job.is_queued(): | ||
q = server.get_queue() | ||
queue = q.get_queue_items_for_job(jobname) | ||
for qitem in queue: | ||
queueitems.append(qitem.params.replace('\nBRANCH=', '')) | ||
|
||
queue = len(queueitems) | ||
print('Queue length: %d' % queue) | ||
if queue: | ||
print('Queue: %s' % queueitems) | ||
|
||
builddata = [] | ||
for jobname in jobs: | ||
job = server[jobname] | ||
|
||
print('Job: %s' % jobname) | ||
print('Is running build: %s' % ('yes' if job.is_running() else 'no')) | ||
builds = job.get_build_ids() | ||
|
||
bcount = 0 | ||
for bid in builds: | ||
bcount += 1 | ||
if bcount > 10: | ||
break | ||
|
||
build = job.get_build(bid) | ||
|
||
name = build.name.split(' ') | ||
namestr = name[0] | ||
if len(name) > 2: | ||
namestr = name[2] | ||
|
||
if build.is_running(): | ||
status = 'RUNNING' | ||
else: | ||
status = build.get_status() | ||
|
||
duration = str(build.get_duration()).split('.')[0] | ||
|
||
data = {} | ||
data['id'] = jobname+'_'+str(bid) | ||
data['starttime'] = str(build.get_timestamp()) | ||
data['sort'] = data['starttime'] + '_' + data['id'] | ||
data['name'] = namestr | ||
data['status'] = status | ||
data['duration'] = duration | ||
data['href'] = build.get_result_url() | ||
|
||
# If this build is running, note queue length | ||
if status == 'RUNNING': | ||
data['queue'] = queue | ||
|
||
print(data) | ||
|
||
builddata.append(data) | ||
|
||
dashboard_push_data('jenkins', builddata, True) | ||
|
||
except Exception as e: | ||
print 'Exceptional exception!' | ||
logging.exception(e) | ||
|
||
time.sleep(30) | ||
|
||
if __name__ == "__main__": | ||
main() |