testbot 0.4.7 → 0.4.8

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,7 @@
1
+ 0.4.8
2
+
3
+ Removed all remaining native dependencies to make testbot simpler to install.
4
+
1
5
  0.4.7
2
6
 
3
7
  - Refactored the code into modules with one directory for each.
data/README.markdown CHANGED
@@ -69,7 +69,7 @@ Using testbot with Rails 3:
69
69
 
70
70
  Using testbot with Rails 2:
71
71
 
72
- ruby script/plugin install git://github.com/joakimk/testbot.git -r 'refs/tags/v0.4.7'
72
+ ruby script/plugin install git://github.com/joakimk/testbot.git -r 'refs/tags/v0.4.8'
73
73
  script/generate testbot --connect 192.168.0.100
74
74
 
75
75
  rake testbot:spec (or :test, :features)
data/lib/runner/job.rb CHANGED
@@ -33,7 +33,7 @@ module Testbot::Runner
33
33
  def measure_run_time
34
34
  start_time = Time.now
35
35
  yield
36
- Time.now - start_time
36
+ (Time.now - start_time) * 100
37
37
  end
38
38
 
39
39
  def run_and_return_result(command)
data/lib/server/build.rb CHANGED
@@ -1,6 +1,10 @@
1
1
  module Testbot::Server
2
2
 
3
- class Build < Sequel::Model
3
+ class Build < MemoryModel
4
+
5
+ def initialize(hash)
6
+ super({ :success => true, :done => false, :results => '' }.merge(hash))
7
+ end
4
8
 
5
9
  def self.create_and_build_jobs(hash)
6
10
  hash["jruby"] = (hash["jruby"] == "true") ? 1 : 0
@@ -10,21 +14,21 @@ module Testbot::Server
10
14
  end
11
15
 
12
16
  def create_jobs!(available_runner_usage)
13
- groups = Group.build(self[:files].split, self[:sizes].split.map { |size| size.to_i },
14
- Runner.total_instances.to_f * (available_runner_usage.to_i / 100.0), self[:type])
17
+ groups = Group.build(self.files.split, self.sizes.split.map { |size| size.to_i },
18
+ Runner.total_instances.to_f * (available_runner_usage.to_i / 100.0), self.type)
15
19
  groups.each do |group|
16
20
  Job.create(:files => group.join(' '),
17
- :root => self[:root],
18
- :project => self[:project],
19
- :type => self[:type],
20
- :requester_mac => self[:requester_mac],
21
- :build_id => self[:id],
22
- :jruby => self[:jruby])
21
+ :root => self.root,
22
+ :project => self.project,
23
+ :type => self.type,
24
+ :requester_mac => self.requester_mac,
25
+ :build => self,
26
+ :jruby => self.jruby)
23
27
  end
24
28
  end
25
29
 
26
30
  def destroy
27
- Job.filter([ 'build_id = ?', self[:id] ]).each { |job| job.destroy }
31
+ Job.all.find_all { |j| j.build == self }.each { |job| job.destroy }
28
32
  super
29
33
  end
30
34
 
data/lib/server/job.rb CHANGED
@@ -1,17 +1,18 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), 'db.rb'))
2
-
3
1
  module Testbot::Server
4
2
 
5
- class Job < Sequel::Model
3
+ class Job < MemoryModel
4
+
5
+ attribute :success, :boolean
6
+
6
7
  def update(hash)
7
8
  super(hash)
8
- if build = Build.find([ "id = ?", self[:build_id] ])
9
- done = Job.filter([ "result IS NULL AND build_id = ?", self[:build_id] ]).count == 0
10
- build.update(:results => build[:results].to_s + hash[:result].to_s,
11
- :done => done)
9
+ if self.build
10
+ done = !Job.all.find { |j| !j.result && j.build == self.build }
11
+ self.build.update(:results => build.results.to_s + self.result.to_s,
12
+ :done => done)
12
13
 
13
- build_broken_by_job = (hash[:success] == "false" && build[:success])
14
- build.update(:success => false) if build_broken_by_job
14
+ build_broken_by_job = (!self.success && build.success)
15
+ self.build.update(:success => false) if build_broken_by_job
15
16
  end
