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.
Files changed (69) hide show
  1. data/.gitignore +2 -0
  2. data/Gemfile +4 -1
  3. data/Gemfile.lock +26 -16
  4. data/README.md +45 -6
  5. data/Rakefile +24 -0
  6. data/bin/juicic +54 -0
  7. data/config/mongoid.yml.sample +20 -5
  8. data/juici-interface.gemspec +19 -0
  9. data/juici.gemspec +7 -3
  10. data/lib/juici.rb +8 -3
  11. data/lib/juici/app.rb +19 -23
  12. data/lib/juici/build_environment.rb +1 -1
  13. data/lib/juici/build_logic.rb +10 -1
  14. data/lib/juici/build_queue.rb +30 -3
  15. data/lib/juici/callback.rb +9 -5
  16. data/lib/juici/config.rb +4 -0
  17. data/lib/juici/controllers.rb +6 -0
  18. data/lib/juici/controllers/base.rb +26 -0
  19. data/lib/juici/controllers/build_queue.rb +14 -0
  20. data/lib/juici/controllers/builds.rb +74 -0
  21. data/lib/juici/controllers/index.rb +20 -0
  22. data/lib/juici/controllers/{trigger_controller.rb → trigger.rb} +24 -5
  23. data/lib/juici/database.rb +19 -13
  24. data/lib/juici/exceptions.rb +2 -0
  25. data/lib/juici/find_logic.rb +11 -0
  26. data/lib/juici/helpers/form_helpers.rb +11 -0
  27. data/lib/juici/helpers/html_helpers.rb +4 -0
  28. data/lib/juici/helpers/url_helpers.rb +28 -0
  29. data/lib/juici/interface.rb +13 -0
  30. data/lib/juici/models/build.rb +81 -24
  31. data/lib/juici/models/project.rb +1 -1
  32. data/lib/juici/server.rb +103 -40
  33. data/lib/juici/version.rb +8 -0
  34. data/lib/juici/views/README.markdown +45 -6
  35. data/lib/juici/views/about.erb +5 -5
  36. data/lib/juici/views/builds/edit.erb +23 -0
  37. data/lib/juici/views/builds/list.erb +26 -33
  38. data/lib/juici/views/builds/new.erb +42 -37
  39. data/lib/juici/views/builds/show.erb +4 -28
  40. data/lib/juici/views/index.erb +30 -13
  41. data/lib/juici/views/layout.erb +22 -13
  42. data/lib/juici/views/not_found.erb +3 -0
  43. data/lib/juici/views/partials/builds/debug.erb +12 -18
  44. data/lib/juici/views/partials/builds/output.erb +1 -0
  45. data/lib/juici/views/partials/builds/show.erb +19 -0
  46. data/lib/juici/views/partials/builds/sidebar.erb +13 -0
  47. data/lib/juici/views/partials/index/recently_built.erb +19 -0
  48. data/lib/juici/views/queue/list.erb +6 -0
  49. data/lib/juici/watcher.rb +33 -25
  50. data/public/favicon.ico +0 -0
  51. data/public/images/black_denim.png +0 -0
  52. data/public/styles/builds.css +59 -8
  53. data/public/styles/juici.css +226 -2
  54. data/public/vendor/bootstrap.css +6004 -0
  55. data/public/vendor/bootstrap.js +2036 -0
  56. data/public/vendor/img/glyphicons-halflings-white.png +0 -0
  57. data/public/vendor/jquery.js +9440 -0
  58. data/script/cibuild +10 -0
  59. data/spec/build_callback_spec.rb +46 -1
  60. data/spec/build_process_spec.rb +71 -5
  61. data/spec/build_queue_spec.rb +3 -1
  62. data/spec/controllers/builds_spec.rb +68 -0
  63. data/spec/controllers/index_spec.rb +28 -0
  64. data/spec/juici_app_spec.rb +0 -15
  65. data/spec/models/build_spec.rb +54 -0
  66. data/spec/spec_helper.rb +13 -0
  67. metadata +76 -12
  68. data/lib/juici/controllers/build_controller.rb +0 -0
  69. data/lib/juici/url_helpers.rb +0 -15
@@ -0,0 +1,10 @@
1
+ #!/bin/sh
2
+
3
+ be="bundle exec"
4
+
5
+ export RACK_ENV="test"
6
+
7
+ bundle install --path .bundle
8
+
9
+ $be rake db:destroy
10
+ $be rake spec
@@ -3,7 +3,52 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
3
3
  describe "Juicy::Build::Callback" do
4
4
 
5
5
  it "should call #process! on each of it's callbacks" do
