testbot 0.5.8 → 0.5.9

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,11 @@
1
+ 0.5.9
2
+
3
+ When you hit ctrl+c all related test jobs will be stopped (within about 5 seconds). You can
4
+ now exit, change code and re-run much faster than before.
5
+
6
+ It does not stop before_run or code fetch. But no tests will be run after
7
+ those complete when the build is stopped.
8
+
1
9
  0.5.8
2
10
 
3
11
  Now only running tests from one build on a runner at a time.
data/README.markdown CHANGED
@@ -64,7 +64,7 @@ Using testbot with Rails 2:
64
64
 
65
65
  # Add testbot to your Gemfile if you use bundler. You also need the plugin because
66
66
  # Rails 2 does not load raketasks from gems.
67
- ruby script/plugin install git://github.com/joakimk/testbot.git -r 'refs/tags/v0.5.8'
67
+ ruby script/plugin install git://github.com/joakimk/testbot.git -r 'refs/tags/v0.5.9'
68
68
  script/generate testbot --connect 192.168.0.100
69
69
 
70
70
  rake testbot:spec (or :rspec, :test, :features)
@@ -107,6 +107,7 @@ Features
107
107
  * Testbot will try to balance the testload so that every computer finishes running the tests at the same time to reduce the time it takes to run the entire test suite. It does a good job, but has potential for further improvement.
108
108
  * You can access your testbot network through SSH by using the built in SSH tunneling code.
109
109
  * You can use the same testbot network with multiple projects.
110
+ * You can abort a test run with ctrl+c and all remote processes will be stopped.
110
111
  * Testbot is continuously tested for compability with Ruby 1.8.7 and 1.9.2.
111
112
 
112
113
  Contributing to testbot
@@ -53,6 +53,7 @@ module Testbot::Requester
53
53
  :sizes => sizes.join(' '),
54
54
  :jruby => jruby? })
55
55
 
56
+ trap("SIGINT") { HTTParty.delete("#{server_uri}/builds/#{build_id}"); return false }
56
57
 
57
58
  last_results_size = 0
58
59
  success = true
data/lib/runner/job.rb CHANGED
@@ -14,6 +14,7 @@ module Testbot::Runner
14
14
  end
15
15
 
16
16
  def run(instance)
17
+ return if @killed
17
18
  puts "Running job #{@id} (build #{@build_id})... "
18
19
  test_env_number = (instance == 0) ? '' : instance + 1
19
20
  result = "\n#{`hostname`.chomp}:#{Dir.pwd}\n"
@@ -28,6 +29,14 @@ module Testbot::Runner
28
29
  puts "Job #{@id} finished."
29
30
  end
30
31
 
32
+ def kill!(build_id)
33
+ if @build_id == build_id && @test_process
34
+ # The child process that runs the tests is a shell, we need to kill it's child process
35
+ system("pkill -KILL -P #{@test_process.pid}")
36
+ @killed = true
37
+ end
38
+ end
39
+
31
40
  private
32
41
 
33
42
  def measure_run_time
@@ -37,7 +46,10 @@ module Testbot::Runner
37
46
  end
38
47
 
39
48
  def run_and_return_result(command)
40
- `#{command} 2>&1`
49
+ @test_process = open("|#{command} 2>&1", 'r')
50
+ output = @test_process.read
51
+ @test_process.close
52
+ output
41
53
  end
42
54
 
43
55
  def success?
data/lib/runner/runner.rb CHANGED
@@ -107,9 +107,9 @@ module Testbot::Runner
107
107
  before_run(job) if File.exists?("#{job.project}/lib/tasks/testbot.rake")
108
108
  end
109
109
 
110
+ @last_build_id = job.build_id
110
111
  @instances << [ Thread.new { job.run(free_instance_number) },
111
112
  free_instance_number, job ]
112
- @last_build_id = job.build_id
113
113
  loop do
114
114
  clear_completed_instances
115
115
  break unless max_instances_running?
@@ -164,7 +164,7 @@ module Testbot::Runner
164
164
 
165
165
  def ping_params
