octopusci 0.2.3 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. data/README.markdown +132 -0
  2. data/bin/octopusci-reset-redis +26 -0
  3. data/bin/octopusci-skel +2 -7
  4. data/bin/octopusci-tentacles +2 -2
  5. data/config.ru +1 -1
  6. data/lib/octopusci.rb +3 -7
  7. data/lib/octopusci/config.rb +63 -49
  8. data/lib/octopusci/errors.rb +2 -0
  9. data/lib/octopusci/helpers.rb +16 -15
  10. data/lib/octopusci/io.rb +70 -0
  11. data/lib/octopusci/job.rb +145 -34
  12. data/lib/octopusci/job_store.rb +67 -0
  13. data/lib/octopusci/notifier.rb +7 -17
  14. data/lib/octopusci/notifier/job_complete.html.erb +76 -3
  15. data/lib/octopusci/queue.rb +14 -10
  16. data/lib/octopusci/server.rb +17 -20
  17. data/lib/octopusci/server/views/index.erb +3 -4
  18. data/lib/octopusci/server/views/job.erb +3 -3
  19. data/lib/octopusci/server/views/job_summary.erb +18 -18
  20. data/lib/octopusci/server/views/layout.erb +6 -5
  21. data/lib/octopusci/stage_locker.rb +11 -7
  22. data/lib/octopusci/version.rb +1 -1
  23. data/lib/octopusci/worker_launcher.rb +1 -1
  24. data/spec/lib/octopusci/config_spec.rb +195 -0
  25. data/spec/lib/octopusci/io_spec.rb +64 -0
  26. data/spec/lib/octopusci/job_spec.rb +122 -0
  27. data/spec/lib/octopusci/job_store_spec.rb +155 -0
  28. data/spec/lib/octopusci/notifier_spec.rb +0 -15
  29. data/spec/lib/octopusci/queue_spec.rb +122 -0
  30. data/spec/lib/octopusci/server_spec.rb +92 -1
  31. data/spec/lib/octopusci/stage_locker_spec.rb +94 -0
  32. data/spec/spec_helper.rb +8 -0
  33. metadata +39 -58
  34. data/README +0 -63
  35. data/bin/octopusci-db-migrate +0 -10
  36. data/db/migrate/0001_init.rb +0 -29
  37. data/db/migrate/0002_add_status_job.rb +0 -19
  38. data/lib/octopusci/notifier/job_complete.text.erb +0 -5
  39. data/lib/octopusci/schema.rb +0 -140
