Skip to content

Instantly share code, notes, and snippets.

@joepadmiraal
Last active December 21, 2020 16:41
Show Gist options
  • Star 16 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save joepadmiraal/33e0c2a7a7b00cc2e0aa to your computer and use it in GitHub Desktop.
Save joepadmiraal/33e0c2a7a7b00cc2e0aa to your computer and use it in GitHub Desktop.
Jenkins build status widget for Dashing

##Preview See images below.

Description

Simple Dashing widget (and associated job) to display the current build status of a Jenkins server. When all jobs are fine a blue background with a thumbs-up icons is shown. When one or more jobs are in a failed state, they are listed on a red background. If culprits are available the user which has broken the build will also be shown. When the Speech Synthesis API is available on the browser it will say one of the predefined texts out loud every 5 minutes. See jenkins_build_status.coffee for the texts and the timeBetweenSounds parameter.

Calls are made to the Jenkins API to retrieve the build status and culprits if they are available.

Please leave a comment below or click on the star if you are using this widget :-)

Installing the widget

Create the folder widgets/jenkins_build_status and put these files in it:

  • jenkins_build_status.coffee
  • jenkins_build_status.html
  • jenkins_build_status.scss

Place the following file in your jobs/ folder:

  • jenkins_build_status.rb

Configuring the widget for use with your Jenkins instance

There are a few parameters that must be set up before using this widget with your Jenkins instance.

In the jenkins_build_status.rb file, modify the following parameters according to your needs:

Parameter Meaning
JENKINS_URI Jenkins base URL
JENKINS_AUTH Jenkins user credentials

Adding the Jenkins build status widget to your dashboard

To add this widget to your dashboard, add the following to your [Dashboard-filename].erb file:

    <li data-row="1" data-col="1" data-sizex="2" data-sizey="1">
      <div data-id="jenkinsBuildStatus" data-view="JenkinsBuildStatus" data-title="Jenkins"></div>
    </li>