16
17
  end
17
18
 
@@ -19,29 +20,27 @@ module Testbot::Server
19
20
  clean_params = params.reject { |k, v| [ "requester_mac", "no_jruby" ].include?(k) }
20
21
  runner = Runner.record! clean_params.merge({ :ip => remove_addr, :last_seen_at => Time.now })
21
22
  return unless Server.valid_version?(params[:version])
22
- [ next_job_query(params["requester_mac"], params["no_jruby"]).first, runner ]
23
+ [ next_job(params["requester_mac"], params["no_jruby"]), runner ]
23
24
  end
24
25
 
25
26
  private
26
27
 
27
- def self.next_job_query(requester_mac, no_jruby)
28
+ def self.next_job(requester_mac, no_jruby)
28
29
  release_jobs_taken_by_missing_runners!
29
- query = Job.filter("taken_at IS NULL").order("Random()".lit)
30
- filters = []
31
- filters << "requester_mac = '#{requester_mac}'" if requester_mac
32
- filters << "jruby != 1" if no_jruby
33
- if filters.empty?
34
- query
35
- else
36
- query.filter(filters.join(' AND '))
37
- end
30
+ jobs = Job.all.find_all { |j|
31
+ !j.taken_at &&
32
+ (requester_mac ? j.requester_mac == requester_mac : true) &&
33
+ (no_jruby ? j.jruby != 1 : true)
34
+ }
35
+
36
+ jobs[rand(jobs.size)]
38
37
  end
39
38
 
40
39
  def self.release_jobs_taken_by_missing_runners!
41
- missing_runners = Runner.filter([ "last_seen_at < ?", (Time.now - Runner.timeout) ])
42
- missing_runners.each { |r|
43
- Job.filter(:taken_by_id => r[:id]).update(:taken_at => nil)
44
- }
40
+ missing_runners = Runner.all.find_all { |r| r.last_seen_at < (Time.now - Runner.timeout) }
41
+ missing_runners.each { |runner|
42
+ Job.all.find_all { |job| job.taken_by == runner }.each { |job| job.update(:taken_at => nil) }
43
+ }
45
44
  end
46
45
  end
47
46
 
@@ -0,0 +1,87 @@
1
+ class MemoryModel < OpenStruct
2
+
3
+ @@db = {}
4
+ @@types = {}
5
+
6
+ def initialize(hash)
7
+ @@types[self.class] ||= {}
8
+ hash = resolve_types(symbolize_keys(hash))
9
+ super(hash)
10
+ end
11
+
12
+ def id
13
+ object_id
14
+ end
15
+
16
+ def type
17
+ @table[:type]
18
+ end
19
+
20
+ def update(hash)
21
+ @table.merge!(resolve_types(symbolize_keys(hash)))
22
+ self
23
+ end
24
+
25
+ def destroy
26
+ self.class.all.delete_if { |b| b.id == id }
27
+ end
28
+
29
+ def self.find(id)
30
+ all.find { |r| r.id == id.to_i }
31
+ end
32
+
33
+ def self.create(hash = {})
34
+ all << new(hash)
35
+ all[-1]
36
+ end
37
+
38
+ def self.all
39
+ @@db[self] ||= []
40
+ @@db[self]
41
+ end
42
+
43
+ def self.first
44
+ all.first
45
+ end
46
+
47
+ def self.delete_all
48
+ all.clear
49
+ end
50
+
51
+ def self.count
52
+ all.size
53
+ end
54
+
55
+ def self.attribute(attribute, type)
56
+ @@types[self] ||= {}
57
+ @@types[self][attribute] = type
58
+ end
59
+
60
+ private
61
+
62
+ def resolve_types(hash)
63
+ hash.each { |attribute, value|
64
+ case @@types[self.class][attribute]
65
+ when :integer
66
+ hash[attribute] = value.to_i
67
+ when :boolean
68
+ if value == "true"
69
+ hash[attribute] = true
70
+ elsif value == "false"
71
+ hash[attribute] = false
72
+ elsif value != true && value != false
73
+ hash[attribute] = nil
74
+ end
75
+ end
76
+ }
77
+ hash
78
+ end
79
+
80
+ def symbolize_keys(hash)
81
+ h = {}
82
+ hash.each { |k, v| h[k.to_sym] = v }
83
+ h
84
+ end
85
+
86
+ end
87
+
data/lib/server/runner.rb CHANGED
@@ -1,15 +1,16 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), 'db.rb'))
2
-
3
1
  module Testbot::Server
4
2
 
5
- class Runner < Sequel::Model
3
+ class Runner < MemoryModel
4
+
5
+ attribute :idle_instances, :integer
6
+ attribute :max_instances, :integer
6
7
 
7
8
  def self.record!(hash)
8
9
  create_or_update_by_mac!(hash)
9
10
  end
10
11
 
11
12
  def self.create_or_update_by_mac!(hash)
12
- if (runner = find(:uid => hash[:uid]))
13
+ if runner = find_by_uid(hash[:uid])
13
14
  runner.update hash
14
15
  else
15
16
  Runner.create hash
@@ -20,21 +21,25 @@ module Testbot::Server
20
21
  10
21
22
  end
22
23
 
24
+ def self.find_by_uid(uid)
25
+ all.find { |r| r.uid == uid }
26
+ end
27
+
23
28
  def self.find_all_outdated
24
- DB[:runners].filter("version != ? OR version IS NULL", Testbot.version)
29
+ all.find_all { |r| r.version != Testbot.version }
25
30
  end
26
31
 
27
32
  def self.find_all_available
28
- DB[:runners].filter("version = ? AND last_seen_at > ?", Testbot.version, Time.now - Runner.timeout)
33
+ all.find_all { |r| r.version == Testbot.version && r.last_seen_at > (Time.now - Runner.timeout) }
29
34
  end
30
35
 
31
36
  def self.available_instances
32
- find_all_available.inject(0) { |sum, r| r[:idle_instances] + sum }
37
+ find_all_available.inject(0) { |sum, r| r.idle_instances + sum }
33
38
  end
34
39
 
35
40
  def self.total_instances
36
41
  return 1 if ENV['INTEGRATION_TEST']
37
- find_all_available.inject(0) { |sum, r| r[:max_instances] + sum }
42
+ find_all_available.inject(0) { |sum, r| r.max_instances + sum }
38
43
  end
39
44
 
40
45
  end
data/lib/server/server.rb CHANGED
@@ -3,6 +3,7 @@ require 'sinatra'
3
3
  require 'yaml'
4
4
  require 'json'
5
5
  require File.expand_path(File.join(File.dirname(__FILE__), '/../shared/testbot'))
6
+ require File.expand_path(File.join(File.dirname(__FILE__), 'memory_model.rb'))
6
7
  require File.expand_path(File.join(File.dirname(__FILE__), 'job.rb'))
7
8
  require File.expand_path(File.join(File.dirname(__FILE__), 'group.rb')) #unless defined?(Group)
8
9
  require File.expand_path(File.join(File.dirname(__FILE__), 'runner.rb'))
@@ -23,36 +24,36 @@ module Testbot::Server
23
24
  end
24
25
 
25
26
  post '/builds' do
26
- build = Build.create_and_build_jobs(params)[:id].to_s
27
+ build = Build.create_and_build_jobs(params).id.to_s
27
28
  end
28
29
 
29
30
  get '/builds/:id' do
30
- build = Build.find(:id => params[:id].to_i)
31
- build.destroy if build[:done]
32
- { "done" => build[:done], "results" => build[:results], "success" => build[:success] }.to_json
31
+ build = Build.find(params[:id])
32
+ build.destroy if build.done
33
+ { "done" => build.done, "results" => build.results, "success" => build.success }.to_json
33
34
  end
34
35
 
35
36
  get '/jobs/next' do
36
37
  next_job, runner = Job.next(params, @env['REMOTE_ADDR'])
37
38
  if next_job
38
- next_job.update(:taken_at => Time.now, :taken_by_id => runner.id)
39
- [ next_job[:id], next_job[:requester_mac], next_job[:project], next_job[:root], next_job[:type], (next_job[:jruby] == 1 ? 'jruby' : 'ruby'), next_job[:files] ].join(',')
39
+ next_job.update(:taken_at => Time.now, :taken_by => runner)
40
+ [ next_job.id, next_job.requester_mac, next_job.project, next_job.root, next_job.type, (next_job.jruby == 1 ? 'jruby' : 'ruby'), next_job.files ].join(',')
40
41
  end
41
42
  end
42
43
 
43
44
  put '/jobs/:id' do
44
- Job.find(:id => params[:id].to_i).update(:result => params[:result], :success => params[:success]); nil
45
+ Job.find(params[:id]).update(:result => params[:result], :success => params[:success]); nil
45
46
  end
46
47
 
47
48
  get '/runners/ping' do
48
49
  return unless Server.valid_version?(params[:version])
49
- runner = Runner.find(:uid => params[:uid])
50
+ runner = Runner.find_by_uid(params[:uid])
50
51
  runner.update(params.merge({ :last_seen_at => Time.now })) if runner
51
52
  nil
52
53
  end
53
54
 
54
55
  get '/runners/outdated' do
55
- Runner.find_all_outdated.map { |runner| [ runner[:ip], runner[:hostname], runner[:uid] ].join(' ') }.join("\n").strip
56
+ Runner.find_all_outdated.map { |runner| [ runner.ip, runner.hostname, runner.uid ].join(' ') }.join("\n").strip
56
57
  end
57
58
 
58
59
  get '/runners/available_instances' do
@@ -64,7 +65,7 @@ module Testbot::Server
64
65
  end
65
66
 
66
67
  get '/runners/available' do
67
- Runner.find_all_available.map { |runner| [ runner[:ip], runner[:hostname], runner[:uid], runner[:username], runner[:idle_instances] ].join(' ') }.join("\n").strip
68
+ Runner.find_all_available.map { |runner| [ runner.ip, runner.hostname, runner.uid, runner.username, runner.idle_instances ].join(' ') }.join("\n").strip
68
69
  end
69
70
 
70
71
  get '/version' do
@@ -7,7 +7,7 @@ module Testbot
7
7
 
8
8
  # Don't forget to update readme and changelog
9
9
  def self.version
10
- version = "0.4.7"
10
+ version = "0.4.8"
11
11
  dev_version_file = File.join(File.dirname(__FILE__), '..', '..', 'DEV_VERSION')
12
12
  if File.exists?(dev_version_file)
13
13
  version += File.read(dev_version_file)
data/testbot.gemspec CHANGED
@@ -17,12 +17,8 @@ Gem::Specification.new do |s|
17
17
  s.add_dependency('httparty', '>= 0.6.1')
18
18
  s.add_dependency('macaddr', '>= 1.0.0')
19
19
  s.add_dependency('net-ssh', '>= 2.0.23')
20
- s.add_dependency('sequel', '>= 3.16.0')
21
- s.add_dependency('json', '>= 1.4.6')
20
+ s.add_dependency('json_pure', '>= 1.4.6')
22
21
  s.add_dependency('daemons', '>= 1.0.10')
23
22
  s.add_dependency('acts_as_rails3_generator')
24
-
25
- # Could work with older versions, but not newer (when deploying on debian)
26
- s.add_dependency('sqlite3-ruby', '= 1.2.5')
27
23
  end
28
24
 
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: 1
4
+ hash: 31
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 4
9
- - 7
10
- version: 0.4.7
9
+ - 8
10
+ version: 0.4.8
11
11
  platform: ruby
12
12
  authors:
13
13
  - "Joakim Kolsj\xC3\xB6"
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-12-05 00:00:00 +01:00
18
+ date: 2010-12-06 00:00:00 +01:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -83,25 +83,9 @@ dependencies:
83
83
  type: :runtime
84
84
  version_requirements: *id004
85
85
  - !ruby/object:Gem::Dependency
86
- name: sequel
86
+ name: json_pure
87
87
  prerelease: false
88
88
  requirement: &id005 !ruby/object:Gem::Requirement