166
166
  { :hostname => (@hostname ||= `hostname`.chomp), :max_instances => @config.max_instances,
167
- :idle_instances => (@config.max_instances - @instances.size), :username => ENV['USER'] }.merge(base_params)
167
+ :idle_instances => (@config.max_instances - @instances.size), :username => ENV['USER'], :build_id => @last_build_id }.merge(base_params)
168
168
  end
169
169
 
170
170
  def base_params
@@ -191,7 +191,11 @@ module Testbot::Runner
191
191
  Thread.new do
192
192
  while true
193
193
  begin
194
- Server.get("/runners/ping", :body => ping_params)
194
+ response = Server.get("/runners/ping", :body => ping_params).body
195
+ if response.include?('stop_build')
196
+ build_id = response.split(',').last
197
+ @instances.each { |instance, n, job| job.kill!(build_id) }
198
+ end
195
199
  rescue
196
200
  end
197
201
  sleep TIME_BETWEEN_PINGS
data/lib/server/server.rb CHANGED
@@ -33,6 +33,12 @@ module Testbot::Server
33
33
  { "done" => build.done, "results" => build.results, "success" => build.success }.to_json
34
34
  end
35
35
 
36
+ delete '/builds/:id' do
37
+ build = Build.find(params[:id])
38
+ build.destroy if build
39
+ nil
40
+ end
41
+
36
42
  get '/jobs/next' do
37
43
  next_job, runner = Job.next(params, @env['REMOTE_ADDR'])
38
44
  if next_job
@@ -48,7 +54,12 @@ module Testbot::Server
48
54
  get '/runners/ping' do
49
55
  return unless Server.valid_version?(params[:version])
50
56
  runner = Runner.find_by_uid(params[:uid])
51
- runner.update(params.merge({ :last_seen_at => Time.now })) if runner
57
+ if runner
58
+ runner.update(params.reject { |k, v| k == "build_id" }.merge({ :last_seen_at => Time.now, :build => Build.find(params[:build_id]) }))
59
+ unless params[:build_id] == '' || params[:build_id] == nil || runner.build
60
+ return "stop_build,#{params[:build_id]}"
61
+ end
62
+ end
52
63
  nil
53
64
  end
54
65
 
@@ -1,7 +1,7 @@
1
1
  module Testbot
2
2
  # Don't forget to update readme and changelog
3
3
  def self.version
4
- version = "0.5.8"
4
+ version = "0.5.9"
5
5
  dev_version_file = File.join(File.dirname(__FILE__), '..', '..', 'DEV_VERSION')
6
6
  if File.exists?(dev_version_file)
7
7
  version += File.read(dev_version_file)
@@ -330,8 +330,9 @@ module Testbot::Server
330
330
  end
331
331
 
332
332
  should "update data on the runner" do
333
+ build = Build.create
333
334
  runner = Runner.create(:uid => 'aa:aa:..')
334
- get "/runners/ping", :uid => 'aa:aa:..', :max_instances => 4, :idle_instances => 2, :hostname => "hostname1", :version => Testbot.version, :username => 'jocke'
335
+ get "/runners/ping", :uid => 'aa:aa:..', :max_instances => 4, :idle_instances => 2, :hostname => "hostname1", :version => Testbot.version, :username => 'jocke', :build_id => build.id
335
336
  assert last_response.ok?
336
337
  assert_equal 'aa:aa:..', runner.uid
337
338
  assert_equal 4, runner.max_instances
@@ -339,6 +340,7 @@ module Testbot::Server
339
340
  assert_equal 'hostname1', runner.hostname
340
341
  assert_equal Testbot.version, runner.version
341
342
  assert_equal 'jocke', runner.username
343
+ assert_equal build, runner.build
342
344
  end
343
345
 
344
346
  should "do nothing if the version does not match" do
@@ -353,6 +355,20 @@ module Testbot::Server
353
355
  assert last_response.ok?
354
356
  end
355
357
 
