juici 0.0.0.alpha1 → 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -2,13 +2,11 @@ PATH
|
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
4
|
juici (0.0.0)
|
5
|
-
ansible
|
6
5
|
bson_ext
|
7
6
|
github-markdown
|
8
7
|
json
|
9
|
-
mongoid
|
8
|
+
mongoid (~> 2)
|
10
9
|
sinatra
|
11
|
-
thin
|
12
10
|
|
13
11
|
GEM
|
14
12
|
remote: http://rubygems.org/
|
@@ -19,28 +17,24 @@ GEM
|
|
19
17
|
activesupport (3.2.8)
|
20
18
|
i18n (~> 0.6)
|
21
19
|
multi_json (~> 1.0)
|
22
|
-
ansible (0.2.0)
|
23
20
|
bson (1.7.0)
|
24
21
|
bson_ext (1.7.0)
|
25
22
|
bson (~> 1.7.0)
|
26
|
-
builder (3.0.
|
27
|
-
daemons (1.1.9)
|
23
|
+
builder (3.0.3)
|
28
24
|
diff-lcs (1.1.3)
|
29
|
-
|
30
|
-
github-markdown (0.5.3)
|
25
|
+
github-markdown (0.5.1)
|
31
26
|
i18n (0.6.1)
|
32
27
|
json (1.7.5)
|
33
28
|
metaclass (0.0.1)
|
34
29
|
mocha (0.11.4)
|
35
30
|
metaclass (~> 0.0.1)
|
36
|
-
|
31
|
+
mongo (1.7.0)
|
32
|
+
bson (~> 1.7.0)
|
33
|
+
mongoid (2.5.0)
|
37
34
|
activemodel (~> 3.1)
|
38
|
-
|
39
|
-
origin (~> 1.0)
|
35
|
+
mongo (~> 1.7)
|
40
36
|
tzinfo (~> 0.3.22)
|
41
|
-
|
42
|
-
multi_json (1.3.7)
|
43
|
-
origin (1.0.10)
|
37
|
+
multi_json (1.3.6)
|
44
38
|
rack (1.4.1)
|
45
39
|
rack-protection (1.2.0)
|
46
40
|
rack
|
@@ -57,12 +51,8 @@ GEM
|
|
57
51
|
rack (~> 1.3, >= 1.3.6)
|
58
52
|
rack-protection (~> 1.2)
|
59
53
|
tilt (~> 1.3, >= 1.3.3)
|
60
|
-
thin (1.5.0)
|
61
|
-
daemons (>= 1.0.9)
|
62
|
-
eventmachine (>= 0.12.6)
|
63
|
-
rack (>= 1.0.0)
|
64
54
|
tilt (1.3.3)
|
65
|
-
tzinfo (0.3.
|
55
|
+
tzinfo (0.3.33)
|
66
56
|
|
67
57
|
PLATFORMS
|
68
58
|
ruby
|
data/README.md
CHANGED
@@ -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/Rakefile
CHANGED
@@ -1,33 +1,9 @@
|
|
1
1
|
require 'rake'
|
2
2
|
require 'rspec/core/rake_task'
|
3
3
|
|
4
|
-
require 'juici/database'
|
5
|
-
|
6
4
|
RSpec::Core::RakeTask.new(:spec) do |t|
|
7
5
|
t.pattern = "spec/**/*_spec.rb"
|
8
6
|
end
|
9
7
|
|
10
8
|
desc 'Default: run specs'
|
11
9
|
task :default => :spec
|
12
|
-
|
13
|
-
namespace :db do
|
14
|
-
desc "Destroy the test db specified in mongoid.yml"
|
15
|
-
task :destroy do
|
16
|
-
Juici::Database.initialize!
|
17
|
-
Mongoid.purge!
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
desc "Build all gems"
|
22
|
-
task :gems do
|
23
|
-
%w[juici juici-interface].each do |gem|
|
24
|
-
`gem build #{gem}.gemspec`
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
desc "Delete all built gems"
|
29
|
-
task :clean do
|
30
|
-
Dir["juici-*.gem"].each do |gem|
|
31
|
-
File.unlink(gem)
|
32
|
-
end
|
33
|
-
end
|
data/config/mongoid.yml.sample
CHANGED
@@ -1,25 +1,10 @@
|
|
1
1
|
development:
|
2
|
-
|
3
|
-
|
4
|
-
database: juici
|
5
|
-
hosts:
|
6
|
-
- localhost:27017
|
2
|
+
database: juici
|
3
|
+
host: localhost
|
7
4
|
|
8
5
|
production:
|
9
|
-
|
10
|
-
|
11
|
-
database: juici
|
12
|
-
hosts:
|
13
|
-
- localhost:27017
|
14
|
-
|
15
|
-
test:
|
16
|
-
sessions:
|
17
|
-
default:
|
18
|
-
database: juici-test
|
19
|
-
hosts:
|
20
|
-
- localhost:27017
|
6
|
+
database: juici
|
7
|
+
host: localhost
|
21
8
|
|
22
9
|
heroku:
|
23
|
-
|
24
|
-
default:
|
25
|
-
uri: <%= ENV['MONGOLAB_URI'] %>
|
10
|
+
uri: <%= ENV['MONGOLAB_URI'] %>
|
data/juici.gemspec
CHANGED
@@ -1,10 +1,8 @@
|
|
1
1
|
# vim: ft=ruby
|
2
|
-
#
|
3
|
-
require File.expand_path("../lib/juici/version", __FILE__)
|
4
2
|
|
5
3
|
Gem::Specification.new do |s|
|
6
4
|
s.name = "juici"
|
7
|
-
s.version =
|
5
|
+
s.version = "0.0.0"
|
8
6
|
s.authors = ["Richo Healey"]
|
9
7
|
s.email = ["richo@psych0tik.net"]
|
10
8
|
s.homepage = "http://github.com/richo/juici"
|
@@ -12,12 +10,10 @@ Gem::Specification.new do |s|
|
|
12
10
|
s.description = s.summary
|
13
11
|
|
14
12
|
s.add_dependency "sinatra"
|
15
|
-
s.add_dependency "thin"
|
16
13
|
s.add_dependency "json"
|
17
|
-
s.add_dependency "mongoid"
|
14
|
+
s.add_dependency "mongoid", "~> 2"
|
18
15
|
s.add_dependency "bson_ext"
|
19
16
|
s.add_dependency "github-markdown"
|
20
|
-
s.add_dependency "ansible"
|
21
17
|
|
22
18
|
s.add_development_dependency "rake"
|
23
19
|
s.add_development_dependency "mocha"
|
@@ -25,7 +21,7 @@ Gem::Specification.new do |s|
|
|
25
21
|
|
26
22
|
s.files = `git ls-files`.split("\n")
|
27
23
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
28
|
-
s.executables =
|
24
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
29
25
|
s.require_paths = ["lib"]
|
30
26
|
end
|
31
27
|
|
data/lib/juici.rb
CHANGED
@@ -1,17 +1,12 @@
|
|
1
|
+
require 'mongo'
|
2
|
+
require 'mongoid'
|
1
3
|
require 'github/markdown'
|
2
|
-
require 'ansible'
|
3
4
|
|
4
5
|
ENV['RACK_ENV'] ||= "development"
|
5
6
|
|
6
7
|
module Juici
|
7
8
|
def self.dbgp(*args)
|
8
|
-
|
9
|
-
$stderr.puts(args)
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
def self.env
|
14
|
-
ENV['JUICI_ENV'] || ENV['RACK_ENV']
|
9
|
+
ENV['JUICY_DEBUG'] && $stderr.puts(args)
|
15
10
|
end
|
16
11
|
end
|
17
12
|
|
data/lib/juici/app.rb
CHANGED
@@ -8,20 +8,31 @@ module Juici
|
|
8
8
|
|
9
9
|
def self.shutdown
|
10
10
|
::Juici.dbgp "Shutting down Juici"
|
11
|
-
|
11
|
+
@@watchers.each do |watcher|
|
12
|
+
::Juici.dbgp "Killing #{watcher.inspect}"
|
13
|
+
watcher.kill
|
14
|
+
watcher.join
|
15
|
+
::Juici.dbgp "Dead: #{watcher.inspect}"
|
16
|
+
end
|
12
17
|
|
13
18
|
shutdown_build_queue
|
14
19
|
end
|
15
20
|
|
16
21
|
attr_reader :opts
|
17
22
|
def initialize(opts={})
|
18
|
-
Database.initialize!
|
19
23
|
@opts = opts
|
20
|
-
|
21
|
-
|
24
|
+
# NOTE: this happening before we start a build queue is important, it
|
25
|
+
# means we can't start any more workers and get tied in knots
|
26
|
+
# clear_stale_children
|
27
|
+
#
|
28
|
+
# Urgh
|
22
29
|
init_build_queue
|
23
30
|
reload_unfinished_work
|
24
|
-
|
31
|
+
start_workers
|
32
|
+
end
|
33
|
+
|
34
|
+
def spawn_watcher
|
35
|
+
@@watchers << Watcher.start!
|
25
36
|
end
|
26
37
|
|
27
38
|
private
|
@@ -40,28 +51,21 @@ module Juici
|
|
40
51
|
# Ensure that any killed builds will be retried
|
41
52
|
end
|
42
53
|
|
43
|
-
def
|
44
|
-
|
54
|
+
def start_workers
|
55
|
+
no_workers = opts[:workers] || 1
|
56
|
+
warn "More than 1 worker is liable to do strange things" if no_workers > 1
|
57
|
+
no_workers.times do
|
58
|
+
spawn_watcher
|
59
|
+
end
|
45
60
|
end
|
46
61
|
|
47
62
|
def reload_unfinished_work
|
48
63
|
# At this point no workers have started yet, we can safely assume that
|
49
64
|
# :started means aborted
|
50
|
-
Build.where(:status =>
|
65
|
+
Build.where(:status.in => [:started, :waiting]).each do |build|
|
51
66
|
$build_queue << build
|
52
67
|
end
|
53
68
|
end
|
54
69
|
|
55
|
-
def reset_stale_children
|
56
|
-
Build.where(:status => Juici::BuildStatus::START).each do |build|
|
57
|
-
build[:status] = Juici::BuildStatus::WAIT
|
58
|
-
build.save!
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
def start_queue
|
63
|
-
$build_queue.start!
|
64
|
-
end
|
65
|
-
|
66
70
|
end
|
67
71
|
end
|
data/lib/juici/build_logic.rb
CHANGED
@@ -1,20 +1,11 @@
|
|
1
1
|
require 'fileutils'
|
2
2
|
require 'tempfile'
|
3
3
|
module Juici
|
4
|
-
|
4
|
+
module BuildLogic
|
5
5
|
|
6
6
|
def spawn_build
|
7
7
|
raise "No such work tree" unless FileUtils.mkdir_p(worktree)
|
8
8
|
spawn(command, worktree)
|
9
|
-
rescue AbortBuild
|
10
|
-
:buildaborted
|
11
|
-
end
|
12
|
-
|
13
|
-
def kill!
|
14
|
-
warn! "Killed!"
|
15
|
-
if pid = self[:pid]
|
16
|
-
Process.kill(15, pid)
|
17
|
-
end
|
18
9
|
end
|
19
10
|
|
20
11
|
private
|
data/lib/juici/build_queue.rb
CHANGED
@@ -9,7 +9,6 @@ module Juici
|
|
9
9
|
@child_pids = []
|
10
10
|
# This is never expired, for now
|
11
11
|
@builds_by_pid = {}
|
12
|
-
@started = false
|
13
12
|
end
|
14
13
|
|
15
14
|
def shutdown!
|
@@ -40,28 +39,17 @@ module Juici
|
|
40
39
|
end
|
41
40
|
end
|
42
41
|
|
43
|
-
def delete(id)
|
44
|
-
purge(:_id, OpenStruct.new(:_id => id))
|
45
|
-
end
|
46
|
-
|
47
42
|
# Magic hook that starts a process if there's a good reason to.
|
48
43
|
# Stopgap measure that means you can knock on this if there's a chance we
|
49
44
|
# should start a process
|
50
45
|
def bump!
|
51
|
-
return unless @started
|
52
46
|
update_children
|
53
47
|
if not_working? && work_to_do?
|
54
48
|
Juici.dbgp "Starting another child process"
|
55
49
|
next_child.tap do |child|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
@builds_by_pid[pid] = child
|
60
|
-
else
|
61
|
-
Juici.dbgp "Child #{child} failed to start"
|
62
|
-
bump! # Ruby's recursion isn't great, but re{try,do} may as well be
|
63
|
-
# undefined behaviour here.
|
64
|
-
end
|
50
|
+
pid = child.build!
|
51
|
+
@child_pids << pid
|
52
|
+
@builds_by_pid[pid] = child
|
65
53
|
end
|
66
54
|
else
|
67
55
|
Juici.dbgp "I have quite enough to do"
|
@@ -92,20 +80,5 @@ module Juici
|
|
92
80
|
@builds.length > 0
|
93
81
|
end
|
94
82
|
|
95
|
-
def currently_building
|
96
|
-
@child_pids.map do |pid|
|
97
|
-
get_build_by_pid(pid)
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
def start!
|
102
|
-
@started = true
|
103
|
-
bump!
|
104
|
-
end
|
105
|
-
|
106
|
-
def builds
|
107
|
-
@builds
|
108
|
-
end
|
109
|
-
|
110
83
|
end
|
111
84
|
end
|
data/lib/juici/callback.rb
CHANGED
@@ -2,24 +2,20 @@ require 'net/http'
|
|
2
2
|
module Juici
|
3
3
|
class Callback
|
4
4
|
|
5
|
-
attr_reader :url
|
6
|
-
attr_accessor :payload
|
5
|
+
attr_reader :build, :url
|
7
6
|
|
8
|
-
def initialize(
|
7
|
+
def initialize(build, url)
|
8
|
+
@build = build
|
9
9
|
@url = URI(url)
|
10
|
-
@payload = pl if pl
|
11
10
|
end
|
12
11
|
|
13
12
|
def process!
|
14
13
|
Net::HTTP.start(url.host, url.port) do |http|
|
15
14
|
request = Net::HTTP::Post.new(url.request_uri)
|
16
|
-
request.body =
|
15
|
+
request.body = build.to_callback_json
|
17
16
|
|
18
|
-
http.request request # Net::HTTPResponse object
|
17
|
+
response = http.request request # Net::HTTPResponse object
|
19
18
|
end
|
20
|
-
rescue SocketError => e
|
21
|
-
# We don't get a reference to build any more, can't warn :(
|
22
|
-
# TODO Throw a warning on the build
|
23
19
|
end
|
24
20
|
|
25
21
|
end
|