juici 0.0.0 → 0.0.1.alpha1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/Gemfile +4 -1
- data/Gemfile.lock +26 -16
- data/README.md +45 -6
- data/Rakefile +24 -0
- data/bin/juicic +54 -0
- data/config/mongoid.yml.sample +20 -5
- data/juici-interface.gemspec +19 -0
- data/juici.gemspec +7 -3
- data/lib/juici.rb +8 -3
- data/lib/juici/app.rb +19 -23
- data/lib/juici/build_environment.rb +1 -1
- data/lib/juici/build_logic.rb +10 -1
- data/lib/juici/build_queue.rb +30 -3
- data/lib/juici/callback.rb +9 -5
- data/lib/juici/config.rb +4 -0
- data/lib/juici/controllers.rb +6 -0
- data/lib/juici/controllers/base.rb +26 -0
- data/lib/juici/controllers/build_queue.rb +14 -0
- data/lib/juici/controllers/builds.rb +74 -0
- data/lib/juici/controllers/index.rb +20 -0
- data/lib/juici/controllers/{trigger_controller.rb → trigger.rb} +24 -5
- data/lib/juici/database.rb +19 -13
- data/lib/juici/exceptions.rb +2 -0
- data/lib/juici/find_logic.rb +11 -0
- data/lib/juici/helpers/form_helpers.rb +11 -0
- data/lib/juici/helpers/html_helpers.rb +4 -0
- data/lib/juici/helpers/url_helpers.rb +28 -0
- data/lib/juici/interface.rb +13 -0
- data/lib/juici/models/build.rb +81 -24
- data/lib/juici/models/project.rb +1 -1
- data/lib/juici/server.rb +103 -40
- data/lib/juici/version.rb +8 -0
- data/lib/juici/views/README.markdown +45 -6
- data/lib/juici/views/about.erb +5 -5
- data/lib/juici/views/builds/edit.erb +23 -0
- data/lib/juici/views/builds/list.erb +26 -33
- data/lib/juici/views/builds/new.erb +42 -37
- data/lib/juici/views/builds/show.erb +4 -28
- data/lib/juici/views/index.erb +30 -13
- data/lib/juici/views/layout.erb +22 -13
- data/lib/juici/views/not_found.erb +3 -0
- data/lib/juici/views/partials/builds/debug.erb +12 -18
- data/lib/juici/views/partials/builds/output.erb +1 -0
- data/lib/juici/views/partials/builds/show.erb +19 -0
- data/lib/juici/views/partials/builds/sidebar.erb +13 -0
- data/lib/juici/views/partials/index/recently_built.erb +19 -0
- data/lib/juici/views/queue/list.erb +6 -0
- data/lib/juici/watcher.rb +33 -25
- data/public/favicon.ico +0 -0
- data/public/images/black_denim.png +0 -0
- data/public/styles/builds.css +59 -8
- data/public/styles/juici.css +226 -2
- data/public/vendor/bootstrap.css +6004 -0
- data/public/vendor/bootstrap.js +2036 -0
- data/public/vendor/img/glyphicons-halflings-white.png +0 -0
- data/public/vendor/jquery.js +9440 -0
- data/script/cibuild +10 -0
- data/spec/build_callback_spec.rb +46 -1
- data/spec/build_process_spec.rb +71 -5
- data/spec/build_queue_spec.rb +3 -1
- data/spec/controllers/builds_spec.rb +68 -0
- data/spec/controllers/index_spec.rb +28 -0
- data/spec/juici_app_spec.rb +0 -15
- data/spec/models/build_spec.rb +54 -0
- data/spec/spec_helper.rb +13 -0
- metadata +76 -12
- data/lib/juici/controllers/build_controller.rb +0 -0
- data/lib/juici/url_helpers.rb +0 -15
@@ -1,28 +1,4 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
<div class="accordion-heading">
|
6
|
-
<a class="accordion-toggle <%= build.heading_color %>" data-toggle="collapse" data-parent="#accordion0" href="#collapse_0">
|
7
|
-
<%= build.create_time %> <% build[:warnings].each do |warning| %><span class="label label-important"><%= warning %></span><% end %>
|
8
|
-
</a>
|
9
|
-
</div>
|
10
|
-
<div id="collapse_0" class="accordion-body collapse in">
|
11
|
-
<div class="row">
|
12
|
-
<div class="span8">
|
13
|
-
<div>
|
14
|
-
<a href="/builds/<%= proj.name %>/show/<%= build[:_id] %>">Link to this build</a>
|
15
|
-
</div>
|
16
|
-
<div class="accordion-inner build-output">
|
17
|
-
<%= build.output if build.respond_to? :output %>
|
18
|
-
</div>
|
19
|
-
</div>
|
20
|
-
<div class="span4">
|
21
|
-
<%= erb(:"partials/builds/debug", :locals => { :build => build }) %>
|
22
|
-
</div>
|
23
|
-
</div>
|
24
|
-
</div>
|
25
|
-
</div>
|
26
|
-
<% else %>
|
27
|
-
No such project.
|
28
|
-
<% end %>
|
1
|
+
<h3 class="project-title"><a href="<%= build_url_for(project) %>"><%= project.name %></a><a class="btn pull-right" href="/builds/new?project=<%= project.name %>">New Build</a></h3>
|
2
|
+
<div class="accordion" id="accordion0">
|
3
|
+
<%= erb(:"partials/builds/show", :locals => { :build => build, :idx => 0, :show => true }) %>
|
4
|
+
</div>
|
data/lib/juici/views/index.erb
CHANGED
@@ -1,13 +1,30 @@
|
|
1
|
-
<
|
2
|
-
<
|
3
|
-
|
4
|
-
|
5
|
-
<
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
<
|
11
|
-
|
12
|
-
|
13
|
-
|
1
|
+
<div class="row-fluid">
|
2
|
+
<div class="span8">
|
3
|
+
<h1 class="block-header">JuiCI</h1>
|
4
|
+
<p>
|
5
|
+
JuiCI is a CI server, written at RailsCamp after Jenkins left me feeling a little dead inside. JuiCI aims to solve some of the issues with existing (and outstanding) CI solutions like <a href="http://jenkins-ci.org/">Jenkins</a> and <a href="http://travis-ci.org">Travis</a>, by not trying to be all things to all people.
|
6
|
+
</p>
|
7
|
+
<p>
|
8
|
+
JuiCI has a very thin wrapper around build triggers, is almost entirely API driven, and has a queuing system with a notion of priority, globally shared across all projects.
|
9
|
+
</p>
|
10
|
+
<div>
|
11
|
+
In the past, this instance of Juici has built code for:
|
12
|
+
<ul>
|
13
|
+
<% ::Juici::Project.all.each do |p| %>
|
14
|
+
<li><a href="<%= build_url_for(p) %>"><%= p.name %></a></li>
|
15
|
+
<% end %>
|
16
|
+
</ul>
|
17
|
+
</div>
|
18
|
+
</div>
|
19
|
+
<div class="span4">
|
20
|
+
<h4 class="block-header builds-header">currently building</h4>
|
21
|
+
<ul class="builds">
|
22
|
+
<% $build_queue.currently_building.each do |build| %>
|
23
|
+
<li>
|
24
|
+
<a class="<%= build.heading_color %>" href="<%= build_url_for(build) %>"><%= build.link_title %></a>
|
25
|
+
</li>
|
26
|
+
<% end %>
|
27
|
+
</ul>
|
28
|
+
<%= erb(:"partials/index/recently_built") %>
|
29
|
+
</div>
|
30
|
+
</div>
|
data/lib/juici/views/layout.erb
CHANGED
@@ -1,34 +1,43 @@
|
|
1
1
|
<!doctype html>
|
2
2
|
<html>
|
3
3
|
<head>
|
4
|
-
<
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
4
|
+
<meta charset="UTF-8">
|
5
|
+
<% if ::Juici.env == "development" %>
|
6
|
+
<link href="/vendor/bootstrap.css" rel="stylesheet">
|
7
|
+
<script src="/vendor/jquery.js"></script>
|
8
|
+
<script src="/vendor/bootstrap.js"></script>
|
9
|
+
<% else %>
|
10
|
+
<link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.2.1/css/bootstrap.min.css" rel="stylesheet">
|
9
11
|
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
|
10
|
-
<script src="//netdna.bootstrapcdn.com/twitter-bootstrap/2.
|
12
|
+
<script src="//netdna.bootstrapcdn.com/twitter-bootstrap/2.2.1/js/bootstrap.min.js"></script>
|
13
|
+
<% end %>
|
14
|
+
<link href="/styles/juici.css" rel="stylesheet">
|
15
|
+
<% styles.each do |style| %>
|
16
|
+
<link href="/styles/<%= style %>.css" rel="stylesheet">
|
17
|
+
<% end rescue nil%>
|
11
18
|
<title>JuiCI</title>
|
12
19
|
<% if @redirect_to %>
|
13
|
-
<meta http-equiv="Refresh" content="0; url=<%=
|
20
|
+
<meta http-equiv="Refresh" content="0; url=<%= @redirect_to %>" />
|
14
21
|
<% end %>
|
15
22
|
</head>
|
16
23
|
<body>
|
17
24
|
<div class="navbar navbar-fixed-top">
|
18
25
|
<div class="navbar-inner">
|
19
|
-
<div class="container">
|
26
|
+
<div class="container-fluid">
|
20
27
|
<div class="nav-collapse">
|
21
28
|
<ul class="nav">
|
22
|
-
|
23
|
-
<li class="<%= "active" if
|
24
|
-
<li class="<%= "active" if
|
25
|
-
<li class="<%= "active" if
|
29
|
+
<% active rescue active = nil %>
|
30
|
+
<li class="main <%= "active" if active == :index %>"><a href="/">JuiCI</a></li>
|
31
|
+
<li class="<%= "active" if active == :new_build %>"><a href="/builds/new">New Build</a></li>
|
32
|
+
<li class="<%= "active" if active == :about %>"><a href="/about">About</a></li>
|
33
|
+
<li class="<%= "active" if active == :support %>"><a href="/support">Support</a></li>
|
34
|
+
<li class="<%= "active" if active == :queue %>"><a href="/queue">Build Queue</a></li>
|
26
35
|
</ul>
|
27
36
|
</div><!--/.nav-collapse -->
|
28
37
|
</div>
|
29
38
|
</div>
|
30
39
|
</div>
|
31
|
-
<div class="container">
|
40
|
+
<div class="container-fluid">
|
32
41
|
<%= yield %>
|
33
42
|
</div>
|
34
43
|
</body>
|
@@ -1,28 +1,22 @@
|
|
1
|
-
|
2
|
-
<h3>Environment:</h3>
|
3
|
-
<pre class="prettyprint">
|
4
|
-
<% build[:environment].each do |k, v| %>
|
5
|
-
<%= "#{k}=#{v}" %>
|
6
|
-
<% end %>
|
7
|
-
</pre>
|
8
|
-
<% end %>
|
1
|
+
<div class="debug-output">
|
9
2
|
<% if build[:priority] %>
|
10
|
-
<h3>
|
11
|
-
<pre class="prettyprint">
|
3
|
+
<h3 class="block-header">priority:</h3>
|
12
4
|
<%= build[:priority] %>
|
13
|
-
</pre>
|
14
5
|
<% end %>
|
15
6
|
<% if build[:command] %>
|
16
|
-
<h3>
|
17
|
-
<pre class="prettyprint">
|
7
|
+
<h3 class="block-header">command:</h3>
|
18
8
|
<%= build[:command] %>
|
19
|
-
|
9
|
+
<% end %>
|
10
|
+
<% if build[:environment] %>
|
11
|
+
<h3 class="block-header">environment:</h3>
|
12
|
+
<% build[:environment].reject{|k, v| v.nil?}.each do |k, v| %>
|
13
|
+
<p><strong><%="#{k} = " %></strong><%="#{v}" %></p>
|
14
|
+
<% end %>
|
20
15
|
<% end %>
|
21
16
|
<% if build[:callbacks] %>
|
22
|
-
<h3>
|
23
|
-
<pre class="prettyprint">
|
17
|
+
<h3 class="block-header">callbacks:</h3>
|
24
18
|
<% build[:callbacks].each do |callback| %>
|
25
|
-
|
19
|
+
<p><%= callback %><p>
|
26
20
|
<% end %>
|
27
|
-
</pre>
|
28
21
|
<% end %>
|
22
|
+
</div>
|
@@ -0,0 +1 @@
|
|
1
|
+
<div class="build-output"><%= ansi_escaped(escaped(build.output)) if build.respond_to? :output %></div>
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<div class="row-fluid">
|
2
|
+
<div class="accordion-heading span10">
|
3
|
+
<a class="set-url accordion-toggle <%= build.heading_color %>" data-toggle="collapse" data-parent="#accordion<%= idx+1 %>" href="#collapse_<%= idx %>" data-url="<%= build_url_for(build) %>">
|
4
|
+
<%= display_title rescue build.display_title %> <% build[:warnings].each do |warning| %><span class="label label-important"><%= warning %></span><% end %>
|
5
|
+
<% if build[:status] == :started %>
|
6
|
+
<div class="bowlG pull-right"><div class="bowl_ringG"><div class="ball_holderG"><div class="ballG"></div></div></div></div>
|
7
|
+
<% end %>
|
8
|
+
</a>
|
9
|
+
</div>
|
10
|
+
<a class="btn span2" href="<%= build_url_for(build) %>">Build Link</a>
|
11
|
+
</div>
|
12
|
+
<div id="collapse_<%= idx %>" class="accordion-body collapse <%= "in" if show rescue nil %>">
|
13
|
+
<div class="row-fluid" style="padding-top:20px">
|
14
|
+
<div class="span8">
|
15
|
+
<%= erb(:"partials/builds/output", :locals => { :build => build }) %>
|
16
|
+
</div>
|
17
|
+
<div class="span4"><%= erb(:"partials/builds/sidebar", :locals => { :build => build }) %><%= erb(:"partials/builds/debug", :locals => { :build => build }) %></div>
|
18
|
+
</div>
|
19
|
+
</div>
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<div class="build-sidebar">
|
2
|
+
<span><%= form_at(rebuild_url_for(build), {}, :submit => "Rebuild") %></span>
|
3
|
+
<% if build.status == Juici::BuildStatus::START %>
|
4
|
+
<span><%= form_at(kill_url_for(build),
|
5
|
+
{:project => build[:parent], :id => build[:_id]},
|
6
|
+
:submit => "Kill!") %></span>
|
7
|
+
<% elsif build.status == Juici::BuildStatus::WAIT %>
|
8
|
+
<span><%= form_at(cancel_url_for(build),
|
9
|
+
{:project => build[:parent], :id => build[:_id]},
|
10
|
+
:submit => "Cancel") %></span>
|
11
|
+
<% end %>
|
12
|
+
<span><a class="btn" href="<%= edit_url_for(build) %>">Edit</a></span>
|
13
|
+
</div>
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<h1 class="block-header builds-header builds-header--failure">fail!<span class="pull-right table-flipper">(╯°□°)╯︵ ┻━┻</span></h1>
|
2
|
+
<ul class="builds">
|
3
|
+
<% ::Juici::Build.get_recent(5, :status.in => [::Juici::BuildStatus::FAIL]).each do |build| %>
|
4
|
+
<li>
|
5
|
+
<a class="recently-built--fail" href="<%= build_url_for(build) %>"><%= build.link_title %></a>
|
6
|
+
</li>
|
7
|
+
<% end %>
|
8
|
+
</ul>
|
9
|
+
|
10
|
+
<hr>
|
11
|
+
|
12
|
+
<h1 class="block-header builds-header builds-header--success">pass!<span class="pull-right table-flipper">┬─┬ノ( º _ ºノ)</span></h1>
|
13
|
+
<ul class="builds">
|
14
|
+
<% ::Juici::Build.get_recent(5, :status.in => [::Juici::BuildStatus::PASS]).each do |build| %>
|
15
|
+
<li>
|
16
|
+
<a class="recently-built--pass" href="<%= build_url_for(build) %>"><%= build.link_title %></a>
|
17
|
+
</li>
|
18
|
+
<% end %>
|
19
|
+
</ul>
|
data/lib/juici/watcher.rb
CHANGED
@@ -1,39 +1,47 @@
|
|
1
1
|
module Juici
|
2
|
-
class Watcher
|
2
|
+
class Watcher
|
3
3
|
|
4
|
-
def self.
|
5
|
-
new
|
6
|
-
|
7
|
-
|
4
|
+
def self.instance
|
5
|
+
@@instance ||= self.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@active = true
|
8
10
|
end
|
9
11
|
|
10
|
-
def
|
11
|
-
|
12
|
-
loop do
|
12
|
+
def register_handler
|
13
|
+
Signal.trap("CHLD") do
|
13
14
|
begin
|
14
|
-
|
15
|
+
if @active
|
16
|
+
pid, status = Process.wait2(-1)
|
17
|
+
$build_queue.purge(:pid, OpenStruct.new(:pid => pid))
|
18
|
+
::Juici.dbgp "Trying to find pid: #{pid}"
|
19
|
+
handle(pid, status)
|
20
|
+
end
|
15
21
|
rescue Errno::ECHILD
|
16
|
-
|
17
|
-
# TODO: It'd be a nice optimisation to actually die here, and
|
18
|
-
# optionally start a worker if we're the first child
|
19
|
-
sleep 5
|
20
|
-
next
|
22
|
+
nil
|
21
23
|
end
|
22
|
-
|
23
|
-
|
24
|
+
$build_queue.bump! if $build_queue && @active
|
25
|
+
end
|
26
|
+
end
|
24
27
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
def handle(pid, status)
|
29
|
+
build = $build_queue.get_build_by_pid(pid)
|
30
|
+
|
31
|
+
if status == 0
|
32
|
+
build.success!
|
33
|
+
else
|
34
|
+
build.failure!
|
31
35
|
end
|
36
|
+
$build_queue.bump! if $build_queue
|
37
|
+
end
|
38
|
+
|
39
|
+
def shutdown!
|
40
|
+
@active = false
|
32
41
|
end
|
33
42
|
|
34
|
-
|
35
|
-
|
36
|
-
Process.wait2(-1, Process::WNOHANG)
|
43
|
+
def start
|
44
|
+
register_handler
|
37
45
|
end
|
38
46
|
|
39
47
|
end
|
data/public/favicon.ico
ADDED
Binary file
|
Binary file
|
data/public/styles/builds.css
CHANGED
@@ -1,11 +1,62 @@
|
|
1
|
-
.build-
|
2
|
-
:
|
1
|
+
.build-output {
|
2
|
+
font-family: Monaco, Menlo, Consolas, "Courier New", monospace;
|
3
|
+
white-space: pre-wrap;
|
4
|
+
word-wrap: break-word;
|
5
|
+
text-align: left;
|
6
|
+
}
|
3
7
|
|
4
|
-
.
|
5
|
-
|
8
|
+
.dark-background {
|
9
|
+
background-color: black !important;
|
10
|
+
}
|
6
11
|
|
7
|
-
.build-
|
8
|
-
|
12
|
+
.build-output .ansible_none {
|
13
|
+
color: #a8a8a8;
|
14
|
+
}
|
15
|
+
|
16
|
+
.build-output .ansible_1 {
|
17
|
+
color: #ffffff;
|
18
|
+
}
|
19
|
+
|
20
|
+
.build-output .ansible_30 {
|
21
|
+
color: #222222;
|
22
|
+
}
|
23
|
+
.build-output .ansible_31 {
|
24
|
+
color: #a80000;
|
25
|
+
}
|
26
|
+
.build-output .ansible_32 {
|
27
|
+
color: #00a800;
|
28
|
+
}
|
29
|
+
.build-output .ansible_33 {
|
30
|
+
color: #a8a800;
|
31
|
+
}
|
32
|
+
.build-output .ansible_34 {
|
33
|
+
color: #3333a8;
|
34
|
+
}
|
35
|
+
.build-output .ansible_35 {
|
36
|
+
color: #a800a8;
|
37
|
+
}
|
38
|
+
.build-output .ansible_36 {
|
39
|
+
color: #00a8a8;
|
40
|
+
}
|
41
|
+
.build-output .ansible_30.ansible_1 {
|
42
|
+
color: #545454;
|
43
|
+
}
|
44
|
+
.build-output .ansible_31.ansible_1 {
|
45
|
+
color: #ff0054;
|
46
|
+
}
|
47
|
+
.build-output .ansible_32.ansible_1 {
|
48
|
+
color: #00ff54;
|
49
|
+
}
|
50
|
+
.build-output .ansible_33.ansible_1 {
|
51
|
+
color: #ffff54;
|
52
|
+
}
|
53
|
+
.build-output .ansible_34.ansible_1 {
|
54
|
+
color: #5555ff;
|
55
|
+
}
|
56
|
+
.build-output .ansible_35.ansible_1 {
|
57
|
+
color: #ff00ff;
|
58
|
+
}
|
59
|
+
.build-output .ansible_36.ansible_1 {
|
60
|
+
color: #00ffff;
|
61
|
+
}
|
9
62
|
|
10
|
-
.build-heading-started { color: #CC0 }
|
11
|
-
:hover .build-heading-started { color: #CC0 }
|
data/public/styles/juici.css
CHANGED
@@ -1,2 +1,226 @@
|
|
1
|
-
body { padding-top: 60px; }
|
2
|
-
|
1
|
+
body { background: black url(../images/black_denim.png); color: #a8a8a8; font-family: "Monaco"; font-size: 12px; padding-top: 60px; }
|
2
|
+
|
3
|
+
a { color: white; font-weight: bold; }
|
4
|
+
a:hover { color: red; text-decoration: none; }
|
5
|
+
|
6
|
+
.navbar, .navbar-inner, .nav { background: #2dffff !important; border-bottom-color: #00dfe0; }
|
7
|
+
.nav > li > a { color: black !important; text-shadow: none !important; }
|
8
|
+
.nav > li:hover { background-color: #00dfe0; }
|
9
|
+
.nav > li.active > a { background-color: #00dfe0 !important; }
|
10
|
+
.accordion-inner {border-top: none;}
|
11
|
+
.currently-building { white-space: pre-wrap; word-wrap: break-word; }
|
12
|
+
.block-header { font-size: 12px; line-height: 24px; color: black; background-color: #2dffff; font-weight: bold; padding: 0 3px 0 3px; }
|
13
|
+
.builds-header { margin: 10px 0 0 0; }
|
14
|
+
.builds-header--failure { color: #fff; background-color: #c800c9; }
|
15
|
+
.builds-header--success { background-color: #7e9eff; }
|
16
|
+
.project-title { margin-top: 0; }
|
17
|
+
|
18
|
+
/* Builds */
|
19
|
+
.table-flipper { color: white; }
|
20
|
+
.builds { list-style: none; overflow: auto; padding: 0; margin: 0; }
|
21
|
+
.builds a { display: block; font-weight: normal; text-decoration: none; padding: 34px 3px 3px 3px; border-top: 2px solid #000; }
|
22
|
+
|
23
|
+
.recently-built--fail {
|
24
|
+
color: black;
|
25
|
+
background-color: #ff7bff;
|
26
|
+
padding: 16px 3px 3px 3px !important;
|
27
|
+
}
|
28
|
+
|
29
|
+
.recently-built--fail:hover {
|
30
|
+
color: white;
|
31
|
+
background-color: #e100e1;
|
32
|
+
}
|
33
|
+
|
34
|
+
.recently-built--pass {
|
35
|
+
color: white;
|
36
|
+
background-color: #595959;
|
37
|
+
padding: 16px 3px 3px 3px !important;
|
38
|
+
}
|
39
|
+
|
40
|
+
.recently-built-pass:hover {
|
41
|
+
color: white;
|
42
|
+
background-color: #3f3f3f;
|
43
|
+
}
|
44
|
+
|
45
|
+
.submit-build label {
|
46
|
+
font-size: 12px;
|
47
|
+
color: #8091ff;
|
48
|
+
}
|
49
|
+
|
50
|
+
button, .btn {
|
51
|
+
font-size: 12px;
|
52
|
+
font-weight: normal;
|
53
|
+
border: 2px solid rgba(255,255,255,0.25);
|
54
|
+
padding: 5px;
|
55
|
+
border-radius: 0;
|
56
|
+
background: #8091ff !important;
|
57
|
+
text-shadow: none !important;
|
58
|
+
color: #000 !important;
|
59
|
+
font-family: "Monaco";
|
60
|
+
}
|
61
|
+
|
62
|
+
button:hover, .btn:hover {
|
63
|
+
background: red !important;
|
64
|
+
color: #FFF;
|
65
|
+
}
|
66
|
+
|
67
|
+
button:before, button:after, .btn:before, .btn:after {
|
68
|
+
content: " ** ";
|
69
|
+
}
|
70
|
+
|
71
|
+
.build-heading-started {
|
72
|
+
color: #DFFF80;
|
73
|
+
border: 2px dashed #DFFF80;
|
74
|
+
}
|
75
|
+
.build-heading-started:hover {
|
76
|
+
color: #ccff33;
|
77
|
+
border: 2px dashed #ccff33;
|
78
|
+
}
|
79
|
+
|
80
|
+
.build-heading-failed {
|
81
|
+
color: black;
|
82
|
+
background-color: #ff7bff;
|
83
|
+
}
|
84
|
+
.build-heading-failed:hover {
|
85
|
+
color: white;
|
86
|
+
background-color: #e100e1;
|
87
|
+
}
|
88
|
+
|
89
|
+
.build-heading-success {
|
90
|
+
color: white;
|
91
|
+
background: #8091ff;
|
92
|
+
}
|
93
|
+
.build-heading-success:hover {
|
94
|
+
color: white;
|
95
|
+
background-color: #334fff;
|
96
|
+
}
|
97
|
+
|
98
|
+
.build-heading-pending { color: gray; }
|
99
|
+
.build-heading-pending:hover { color: gray; }
|
100
|
+
|
101
|
+
.build-sidebar {
|
102
|
+
height: 48px;
|
103
|
+
}
|
104
|
+
|
105
|
+
.build-sidebar > span {
|
106
|
+
float: left;
|
107
|
+
}
|
108
|
+
|
109
|
+
.build-sidebar > span > form > button {
|
110
|
+
margin-left: 10px;
|
111
|
+
margin-right: 10px;
|
112
|
+
}
|
113
|
+
|
114
|
+
.build-output {
|
115
|
+
padding: 20px;
|
116
|
+
background-color: black;
|
117
|
+
border: 1px solid #2dffff;
|
118
|
+
box-shadow: 0 0 2px #2dffff;
|
119
|
+
border-radius: 3px;
|
120
|
+
}
|
121
|
+
|
122
|
+
.bloop {
|
123
|
+
color: transparent;
|
124
|
+
text-decoration: none;
|
125
|
+
font-size: 12px;
|
126
|
+
font-weight: normal;
|
127
|
+
display: block;
|
128
|
+
height: 79px;
|
129
|
+
width: 20px;
|
130
|
+
margin: 3px auto 0 auto;
|
131
|
+
background-color: #ff7bff;
|
132
|
+
}
|
133
|
+
.bloop:hover, .bloop.active { color: transparent; background-color: #c800c9; }
|
134
|
+
|
135
|
+
.disclosure { display: inline-block; width: 20px; }
|
136
|
+
.link-to-build { padding: 10px 0 10px 0; }
|
137
|
+
|
138
|
+
.bowlG{
|
139
|
+
margin-top: 2px;
|
140
|
+
position:relative;
|
141
|
+
width:14px;
|
142
|
+
height:14px;
|
143
|
+
}
|
144
|
+
|
145
|
+
.bowl_ringG{
|
146
|
+
position:absolute;
|
147
|
+
width:14px;
|
148
|
+
height:14px;
|
149
|
+
border:1px solid #DFFF80;
|
150
|
+
-moz-border-radius:14px;
|
151
|
+
-webkit-border-radius:14px;
|
152
|
+
border-radius:14px;
|
153
|
+
box-shadow: 0 0 3px #DFFF80;
|
154
|
+
}
|
155
|
+
|
156
|
+
.ball_holderG{
|
157
|
+
position:absolute;
|
158
|
+
width:4px;
|
159
|
+
height:14px;
|
160
|
+
left:5px;
|
161
|
+
top:0px;
|
162
|
+
-webkit-animation-name:ball_moveG;
|
163
|
+
-webkit-animation-duration:1.8s;
|
164
|
+
-webkit-animation-iteration-count:infinite;
|
165
|
+
-webkit-animation-timing-function:linear;
|
166
|
+
-moz-animation-name:ball_moveG;
|
167
|
+
-moz-animation-duration:1.8s;
|
168
|
+
-moz-animation-iteration-count:infinite;
|
169
|
+
-moz-animation-timing-function:linear;
|
170
|
+
-o-animation-name:ball_moveG;
|
171
|
+
-o-animation-duration:1.8s;
|
172
|
+
-o-animation-iteration-count:infinite;
|
173
|
+
-o-animation-timing-function:linear;
|
174
|
+
-ms-animation-name:ball_moveG;
|
175
|
+
-ms-animation-duration:1.8s;
|
176
|
+
-ms-animation-iteration-count:infinite;
|
177
|
+
-ms-animation-timing-function:linear;
|
178
|
+
}
|
179
|
+
|
180
|
+
.ballG{
|
181
|
+
position:absolute;
|
182
|
+
left:0px;
|
183
|
+
top:-3px;
|
184
|
+
width:6px;
|
185
|
+
height:6px;
|
186
|
+
background:#DFFF80;
|
187
|
+
-moz-border-radius:5px;
|
188
|
+
-webkit-border-radius:5px;
|
189
|
+
border-radius:5px;
|
190
|
+
box-shadow: 0 0 3px #DFFF80;
|
191
|
+
}
|
192
|
+
|
193
|
+
@-webkit-keyframes ball_moveG{
|
194
|
+
0%{
|
195
|
+
-webkit-transform:rotate(0deg)}
|
196
|
+
|
197
|
+
100%{
|
198
|
+
-webkit-transform:rotate(360deg)}
|
199
|
+
|
200
|
+
}
|
201
|
+
|
202
|
+
@-moz-keyframes ball_moveG{
|
203
|
+
0%{
|
204
|
+
-moz-transform:rotate(0deg)}
|
205
|
+
|
206
|
+
100%{
|
207
|
+
-moz-transform:rotate(360deg)}
|
208
|
+
|
209
|
+
}
|
210
|
+
|
211
|
+
@-o-keyframes ball_moveG{
|
212
|
+
0%{
|
213
|
+
-o-transform:rotate(0deg)}
|
214
|
+
|
215
|
+
100%{
|
216
|
+
-o-transform:rotate(360deg)}
|
217
|
+
|
218
|
+
}
|
219
|
+
|
220
|
+
@-ms-keyframes ball_moveG{
|
221
|
+
0%{
|
222
|
+
-ms-transform:rotate(0deg)}
|
223
|
+
|
224
|
+
100%{
|
225
|
+
-ms-transform:rotate(360deg)}
|
226
|
+
}
|