class Dashing.JenkinsBuildStatus extends Dashing.Widget
lastPlayed: 0
timeBetweenSounds: 300000
onData: (data) ->
if data.failed
$(@node).find('div.build-failed').show()
$(@node).find('div.build-succeeded').hide()
$(@node).css("background-color", "red")
if 'speechSynthesis' of window
@playSoundForUser data.failedJobs[0].value if Date.now() - @lastPlayed > @timeBetweenSounds
else
$(@node).find('div.build-failed').hide()
$(@node).find('div.build-succeeded').show()
$(@node).css("background-color", "#12b0c5")
playSoundForUser: (user) ->
@lastPlayed = Date.now()
texts = ["#{user} has broken the build.", "The build is broken by #{user}", "#{user} is great, but lacks some programming skills", "Oops, I did it again."]
textNr = Math.floor((Math.random() * texts.length));
@playSound texts[textNr]
playSound: (text) ->
msg = new SpeechSynthesisUtterance(text)
msg.voice = speechSynthesis.getVoices()[0]
speechSynthesis.speak msg
<div class="build-failed">
<h1 class="jenkins-status"><span data-bind="title"></span> FAILED</h1>
<ul class="list-nostyle list-failed">
<li data-foreach-item="failedJobs">
<div class="label" data-bind="item.label"></div>
<div class="value" data-bind="item.value"></div>
</li>
</ul>
</div>
<div class="build-succeeded">
<h1 class="jenkins-status">All <span data-bind="title"></span> builds are successful</h1>
<i class="fa fa-thumbs-o-up"></i>
</div>
<p class="updated-at" data-bind="updatedAtMessage"></p>
require 'net/http'
require 'json'
JENKINS_URI = "http://localhost:8080/"
JENKINS_AUTH = {
'name' => null,
'password' => null
}
SCHEDULER.every '10s' do
json = getFromJenkins(JENKINS_URI + 'api/json?pretty=true')
failedJobs = Array.new
succeededJobs = Array.new
array = json['jobs']
array.each {
|job|
next if job['color'] == 'disabled'
next if job['color'] == 'notbuilt'
next if job['color'] == 'blue'
next if job['color'] == 'blue_anime'
jobStatus = '';
if job['color'] == 'yellow' || job['color'] == 'yellow_anime'
jobStatus = getFromJenkins(job['url'] + 'lastUnstableBuild/api/json')
elsif job['color'] == 'aborted' || job['color'] == 'aborted_anime'
jobStatus = getFromJenkins(job['url'] + 'lastUnsuccessfulBuild/api/json')
else
jobStatus = getFromJenkins(job['url'] + 'lastFailedBuild/api/json')
end
culprits = jobStatus['culprits']
culpritName = getNameFromCulprits(culprits)
if culpritName != ''
culpritName = culpritName.partition('<').first
end
failedJobs.push({ label: job['name'], value: culpritName})
}
failed = failedJobs.size > 0
send_event('jenkinsBuildStatus', { failedJobs: failedJobs, succeededJobs: succeededJobs, failed: failed })
end
def getFromJenkins(path)
uri = URI.parse(path)
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Get.new(uri.request_uri)
if JENKINS_AUTH['name']
request.basic_auth(JENKINS_AUTH['name'], JENKINS_AUTH['password'])
end
response = http.request(request)
json = JSON.parse(response.body)
return json
end
def getNameFromCulprits(culprits)
culprits.each {
|culprit|
return culprit['fullName']
}
return ''
end
// ----------------------------------------------------------------------------
// Sass declarations
// ----------------------------------------------------------------------------
$background-color: #ec663c;
$title-color: rgba(255, 255, 255, 0.7);
$label-color: rgba(255, 255, 255, 0.7);
$value-color: #fff;
// ----------------------------------------------------------------------------
// Widget-text styles
// ----------------------------------------------------------------------------
.widget-jenkins-build-status {
background-color: $background-color;
.title {
color: $title-color;
}
.updated-at {
color: rgba(255, 255, 255, 0.7);
}
ol, ul {
margin: 0 15px;
text-align: left;
color: $label-color;
}
li {
margin-bottom: 5px;
font-size: 40px;
}
.label {
color: $label-color;
}
.value {
margin-left: 12px;
font-weight: 600;
color: $value-color;
}
.updated-at {
color: rgba(0, 0, 0, 0.3);
}
.build-failed {
display: none;
}
.fa {
font-size: 10em;
color: $label-color;
}
}

The MIT License (MIT)

Copyright (c) 2014 David Underwood

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

@lethe3000
Copy link

hi, if I have tow jenkins servers to show, which is the correct approach?
I simply copy jenkins_build_status.rb to jenkins_build_status-2.rb
and modify the name of JENKINS_URI, JENKINS_AUTH to JENKINS_URI_2 and JENKINS_AUTH_2,but met such error:

