Skip to content

Instantly share code, notes, and snippets.

@petehamilton
Last active July 8, 2021 09:50
Show Gist options
  • Star 34 You must be signed in to star a gist
  • Fork 7 You must be signed in to fork a gist
  • Save petehamilton/5494978 to your computer and use it in GitHub Desktop.
Save petehamilton/5494978 to your computer and use it in GitHub Desktop.
Circle CI Build Status widget for Dashing (Single Builds)

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 below into your assets folder

CircleCI Dashing Widget

There is also another version for more compactly displaying multiple builds which you can see here

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/logo-circle-ci.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: 'MY_GITHUB_USER_OR_ORG', repo: 'XXX', branch: 'master' },
{ user: 'MY_GITHUB_USER_OR_ORG', repo: 'YYY', branch: 'dev' },
]
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;
}
}
@jeromelachaud
Copy link

jeromelachaud commented Jan 22, 2018

in circle_ci.rb:
line 41, should be: api_url = 'https://circleci.com/api/v1.1/project/github/%s/%s/tree/%s?circle-token=%s'
and line 59: commit_body: "\"#{latest_build['subject']}\""

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