6
- pending("Not yet specced")
6
+ def mock_callback
7
+ mock(:payload= => nil).tap do |callback|
8
+ callback.expects(:process!).once
9
+ end
10
+ end
11
+
12
+ callbacks = ["rawr", "test"]
13
+
14
+ callbacks.each do |callback|
15
+ Juici::Callback.stubs(:new).with(callback).
16
+ returns(mock_callback)
17
+ end
18
+
19
+ build = Juici::Build.new(:callbacks => callbacks)
20
+ build.start!
21
+ build.success!
22
+ build.destroy
23
+ end
24
+
25
+ # TODO DRY This right up
26
+ it "should have status success on success" do
27
+ cb = Juici::Callback.new("test")
28
+ cb.stubs(:process!)
29
+
30
+ Juici::Callback.stubs(:new).with("test").returns(cb)
31
+
32
+ build = Juici::Build.new(:callbacks => ["test"])
33
+ build.start!
34
+ build.success!
35
+
36
+ JSON.load(cb.payload)["status"].should == Juici::BuildStatus::PASS
37
+ build.destroy
38
+ end
39
+
40
+ it "should have status failed on failure" do
41
+ cb = Juici::Callback.new("test")
42
+ cb.stubs(:process!)
43
+
44
+ Juici::Callback.stubs(:new).with("test").returns(cb)
45
+
46
+ build = Juici::Build.new(:callbacks => ["test"])
47
+ build.start!
48
+ build.failure!
49
+
50
+ JSON.load(cb.payload)["status"].should == Juici::BuildStatus::FAIL
51
+ build.destroy
7
52
  end
8
53
 
9
54
  end
@@ -3,7 +3,7 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
3
3
  describe "Juici build abstraction" do
4
4
 
5
5
  before(:all) do
6
- @app = Juici::App.new(workers: 0)
6
+ @app = Juici::App.new
7
7
  end
8
8
 
9
9
  after(:all) do
@@ -12,19 +12,85 @@ describe "Juici build abstraction" do
12
12
 
13
13
 
14
14
  it "Should run a given command in a subshell" do
15
- worker = Juici::Watcher.start!
15
+ watcher = Juici::Watcher.instance.start
16
16
  build = Juici::Build.new(parent: "test project",
17
17
  environment: {},
18
18
  command: "/bin/echo 'test build succeeded'")
19
19
  $build_queue << build
20
+
20
21
  # Wait a reasonable time for build to finish
21
22
  # TODO: This can leverage the hooks system
22
23
  # TODO: Easer will be to have worker.block or something
23
- sleep 5
24
+ Timeout::timeout(2) do
25
+ poll_build(build)
26
+
27
+ build.reload
28
+ build.status.should == Juici::BuildStatus::PASS
29
+ build[:output].chomp.should == "test build succeeded"
30
+ end
31
+ end
32
+
33
+ it "Should catch failed builds" do
34
+ watcher = Juici::Watcher.instance.start
35
+ build = Juici::Build.new(parent: "test project",
36
+ environment: {},
37
+ command: "exit 3")
38
+ $build_queue << build
39
+
40
+ # Wait a reasonable time for build to finish
41
+ # TODO: This can leverage the hooks system
42
+ # TODO: Easer will be to have worker.block or something
43
+ Timeout::timeout(2) do
44
+ poll_build(build)
45
+
46
+ build.reload
47
+ build.status.should == Juici::BuildStatus::FAIL
48
+ build[:output].chomp.should == ""
49
+ end
50
+ end
51
+
52
+ it "Should kill builds" do
53
+ build = Juici::Build.new(parent: "test",
54
+ command: "sleep 30")
55
+ $build_queue << build
56
+ sleep 1
57
+ build.kill!
24
58
 
25
59
  build.reload
26
- build[:status].should == :success
27
- build[:output].chomp.should == "test build succeeded"
60
+
61
+ build.status.should == Juici::BuildStatus::FAIL
62
+ build.warnings.should include("Killed!")
63
+ end
64
+
65
+ it "Can create and fetch new bundles" do
66
+ watcher = Juici::Watcher.instance.start
67
+ build = Juici::Build.new(parent: "test project",
68
+ environment: ::Juici::BuildEnvironment.new.to_hash,
69
+ command: <<-EOS)
70
+ #!/bin/sh
71
+ set -e
72
+
73
+ cat > Gemfile <<EOF
74
+ source :rubygems
75
+ gem "m2a"
76
+ EOF
77
+
78
+ env
79
+
80
+ bundle install
81
+ bundle list
82
+ bundle config
83
+ EOS
84
+
85
+ build.save!
86
+ $build_queue << build
87
+
88
+ Timeout::timeout(10) do
89
+ poll_build(build)
90
+
91
+ build.status.should == Juici::BuildStatus::PASS
92
+ build[:output].chomp.should match /m2a/
93
+ end
28
94
  end