358
+ should "return an order to stop the build if the build id does not exist anymore" do
359
+ runner = Runner.create(:uid => 'aa:aa:..')
360
+ get "/runners/ping", :uid => 'aa:aa:..', :max_instances => 4, :idle_instances => 2, :hostname => "hostname1", :version => Testbot.version, :username => 'jocke', :build_id => 1
361
+ assert_equal last_response.body, "stop_build,1"
362
+ end
363
+
364
+ should "not return an order to stop a build without an id" do
365
+ runner = Runner.create(:uid => 'aa:aa:..')
366
+ get "/runners/ping", :uid => 'aa:aa:..', :max_instances => 4, :idle_instances => 2, :hostname => "hostname1", :version => Testbot.version, :username => 'jocke', :build_id => ''
367
+ assert_equal last_response.body, ''
368
+ get "/runners/ping", :uid => 'aa:aa:..', :max_instances => 4, :idle_instances => 2, :hostname => "hostname1", :version => Testbot.version, :username => 'jocke', :build_id => nil
369
+ assert_equal last_response.body, ''
370
+ end
371
+
356
372
  end
357
373
 
358
374
  context "PUT /jobs/:id" do
@@ -409,11 +425,11 @@ module Testbot::Server
409
425
 
410
426
  should "return runner information in json format" do
411
427
  get '/jobs/next', :version => Testbot.version, :uid => "00:01"
412
- get "/runners/ping", :uid => '00:01', :max_instances => 4, :idle_instances => 2, :hostname => "hostname1", :version => Testbot.version, :username => 'testbot'
428
+ get "/runners/ping", :uid => '00:01', :max_instances => 4, :idle_instances => 2, :hostname => "hostname1", :version => Testbot.version, :username => 'testbot', :build_id => nil
413
429
  get '/runners'
414
430
 
415
431
  assert last_response.ok?