@@ -0,0 +1,94 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Octopusci::StageLocker" do
4
+ describe "#load" do
5
+ it "should clear the pool of stages" do
6
+ @mock_redis.stub(:rpush)
7
+ Octopusci::StageLocker.should_receive(:clear)
8
+ Octopusci::StageLocker.load(['a', 'b', 'c'])
9
+ end
10
+
11
+ it "should push each of the provided stages into the stage pool" do
12
+ Octopusci::StageLocker.stub(:clear)
13
+ Octopusci::StageLocker.should_receive(:push).with('a')
14
+ Octopusci::StageLocker.should_receive(:push).with('b')
15
+ Octopusci::StageLocker.should_receive(:push).with('c')
16
+ Octopusci::StageLocker.load(['a', 'b', 'c'])
17
+ end
18
+ end
19
+
20
+ describe "#clear" do
21
+ it "should clear all of the stages out of the stage locker" do
22
+ r = mock('redis')
23
+ Octopusci::StageLocker.stub(:redis).and_return(r)
24
+ r.should_receive(:del).with('octopusci:stagelocker')
25
+ Octopusci::StageLocker.clear
26
+ end
27
+ end
28
+
29
+ describe "#pop" do
30
+ it "should pop the left most stage out of the stage locker" do
31
+ r = mock('redis')
32
+ Octopusci::StageLocker.stub(:redis).and_return(r)
33
+ r.should_receive(:lpop).with('octopusci:stagelocker')
34
+ Octopusci::StageLocker.pop
35
+ end
36
+ end
37
+
38
+ describe "#rem" do
39
+ it "should remove the provided stage from the stage locker pool" do
40
+ r = mock('redis')
41
+ Octopusci::StageLocker.stub(:redis).and_return(r)
42
+ r.should_receive(:lrem).with('octopusci:stagelocker', 1, 'a')
43
+ Octopusci::StageLocker.rem('a')
44
+ end
45
+ end
46
+
47
+ describe "#push" do
48
+ it "should append the provided stage to the right of the stage locker" do
49
+ r = mock('redis')
50
+ Octopusci::StageLocker.stub(:redis).and_return(r)
51
+ r.should_receive(:rpush).with('octopusci:stagelocker', 'a')
52
+ Octopusci::StageLocker.push('a')
53
+ end
54
+ end
55
+
56
+ describe "#stages" do
57
+ it "should return the defined stages from the configuration" do
58
+ Octopusci::Config.should_receive(:[]).with('stages').and_return(['a', 'b', 'c', 'd'])
59
+ Octopusci::StageLocker.stages.should == ['a', 'b', 'c', 'd']
60
+ end
61
+ end
62
+
63
+ describe "#pool" do
64
+ it "should return the pool of stages" do
65
+ r = stub('redis').as_null_object
66
+ Octopusci::StageLocker.stub(:redis).and_return(r)
67
+ r.stub(:peek).and_return(['stage_a', 'stage_b', 'stage_c'])
68
+ Octopusci::StageLocker.pool.should == ['stage_a', 'stage_b', 'stage_c']
69
+ end
70
+
71
+ it "should get the size of the current pool stored in redis" do
72
+ r = mock('redis').as_null_object
73
+ Octopusci::StageLocker.stub(:redis).and_return(r)
74
+ r.should_receive(:size).with('octopusci:stagelocker')
75
+ Octopusci::StageLocker.pool
76
+ end
77
+
78
+ it "should get the current pool of stages stored in redis" do
79
+ r = mock('redis')
80
+ Octopusci::StageLocker.stub(:redis).and_return(r)
81
+ r.stub(:size).and_return(4)
82
+ r.should_receive(:peek).with('octopusci:stagelocker', 0, 4)
83
+ Octopusci::StageLocker.pool
84
+ end
85
+ end
86
+
87
+ describe "#redis" do
88
+ it "should return redis instance provided by resqueue" do
89
+ r = stub('redis')
90
+ Resque.should_receive(:redis).and_return(r)
91
+ Octopusci::StageLocker.redis.should == r
92
+ end
93
+ end
94
+ end
@@ -9,3 +9,11 @@ def app
9
9
  end
10
10
 
11
11
  include Rack::Test::Methods
12
+
13
+ RSpec.configure do |config|
14
+ config.before(:each) do
15
+ # Here I mock the Resque redis method to prevent the tests from actually storing any data in redis
16
+ @mock_redis = mock('redis')
17
+ Resque.stub(:redis).and_return(@mock_redis)
18
+ end
19
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: octopusci
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,11 +10,11 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2011-10-13 00:00:00.000000000Z
13
+ date: 2011-11-04 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: sinatra
17
- requirement: &70141088955920 !ruby/object:Gem::Requirement
17
+ requirement: &70256773373660 !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ! '>='
@@ -22,10 +22,10 @@ dependencies:
22
22
  version: '0'
23
23
  type: :runtime
24
24
  prerelease: false
25
- version_requirements: *70141088955920
25
+ version_requirements: *70256773373660
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: json
28
- requirement: &70141088955500 !ruby/object:Gem::Requirement
28
+ requirement: &70256773372560 !ruby/object:Gem::Requirement
29
29
  none: false
30
30
  requirements:
31
31
  - - ! '>='
@@ -33,10 +33,10 @@ dependencies:
33
33
  version: '0'
34
34
  type: :runtime
35
35
  prerelease: false
36
- version_requirements: *70141088955500
36
+ version_requirements: *70256773372560
37
37
  - !ruby/object:Gem::Dependency
38
38
  name: resque
39
- requirement: &70141088955080 !ruby/object:Gem::Requirement
39
+ requirement: &70256773372040 !ruby/object:Gem::Requirement
40
40
  none: false
41
41
  requirements:
42
42
  - - ! '>='
@@ -44,10 +44,10 @@ dependencies:
44
44
  version: '0'
45
45
  type: :runtime
46
46
  prerelease: false