29
95
 
30
96
  end
@@ -33,7 +33,9 @@ describe Juici::BuildQueue do
33
33
  end
34
34
 
35
35
  it "Should remove a given build by id" do
36
- pending("To be implemented")
36
+ @builds = builds_with(_id: [1, 2, 3, 4, 5, 6])
37
+ subject.delete(3)
38
+ @builds.collect(&:_id).should == [1, 2, 4, 5, 6]
37
39
  end
38
40
 
39
41
  it "Should return a low priority job from #next_child" do
@@ -0,0 +1,68 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Juici::Controllers::Builds do
4
+
5
+ describe "list" do
6
+ it "should throw not_found for invalid projects" do
7
+ params = { :project => "__LolIDon'tExist" }
8
+ lambda {
9
+ Juici::Controllers::Builds.new(params).list
10
+ }.should raise_error(Sinatra::NotFound)
11
+ end
12
+ end
13
+
14
+ describe "show" do
15
+ it "should throw not_found for invalid projects" do
16
+ params = { :project => "__LolIDon'tExist" }
17
+ lambda {
18
+ Juici::Controllers::Builds.new(params).show
19
+ }.should raise_error(Sinatra::NotFound)
20
+ end
21
+ end
22
+
23
+ describe "new" do
24
+ it "should return the new template" do
25
+ Juici::Controllers::Builds.new({}).new do |opts, template|
26
+ end
27
+ end
28
+ end
29
+
30
+ describe "edit" do
31
+ it "should throw not_found for invalid projects" do
32
+ params = { :project => "__LolIDon'tExist" }
33
+ lambda {
34
+ Juici::Controllers::Builds.new(params).show
35
+ }.should raise_error(Sinatra::NotFound)
36
+ end
37
+
38
+ it "Should update build objects when given data" do
39
+ # FIXME This is a kludge to work around #38
40
+ ::Juici::Project.find_or_create_by(name: "test project")
41
+ build = Juici::Build.new(parent: "test project", priority: 1, title: "test build")
42
+ build.save!
43
+
44
+ Juici::Controllers::Builds.new({:priority => 15, :title => "butts lol", :id => build[:_id], :project => "test project"}).update!
45
+ build.reload
46
+
47
+ build[:title].should == "butts lol"
48
+ build[:priority].should == 15
49
+ end
50
+
51
+ it "Should not let you update a build's ID" do
52
+ # FIXME This is a kludge to work around #38
53
+ ::Juici::Project.find_or_create_by(name: "test project")
54
+ build = Juici::Build.new(parent: "test project")
55
+ build.save!
56
+
57
+ updated_build = Juici::Controllers::Builds.new({:_id => "New id lol", :id => build[:_id], :project => "test project"}).update!
58
+
59
+ updated_build[:_id].should == build[:_id]
60
+ end
61
+
62
+ it "Should not touch values if given invalid values" do
63
+ pending("Needs more research on mongoid")
64
+ end
65
+
66
+ end
67
+
68
+ end
@@ -0,0 +1,28 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Juici::Controllers::Index do
4
+
5
+ describe "index" do
6
+ it "should render index" do
7
+ Juici::Controllers::Index.new().index do |template, opts|
8
+ end
9
+ end
10
+ end
11
+
12
+ describe "about" do
13
+ it "should add block-header to all h1 tags" do
14
+ Juici::Controllers::Index.new().about do |template, opts|
15
+ opts[:content].should match(/class="block-header"/)
16
+ end
17
+ end
18
+ end
19
+
20
+ describe "support" do
21
+ it "should render support" do
22
+ Juici::Controllers::Index.new().support do |template, opts|
23
+ end
24
+ end
25
+ end
26
+
27
+ end
28
+
@@ -2,22 +2,7 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
 
3
3
  describe Juici::App do
4
4
  it "instanciates cleanly and exits cleanly" do
5
- threads = Thread.list.length
6
-
7
5
  app = Juici::App.new
8
- Thread.list.length.should == threads + 1
9
-
10
- Juici::App.shutdown
11
- Thread.list.length.should == threads
12
- end
13
-
14
- it "Can be started without workers" do
15
- threads = Thread.list.length
16
-
17
- app = Juici::App.new(workers: 0)
18
- Thread.list.length.should == threads
19
-
20
6
  Juici::App.shutdown
21
- Thread.list.length.should == threads
22
7
  end
23
8
  end
@@ -0,0 +1,54 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Juici::Build do
4
+
5
+ describe "Time elapsed" do
6
+ it "Should have the total duration if complete" do
7
+
8
+ build = Juici::Build.new
9
+ Time.stubs(:now).returns(Time.at(5000)).then.returns(Time.at(5005))
10
+ build.start!
11
+ build.success!
12
+
13
+ build.time_elapsed.to_i.should == 5
14
+ end
15
+
16
+ it "Should have the time running if started" do
17
+ build = Juici::Build.new
18
+ Time.stubs(:now).returns(Time.at(5000)).then.returns(Time.at(5006))
19
+ build.start!
20
+
21
+ build.time_elapsed.to_i.should == 6
22
+ end
23
+
24
+ it "Should be nil if not started" do
25
+ build = Juici::Build.new
26
+ build.time_elapsed.should be_nil
27
+ end
28
+ end
29
+
30
+ it "Should clone itself with #new_from" do
31
+ values = {}
32
+ Juici::Build::CLONABLE_FIELDS.each do |k|
33
+ case k
34
+ when :environment
35
+ values[k] = {:something => "#{k}_value"}
36
+ else
37
+ values[k] = "#{k}_value"
38
+ end
39
+ end
40
+
41
+ build = Juici::Build.new(values)
42
+ build[:output] = "Lol, I has an output"
43
+ build[:buffer] = "/tmp/buffer/lol"
44
+ new_build = Juici::Build.new_from(build)
45
+
46
+ Juici::Build::CLONABLE_FIELDS.each do |k|
47
+ build[k].should == new_build[k]
48
+ end
49
+
50
+ build[:_id].should_not == new_build[:_id]
51
+ new_build[:output].should be_nil
52
+ new_build[:buffer].should be_nil
53
+ end
54
+ end
@@ -1,7 +1,10 @@
1
+ ENV['RACK_ENV'] ||= "test"
2
+
1
3
  require 'juici'
2
4
  require 'mocha'
3
5
 
4
6
  require 'fileutils'
7
+ require 'timeout'
5
8
 
6
9
  Dir["#{File.expand_path(File.dirname(__FILE__))}/helpers/**/*.rb"].each do |f|
7
10
  puts "Requiring #{f}"
@@ -11,3 +14,13 @@ end
11
14
  RSpec.configure do |config|
12
15
  config.mock_framework = :mocha
13
16
  end
17
+
18
+ def poll_build(build)
19
+ loop do
20
+ sleep(0.1)
21
+ build.reload
22
+ break if build.status != Juici::BuildStatus::START
23
+ end
24
+ end
25
+
26
+ Juici::Database.initialize!
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: juici
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
5
- prerelease:
4
+ version: 0.0.1.alpha1
5
+ prerelease: 6
6
6
  platform: ruby
7
7
  authors:
8
8
  - Richo Healey
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-10-07 00:00:00.000000000 Z
12
+ date: 2012-11-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: sinatra
@@ -27,6 +27,22 @@ dependencies:
27
27
  - - ! '>='
28
28
  - !ruby/object:Gem::Version
29
29
  version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: thin
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
30
46
  - !ruby/object:Gem::Dependency
31
47
  name: json
32
48
  requirement: !ruby/object:Gem::Requirement
@@ -48,17 +64,17 @@ dependencies:
48
64
  requirement: !ruby/object:Gem::Requirement
49
65
  none: false
50
66
  requirements:
51
- - - ~>
67
+ - - ! '>='
52
68
  - !ruby/object:Gem::Version
53
- version: '2'
69
+ version: '0'
54
70
  type: :runtime
55
71
  prerelease: false
56
72
  version_requirements: !ruby/object:Gem::Requirement
57
73
  none: false
58
74
  requirements:
59
- - - ~>
75
+ - - ! '>='
60
76
  - !ruby/object:Gem::Version
61
- version: '2'
77
+ version: '0'
62
78
  - !ruby/object:Gem::Dependency
63
79
  name: bson_ext
64
80
  requirement: !ruby/object:Gem::Requirement
@@ -91,6 +107,22 @@ dependencies:
91
107
  - - ! '>='
92
108
  - !ruby/object:Gem::Version
93
109
  version: '0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: ansible
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
94
126
  - !ruby/object:Gem::Dependency
95
127
  name: rake
96
128
  requirement: !ruby/object:Gem::Requirement
@@ -147,6 +179,7 @@ executables:
147
179
  extensions: []
148
180
  extra_rdoc_files: []
149
181
  files:
182
+ - .gitignore
150
183
  - Gemfile
151
184
  - Gemfile.lock
152
185
  - Procfile
@@ -154,7 +187,9 @@ files:
154
187
  - Rakefile
155
188
  - TODO.md
156
189
  - bin/juici
190
+ - bin/juicic
157
191
  - config/mongoid.yml.sample
192
+ - juici-interface.gemspec
158
193
  - juici.gemspec
159
194
  - lib/juici.rb
160
195
  - lib/juici/app.rb
@@ -163,35 +198,61 @@ files:
163
198
  - lib/juici/build_queue.rb
164
199
  - lib/juici/callback.rb
165
200
  - lib/juici/config.rb
166
- - lib/juici/controllers/build_controller.rb
167
- - lib/juici/controllers/trigger_controller.rb
201
+ - lib/juici/controllers.rb
202
+ - lib/juici/controllers/base.rb
203
+ - lib/juici/controllers/build_queue.rb
204
+ - lib/juici/controllers/builds.rb
205
+ - lib/juici/controllers/index.rb
206
+ - lib/juici/controllers/trigger.rb
168
207
  - lib/juici/database.rb
208
+ - lib/juici/exceptions.rb
209
+ - lib/juici/find_logic.rb
210
+ - lib/juici/helpers/form_helpers.rb
211
+ - lib/juici/helpers/html_helpers.rb
169
212
  - lib/juici/helpers/url_helpers.rb
213
+ - lib/juici/interface.rb
170
214
  - lib/juici/models/build.rb
171
215
  - lib/juici/models/build_process.rb
172
216
  - lib/juici/models/project.rb
173
217
  - lib/juici/server.rb
174
- - lib/juici/url_helpers.rb
218
+ - lib/juici/version.rb
175
219
  - lib/juici/views/README.markdown
176
220
  - lib/juici/views/about.erb
177
221
  - lib/juici/views/builds.erb
222
+ - lib/juici/views/builds/edit.erb
178
223
  - lib/juici/views/builds/list.erb
179
224
  - lib/juici/views/builds/new.erb
180
225
  - lib/juici/views/builds/show.erb
181
226
  - lib/juici/views/index.erb
182
227
  - lib/juici/views/layout.erb
228
+ - lib/juici/views/not_found.erb
183
229
  - lib/juici/views/partials/builds/debug.erb
230
+ - lib/juici/views/partials/builds/output.erb
231
+ - lib/juici/views/partials/builds/show.erb
232
+ - lib/juici/views/partials/builds/sidebar.erb
233
+ - lib/juici/views/partials/index/recently_built.erb
234
+ - lib/juici/views/queue/list.erb
184
235
  - lib/juici/views/redirect.erb
185
236
  - lib/juici/views/support.erb
186
237
  - lib/juici/watcher.rb
238
+ - public/favicon.ico
239
+ - public/images/black_denim.png
187
240
  - public/styles/builds.css
188
241
  - public/styles/juici.css
242
+ - public/vendor/bootstrap.css
243
+ - public/vendor/bootstrap.js
244
+ - public/vendor/img/glyphicons-halflings-white.png
245
+ - public/vendor/jquery.js
189
246
  - sample/mongod.conf
247
+ - script/cibuild
190
248
  - spec/build_callback_spec.rb
191
249
  - spec/build_environment_spec.rb
192
250
  - spec/build_process_spec.rb
193
251
  - spec/build_queue_spec.rb
252
+ - spec/controllers/builds_spec.rb
253
+ - spec/controllers/index_spec.rb
194
254
  - spec/juici_app_spec.rb
255
+ - spec/models/build_spec.rb
195
256
  - spec/spec_helper.rb
196
257
  homepage: http://github.com/richo/juici
197
258
  licenses: []
@@ -208,9 +269,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
208
269
  required_rubygems_version: !ruby/object:Gem::Requirement
209
270
  none: false
210
271
  requirements:
211
- - - ! '>='
272
+ - - ! '>'
212
273
  - !ruby/object:Gem::Version
213
- version: '0'
274
+ version: 1.3.1
214
275
  requirements: []
215
276
  rubyforge_project:
216
277
  rubygems_version: 1.8.24
@@ -222,5 +283,8 @@ test_files:
222
283
  - spec/build_environment_spec.rb
223
284
  - spec/build_process_spec.rb
224
285
  - spec/build_queue_spec.rb
286
+ - spec/controllers/builds_spec.rb
287
+ - spec/controllers/index_spec.rb
225
288
  - spec/juici_app_spec.rb
289
+ - spec/models/build_spec.rb
226
290
  - spec/spec_helper.rb