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.
- data/Gemfile +1 -4
- data/Gemfile.lock +9 -19
- data/README.md +6 -45
- data/Rakefile +0 -24
- data/config/mongoid.yml.sample +5 -20
- data/juici.gemspec +3 -7
- data/lib/juici.rb +3 -8
- data/lib/juici/app.rb +23 -19
- data/lib/juici/build_environment.rb +1 -1
- data/lib/juici/build_logic.rb +1 -10
- data/lib/juici/build_queue.rb +3 -30
- data/lib/juici/callback.rb +5 -9
- data/lib/juici/config.rb +0 -4
- data/lib/juici/controllers/build_controller.rb +0 -0
- data/lib/juici/controllers/{trigger.rb → trigger_controller.rb} +5 -24
- data/lib/juici/database.rb +13 -19
- data/lib/juici/helpers/url_helpers.rb +0 -28
- data/lib/juici/models/build.rb +24 -81
- data/lib/juici/models/project.rb +1 -1
- data/lib/juici/server.rb +40 -103
- data/lib/juici/url_helpers.rb +15 -0
- data/lib/juici/views/README.markdown +6 -45
- data/lib/juici/views/about.erb +5 -5
- data/lib/juici/views/builds/list.erb +33 -26
- data/lib/juici/views/builds/new.erb +37 -42
- data/lib/juici/views/builds/show.erb +28 -4
- data/lib/juici/views/index.erb +13 -30
- data/lib/juici/views/layout.erb +13 -22
- data/lib/juici/views/partials/builds/debug.erb +18 -12
- data/lib/juici/watcher.rb +25 -33
- data/public/styles/builds.css +8 -59
- data/public/styles/juici.css +2 -226
- data/spec/build_callback_spec.rb +1 -46
- data/spec/build_process_spec.rb +5 -71
- data/spec/build_queue_spec.rb +1 -3
- data/spec/juici_app_spec.rb +15 -0
- data/spec/spec_helper.rb +0 -13
- metadata +12 -76
- data/.gitignore +0 -2
- data/bin/juicic +0 -54
- data/juici-interface.gemspec +0 -19
- data/lib/juici/controllers.rb +0 -6
- data/lib/juici/controllers/base.rb +0 -26
- data/lib/juici/controllers/build_queue.rb +0 -14
- data/lib/juici/controllers/builds.rb +0 -74
- data/lib/juici/controllers/index.rb +0 -20
- data/lib/juici/exceptions.rb +0 -2
- data/lib/juici/find_logic.rb +0 -11
- data/lib/juici/helpers/form_helpers.rb +0 -11
- data/lib/juici/helpers/html_helpers.rb +0 -4
- data/lib/juici/interface.rb +0 -13
- data/lib/juici/version.rb +0 -8
- data/lib/juici/views/builds/edit.erb +0 -23
- data/lib/juici/views/not_found.erb +0 -3
- data/lib/juici/views/partials/builds/output.erb +0 -1
- data/lib/juici/views/partials/builds/show.erb +0 -19
- data/lib/juici/views/partials/builds/sidebar.erb +0 -13
- data/lib/juici/views/partials/index/recently_built.erb +0 -19
- data/lib/juici/views/queue/list.erb +0 -6
- data/public/favicon.ico +0 -0
- data/public/images/black_denim.png +0 -0
- data/public/vendor/bootstrap.css +0 -6004
- data/public/vendor/bootstrap.js +0 -2036
- data/public/vendor/img/glyphicons-halflings-white.png +0 -0
- data/public/vendor/jquery.js +0 -9440
- data/script/cibuild +0 -10
- data/spec/controllers/builds_spec.rb +0 -68
- data/spec/controllers/index_spec.rb +0 -28
- 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
|
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
|
46
|
-
|
47
|
-
|
48
|
-
|
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.
|
data/lib/juici/views/about.erb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
|
-
<div class="row
|
2
|
-
<div class="
|
1
|
+
<div class="row">
|
2
|
+
<div class="span8">
|
3
3
|
<div>
|
4
|
-
<%=
|
4
|
+
<%= GitHub::Markdown.render(File.read("lib/juici/views/README.markdown")) %>
|
5
5
|
</div>
|
6
6
|
</div>
|
7
|
-
<div class="
|
7
|
+
<div class="span4">
|
8
8
|
<div>
|
9
|
-
<
|
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
|
-
|
2
|
-
|
3
|
-
$(
|
4
|
-
|
5
|
-
})
|
6
|
-
|
7
|
-
</
|
8
|
-
|
9
|
-
<div class="
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
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 %> <% build[:warnings].each do |warning| %><span class="label label-important"><%= warning %></span><% end %>
|
13
|
+
</a>
|
24
14
|
</div>
|
25
|
-
|
26
|
-
|
27
|
-
|
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
|
2
|
-
|
3
|
-
<
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
<
|
10
|
-
<
|
11
|
-
<
|
12
|
-
<
|
13
|
-
|
14
|
-
<
|
15
|
-
|
16
|
-
<
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
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
|
-
|
2
|
-
<
|
3
|
-
|
4
|
-
|
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 %> <% 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 %>
|
data/lib/juici/views/index.erb
CHANGED
@@ -1,30 +1,13 @@
|
|
1
|
-
<
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
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>
|
data/lib/juici/views/layout.erb
CHANGED
@@ -1,43 +1,34 @@
|
|
1
1
|
<!doctype html>
|
2
2
|
<html>
|
3
3
|
<head>
|
4
|
-
<
|
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
|
-
<%
|
16
|
-
<link href="/styles/<%=
|
17
|
-
<% end
|
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
|
19
|
+
<div class="container">
|
27
20
|
<div class="nav-collapse">
|
28
21
|
<ul class="nav">
|
29
|
-
|
30
|
-
<li class="
|
31
|
-
<li class="<%= "active" if
|
32
|
-
<li class="<%= "active" if
|
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
|
31
|
+
<div class="container">
|
41
32
|
<%= yield %>
|
42
33
|
</div>
|
43
34
|
</body>
|
@@ -1,22 +1,28 @@
|
|
1
|
-
|
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
|
10
|
+
<h3>Priority:</h3>
|
11
|
+
<pre class="prettyprint">
|
4
12
|
<%= build[:priority] %>
|
13
|
+
</pre>
|
5
14
|
<% end %>
|
6
15
|
<% if build[:command] %>
|
7
|
-
<h3
|
16
|
+
<h3>Command:</h3>
|
17
|
+
<pre class="prettyprint">
|
8
18
|
<%= build[:command] %>
|
9
|
-
|
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
|
22
|
+
<h3>Callbacks:</h3>
|
23
|
+
<pre class="prettyprint">
|
18
24
|
<% build[:callbacks].each do |callback| %>
|
19
|
-
|
25
|
+
<%= callback %>
|
20
26
|
<% end %>
|
27
|
+
</pre>
|
21
28
|
<% end %>
|
22
|
-
</div>
|
data/lib/juici/watcher.rb
CHANGED
@@ -1,47 +1,39 @@
|
|
1
1
|
module Juici
|
2
|
-
class Watcher
|
2
|
+
class Watcher < Thread
|
3
3
|
|
4
|
-
def self.
|
5
|
-
|
6
|
-
|
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
|
13
|
-
|
10
|
+
def self.mainloop
|
11
|
+
#XXX No classvariables ever!
|
12
|
+
loop do
|
14
13
|
begin
|
15
|
-
|
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
|
-
|
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
|
-
|
25
|
-
|
26
|
-
end
|
22
|
+
next unless pid
|
23
|
+
build = $build_queue.get_build_by_pid(pid)
|
27
24
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
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
|
-
|
44
|
-
|
34
|
+
# Hook for testing
|
35
|
+
def self.catch_child
|
36
|
+
Process.wait2(-1, Process::WNOHANG)
|
45
37
|
end
|
46
38
|
|
47
39
|
end
|