/usr/local/rvm/gems/ruby-2.1.2/gems/eventmachine-1.0.7/lib/eventmachine.rb:526:in start_tcp_server': no acceptor (port is in use or requires root privileges) (RuntimeError) from /usr/local/rvm/gems/ruby-2.1.2/gems/eventmachine-1.0.7/lib/eventmachine.rb:526:instart_server'
from /usr/local/rvm/gems/ruby-2.1.2/gems/thin-1.6.3/lib/thin/backends/tcp_server.rb:16:in connect' from /usr/local/rvm/gems/ruby-2.1.2/gems/thin-1.6.3/lib/thin/backends/base.rb:63:inblock in start'
from /usr/local/rvm/gems/ruby-2.1.2/gems/eventmachine-1.0.7/lib/eventmachine.rb:187:in call' from /usr/local/rvm/gems/ruby-2.1.2/gems/eventmachine-1.0.7/lib/eventmachine.rb:187:inrun_machine'
from /usr/local/rvm/gems/ruby-2.1.2/gems/eventmachine-1.0.7/lib/eventmachine.rb:187:in run' from /usr/local/rvm/gems/ruby-2.1.2/gems/thin-1.6.3/lib/thin/backends/base.rb:73:instart'
from /usr/local/rvm/gems/ruby-2.1.2/gems/thin-1.6.3/lib/thin/server.rb:162:in start' from /usr/local/rvm/gems/ruby-2.1.2/gems/thin-1.6.3/lib/thin/controllers/controller.rb:87:instart'
from /usr/local/rvm/gems/ruby-2.1.2/gems/thin-1.6.3/lib/thin/runner.rb:200:in run_command' from /usr/local/rvm/gems/ruby-2.1.2/gems/thin-1.6.3/lib/thin/runner.rb:156:inrun!'
from /usr/local/rvm/gems/ruby-2.1.2/gems/thin-1.6.3/bin/thin:6:in <top (required)>' from /usr/local/rvm/gems/ruby-2.1.2/bin/thin:23:inload'
from /usr/local/rvm/gems/ruby-2.1.2/bin/thin:23:in <main>' from /usr/local/rvm/gems/ruby-2.1.2/bin/ruby_executable_hooks:15:ineval'
from /usr/local/rvm/gems/ruby-2.1.2/bin/ruby_executable_hooks:15:in `

'

@joepadmiraal
Copy link
Author

@aspence7 Please provide some more information. What do the logs say. Did you follow the tip from larrycai?

@larrycai
Copy link

Hi Joe:

Curious to know where is fa-thumbs-o-up, how can I see the thumb icon ?

@bemosior
Copy link

Thanks for sharing this, @joepadmiraal!

Found a minor bug. Line 29 of jenkins_build_status.rb should probably accommodate the aborted_anime "color", as it's the state entered when an aborted build becomes in-progress again:

elsif job['color'] == 'aborted' || job['color'] == 'aborted_anime'

@bemosior
Copy link

@larrycai: The Font Awesome icon set is used: https://fortawesome.github.io/Font-Awesome/icons/

@meichau
Copy link

meichau commented Oct 9, 2015

Thanks for sharing this @joepadmiraal.

Since you unfortunately didn't provide a license file with it: could you make clear under which license this project has been provided? Did you intend to use the MIT as given in the Dashing dashboard itself? Or anything else?

Thanks for any clarification.

@bean5
Copy link

bean5 commented Oct 27, 2015

@joepadmiraal Could you ad a license to this? It might be the only thing keeping it from being merged in...is that right @meichau.

@joepadmiraal
Copy link
Author

@bemosior Thanks for sharing the fix. I will update the script.
@meichau I'll add the MIT license

@meichau
Copy link

meichau commented Dec 16, 2015

@joepadmiraal Great, thanks.

@ch0wdan
Copy link

ch0wdan commented Jan 21, 2016

@joepadmiraal - My jenkins server is behind Okta integration. Due to this, running a redirect to Okta signin occurs, which triggers an exception of the widget. Ideas/tips on how to account for this?

scheduler caught exception:
757: unexpected token at '<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head>
                                        <meta http-equiv="content-type" content="text/html; charset=utf-8">
                                        <title>Redirect</title>
                                </head><body><h1>Redirect</h1><p>You were redirected to: <a id="redirlink" href=

@joepadmiraal
Copy link
Author

@ch0wdan Looking at your exception it seems like Otwa is returning a normal html page for its redirect. So there is no way for me to create a generic redirect function for this. I guess you would have to parse the html response yourself in the jenkins_build_status.rb file and use the link from redirlink to connect to your Jenkins server.

@ziadvictor
Copy link

I got this in the console:
"You're speaking plain HTTP to an SSL-enabled server port."
Where should I put these lines for HTTPS ?
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE

@joepadmiraal
Copy link
Author

@ziadvictor
This could be placed below:

http = Net::HTTP.new(uri.host, uri.port)

after line 53.

@levsa
Copy link

levsa commented Sep 26, 2016

Default values for JENKINS_AUTH['name'] and JENKINS_AUTH['password'] should be nil, null is not a valid ruby value.

@dramamask
Copy link

jenkins_build_status.rb needs the following line:

next if job['color'].nil?

Because jobs of the 'jenkins.branch.OrganizationFolder' do not have a color.

@ak-roche
Copy link

@joepadmiraal thank you.

I would like to monitor specific jobs on my jenkins server -- currently is shows all jobs on my server

ie one release of our product consists of 3 jenkins jobs out of the many we have running.

I would also like to include the iframe widget to show our sonar status of the above 3 git repositories.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment