juici 0.0.0.alpha1 → 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. data/Gemfile +1 -4
  2. data/Gemfile.lock +9 -19
  3. data/README.md +6 -45
  4. data/Rakefile +0 -24
  5. data/config/mongoid.yml.sample +5 -20
  6. data/juici.gemspec +3 -7
  7. data/lib/juici.rb +3 -8
  8. data/lib/juici/app.rb +23 -19
  9. data/lib/juici/build_environment.rb +1 -1
  10. data/lib/juici/build_logic.rb +1 -10
  11. data/lib/juici/build_queue.rb +3 -30
  12. data/lib/juici/callback.rb +5 -9
  13. data/lib/juici/config.rb +0 -4
  14. data/lib/juici/controllers/build_controller.rb +0 -0
  15. data/lib/juici/controllers/{trigger.rb → trigger_controller.rb} +5 -24
  16. data/lib/juici/database.rb +13 -19
  17. data/lib/juici/helpers/url_helpers.rb +0 -28
  18. data/lib/juici/models/build.rb +24 -81
  19. data/lib/juici/models/project.rb +1 -1
  20. data/lib/juici/server.rb +40 -103
  21. data/lib/juici/url_helpers.rb +15 -0
  22. data/lib/juici/views/README.markdown +6 -45
  23. data/lib/juici/views/about.erb +5 -5
  24. data/lib/juici/views/builds/list.erb +33 -26
  25. data/lib/juici/views/builds/new.erb +37 -42
  26. data/lib/juici/views/builds/show.erb +28 -4
  27. data/lib/juici/views/index.erb +13 -30
  28. data/lib/juici/views/layout.erb +13 -22
  29. data/lib/juici/views/partials/builds/debug.erb +18 -12
  30. data/lib/juici/watcher.rb +25 -33
  31. data/public/styles/builds.css +8 -59
  32. data/public/styles/juici.css +2 -226
  33. data/spec/build_callback_spec.rb +1 -46
  34. data/spec/build_process_spec.rb +5 -71
  35. data/spec/build_queue_spec.rb +1 -3
  36. data/spec/juici_app_spec.rb +15 -0
  37. data/spec/spec_helper.rb +0 -13
  38. metadata +12 -76
  39. data/.gitignore +0 -2
  40. data/bin/juicic +0 -54
  41. data/juici-interface.gemspec +0 -19
  42. data/lib/juici/controllers.rb +0 -6
  43. data/lib/juici/controllers/base.rb +0 -26
  44. data/lib/juici/controllers/build_queue.rb +0 -14
  45. data/lib/juici/controllers/builds.rb +0 -74
  46. data/lib/juici/controllers/index.rb +0 -20
  47. data/lib/juici/exceptions.rb +0 -2
  48. data/lib/juici/find_logic.rb +0 -11
  49. data/lib/juici/helpers/form_helpers.rb +0 -11
  50. data/lib/juici/helpers/html_helpers.rb +0 -4
  51. data/lib/juici/interface.rb +0 -13
  52. data/lib/juici/version.rb +0 -8
  53. data/lib/juici/views/builds/edit.erb +0 -23
  54. data/lib/juici/views/not_found.erb +0 -3
  55. data/lib/juici/views/partials/builds/output.erb +0 -1
  56. data/lib/juici/views/partials/builds/show.erb +0 -19
  57. data/lib/juici/views/partials/builds/sidebar.erb +0 -13
  58. data/lib/juici/views/partials/index/recently_built.erb +0 -19
  59. data/lib/juici/views/queue/list.erb +0 -6
  60. data/public/favicon.ico +0 -0
  61. data/public/images/black_denim.png +0 -0
  62. data/public/vendor/bootstrap.css +0 -6004
  63. data/public/vendor/bootstrap.js +0 -2036
  64. data/public/vendor/img/glyphicons-halflings-white.png +0 -0
  65. data/public/vendor/jquery.js +0 -9440
  66. data/script/cibuild +0 -10
  67. data/spec/controllers/builds_spec.rb +0 -68
  68. data/spec/controllers/index_spec.rb +0 -28
  69. data/spec/models/build_spec.rb +0 -54
@@ -0,0 +1,15 @@
1
+ # So this is pretty much just horrific, but at least an interestingish
2
+ # proof of concept
3
+ # XXX Deprecated
4
+ module Juici
5
+ def self.url_helpers(route)
6
+ Module.new do
7
+ @@route = route
8
+
9
+ def url_for(child)
10
+ "/#{@@route}/#{child}"
11
+ end
12
+
13
+ end
14
+ end
15
+ end
@@ -13,8 +13,8 @@ It's designed to work well with [agent99](https://github.com/99designs/agent99)
13
13
 
14
14
  ## Important but Miscellaneous
15
15
 
16
- If you create child processes in modules/plugins then you need to register your
17
- disinterest or JuiCI will think they're builds and that would be bad.
16
+ If you create child process in modules/plugins then you need to register your
17
+ disinterest or JuiCI will think they're builds and that would be bad
18
18
 
19
19
  ## Setup
20
20
 
@@ -27,26 +27,12 @@ bundle exec bin/juici
27
27
 
28
28
  is all you need to have a working instance (provided that you have mongo installed)
29
29
 
30
- ### Gotchas
31
-
32
- Make sure you don't do something innocuous like
33
-
34
- ```bash
35
- bundle install --path .bundle
36
- ```
37
-
38
- this might look sane (and it is, kinda) but owing to a quick in bundler, it
39
- will break any ruby code you try to build.
40
-
41
- I'm working on a workaround, but in the meantime the fix is to not do it!
42
-
43
30
  ## Usage
44
31
 
45
- JuiCI is very focused on minimal configuration; meaning that beyond starting
46
- the server and pointing it at a mongoDB instance, you do not need to do
47
- anything special to build a new project. Just request a build; however this
48
- means that on your first build you will need to send the commands to create
49
- your test environment)
32
+ JuiCI chooses to be very "Mongo" (which is an adjective now), in that you don't
33
+ need to formally create a project. Just request a build; however this means
34
+ that on your first build you will need to send the commands to create your test
35
+ environment)
50
36
 
51
37
  Example:
52
38
 
@@ -81,20 +67,6 @@ called with an (as yet unformalised) json body as the body if/when the build
81
67
  reaches that state. Alternately you may specify "any" as the callback state and
82
68
  it will be called on all state changes.
83
69
 
84
- ## Integration
85
-
86
- Apps written in ruby wanting to interact with Juici can include the
87
- `juici-interface` gem, which presently exposes a few constants to line up with
88
- JuiCI's internal state.
89
- Over time this will be expanded, but for now they are:
90
-
91
- ```ruby
92
- Juici::BuildStatus::PASS
93
- Juici::BuildStatus::FAIL
94
- Juici::BuildStatus::START
95
- Juici::BuildStatus::WAIT
96
- ```
97
-
98
70
  ## Security
99
71
 
100
72
  JuiCI poses some interesting security conecerns. First off, it will allow
@@ -120,19 +92,8 @@ specifically implement it, your process won't see any of the signal handling
120
92
  madness. The shell(`/bin/sh`) will see everything, and if killed, your
121
93
  processes will become orphaned, but carry on.
122
94
 
123
- ## Authors
124
-
125
- * [Richo Healey](https://github.com/rcho)
126
- * [Alec Sloman](https://github.com/alecsloman)
127
-
128
95
  ## Contact
129
96
 
130
97
  JuiCI's code lives on [Github](https://github.com/richo/juici)
131
98
  and the [author](mailto:richo@psych0tik.net) can be contacted on
132
99
  [Twitter](https://twitter.com/rich0H)
133
-
134
- ## Legalese
135
-
136
- (c) Richo Healey 2012, richo@psych0tik.net
137
-
138
- Released under the terms of the MIT license.
@@ -1,12 +1,12 @@
1
- <div class="row-fluid">
2
- <div class="span9">
1
+ <div class="row">
2
+ <div class="span8">
3
3
  <div>
4
- <%= content %>
4
+ <%= GitHub::Markdown.render(File.read("lib/juici/views/README.markdown")) %>
5
5
  </div>
6
6
  </div>
7
- <div class="span2 offset1">
7
+ <div class="span4">
8
8
  <div>
9
- <h3 class="block-header builds-header--failure">quick links</h3>
9
+ <p>Quick Links</p>
10
10
  <ul>
11
11
  <li>richo on <a href="https://twitter.com/rich0H">twitter</a></li>
12
12
  <li>richo on <a href="https://github.com/richo">github</a></li>
@@ -1,27 +1,34 @@
1
- <script>
2
- $(function() {
3
- $('.accordion-set-url').on('click', '.set-url', function() {
4
- history.pushState(null, null, $(this).data('url'));
5
- })
6
- });
7
- </script>
8
-
9
- <div class="row-fluid">
10
- <!-- Pagination -->
11
- <div class="span1">
12
- <% pages.times.with_index do |page| %>
13
- <a href="?page=<%= page %>" class="bloop<%= " active" if page == params[:page] %>"><%= page %></a>
14
- <% end %>
15
- </div>
16
- <!-- Main contents -->
17
- <div class="span11">
18
- <!-- Create a new build -->
19
- <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>
20
- <!-- Build history -->
21
- <% builds.each_with_index do |build, idx| %>
22
- <div class="accordion accordion-set-url" id="accordion<%= idx %>">
23
- <%= erb(:"partials/builds/show", :locals => { :build => build, :idx => idx }) %>
1
+ <% if proj = ::Juici::Project.where(name: project).first %>
2
+ <script>
3
+ $(document).ready(function() {
4
+ $(".collapse").collapse();
5
+ });
6
+ </script>
7
+ <h3><em><%= proj.name %></em> - <a href="/builds/new?project=<%= proj.name %>"><em>New Build</em></a></h3>
8
+ <% ::Juici::Build.where(parent: proj.name).sort.reverse.each_with_index do |build, idx| %>
9
+ <div class="accordion" id="accordion<%= idx %>">
10
+ <div class="accordion-heading">
11
+ <a class="accordion-toggle <%= build.heading_color %>" data-toggle="collapse" data-parent="#accordion<%= idx+1 %>" href="#collapse_<%= idx %>">
12
+ <%= build.display_title %>&nbsp;<% build[:warnings].each do |warning| %><span class="label label-important"><%= warning %></span><% end %>
13
+ </a>
24
14
  </div>
25
- <% end %>
26
- </div>
27
- </div>
15
+ <div id="collapse_<%= idx %>" class="accordion-body collapse in">
16
+ <div class="row">
17
+ <div class="span8">
18
+ <div>
19
+ <a href="<%= build_url_for(build) %>">Link to this build</a>
20
+ </div>
21
+ <div class="accordion-inner build-output">
22
+ <%= build.output if build.respond_to? :output %>
23
+ </div>
24
+ </div>
25
+ <div class="span4">
26
+ <%= erb(:"partials/builds/debug", :locals => { :build => build }) %>
27
+ </div>
28
+ </div>
29
+ </div>
30
+ </div>
31
+ <% end %>
32
+ <% else %>
33
+ No such project.
34
+ <% end %>
@@ -1,43 +1,38 @@
1
- <div class="row-fluid">
2
-
3
- <div class="span4">
4
- <%= erb(:"partials/index/recently_built") %>
5
- </div>
6
-
7
- <div class="span8">
8
-
9
- <h1 class="block-header">new</h1>
10
- <p>From here you can create a new build</p>
11
- <p>Name is a unique identifier for the project. It doesn't need to already exist, but builds for a like project need to be named identically</p>
12
- <p>Environment is a json hash of KEY - VALUE pairs, to be passed into the child environment</p>
13
- <p>Command is where the magic happens. Often they'll be longwinded, but a reasonable boilerplate might look <a href="#">something like this.</a><p>
14
- <hr>
15
-
16
- <form action="/builds/new" method="post" class="submit-build">
17
-
18
- <div class="row-fluid">
19
-
20
- <!-- First Column -->
21
- <div class="span3">
22
- <label>Project Name</label>
23
- <input type="text" name="project" value="<%= params[:project] %>" <%= "readonly" if params[:project] %>>
24
- <label>Environment</label>
25
- <input type="text" name="environment" placeholder="expects a valid json hash" value="">
26
- <label>Priority</label>
27
- <input type="text" name="priority" value="1">
28
- </div><!-- End first column -->
29
-
30
- <div class="span8 offset1">
31
- <label>Command</label>
32
- <textarea name="command" class="input-xxlarge" rows="4"></textarea>
33
- <%# TODO -> When callbacks get implemented %>
34
- <%# <label>Callback URL</label> %>
35
- <%# <input type="text" name="callback" class="span3"> %>
36
- <!-- <label><%# HACK %></label> -->
37
- <button type="submit">START BUILD</button>
38
- </div>
39
-
40
- </div>
41
- </form>
42
- </div>
1
+ <div class="row">
2
+ <div class="span6">
3
+ <form class="well" action="/builds/new" method="post">
4
+ <label>Project Name</label>
5
+ <input type="text" name="project" class="span3" value="<%= params[:project] %>" <%= "readonly" if params[:project] %>>
6
+ <label>Environment</label>
7
+ <input type="text" name="environment" class="span3" value="">
8
+ <span class="help-block">nb: Expects a valid json hash</span>
9
+ <label>Priority</label>
10
+ <input type="text" name="priority" class="span3" value="1">
11
+ <label>Command</label>
12
+ <textarea name="command" class="span3"></textarea>
13
+ <%# TODO -> When callbacks get implemented %>
14
+ <%# <label>Callback URL</label> %>
15
+ <%# <input type="text" name="callback" class="span3"> %>
16
+ <label><%# HACK %></label>
17
+ <button type="submit" class="btn">Submit</button>
18
+ </form>
19
+ </div>
20
+ <div class="span6">
21
+ <p>From here you can create a new build</p>
22
+ <p>Name is a unique identifier for the project. It doesn't need to already exist, but builds for a like project need to be named identically</p>
23
+ <p>Environment is a json hash of KEY - VALUE pairs, to be passed into the child environment</p>
24
+ <p>Command is where the magic happens. Often they'll be longwinded, but a reasonable boilerplate might look something like<p>
25
+ <pre class="prettyprint linenums">
26
+ if [ ! -d .git ]; then
27
+ git init .
28
+ git remote add origin git://github.com/$user/$project.git
29
+ fi
30
+
31
+ git fetch origin
32
+ git checkout -fq origin/master
33
+
34
+ bundle install --path .bundle
35
+ bundle exec rake spec
36
+ </pre>
37
+ </div>
43
38
  </div>
@@ -1,4 +1,28 @@
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>
1
+ <% if proj = ::Juici::Project.where(name: project).first %>
2
+ <h3><em><%= proj.name %></em> - <a href="/builds/new?project=<%= proj.name %>"><em>New Build</em></a></h3>
3
+ <% build =::Juici::Build.where(parent: proj.name, _id: id).first %>
4
+ <div class="accordion" id="accordion0">
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 %>&nbsp;<% 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,30 +1,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>
1
+ <h1>JuiCI</h1>
2
+ <p>
3
+ 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.
4
+ </p>
5
+ <p>
6
+ 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.
7
+ </p>
8
+ <p>
9
+ In the past, this instance of Juici has built code for:
10
+ <ul><% ::Juici::Project.all.each do |p| %>
11
+ <li><a href="<%= build_url_for(p) %>"><%= p.name %></a></li>
12
+ <% end %></ul>
13
+ </p>
@@ -1,43 +1,34 @@
1
1
  <!doctype html>
2
2
  <html>
3
3
  <head>
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">
11
- <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
12
- <script src="//netdna.bootstrapcdn.com/twitter-bootstrap/2.2.1/js/bootstrap.min.js"></script>
13
- <% end %>
4
+ <link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.1.1/css/bootstrap.min.css" rel="stylesheet">
14
5
  <link href="/styles/juici.css" rel="stylesheet">
15
- <% styles.each do |style| %>
16
- <link href="/styles/<%= style %>.css" rel="stylesheet">
17
- <% end rescue nil%>
6
+ <% if @page # This will 404 a ton of page XXX %>
7
+ <link href="/styles/<%= @page %>.css" rel="stylesheet">
8
+ <% end %>
9
+ <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
10
+ <script src="//netdna.bootstrapcdn.com/twitter-bootstrap/2.1.1/js/bootstrap.min.js"></script>
18
11
  <title>JuiCI</title>
19
12
  <% if @redirect_to %>
20
- <meta http-equiv="Refresh" content="0; url=<%= @redirect_to %>" />
13
+ <meta http-equiv="Refresh" content="0; url=<%= URI.escape(@redirect_to) %>" />
21
14
  <% end %>
22
15
  </head>
23
16
  <body>
24
17
  <div class="navbar navbar-fixed-top">
25
18
  <div class="navbar-inner">
26
- <div class="container-fluid">
19
+ <div class="container">
27
20
  <div class="nav-collapse">
28
21
  <ul class="nav">
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>
22
+ <li class="<%= "active" if @page == :index %>"><a class="brand" href="/">JuiCI</a></li>
23
+ <li class="<%= "active" if @page == :builds && @action == :new %>"><a href="/builds/new">New Build</a></li>
24
+ <li class="<%= "active" if @page == :about %>"><a href="/about">About</a></li>
25
+ <li class="<%= "active" if @page == :support %>"><a href="/support">Support</a></li>
35
26
  </ul>
36
27
  </div><!--/.nav-collapse -->
37
28
  </div>
38
29
  </div>
39
30
  </div>
40
- <div class="container-fluid">
31
+ <div class="container">
41
32
  <%= yield %>
42
33
  </div>
43
34
  </body>
@@ -1,22 +1,28 @@
1
- <div class="debug-output">
1
+ <% if build[:environment] %>
2
+ <h3>Environment:</h3>
3
+ <pre class="prettyprint">
4
+ <% build[:environment].each do |k, v| %>
5
+ <%= "#{k}=#{v}" %>
6
+ <% end %>
7
+ </pre>
8
+ <% end %>
2
9
  <% if build[:priority] %>
3
- <h3 class="block-header">priority:</h3>
10
+ <h3>Priority:</h3>
11
+ <pre class="prettyprint">
4
12
  <%= build[:priority] %>
13
+ </pre>
5
14
  <% end %>
6
15
  <% if build[:command] %>
7
- <h3 class="block-header">command:</h3>
16
+ <h3>Command:</h3>
17
+ <pre class="prettyprint">
8
18
  <%= build[:command] %>
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 %>
19
+ </pre>
15
20
  <% end %>
16
21
  <% if build[:callbacks] %>
17
- <h3 class="block-header">callbacks:</h3>
22
+ <h3>Callbacks:</h3>
23
+ <pre class="prettyprint">
18
24
  <% build[:callbacks].each do |callback| %>
19
- <p><%= callback %><p>
25
+ <%= callback %>
20
26
  <% end %>
27
+ </pre>
21
28
  <% end %>
22
- </div>
@@ -1,47 +1,39 @@
1
1
  module Juici
2
- class Watcher
2
+ class Watcher < Thread
3
3
 
4
- def self.instance
5
- @@instance ||= self.new
6
- end
7
-
8
- def initialize
9
- @active = true
4
+ def self.start!
5
+ new do
6
+ self.mainloop
7
+ end
10
8
  end
11
9
 
12
- def register_handler
13
- Signal.trap("CHLD") do
10
+ def self.mainloop
11
+ #XXX No classvariables ever!
12
+ loop do
14
13
  begin
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
14
+ pid, status = catch_child
21
15
  rescue Errno::ECHILD
22
- nil
16
+ # No children available, sleep for a while until some might exist
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
23
21
  end
24
- $build_queue.bump! if $build_queue && @active
25
- end
26
- end
22
+ next unless pid
23
+ build = $build_queue.get_build_by_pid(pid)
27
24
 
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!
25
+ if status == 0
26
+ build.success!
27
+ else
28
+ build.failure!
29
+ end
30
+ $build_queue.bump! if $build_queue
35
31
  end
36
- $build_queue.bump! if $build_queue
37
- end
38
-
39
- def shutdown!
40
- @active = false
41
32
  end
42
33
 
43
- def start
44
- register_handler
34
+ # Hook for testing
35
+ def self.catch_child
36
+ Process.wait2(-1, Process::WNOHANG)
45
37
  end
46
38
 
47
39
  end