Skip to content

Instantly share code, notes, and snippets.

@Brunas
Last active August 29, 2015 14:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Brunas/b39380801f38f15254f8 to your computer and use it in GitHub Desktop.
Save Brunas/b39380801f38f15254f8 to your computer and use it in GitHub Desktop.
TFS Build Queue using ODataTFS

Description

This is Dashing widget to display TFS build queue.

##Usage

The widget requires ODataTFS modified by me installed on some machine with access to TFS2012 server.

Put the tfs_build_queue.rb file in your /jobs folder. tfs_build_queue.coffee, tfs_build_queue.html and tfs_build_queue.scss to /widgets/tfs_build_queue.

To include the widget in a dashboard, add the following snippet to the dashboard layout file:

<li data-row="1" data-col="1" data-sizex="3" data-sizey="4">
  <div data-id="tfsBuildQueue" data-view="TFSBuildQueue" data-title="TFS 2012 Build Queue" data-date-time-format="%Y-%m-%d %H:%M:%S" data-max-items-to-show="14" data-one-row="1"></div>
</li>

##Settings

Change ODATA_URL value in /jobs/tfs_build_queue.rb to point to ODataTFS service.

class Dashing.TFSBuildQueue extends Dashing.Widget
ready: ->
@addDivs()
onData: (data) ->
@addDivs()
addDivs: ->
builds = @get('queue') if @get('queue')
@handleBgIcon(builds.length) if builds
divPa = $(@node).find('.builds')
divPa.find('.build').remove()
divPa.find('.build-in-progress').remove()
maxItems = 6
maxItems = $(@node).data('max-items-to-show') if $(@node).data('max-items-to-show')
for i,build of builds
divPa.append(@buildDiv(build)) if i < maxItems
buildDiv: (build) ->
return if !build
clazz = 'build'
clazz += '-in-progress' if build['BuildStatus'] == 'InProgress'
text = '<div class="'+clazz+'">'
text += '<div class="controller">'+build['BuildController'] if build['BuildController']
text += '<span class="agent">' +build['BuildAgent']+'</span>' if build['BuildAgent']
text += '</div>' if build['BuildController'] and !$(@node).data('one-row')
text += '<div class="details">' if !$(@node).data('one-row')
text += '&nbsp;' if $(@node).data('one-row')
text += @buildDetails(build['Date'], build['ElapsedTime'], build['User'], build['Project'], build['BuildDefinition'], build['Priority'])+'</div>'
text += '</div>'
buildDetails: (date, duration, user, project, definition, priority) ->
text = ''
date = @formatDateTime(new Date(parseInt(date.substr(6))))
text = "<i class='icon-simple icon-flag'></i>"+date+("&nbsp;("+user+")" if user) if date
text += "<br>" if $(@node).data('details-new-lines')
text += "<i class='icon-simple"+("-left-padded" if !$(@node).data('details-new-lines'))+" icon-resize-horizontal'></i>"+duration.substring(0, duration.indexOf('.')) if duration
text += "<br>" if $(@node).data('details-new-lines')
text += "<span class='nowrap'><i class='icon-simple"+("-left-padded" if !$(@node).data('details-new-lines'))+" icon-info-sign'></i>"
text += definition + ' ('+priority+')' if definition
text += '</span>'
text
formatDateTime: (dateTime) ->
format = $(@node).data('date-time-format')
if format
format.replace('%Y',dateTime.getFullYear()).replace('%m', @zeroLPad(dateTime.getMonth()+1)).replace('%d',@zeroLPad(dateTime.getDate())).replace('%H',@zeroLPad(dateTime.getHours())).replace('%M', @zeroLPad(dateTime.getMinutes())).replace('%S', @zeroLPad(dateTime.getSeconds()))
else
dateTime.toLocaleDateString()+" "+dateTime.toLocaleTimeString()
zeroLPad: (i) ->
if i < 10 then "0" + i else i
handleBgIcon: (number) ->
$(@node).find(".icon-background").remove()
max = $(@node).data('safe-queue-length')
max = 6 if !max
text = '<span class="icon-background queue-length'
text += ' red' if number > max
text += '">' + number + '</span>'
$(@node).prepend(text)
<h2 class="title" data-bind="title"></h2>
<div class="builds"></div>
<p class="updated-at" data-bind="updatedAtMessage"></p>
require 'net/http'
require 'json'
require 'time'
class TFSBuildQueue
#URL to ODataTFS
ODATA_URL = URI.parse('http://127.0.0.1:8080')
REQ_URL = '/QueuedBuilds?$format=json'
READ_TIMEOUT = 120 #seconds
DEBUG = 0
def debug
DEBUG
end
# function to validate json
def valid_json? (json)
JSON.parse(json)
return true
rescue JSON::ParserError
return false
end
def get_queue
url = URI.encode(REQ_URL)
http = Net::HTTP.new(ODATA_URL.host, ODATA_URL.port)
http.read_timeout = READ_TIMEOUT
request = Net::HTTP::Get.new(url)
response = http.request(request)
return if not valid_json?(response.body)
json = JSON.parse(response.body)
puts json if DEBUG > 3
return json['d']['results'] if json and json['d'] and json['d']['results']
rescue Timeout::Error
puts DateTime.now.to_s+' Timeout occured while requesting '+url
rescue Errno::ECONNRESET => e
puts DateTime.now.to_s+' Connection reset by pear exception occured while requesting '+url
end
end
@TFSBuildQueue = TFSBuildQueue.new()
SCHEDULER.every '60s', first_in: 0 do |job|
reqStarted = DateTime.now
queue = @TFSBuildQueue.get_queue
next if not queue
reqEnded = DateTime.now
puts reqStarted.strftime('%F %T') + '-'+reqEnded.strftime('%F %T')+' ('+(reqEnded.to_time.to_i-reqStarted.to_time.to_i).to_s+'s):' if @TFSBuildQueue.debug > 0
puts queue if @TFSBuildQueue.debug > 2
send_event('tfsBuildQueue', { 'queue' => queue } )
end
// ----------------------------------------------------------------------------
// Sass declarations
// ----------------------------------------------------------------------------
$background-color: rgba(255,255,255,0.2);
$title-color: rgba(255,255,255,0.4);
$queue-length-color: white;
$build-in-progress-background-color: #96bf48;
$build-background-color: #222;
// ----------------------------------------------------------------------------
// Widget-tfs-build-queue styles
// ----------------------------------------------------------------------------
.widget-tfs-build-queue {
background-color: $background-color;
position: relative;
.title {
position:absolute;
color: $title-color;
top: 0;
text-align:center;
width:100%;
z-index: -10;
}
.queue-length {
color: $queue-length-color;
font-weight: 700;
z-index: 99;
}
.red {
color: red;
}
.build, .build-in-progress {
border: 1px solid white;
border-radius: 3px;
position:relative;
display:block;
background-color:$build-in-progress-background-color;
padding: 5px;
margin: 5px;
}
.controller {
font-weight: bold;
text-shadow:
-1px -1px 0 #000,
1px -1px 0 #000,
-1px 1px 0 #000,
1px 1px 0 #000;
};
.agent {
font-size: 200%;
font-weight: bold;
text-transform:uppercase;
padding-left: 10px;
text-shadow:
-1px -1px 0 #000,
1px -1px 0 #000,
-1px 1px 0 #000,
1px 1px 0 #000;
};
.details {
font-size: 0.85em;
};
.build {
background-color:$build-background-color;
}
.icon-background {
opacity: 0.5;
}
.icon-simple-left-padded {
padding-left:10px;
padding-right:5px;
}
.icon-simple {
padding-left:0;
padding-right:5px;
}
.nowrap {
white-space:nowrap;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment