Skip to content

Instantly share code, notes, and snippets.

@jkassemi
Forked from petehamilton/README.md
Created July 11, 2013 18:35
Show Gist options
  • Save jkassemi/5977969 to your computer and use it in GitHub Desktop.
Save jkassemi/5977969 to your computer and use it in GitHub Desktop.

Description

Dashing widget to show the build status of a CircleCI project.

Usage

  • Get a Circle API Token from your Account Dashboard and set it in your environment as CIRCLE_CI_AUTH_TOKEN
  • Add the httparty to your Gemfile and run bundle install

Then:

  1. Copy the below coffee/scss/html files into a widget folder named circle_ci
  2. Copy the circle_ci.rb file into the jobs folder

OR dashing install 5494978

Then copy the [CircleCI Logo](https://f.cloud.github.com/assets/510845/448516/6e8d2842-b249-11e2-91b6-9a2ffcd08bb0.png into assets/images) into your assets folder

screen shot 2013-05-01 at 13 19 33

class Dashing.CircleCi extends Dashing.Widget
onData: (data) ->
@_checkStatus(data.widget_class)
_checkStatus: (status) ->
$(@node).removeClass('failed pending passed')
$(@node).addClass(status)
<h1 class="title" data-bind="title"></h1>
<img class="background" src="/assets/circle-ci-logo.png">
<span class="label small" data-bind="build_id"></span>
<div class="commit-info">
<img data-bind-src="avatar_url" />
<span class="label committer-name" data-bind="committer_name"></span>
<span class="label small commit-body" data-bind="commit_body"></span>
<div class="clearfix"></div>
</div>
<h2 class="state" data-bind="state"></h2>
<span class="label small" data-bind="time"></span>
<p class="more-info" data-bind="moreinfo"></p>
<p class="updated-at" data-bind="updatedAtMessage"></p>
require 'httparty'
require 'digest/md5'
projects = [
{ user: 'gocardless', repo: 'gocardless', branch: 'dev' },
{ user: 'gocardless', repo: 'dashboard', branch: 'master' },
{ user: 'gocardless', repo: 'payments-service', branch: 'master' },
{ user: 'gocardless', repo: 'payments-client', branch: 'master' },
]
def duration(time)
secs = time.to_int
mins = secs / 60
hours = mins / 60
days = hours / 24
if days > 0
"#{days}d #{hours % 24}h ago"
elsif hours > 0
"#{hours}h #{mins % 60}m ago"
elsif mins > 0
"#{mins}m #{secs % 60}s ago"
elsif secs >= 0
"#{secs}s ago"
end
end
def calculate_time(finished)
finished ? duration(Time.now - Time.parse(finished)) : "--"
end
def translate_status_to_class(status)
statuses = {
'success' => 'passed',
'fixed' => 'passed',
'running' => 'pending',
'failed' => 'failed'
}
statuses[status] || 'pending'
end
def build_data(project, auth_token)
api_url = 'https://circleci.com/api/v1/project/%s/%s/tree/%s?circle-token=%s'
api_url = api_url % [project[:user], project[:repo], project[:branch], auth_token]
api_response = HTTParty.get(api_url, :headers => { "Accept" => "application/json" } )
api_json = JSON.parse(api_response.body)
return {} if api_json.empty?
latest_build = api_json.select{ |build| build['status'] != 'queued' }.first
email_hash = Digest::MD5.hexdigest(latest_build['committer_email'])
build_id = "#{latest_build['branch']}, build ##{latest_build['build_num']}"
data = {
build_id: build_id,
repo: "#{project[:repo]}",
branch: "#{latest_build['branch']}",
time: "#{calculate_time(latest_build['stop_time'])}",
state: "#{latest_build['status'].capitalize}",
widget_class: "#{translate_status_to_class(latest_build['status'])}",
committer_name: latest_build['committer_name'],
commit_body: "\"#{latest_build['body']}\"",
avatar_url: "http://www.gravatar.com/avatar/#{email_hash}"
}
return data
end
SCHEDULER.every '10s', :first_in => 0 do
projects.each do |project|
data_id = "circle-ci-#{project[:user]}-#{project[:repo]}-#{project[:branch]}"
data = build_data(project, ENV['CIRCLE_CI_AUTH_TOKEN'])
send_event(data_id, data) unless data.empty?
end
end
$state-color: #FFF;
$background-color: #8fb347;
$background-error-color: #A31F1F;
$background-passed-color: #8fb347;
$background-pending-color: #47bbb3;
$title-color: rgba(255, 255, 255, 1);
$label-color: rgba(255, 255, 255, 0.7);
$moreinfo-color: rgba(255, 255, 255, 0.7);
.widget-circle-ci{
background-color: $background-color;
vertical-align: top;
img.background {
width: 100% !important;
position: absolute;
left: 0;
top: 30px;
opacity: 0.05;
}
.committer-info {
margin: 10px 0px;
padding: 5px;
background: rgba(255, 255, 255, 0.3);
img {
float:left;
}
.label {
text-align: left;
padding-left: 90px;
font-size: 20px;
&.small {
font-size: 14px;
}
}
}
.title {
color: $title-color;
}
ol, ul {
margin: 0 15px;
text-align: left;
color: $label-color;
}
ol {
list-style-position: inside;
}
li {
margin-bottom: 5px;
}
.list-nostyle {
list-style: none;
}
.label {
text-align: center;
display: block;
color: $label-color;
font-size: 24px;
word-wrap: break-word;
&.small {
font-size: 18px;
}
}
.state {
text-align: center;
display: block;
font-weight: 600;
color: $state-color;
font-size: 40px;
word-wrap: break-word;
}
.updated-at {
color: rgba(0, 0, 0, 0.3);
}
.more-info {
color: $moreinfo-color;
}
&.failed {
background-color: $background-error-color;
}
&.pending {
background-color: $background-pending-color;
}
&.passed {
background-color: $background-passed-color;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment