testbot 0.4.7 → 0.4.8

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/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