juici 0.0.0 → 0.0.1.alpha1
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/.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
data/.gitignore
ADDED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,40 +1,46 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
juici (0.0.0)
|
|
4
|
+
juici (0.0.0.alpha1)
|
|
5
|
+
ansible
|
|
5
6
|
bson_ext
|
|
6
7
|
github-markdown
|
|
7
8
|
json
|
|
8
|
-
mongoid
|
|
9
|
+
mongoid
|
|
9
10
|
sinatra
|
|
11
|
+
thin
|
|
10
12
|
|
|
11
13
|
GEM
|
|
12
14
|
remote: http://rubygems.org/
|
|
13
15
|
specs:
|
|
14
|
-
activemodel (3.2.
|
|
15
|
-
activesupport (= 3.2.
|
|
16
|
+
activemodel (3.2.9)
|
|
17
|
+
activesupport (= 3.2.9)
|
|
16
18
|
builder (~> 3.0.0)
|
|
17
|
-
activesupport (3.2.
|
|
19
|
+
activesupport (3.2.9)
|
|
18
20
|
i18n (~> 0.6)
|
|
19
21
|
multi_json (~> 1.0)
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
ansible (0.2.0)
|
|
23
|
+
bson (1.7.1)
|
|
24
|
+
bson_ext (1.7.1)
|
|
25
|
+
bson (~> 1.7.1)
|
|
26
|
+
builder (3.0.4)
|
|
27
|
+
daemons (1.1.9)
|
|
24
28
|
diff-lcs (1.1.3)
|
|
25
|
-
|
|
29
|
+
eventmachine (1.0.0)
|
|
30
|
+
github-markdown (0.5.3)
|
|
26
31
|
i18n (0.6.1)
|
|
27
32
|
json (1.7.5)
|
|
28
33
|
metaclass (0.0.1)
|
|
29
34
|
mocha (0.11.4)
|
|
30
35
|
metaclass (~> 0.0.1)
|
|
31
|
-
|
|
32
|
-
bson (~> 1.7.0)
|
|
33
|
-
mongoid (2.5.0)
|
|
36
|
+
mongoid (3.0.13)
|
|
34
37
|
activemodel (~> 3.1)
|
|
35
|
-
|
|
38
|
+
moped (~> 1.1)
|
|
39
|
+
origin (~> 1.0)
|
|
36
40
|
tzinfo (~> 0.3.22)
|
|
37
|
-
|
|
41
|
+
moped (1.2.9)
|
|
42
|
+
multi_json (1.3.7)
|
|
43
|
+
origin (1.0.10)
|
|
38
44
|
rack (1.4.1)
|
|
39
45
|
rack-protection (1.2.0)
|
|
40
46
|
rack
|
|
@@ -51,8 +57,12 @@ GEM
|
|
|
51
57
|
rack (~> 1.3, >= 1.3.6)
|
|
52
58
|
rack-protection (~> 1.2)
|
|
53
59
|
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)
|
|
54
64
|
tilt (1.3.3)
|
|
55
|
-
tzinfo (0.3.
|
|
65
|
+
tzinfo (0.3.35)
|
|
56
66
|
|
|
57
67
|
PLATFORMS
|
|
58
68
|
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 processes 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,12 +27,26 @@ 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
|
+
|
|
30
43
|
## Usage
|
|
31
44
|
|
|
32
|
-
JuiCI
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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)
|
|
36
50
|
|
|
37
51
|
Example:
|
|
38
52
|
|
|
@@ -67,6 +81,20 @@ called with an (as yet unformalised) json body as the body if/when the build
|
|
|
67
81
|
reaches that state. Alternately you may specify "any" as the callback state and
|
|
68
82
|
it will be called on all state changes.
|
|
69
83
|
|
|
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
|
+
|
|
70
98
|
## Security
|
|
71
99
|
|
|
72
100
|
JuiCI poses some interesting security conecerns. First off, it will allow
|
|
@@ -92,8 +120,19 @@ specifically implement it, your process won't see any of the signal handling
|
|
|
92
120
|
madness. The shell(`/bin/sh`) will see everything, and if killed, your
|
|
93
121
|
processes will become orphaned, but carry on.
|
|
94
122
|
|
|
123
|
+
## Authors
|
|
124
|
+
|
|
125
|
+
* [Richo Healey](https://github.com/rcho)
|
|
126
|
+
* [Alec Sloman](https://github.com/alecsloman)
|
|
127
|
+
|
|
95
128
|
## Contact
|
|
96
129
|
|
|
97
130
|
JuiCI's code lives on [Github](https://github.com/richo/juici)
|
|
98
131
|
and the [author](mailto:richo@psych0tik.net) can be contacted on
|
|
99
132
|
[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,9 +1,33 @@
|
|
|
1
1
|
require 'rake'
|
|
2
2
|
require 'rspec/core/rake_task'
|
|
3
3
|
|
|
4
|
+
require 'juici/database'
|
|
5
|
+
|
|
4
6
|
RSpec::Core::RakeTask.new(:spec) do |t|
|
|
5
7
|
t.pattern = "spec/**/*_spec.rb"
|
|
6
8
|
end
|
|
7
9
|
|
|
8
10
|
desc 'Default: run specs'
|
|
9
11
|
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/bin/juicic
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
require 'net/http'
|
|
3
|
+
require 'json'
|
|
4
|
+
require 'juici/interface'
|
|
5
|
+
|
|
6
|
+
# TODO Refactor
|
|
7
|
+
def main(args)
|
|
8
|
+
action = args.shift.to_sym
|
|
9
|
+
options = {}
|
|
10
|
+
|
|
11
|
+
until args.empty?
|
|
12
|
+
case args.shift
|
|
13
|
+
when "--command"
|
|
14
|
+
command = args.shift
|
|
15
|
+
options[:command] = if command == "-"
|
|
16
|
+
File.read(command)
|
|
17
|
+
else
|
|
18
|
+
command
|
|
19
|
+
end
|
|
20
|
+
when "--host"
|
|
21
|
+
options[:host] = args.shift
|
|
22
|
+
when "--title"
|
|
23
|
+
options[:title] = args.shift
|
|
24
|
+
when "--project"
|
|
25
|
+
options[:project] = args.shift
|
|
26
|
+
when "--priority"
|
|
27
|
+
options[:priority] = args.shift
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
send(action, options)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def build(opts)
|
|
35
|
+
host = URI(opts[:host])
|
|
36
|
+
Net::HTTP.start(host.host, host.port) do |h|
|
|
37
|
+
req = Net::HTTP::Post.new(Juici::Routes::NEW_BUILD)
|
|
38
|
+
req.body = _create_payload(opts)
|
|
39
|
+
h.request req
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def _create_payload(opts)
|
|
44
|
+
URI.encode_www_form({
|
|
45
|
+
"project" => opts[:project],
|
|
46
|
+
"environment" => (opts[:environment] || {}).to_json,
|
|
47
|
+
"command" => opts[:command],
|
|
48
|
+
"priority" => opts[:priority] || 1,
|
|
49
|
+
"callbacks" => (opts[:callbacks] || []).to_json,
|
|
50
|
+
"title" => opts[:title]
|
|
51
|
+
})
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
main(ARGV.dup)
|
data/config/mongoid.yml.sample
CHANGED
|
@@ -1,10 +1,25 @@
|
|
|
1
1
|
development:
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
sessions:
|
|
3
|
+
default:
|
|
4
|
+
database: juici
|
|
5
|
+
hosts:
|
|
6
|
+
- localhost:27017
|
|
4
7
|
|
|
5
8
|
production:
|
|
6
|
-
|
|
7
|
-
|
|
9
|
+
sessions:
|
|
10
|
+
default:
|
|
11
|
+
database: juici
|
|
12
|
+
hosts:
|
|
13
|
+
- localhost:27017
|
|
14
|
+
|
|
15
|
+
test:
|
|
16
|
+
sessions:
|
|
17
|
+
default:
|
|
18
|
+
database: juici-test
|
|
19
|
+
hosts:
|
|
20
|
+
- localhost:27017
|
|
8
21
|
|
|
9
22
|
heroku:
|
|
10
|
-
|
|
23
|
+
sessions:
|
|
24
|
+
default:
|
|
25
|
+
uri: <%= ENV['MONGOLAB_URI'] %>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# vim: ft=ruby
|
|
2
|
+
#
|
|
3
|
+
require File.expand_path("../lib/juici/version", __FILE__)
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |s|
|
|
6
|
+
s.name = "juici-interface"
|
|
7
|
+
s.version = Juici::VERSION
|
|
8
|
+
s.authors = ["Richo Healey"]
|
|
9
|
+
s.email = ["richo@psych0tik.net"]
|
|
10
|
+
s.homepage = "http://github.com/richo/juici"
|
|
11
|
+
s.summary = "Interface definition for JuiCI callbacks and API"
|
|
12
|
+
s.description = s.summary
|
|
13
|
+
|
|
14
|
+
s.files = "lib/juici/interface.rb"
|
|
15
|
+
s.require_paths = ["lib"]
|
|
16
|
+
s.executables = "juicic"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
|
data/juici.gemspec
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
# vim: ft=ruby
|
|
2
|
+
#
|
|
3
|
+
require File.expand_path("../lib/juici/version", __FILE__)
|
|
2
4
|
|
|
3
5
|
Gem::Specification.new do |s|
|
|
4
6
|
s.name = "juici"
|
|
5
|
-
s.version =
|
|
7
|
+
s.version = Juici::VERSION
|
|
6
8
|
s.authors = ["Richo Healey"]
|
|
7
9
|
s.email = ["richo@psych0tik.net"]
|
|
8
10
|
s.homepage = "http://github.com/richo/juici"
|
|
@@ -10,10 +12,12 @@ Gem::Specification.new do |s|
|
|
|
10
12
|
s.description = s.summary
|
|
11
13
|
|
|
12
14
|
s.add_dependency "sinatra"
|
|
15
|
+
s.add_dependency "thin"
|
|
13
16
|
s.add_dependency "json"
|
|
14
|
-
s.add_dependency "mongoid"
|
|
17
|
+
s.add_dependency "mongoid"
|
|
15
18
|
s.add_dependency "bson_ext"
|
|
16
19
|
s.add_dependency "github-markdown"
|
|
20
|
+
s.add_dependency "ansible"
|
|
17
21
|
|
|
18
22
|
s.add_development_dependency "rake"
|
|
19
23
|
s.add_development_dependency "mocha"
|
|
@@ -21,7 +25,7 @@ Gem::Specification.new do |s|
|
|
|
21
25
|
|
|
22
26
|
s.files = `git ls-files`.split("\n")
|
|
23
27
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
24
|
-
s.executables =
|
|
28
|
+
s.executables = 'juici'
|
|
25
29
|
s.require_paths = ["lib"]
|
|
26
30
|
end
|
|
27
31
|
|
data/lib/juici.rb
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
|
-
require 'mongo'
|
|
2
|
-
require 'mongoid'
|
|
3
1
|
require 'github/markdown'
|
|
2
|
+
require 'ansible'
|
|
4
3
|
|
|
5
4
|
ENV['RACK_ENV'] ||= "development"
|
|
6
5
|
|
|
7
6
|
module Juici
|
|
8
7
|
def self.dbgp(*args)
|
|
9
|
-
ENV['
|
|
8
|
+
if ENV['JUICI_DEBUG'] || env == "development"
|
|
9
|
+
$stderr.puts(args)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def self.env
|
|
14
|
+
ENV['JUICI_ENV'] || ENV['RACK_ENV']
|
|
10
15
|
end
|
|
11
16
|
end
|
|
12
17
|
|
data/lib/juici/app.rb
CHANGED
|
@@ -8,31 +8,20 @@ module Juici
|
|
|
8
8
|
|
|
9
9
|
def self.shutdown
|
|
10
10
|
::Juici.dbgp "Shutting down Juici"
|
|
11
|
-
|
|
12
|
-
::Juici.dbgp "Killing #{watcher.inspect}"
|
|
13
|
-
watcher.kill
|
|
14
|
-
watcher.join
|
|
15
|
-
::Juici.dbgp "Dead: #{watcher.inspect}"
|
|
16
|
-
end
|
|
11
|
+
::Juici::Watcher.instance.shutdown!
|
|
17
12
|
|
|
18
13
|
shutdown_build_queue
|
|
19
14
|
end
|
|
20
15
|
|
|
21
16
|
attr_reader :opts
|
|
22
17
|
def initialize(opts={})
|
|
18
|
+
Database.initialize!
|
|
23
19
|
@opts = opts
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
# clear_stale_children
|
|
27
|
-
#
|
|
28
|
-
# Urgh
|
|
20
|
+
reset_stale_children
|
|
21
|
+
start_watcher
|
|
29
22
|
init_build_queue
|
|
30
23
|
reload_unfinished_work
|
|
31
|
-
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def spawn_watcher
|
|
35
|
-
@@watchers << Watcher.start!
|
|
24
|
+
start_queue
|
|
36
25
|
end
|
|
37
26
|
|
|
38
27
|
private
|
|
@@ -51,21 +40,28 @@ module Juici
|
|
|
51
40
|
# Ensure that any killed builds will be retried
|
|
52
41
|
end
|
|
53
42
|
|
|
54
|
-
def
|
|
55
|
-
|
|
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
|
|
43
|
+
def start_watcher
|
|
44
|
+
::Juici::Watcher.instance.start
|
|
60
45
|
end
|
|
61
46
|
|
|
62
47
|
def reload_unfinished_work
|
|
63
48
|
# At this point no workers have started yet, we can safely assume that
|
|
64
49
|
# :started means aborted
|
|
65
|
-
Build.where(:status
|
|
50
|
+
Build.where(:status => Juici::BuildStatus::WAIT).each do |build|
|
|
66
51
|
$build_queue << build
|
|
67
52
|
end
|
|
68
53
|
end
|
|
69
54
|
|
|
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
|
+
|
|
70
66
|
end
|
|
71
67
|
end
|