416
- assert_equal ([ { "version" => Testbot.version.to_s, "hostname" => 'hostname1', "uid" => "00:01",
432
+ assert_equal ([ { "version" => Testbot.version.to_s, "build" => nil, "hostname" => 'hostname1', "uid" => "00:01",
417
433
  "idle_instances" => 2, "max_instances" => 4, "username" => 'testbot',
418
434
  "ip" => "127.0.0.1", "last_seen_at" => Runner.first.last_seen_at.to_s } ]),
419
435
  JSON.parse(last_response.body)
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: testbot
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 25
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 5
9
- - 8
10
- version: 0.5.8
9
+ - 9
10
+ version: 0.5.9
11
11
  platform: ruby
12
12
  authors:
13
13
  - "Joakim Kolsj\xC3\xB6"
@@ -15,11 +15,13 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-06-29 00:00:00 +02:00
18
+ date: 2011-06-30 00:00:00 +02:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
- version_requirements: &id001 !ruby/object:Gem::Requirement
22
+ name: sinatra
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
23
25
  none: false
24
26
  requirements:
25
27
  - - "="
@@ -30,12 +32,12 @@ dependencies:
30
32
  - 0
31
33
  - 0
32
34
  version: 1.0.0
33
- prerelease: false
34
- name: sinatra
35
35
  type: :runtime
36
- requirement: *id001
36
+ version_requirements: *id001
37
37
  - !ruby/object:Gem::Dependency
38
- version_requirements: &id002 !ruby/object:Gem::Requirement
38
+ name: httparty
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
39
41
  none: false
40
42
  requirements:
41
43
  - - ">="
@@ -46,12 +48,12 @@ dependencies:
46
48
  - 6
47
49
  - 1
48
50
  version: 0.6.1
49
- prerelease: false
50
- name: httparty
51
51
  type: :runtime
52
- requirement: *id002
52
+ version_requirements: *id002
53
53
  - !ruby/object:Gem::Dependency
54
- version_requirements: &id003 !ruby/object:Gem::Requirement
54
+ name: macaddr
55
+ prerelease: false
56
+ requirement: &id003 !ruby/object:Gem::Requirement
55
57
  none: false
56
58
  requirements:
57
59
  - - ">="
@@ -62,12 +64,12 @@ dependencies:
62
64
  - 0
63
65
  - 0
64
66
  version: 1.0.0
65
- prerelease: false
66
- name: macaddr
67
67
  type: :runtime
68
- requirement: *id003
68
+ version_requirements: *id003
69
69
  - !ruby/object:Gem::Dependency
70
- version_requirements: &id004 !ruby/object:Gem::Requirement
70
+ name: net-ssh
71
+ prerelease: false
72
+ requirement: &id004 !ruby/object:Gem::Requirement
71
73
  none: false
72
74
  requirements:
73
75
  - - ">="
@@ -78,12 +80,12 @@ dependencies:
78
80
  - 0
79
81
  - 23
80
82
  version: 2.0.23
81
- prerelease: false
82
- name: net-ssh
83
83
  type: :runtime
84
- requirement: *id004
84
+ version_requirements: *id004
85
85
  - !ruby/object:Gem::Dependency
86
- version_requirements: &id005 !ruby/object:Gem::Requirement
86
+ name: json_pure
87
+ prerelease: false
88
+ requirement: &id005 !ruby/object:Gem::Requirement
87
89
  none: false
88
90
  requirements:
89
91
  - - ">="
@@ -94,12 +96,12 @@ dependencies:
94
96
  - 4
95
97
  - 6
96
98
  version: 1.4.6
97
- prerelease: false
98
- name: json_pure
99
99
  type: :runtime
100
- requirement: *id005
100
+ version_requirements: *id005
101
101
  - !ruby/object:Gem::Dependency
102
- version_requirements: &id006 !ruby/object:Gem::Requirement
102
+ name: daemons
103
+ prerelease: false
104
+ requirement: &id006 !ruby/object:Gem::Requirement
103
105
  none: false
104
106
  requirements:
105
107
  - - ">="
@@ -110,12 +112,12 @@ dependencies:
110
112
  - 0
111
113
  - 10
112
114
  version: 1.0.10
113
- prerelease: false
114
- name: daemons
115
115
  type: :runtime
116
- requirement: *id006
116
+ version_requirements: *id006
117
117
  - !ruby/object:Gem::Dependency
118
- version_requirements: &id007 !ruby/object:Gem::Requirement
118
+ name: acts_as_rails3_generator
119
+ prerelease: false
120
+ requirement: &id007 !ruby/object:Gem::Requirement
119
121
  none: false
120
122
  requirements:
121
123
  - - ">="
@@ -124,12 +126,12 @@ dependencies:
124
126
  segments:
125
127
  - 0
126
128
  version: "0"
127
- prerelease: false
128
- name: acts_as_rails3_generator
129
129
  type: :runtime
130
- requirement: *id007
130
+ version_requirements: *id007
131
131
  - !ruby/object:Gem::Dependency
132
- version_requirements: &id008 !ruby/object:Gem::Requirement
132
+ name: shoulda
133
+ prerelease: false
134
+ requirement: &id008 !ruby/object:Gem::Requirement
133
135
  none: false
134
136
  requirements:
135
137
  - - ">="
@@ -138,12 +140,12 @@ dependencies:
138
140
  segments:
139
141
  - 0
140
142
  version: "0"
141
- prerelease: false
142
- name: shoulda
143
143
  type: :development
144
- requirement: *id008
144
+ version_requirements: *id008
145
145
  - !ruby/object:Gem::Dependency
146
- version_requirements: &id009 !ruby/object:Gem::Requirement
146
+ name: rack-test
147
+ prerelease: false
148
+ requirement: &id009 !ruby/object:Gem::Requirement
147
149
  none: false
148
150
  requirements:
149
151
  - - ">="
@@ -152,12 +154,12 @@ dependencies:
152
154
  segments:
153
155
  - 0
154
156
  version: "0"
155
- prerelease: false
156
- name: rack-test
157
157
  type: :development
158
- requirement: *id009
158
+ version_requirements: *id009
159
159
  - !ruby/object:Gem::Dependency
160
- version_requirements: &id010 !ruby/object:Gem::Requirement
160
+ name: flexmock
161
+ prerelease: false
162
+ requirement: &id010 !ruby/object:Gem::Requirement
161
163
  none: false
162
164
  requirements:
163
165
  - - ">="
@@ -166,12 +168,12 @@ dependencies:
166
168
  segments:
167
169
  - 0
168
170
  version: "0"
169
- prerelease: false
170
- name: flexmock
171
171
  type: :development
172
- requirement: *id010
172
+ version_requirements: *id010
173
173
  - !ruby/object:Gem::Dependency
174
- version_requirements: &id011 !ruby/object:Gem::Requirement
174
+ name: cucumber
175
+ prerelease: false
176
+ requirement: &id011 !ruby/object:Gem::Requirement
175
177
  none: false
176
178
  requirements:
177
179
  - - ">="
@@ -180,12 +182,12 @@ dependencies:
180
182
  segments:
181
183
  - 0
182
184
  version: "0"
183
- prerelease: false
184
- name: cucumber
185
185
  type: :development
186
- requirement: *id011
186
+ version_requirements: *id011
187
187
  - !ruby/object:Gem::Dependency
188
- version_requirements: &id012 !ruby/object:Gem::Requirement
188
+ name: rvm
189
+ prerelease: false
190
+ requirement: &id012 !ruby/object:Gem::Requirement
189
191
  none: false
190
192
  requirements:
191
193
  - - ">="
@@ -194,12 +196,12 @@ dependencies:
194
196
  segments:
195
197
  - 0
196
198
  version: "0"
197
- prerelease: false
198
- name: rvm
199
199
  type: :development
200
- requirement: *id012
200
+ version_requirements: *id012
201
201
  - !ruby/object:Gem::Dependency
202
- version_requirements: &id013 !ruby/object:Gem::Requirement
202
+ name: rake
203
+ prerelease: false
204
+ requirement: &id013 !ruby/object:Gem::Requirement
203
205
  none: false
204
206
  requirements:
205
207
  - - ">="
@@ -208,12 +210,12 @@ dependencies:
208
210
  segments:
209
211
  - 0
210
212
  version: "0"
211
- prerelease: false
212
- name: rake
213
213
  type: :development
214
- requirement: *id013
214
+ version_requirements: *id013
215
215
  - !ruby/object:Gem::Dependency
216
- version_requirements: &id014 !ruby/object:Gem::Requirement
216
+ name: bundler
217
+ prerelease: false
218
+ requirement: &id014 !ruby/object:Gem::Requirement
217
219
  none: false
218
220
  requirements:
219
221
  - - ">="
@@ -222,12 +224,12 @@ dependencies:
222
224
  segments:
223
225
  - 0
224
226
  version: "0"
225
- prerelease: false
226
- name: bundler
227
227
  type: :development
228
- requirement: *id014
228
+ version_requirements: *id014
229
229
  - !ruby/object:Gem::Dependency
230
- version_requirements: &id015 !ruby/object:Gem::Requirement
230
+ name: guard
231
+ prerelease: false
232
+ requirement: &id015 !ruby/object:Gem::Requirement
231
233
  none: false
232
234
  requirements:
233
235
  - - ">="
@@ -236,12 +238,12 @@ dependencies:
236
238
  segments:
237
239
  - 0
238
240
  version: "0"
239
- prerelease: false
240
- name: guard
241
241
  type: :development
242
- requirement: *id015
242
+ version_requirements: *id015
243
243
  - !ruby/object:Gem::Dependency
244
- version_requirements: &id016 !ruby/object:Gem::Requirement
244
+ name: guard-test
245
+ prerelease: false
246
+ requirement: &id016 !ruby/object:Gem::Requirement
245
247
  none: false
246
248
  requirements:
247
249
  - - ">="
@@ -250,10 +252,8 @@ dependencies:
250
252
  segments:
251
253
  - 0
252
254
  version: "0"
253
- prerelease: false
254
- name: guard-test
255
255
  type: :development
256
- requirement: *id016
256
+ version_requirements: *id016
257
257
  description: Testbot is a test distribution tool that works with Rails, RSpec, RSpec2, Test::Unit and Cucumber.
258
258
  email:
259
259
  - joakim.kolsjo@gmail.com