47
- version_requirements: *70141088955080
47
+ version_requirements: *70256773372040
48
48
  - !ruby/object:Gem::Dependency
49
49
  name: actionmailer
50
- requirement: &70141088954660 !ruby/object:Gem::Requirement
50
+ requirement: &70256773371540 !ruby/object:Gem::Requirement
51
51
  none: false
52
52
  requirements:
53
53
  - - ! '>='
@@ -55,32 +55,10 @@ dependencies:
55
55
  version: '0'
56
56
  type: :runtime
57
57
  prerelease: false
58
- version_requirements: *70141088954660
59
- - !ruby/object:Gem::Dependency
60
- name: activerecord
61
- requirement: &70141088954240 !ruby/object:Gem::Requirement
62
- none: false
63
- requirements:
64
- - - ! '>='
65
- - !ruby/object:Gem::Version
66
- version: '0'
67
- type: :runtime
68
- prerelease: false
69
- version_requirements: *70141088954240
70
- - !ruby/object:Gem::Dependency
71
- name: mysql
72
- requirement: &70141088953820 !ruby/object:Gem::Requirement
73
- none: false
74
- requirements:
75
- - - ! '>='
76
- - !ruby/object:Gem::Version
77
- version: '0'
78
- type: :runtime
79
- prerelease: false
80
- version_requirements: *70141088953820
58
+ version_requirements: *70256773371540
81
59
  - !ruby/object:Gem::Dependency
82
60
  name: multi_json
83
- requirement: &70141088953400 !ruby/object:Gem::Requirement
61
+ requirement: &70256773370980 !ruby/object:Gem::Requirement
84
62
  none: false
85
63
  requirements:
86
64
  - - ! '>='
@@ -88,10 +66,10 @@ dependencies:
88
66
  version: '0'
89
67
  type: :runtime
90
68
  prerelease: false
91
- version_requirements: *70141088953400
69
+ version_requirements: *70256773370980
92
70
  - !ruby/object:Gem::Dependency
93
71
  name: time-ago-in-words
94
- requirement: &70141088952980 !ruby/object:Gem::Requirement
72
+ requirement: &70256773369660 !ruby/object:Gem::Requirement
95
73
  none: false
96
74
  requirements:
97
75
  - - ! '>='
@@ -99,10 +77,10 @@ dependencies:
99
77
  version: '0'
100
78
  type: :runtime
101
79
  prerelease: false
102
- version_requirements: *70141088952980
80
+ version_requirements: *70256773369660
103
81
  - !ruby/object:Gem::Dependency
104
82
  name: rake
105
- requirement: &70141088952560 !ruby/object:Gem::Requirement
83
+ requirement: &70256773368320 !ruby/object:Gem::Requirement
106
84
  none: false
107
85
  requirements:
108
86
  - - ! '>='
@@ -110,10 +88,10 @@ dependencies:
110
88
  version: '0'
111
89
  type: :development
112
90
  prerelease: false
113
- version_requirements: *70141088952560
91
+ version_requirements: *70256773368320
114
92
  - !ruby/object:Gem::Dependency
115
93
  name: rspec
116
- requirement: &70141088952140 !ruby/object:Gem::Requirement
94
+ requirement: &70256773367880 !ruby/object:Gem::Requirement
117
95
  none: false
118
96
  requirements:
119
97
  - - ! '>='
@@ -121,10 +99,10 @@ dependencies:
121
99
  version: '0'
122
100
  type: :development
123
101
  prerelease: false
124
- version_requirements: *70141088952140
102
+ version_requirements: *70256773367880
125
103
  - !ruby/object:Gem::Dependency
126
104
  name: rack-test
127
- requirement: &70141088972180 !ruby/object:Gem::Requirement
105
+ requirement: &70256773367280 !ruby/object:Gem::Requirement
128
106
  none: false
129
107
  requirements:
130
108
  - - ! '>='
@@ -132,10 +110,10 @@ dependencies:
132
110
  version: '0'
133
111
  type: :development
134
112
  prerelease: false
135
- version_requirements: *70141088972180
113
+ version_requirements: *70256773367280
136
114
  - !ruby/object:Gem::Dependency
137
115
  name: guard
138
- requirement: &70141088971760 !ruby/object:Gem::Requirement
116
+ requirement: &70256773366640 !ruby/object:Gem::Requirement
139
117
  none: false