89
- none: false
90
- requirements:
91
- - - ">="
92
- - !ruby/object:Gem::Version
93
- hash: 71
94
- segments:
95
- - 3
96
- - 16
97
- - 0
98
- version: 3.16.0
99
- type: :runtime
100
- version_requirements: *id005
101
- - !ruby/object:Gem::Dependency
102
- name: json
103
- prerelease: false
104
- requirement: &id006 !ruby/object:Gem::Requirement
105
89
  none: false
106
90
  requirements:
107
91
  - - ">="
@@ -113,11 +97,11 @@ dependencies:
113
97
  - 6
114
98
  version: 1.4.6
115
99
  type: :runtime
116
- version_requirements: *id006
100
+ version_requirements: *id005
117
101
  - !ruby/object:Gem::Dependency
118
102
  name: daemons
119
103
  prerelease: false
120
- requirement: &id007 !ruby/object:Gem::Requirement
104
+ requirement: &id006 !ruby/object:Gem::Requirement
121
105
  none: false
122
106
  requirements:
123
107
  - - ">="
@@ -129,11 +113,11 @@ dependencies:
129
113
  - 10
130
114
  version: 1.0.10
131
115
  type: :runtime
132
- version_requirements: *id007
116
+ version_requirements: *id006
133
117
  - !ruby/object:Gem::Dependency
134
118
  name: acts_as_rails3_generator
135
119
  prerelease: false
136
- requirement: &id008 !ruby/object:Gem::Requirement
120
+ requirement: &id007 !ruby/object:Gem::Requirement
137
121
  none: false
138
122
  requirements:
139
123
  - - ">="
@@ -143,23 +127,7 @@ dependencies:
143
127
  - 0
144
128
  version: "0"
145
129
  type: :runtime
146
- version_requirements: *id008
147
- - !ruby/object:Gem::Dependency
148
- name: sqlite3-ruby
149
- prerelease: false
150
- requirement: &id009 !ruby/object:Gem::Requirement
151
- none: false
152
- requirements:
153
- - - "="
154
- - !ruby/object:Gem::Version
155
- hash: 21
156
- segments:
157
- - 1
158
- - 2
159
- - 5
160
- version: 1.2.5
161
- type: :runtime
162
- version_requirements: *id009
130
+ version_requirements: *id007
163
131
  description: Testbot is a test distribution tool that works with Rails, RSpec, Test::Unit and Cucumber.
164
132
  email:
165
133
  - joakim.kolsjo@gmail.com
@@ -178,9 +146,9 @@ files:
178
146
  - lib/runner/job.rb
179
147
  - lib/runner/runner.rb
180
148
  - lib/server/build.rb
181
- - lib/server/db.rb
182
149
  - lib/server/group.rb
183
150
  - lib/server/job.rb
151
+ - lib/server/memory_model.rb
184
152
  - lib/server/runner.rb
185
153
  - lib/server/server.rb
186
154
  - lib/shared/adapters/adapter.rb
data/lib/server/db.rb DELETED
@@ -1,49 +0,0 @@
1
- require 'sequel'
2
-
3
- module Testbot::Server
4
-
5
- DB = Sequel.sqlite
6
-
7
- DB.create_table :builds do
8
- primary_key :id
9
- String :files
10
- String :sizes
11
- String :results, :default => ''
12
- String :root
13
- String :project
14
- String :type
15
- String :requester_mac
16
- Integer :jruby
17
- Boolean :success, :default => true
18
- Boolean :done, :default => false
19
- end
20
-
21
-
22
- DB.create_table :jobs do
23
- primary_key :id
24
- String :files
25
- String :result
26
- String :root
27
- String :project
28
- String :type
29
- String :requester_mac
30
- Integer :jruby
31
- Integer :build_id
32
- Integer :taken_by_id
33
- Boolean :success
34
- Datetime :taken_at, :default => nil
35
- end
36
-
37
- DB.create_table :runners do
38
- primary_key :id
39
- String :ip
40
- String :hostname
41
- String :uid
42
- String :username
43
- String :version
44
- Integer :idle_instances
45
- Integer :max_instances
46
- Datetime :last_seen_at
47
- end
48
-
49
- end