140
118
  requirements:
141
119
  - - ! '>='
@@ -143,10 +121,10 @@ dependencies:
143
121
  version: '0'
144
122
  type: :development
145
123
  prerelease: false
146
- version_requirements: *70141088971760
124
+ version_requirements: *70256773366640
147
125
  - !ruby/object:Gem::Dependency
148
126
  name: rb-fsevent
149
- requirement: &70141088971340 !ruby/object:Gem::Requirement
127
+ requirement: &70256773365960 !ruby/object:Gem::Requirement
150
128
  none: false
151
129
  requirements:
152
130
  - - ! '>='
@@ -154,10 +132,10 @@ dependencies:
154
132
  version: '0'
155
133
  type: :development
156
134
  prerelease: false
157
- version_requirements: *70141088971340
135
+ version_requirements: *70256773365960
158
136
  - !ruby/object:Gem::Dependency
159
- name: growl
160
- requirement: &70141088970920 !ruby/object:Gem::Requirement
137
+ name: growl_notify
138
+ requirement: &70256773365160 !ruby/object:Gem::Requirement
161
139
  none: false
162
140
  requirements:
163
141
  - - ! '>='
@@ -165,10 +143,10 @@ dependencies:
165
143
  version: '0'
166
144
  type: :development
167
145
  prerelease: false
168
- version_requirements: *70141088970920
146
+ version_requirements: *70256773365160
169
147
  - !ruby/object:Gem::Dependency
170
148
  name: guard-rspec
171
- requirement: &70141088970500 !ruby/object:Gem::Requirement
149
+ requirement: &70256773364400 !ruby/object:Gem::Requirement
172
150
  none: false
173
151
  requirements:
174
152
  - - ! '>='
@@ -176,7 +154,7 @@ dependencies:
176
154
  version: '0'
177
155
  type: :development
178
156
  prerelease: false
179
- version_requirements: *70141088970500
157
+ version_requirements: *70256773364400
180
158
  description: A multi-branch Continous Integration server that integrates with GitHub
181
159
  email:
182
160
  - cyphactor@gmail.com
@@ -184,22 +162,21 @@ email:
184
162
  executables:
185
163
  - octopusci-tentacles
186
164
  - octopusci-skel
187
- - octopusci-db-migrate
188
165
  extensions: []
189
166
  extra_rdoc_files: []
190
167
  files:
191
- - README
168
+ - README.markdown
192
169
  - LICENSE
193
170
  - config.ru
194
171
  - lib/octopusci/config.rb
195
172
  - lib/octopusci/errors.rb
196
173
  - lib/octopusci/helpers.rb
174
+ - lib/octopusci/io.rb
197
175
  - lib/octopusci/job.rb
176
+ - lib/octopusci/job_store.rb
198
177
  - lib/octopusci/notifier/job_complete.html.erb
199
- - lib/octopusci/notifier/job_complete.text.erb
200
178
  - lib/octopusci/notifier.rb
201
179
  - lib/octopusci/queue.rb
202
- - lib/octopusci/schema.rb
203
180
  - lib/octopusci/server/public/images/ajax-loader-1.gif
204
181
  - lib/octopusci/server/public/images/noise.gif
205
182
  - lib/octopusci/server/public/images/status.png
@@ -216,16 +193,20 @@ files:
216
193
  - lib/octopusci/worker_launcher.rb
217
194
  - lib/octopusci.rb
218
195
  - bin/octopusci
219
- - bin/octopusci-db-migrate
196
+ - bin/octopusci-reset-redis
220
197
  - bin/octopusci-skel
221
198
  - bin/octopusci-tentacles
222
199
  - bin/pusci-stage
200
+ - spec/lib/octopusci/config_spec.rb
201
+ - spec/lib/octopusci/io_spec.rb
202
+ - spec/lib/octopusci/job_spec.rb
203
+ - spec/lib/octopusci/job_store_spec.rb
223
204
  - spec/lib/octopusci/notifier_spec.rb
205
+ - spec/lib/octopusci/queue_spec.rb
224
206
  - spec/lib/octopusci/server_spec.rb
207
+ - spec/lib/octopusci/stage_locker_spec.rb
225
208
  - spec/lib/octopusci_spec.rb
226
209
  - spec/spec_helper.rb
227
- - db/migrate/0001_init.rb
228
- - db/migrate/0002_add_status_job.rb
229
210
  - extra/etc/init.d/octopusci
230
211
  homepage: https://github.com/cyphactor/octopusci
231
212
  licenses: []
data/README DELETED
@@ -1,63 +0,0 @@
1
- The purpose of this project is provide a simple CI server that will work with
2
- GitHub Post-Receive hook. It is also specifically designed to handle multiple
3
- build/job queues for each branch.
4
-
5
- This would basically allow you to every time code is pushed to the central
6
- repository enqueue a build/job for the specific branch. That way if you
7
- have topic branches that are being pushed to the central repository along
8
- side the mainline branch they will get queue properly as well.
9
-
10
- My idea for implementation at this point is that if I can detect the branch
11
- from the GitHub Post-Receive hook then I can identify branch. If I can
12
- identify branch then I can maintain individual queues for each branch.
13
-
14
- Then the execution would look at config values for predefined branches and
15
- priorities for order of running them so that the mainline branch running its
16
- jobs could take precedence over non specified topic branches.
17
-
18
- Install redis and get it starting up appropriately
19
-
20
- gem install octopusci
21
- sudo octopusci-skel
22
- octopusci-db-migrate
23
-
24
- Then update the /etc/octopusci/config.yml appropriately.
25
-
26
- Add any jobs you would like to the /etc/octopusci/jobs directory as rb files
27
- and octopusci will load them appropriately when started.
28
-
29
- Figure out what directory the gem is installed in by running the following
30
- command and stripping off the lib/octopusci.rb at the end.
31
-
32
- gem which octopusci
33
-
34
- Once you have the path we can use that path to setup Passenger with Apache
35
- or something else like nginx as well as setup the database. Note: You will
36
- need to setup a database user and a database for octopusci. The settings for
37
- these should be stored in /etc/octopusci/config.yml.
38
-
39
- rake -f /path/of/octpusci/we/got/before/Rakefile db:migrate
40
-
41
- <VirtualHost *:80>
42
- ServerName octopusci.example.com
43
- PassengerAppRoot /path/of/octpusci/we/got/before
44
- DocumentRoot /path/of/octpusci/we/got/before/lib/octopusci/server/public
45
- <Directory /path/of/octpusci/we/got/before/lib/octopusci/server/public>
46
- Order allow,deny
47
- Allow from all
48
- AllowOverride all
49
- Options -MultiViews
50
- </Directory>
51
- </VirtualHost>
52
-
53
- The above will give us the web Octopusci web interface.
54
-
55
- If you are developing you can simply start this up by running
56
- rackup -p whatever_port while inside the octopusci directory where the
57
- config.ru file exists.
58
-
59
- I recommend you setup the second half of Octopusci (octopusci-tentacles) with
60
- God or some other monitoring system. However, for development you can simply
61
- run octopusci-tentacles directoly as follows:
62
-
63
- otopusci-tentacles
@@ -1,10 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
4
-
5
- require 'rubygems'
6
- require 'octopusci'
7
-
8
- ActiveRecord::Base.logger = Logger.new(STDOUT)
9
- ActiveRecord::Migration.verbose = true
10
- ActiveRecord::Migrator.migrate(File.expand_path(File.dirname(__FILE__) + "/../db/migrate"))
@@ -1,29 +0,0 @@
1
- class Init < ActiveRecord::Migration
2
- def self.up
3
- create_table :jobs do |t|
4
- t.string :ref
5
- t.string :compare
6
- t.string :repo_name
7
- t.string :repo_owner_name
8
- t.string :repo_owner_email
9
- t.timestamp :repo_pushed_at
10
- t.timestamp :repo_created_at
11
- t.text :repo_desc
12
- t.string :repo_url
13
- t.string :before_commit
14
- t.boolean :forced
15
- t.string :after_commit
16
- t.boolean :running
17
- t.boolean :successful
18
- t.text :output
19
- t.timestamps
20
- t.timestamp :started_at
21
- t.timestamp :ended_at
22
- t.text :payload
23
- end
24
- end
25
-
26
- def self.down
27
- drop_table :jobs
28
- end
29
- end