borg 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+
6
+ gem 'eventmachine'
7
+ gem 'redis'
8
+
9
+ # Add dependencies to develop your gem here.
10
+ # Include everything needed to run rake, tests, features, etc.
11
+ group :development do
12
+ gem "bundler", "~> 1.0.0"
13
+ gem "jeweler", "~> 1.5.2"
14
+ gem "rspec"
15
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,30 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ diff-lcs (1.1.2)
5
+ eventmachine (0.12.10)
6
+ git (1.2.5)
7
+ jeweler (1.5.2)
8
+ bundler (~> 1.0.0)
9
+ git (>= 1.2.5)
10
+ rake
11
+ rake (0.8.7)
12
+ redis (2.1.1)
13
+ rspec (2.5.0)
14
+ rspec-core (~> 2.5.0)
15
+ rspec-expectations (~> 2.5.0)
16
+ rspec-mocks (~> 2.5.0)
17
+ rspec-core (2.5.1)
18
+ rspec-expectations (2.5.0)
19
+ diff-lcs (~> 1.1.2)
20
+ rspec-mocks (2.5.0)
21
+
22
+ PLATFORMS
23
+ ruby
24
+
25
+ DEPENDENCIES
26
+ bundler (~> 1.0.0)
27
+ eventmachine
28
+ jeweler (~> 1.5.2)
29
+ redis
30
+ rspec
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Hemant Kumar
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,23 @@
1
+ = Borg
2
+
3
+ Borg is a distributed test runner for running you unit/functionals tests, specs or cucumber scenarios, across a network of machines.
4
+
5
+ It is written using EventMachine and Redis and has rather very simple design at its heart.
6
+ More details forthcoming..
7
+
8
+
9
+ == Contributing to tickle
10
+
11
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
12
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
13
+ * Fork the project
14
+ * Start a feature/bugfix branch
15
+ * Commit and push until you are happy with your contribution
16
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
17
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
18
+
19
+ == Copyright
20
+
21
+ Copyright (c) 2011 Hemant Kumar. See LICENSE.txt for
22
+ further details.
23
+
data/Rakefile ADDED
@@ -0,0 +1,42 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'rake'
11
+
12
+ require 'jeweler'
13
+ Jeweler::Tasks.new do |gem|
14
+ gem.name = "borg"
15
+ gem.homepage = "http://github.com/gnufied/borg"
16
+ gem.license = "MIT"
17
+ gem.summary = %Q{A distributed Test Suite runner for Rails, using Eventmachine and Redis}
18
+ gem.description = %Q{A distributed Test Suite runner for Rails, using Eventmachine and Redis}
19
+ gem.email = "hkumar@crri.co.in"
20
+ gem.authors = ["Hemant Kumar", "Karunakar"]
21
+ end
22
+
23
+ Jeweler::RubygemsDotOrgTasks.new
24
+
25
+ require 'rake/testtask'
26
+ Rake::TestTask.new(:test) do |test|
27
+ test.libs << 'lib' << 'test'
28
+ test.pattern = 'test/**/test_*.rb'
29
+ test.verbose = true
30
+ end
31
+
32
+ task :default => :test
33
+
34
+ require 'rake/rdoctask'
35
+ Rake::RDocTask.new do |rdoc|
36
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
37
+
38
+ rdoc.rdoc_dir = 'rdoc'
39
+ rdoc.title = "borg #{version}"
40
+ rdoc.rdoc_files.include('README*')
41
+ rdoc.rdoc_files.include('lib/**/*.rb')
42
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.6
data/borg.gemspec ADDED
@@ -0,0 +1,72 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{borg}
8
+ s.version = "0.0.6"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Hemant Kumar", "Karunakar"]
12
+ s.date = %q{2011-02-07}
13
+ s.description = %q{A distributed Test Suite runner for Rails, using Eventmachine and Redis}
14
+ s.email = %q{hkumar@crri.co.in}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ "Gemfile",
22
+ "Gemfile.lock",
23
+ "LICENSE.txt",
24
+ "README.rdoc",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "borg.gemspec",
28
+ "lib/borg.rb",
29
+ "lib/borg/borg_abstract_adapter.rb",
30
+ "lib/borg/borg_config.rb",
31
+ "lib/borg/borg_cucumber.rb",
32
+ "lib/borg/borg_git.rb",
33
+ "lib/borg/borg_messages.rb",
34
+ "lib/borg/borg_requestor.rb",
35
+ "lib/borg/borg_server.rb",
36
+ "lib/borg/borg_tasks.rake",
37
+ "lib/borg/borg_test_unit.rb",
38
+ "lib/borg/borg_worker.rb",
39
+ "lib/borg/railtie.rb"
40
+ ]
41
+ s.homepage = %q{http://github.com/gnufied/borg}
42
+ s.licenses = ["MIT"]
43
+ s.require_paths = ["lib"]
44
+ s.rubygems_version = %q{1.3.7}
45
+ s.summary = %q{A distributed Test Suite runner for Rails, using Eventmachine and Redis}
46
+
47
+ if s.respond_to? :specification_version then
48
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
49
+ s.specification_version = 3
50
+
51
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
52
+ s.add_runtime_dependency(%q<eventmachine>, [">= 0"])
53
+ s.add_runtime_dependency(%q<redis>, [">= 0"])
54
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
55
+ s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
56
+ s.add_development_dependency(%q<rspec>, [">= 0"])
57
+ else
58
+ s.add_dependency(%q<eventmachine>, [">= 0"])
59
+ s.add_dependency(%q<redis>, [">= 0"])
60
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
61
+ s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
62
+ s.add_dependency(%q<rspec>, [">= 0"])
63
+ end
64
+ else
65
+ s.add_dependency(%q<eventmachine>, [">= 0"])
66
+ s.add_dependency(%q<redis>, [">= 0"])
67
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
68
+ s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
69
+ s.add_dependency(%q<rspec>, [">= 0"])
70
+ end
71
+ end
72
+
@@ -0,0 +1,138 @@
1
+ module Borg
2
+ module AbstractAdapter
3
+ def load_environment(env_name)
4
+ puts "Loading Rails.."
5
+ ENV["RAILS_ENV"] = env_name
6
+ Rails.env = env_name
7
+ require(File.join(Rails.root, 'config', 'environment'))
8
+ $: << "#{Rails.root}/test"
9
+ $: << "#{Rails.root}/test/test_helpers"
10
+ require File.join(Rails.root, "test", "test_helper")
11
+ end
12
+
13
+ # Free file descriptors and
14
+ # point them somewhere sensible
15
+ # STDOUT/STDERR should go to a logfile
16
+ def redirect_io(logfile_name)
17
+ begin
18
+ ; STDIN.reopen "/dev/null";
19
+ rescue ::Exception;
20
+ end
21
+
22
+ if logfile_name
23
+ begin
24
+ STDOUT.reopen logfile_name, "a"
25
+ STDOUT.sync = true
26
+ rescue ::Exception
27
+ begin
28
+ ; STDOUT.reopen "/dev/null";
29
+ rescue ::Exception;
30
+ end
31
+ end
32
+ else
33
+ begin
34
+ ; STDOUT.reopen "/dev/null";
35
+ rescue ::Exception;
36
+ end
37
+ end
38
+
39
+ begin
40
+ ; STDERR.reopen STDOUT;
41
+ rescue ::Exception;
42
+ end
43
+ STDERR.sync = true
44
+ end
45
+
46
+ def redirect_stdout
47
+ STDOUT.sync = true
48
+ begin
49
+ STDERR.reopen STDOUT;
50
+ rescue ::Exception;
51
+ end
52
+ STDERR.sync = true
53
+ end
54
+
55
+ def try_migration_first(db_counter)
56
+ begin
57
+ db_config = get_connection_config(db_counter)
58
+ ActiveRecord::Base.establish_connection(db_config)
59
+ ActiveRecord::Base.connection()
60
+ migrate_db()
61
+ return true
62
+ rescue Exception => e
63
+ puts e.message
64
+ return false
65
+ rescue StandardError
66
+ puts $!.message
67
+ return false
68
+ rescue Mysql2::Error
69
+ puts $!.message
70
+ return false
71
+ end
72
+ end
73
+
74
+ def prepare_databse(db_counter)
75
+ create_db_using_raw_sql(db_counter)
76
+ try_migration_first(db_counter)
77
+ end
78
+
79
+ def create_db_using_raw_sql(db_counter)
80
+ test_config = config['test']
81
+ sql_connection = Mysql2::Client.new(test_config.symbolize_keys)
82
+ db_config = get_connection_config(db_counter)
83
+ sql_connection.query("DROP DATABASE IF EXISTS #{db_config['database']}")
84
+ sql_connection.query("CREATE DATABASE #{db_config['database']}")
85
+ sql_connection.close()
86
+ end
87
+
88
+ def migrate_db
89
+ ENV["VERBOSE"] = "true"
90
+ Rake::Task["db:migrate"].invoke
91
+ end
92
+
93
+ def get_connection_config(db_counter)
94
+ default_settings = config["test"].clone()
95
+ default_settings['database'] = "#{default_settings['database']}_#{db_counter}"
96
+ default_settings
97
+ end
98
+
99
+ def config
100
+ ActiveRecord::Base.configurations
101
+ end
102
+
103
+ def redis
104
+ Redis.new(:host => Borg::Config.redis_ip,:port => Borg::Config.redis_port)
105
+ end
106
+
107
+ def add_files_to_redis(files,key)
108
+ redis.del key
109
+ files.each { |x| redis.rpush(key, x.join(",")) }
110
+ end
111
+
112
+ def remove_file_groups_from_redis(key,&block)
113
+ redis_has_files = true
114
+ @redis_connection = redis
115
+ all_status = []
116
+
117
+ loop do
118
+ local_pids = []
119
+ n.times do |index|
120
+ test_files = @redis_connection.rpop(key)
121
+ if(test_files)
122
+ local_pids << Process.fork { block.call(index,test_files) }
123
+ else
124
+ redis_has_files = false
125
+ break
126
+ end
127
+ end
128
+
129
+ Signal.trap 'SIGINT', lambda { local_pids.each { |p| Process.kill("KILL", p) }; exit 1 }
130
+ all_status += Process.waitall.map { |pid, status| status.exitstatus }
131
+ break unless redis_has_files
132
+ end #end of loop
133
+
134
+ raise "Error running #{key} tests" if (all_status.any? { |x| x != 0 })
135
+
136
+ end #end of method remove_file_groups_from_redis
137
+ end
138
+ end
@@ -0,0 +1,7 @@
1
+ module Borg
2
+ class Config
3
+ cattr_accessor :ip,:port
4
+ cattr_accessor :redis_ip, :redis_port
5
+ end
6
+ end
7
+
@@ -0,0 +1,28 @@
1
+ module Borg
2
+ class CucumberRunner
3
+ include AbstractAdapter
4
+
5
+ def run(n = 3)
6
+ redirect_stdout()
7
+ load_environment('cucumber')
8
+
9
+ remove_file_groups_from_redis('cucumber') do |index,feature_files|
10
+ prepare_databse(index) unless try_migration_first(index)
11
+ full_feature_path = feature_files.split(',').map do |fl|
12
+ Rails.root.to_s + fl
13
+ end
14
+ args = %w(--format progress) + full_feature_path
15
+ failure = Cucumber::Cli::Main.execute(args)
16
+ raise "Cucumber failed" if failure
17
+ end
18
+
19
+ end
20
+
21
+ def add_to_redis(worker_count)
22
+ feature_files = Dir["#{Rails.root}/features/**/*.feature"].map do |fl|
23
+ fl.gsub(/#{Rails.root}/,'')
24
+ end.sort.in_groups(worker_count, false)
25
+ add_files_to_redis(feature_files,'cucumber')
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,29 @@
1
+ require "fileutils"
2
+
3
+ module Borg
4
+
5
+ class Git
6
+ attr_accessor :status
7
+ def current_branch
8
+ cmd_output = `git symbolic-ref HEAD`
9
+ branch_name = cmd_output.strip.split("/")[-1]
10
+ branch_name
11
+ end
12
+
13
+ def update(worker)
14
+ FileUtils.cd(Rails.root) do
15
+ #update_command = "git reset --hard HEAD && git fetch && git rebase origin/#{current_branch} && git submodule init && git submodule update && bundle install --local"
16
+
17
+ update_command = "bundle install --local"
18
+ puts "Update command is #{update_command}"
19
+ EM.popen(update_command,TestRunner) do |process|
20
+ process.worker = worker
21
+ process.runner_type = 'git'
22
+ end
23
+
24
+ end
25
+
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,13 @@
1
+ module Borg
2
+ class StartBuild;end
3
+
4
+ class StartTest;end
5
+
6
+ class StartCucumber; end
7
+ class BuildRequester; end
8
+
9
+ BuildOutput = Struct.new(:data)
10
+ WorkerConnected = Struct.new(:name)
11
+ BuildStatus = Struct.new(:exit_status)
12
+ end
13
+
@@ -0,0 +1,42 @@
1
+ module Borg
2
+ class Requestor < EM::Connection
3
+ include EM::P::ObjectProtocol
4
+ def self.make_request
5
+ EM.connect(Borg::Config.ip,Borg::Config.port,Requestor)
6
+ end
7
+
8
+ def connection_completed
9
+ @server_running = true
10
+ send_object(BuildRequester.new())
11
+ end
12
+
13
+ def receive_object(ruby_object)
14
+ case ruby_object
15
+ when BuildOutput
16
+ print ruby_object.data
17
+ when BuildStatus
18
+ stop_build(ruby_object)
19
+ end
20
+ end
21
+
22
+ def unbind
23
+ unless @server_running
24
+ puts "Error running server"
25
+ EM.stop()
26
+ else
27
+ EM.stop()
28
+ end
29
+ end
30
+
31
+ def stop_build(ruby_object)
32
+ puts
33
+ if(ruby_object.exit_status == 0)
34
+ puts "Successfully ran all tests"
35
+ EM.stop()
36
+ else
37
+ abort("Error running tests")
38
+ end
39
+ end
40
+
41
+ end
42
+ end
@@ -0,0 +1,89 @@
1
+ module Borg
2
+ class Server < EM::Connection
3
+ include EM::P::ObjectProtocol
4
+ @@workers = {}
5
+ @@requester = {}
6
+
7
+ @@status_count = 0
8
+ @@status_reports = []
9
+ attr_accessor :client_type
10
+
11
+ def receive_object(ruby_object)
12
+ case ruby_object
13
+ when BuildOutput
14
+ send_to_requester(ruby_object)
15
+ when BuildStatus
16
+ puts "Received object #{ruby_object.inspect}"
17
+ collect_status_response(ruby_object)
18
+ when WorkerConnected
19
+ @@workers[self.signature] = self
20
+ @client_type = :worker
21
+ when BuildRequester
22
+ @@requester[self.signature] = self
23
+ @client_type = :requestor
24
+ check_for_workers && add_tests_to_redis && start_build
25
+ end
26
+ end
27
+
28
+ def check_for_workers
29
+ return true unless @@workers.empty?
30
+ send_error_to_requester("No worker found running")
31
+ false
32
+ end
33
+
34
+ def send_error_to_requester(message)
35
+ send_to_requester(BuildOutput.new(message))
36
+ send_to_requester(BuildStatus.new(1))
37
+ end
38
+
39
+ def add_tests_to_redis
40
+ begin
41
+ TestUnit.new().add_to_redis(@@workers.size * 3)
42
+ CucumberRunner.new().add_to_redis(@@workers.size * 3)
43
+ true
44
+ rescue
45
+ puts $!.message
46
+ puts $!.backtrace
47
+ send_error_to_requester("Error adding files to redis")
48
+ false
49
+ end
50
+ end
51
+
52
+ def collect_status_response(ruby_object)
53
+ @@status_reports << ruby_object
54
+ @@status_count -= 1
55
+ puts "Status count is #{@@status_count}"
56
+ if(@@status_count == 0)
57
+ error_status = @@status_reports.any? {|x| x.exit_status != 0 }
58
+ @@status_reports = []
59
+ if(error_status)
60
+ send_to_requester(BuildStatus.new(1))
61
+ else
62
+ send_to_requester(BuildStatus.new(0))
63
+ end
64
+ end
65
+ end
66
+
67
+ def unbind
68
+ @@workers.delete(self.signature)
69
+ @@requester.delete(self.signature)
70
+ if(client_type == :requestor)
71
+ @@status_count = 0
72
+ @@status_reports = []
73
+ end
74
+ end
75
+
76
+ def start_build
77
+ @@workers.each do |key,worker|
78
+ @@status_count += 1
79
+ worker.send_object(StartBuild.new())
80
+ end
81
+ end
82
+
83
+ def send_to_requester(ruby_object)
84
+ @@requester.each do |key,requester|
85
+ requester.send_object(ruby_object)
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,67 @@
1
+
2
+ namespace :borg do
3
+ [:unit, :functional].each do |t|
4
+ type = t.to_s.sub(/s$/, '')
5
+
6
+ desc "Run #{type} tests"
7
+ task t, :count do |t, args|
8
+ Borg.load_environment
9
+ size = args[:count] ? args[:count].to_i : 3
10
+ #Borg.prepare_all_databases(size)
11
+ puts "Running #{type} tests using #{size} processes"
12
+ Borg.run_tests type, size
13
+ end
14
+ end
15
+
16
+ desc "Request server to run test"
17
+ task :build => :environment do
18
+ # Borg::TestUnit.new().add_to_redis
19
+ # Borg::CucumberRunner.new().add_to_redis
20
+ EM.run {
21
+ Borg::Requestor.make_request
22
+ }
23
+ end
24
+
25
+ desc "Start server"
26
+ task :start_server => :environment do
27
+ EM.run {
28
+ puts "Ip is #{Borg::Config.ip} and #{Borg::Config.port}"
29
+ EM.start_server(Borg::Config.ip,Borg::Config.port,Borg::Server)
30
+ }
31
+ end
32
+
33
+ desc "Start Client"
34
+ task :start_client => :environment do
35
+ EM.run {
36
+ EM.connect(Borg::Config.ip,Borg::Config.port,Borg::Worker)
37
+ }
38
+ end
39
+
40
+ desc "Run unit and functional test"
41
+ task :test do
42
+ Borg::TestUnit.new().run()
43
+ end
44
+
45
+ desc "Run cucumber tests"
46
+ task :cucumber do
47
+ Borg::CucumberRunner.new().run()
48
+ end
49
+
50
+
51
+ # desc "Run redis tests"
52
+ # task :redis_test, :count do |t,args|
53
+ # Borg.load_environment('test')
54
+ # size = args[:count] ? args[:count].to_i : 3
55
+ # puts "Running tests using #{size} processes"
56
+ # Borg.run_redis_test(size)
57
+ # end
58
+ #
59
+ # desc "Run cucumber parallel test"
60
+ # task :cucumber, :count do |t,args|
61
+ # Borg.load_environment('cucumber')
62
+ # size = args[:count] ? args[:count].to_i : 3
63
+ # puts "Running Cucumber tests using #{size} processes"
64
+ # puts "Using the default profile..."
65
+ # Borg.run_cucumber(size)
66
+ # end
67
+ end
@@ -0,0 +1,23 @@
1
+ module Borg
2
+ class TestUnit
3
+ include AbstractAdapter
4
+
5
+ def run(n = 3)
6
+ redirect_stdout()
7
+ load_environment('test')
8
+ remove_file_groups_from_redis('tests') do |index,test_files|
9
+ prepare_databse(index) unless try_migration_first(index)
10
+ test_files.split(',').each do |fl|
11
+ load(Rails.root.to_s + fl)
12
+ end
13
+ end
14
+ end
15
+
16
+ def add_to_redis(worker_count)
17
+ test_files = (Dir["#{Rails.root}/test/unit/**/**_test.rb"] + Dir["#{Rails.root}/test/functional/**/**_test.rb"]).map do |fl|
18
+ fl.gsub(/#{Rails.root}/,'')
19
+ end.sort.in_groups(worker_count, false)
20
+ add_files_to_redis(test_files,'tests')
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,102 @@
1
+ module Borg
2
+ class Worker < EM::Connection
3
+ include EM::P::ObjectProtocol
4
+ @@status_reports = []
5
+
6
+ def receive_object(ruby_object)
7
+ case ruby_object
8
+ when StartBuild
9
+ update_code
10
+ when StartTest
11
+ start_test
12
+ end
13
+ end
14
+
15
+ def connection_completed
16
+ send_object(WorkerConnected.new(self.signature))
17
+ end
18
+
19
+ def unbind
20
+ EM.add_timer(3) {
21
+ reconnect(Borg::Config.ip,Borg::Config.port)
22
+ }
23
+ end
24
+
25
+ def update_code
26
+ source_control = Borg::Git.new()
27
+ source_control.update(self)
28
+ end
29
+
30
+ def redis
31
+ Redis.new(:host => Borg::Config.redis_ip,:port => Borg::Config.redis_port)
32
+ end
33
+
34
+ def code_updated(last_status)
35
+ if(last_status.exit_status == 0)
36
+ start_test
37
+ else
38
+ puts "sending error report"
39
+ send_object(BuildStatus.new(1))
40
+ end
41
+ end
42
+
43
+ def start_test
44
+ if(redis.llen("tests") > 0)
45
+ EM.popen("rake tickle:test RAILS_ENV=test", TestRunner) do |process|
46
+ process.worker = self
47
+ process.runner_type = 'unit'
48
+ end
49
+ else
50
+ start_cucumber(BuildStatus.new(0))
51
+ end
52
+ end
53
+
54
+ def start_cucumber(last_status)
55
+ @@status_reports << last_status
56
+ if(redis.llen("cucumber") > 0)
57
+ EM.popen("rake tickle:cucumber RAILS_ENV=cucumber",TestRunner) do |process|
58
+ process.worker = self
59
+ process.runner_type = 'cucumber'
60
+ end
61
+ else
62
+ send_final_report(BuildStatus.new(0))
63
+ end
64
+ end
65
+
66
+ def send_final_report(last_status)
67
+ @@status_reports << last_status
68
+ p @@status_reports
69
+ error_flag = @@status_reports.any? {|x| x.exit_status != 0}
70
+
71
+ if(error_flag)
72
+ send_object(BuildStatus.new(1))
73
+ else
74
+ send_object(BuildStatus.new(0))
75
+ end
76
+ @@status_reports = []
77
+ end
78
+ end
79
+
80
+ class TestRunner < EM::Connection
81
+ attr_accessor :worker
82
+ attr_accessor :runner_type
83
+
84
+ include EM::P::ObjectProtocol
85
+ def receive_data(data)
86
+ worker.send_object(BuildOutput.new(data))
87
+ end
88
+
89
+ def unbind
90
+ puts "Sending the status thingy"
91
+ case runner_type
92
+ when 'unit'
93
+ worker.start_cucumber(BuildStatus.new(get_status.exitstatus))
94
+ when 'git'
95
+ worker.code_updated(BuildStatus.new(get_status.exitstatus))
96
+ else
97
+ worker.send_final_report(BuildStatus.new(get_status.exitstatus))
98
+ end
99
+ end
100
+
101
+ end
102
+ end
@@ -0,0 +1,23 @@
1
+ require 'rails'
2
+ require "eventmachine"
3
+ require "redis"
4
+ require File.join(File.dirname(__FILE__),'borg_abstract_adapter')
5
+ require File.join(File.dirname(__FILE__),'borg_config')
6
+ require File.join(File.dirname(__FILE__),'borg_cucumber')
7
+ require File.join(File.dirname(__FILE__),'borg_git')
8
+ require File.join(File.dirname(__FILE__),'borg_messages')
9
+
10
+ require File.join(File.dirname(__FILE__),'borg_requestor')
11
+ require File.join(File.dirname(__FILE__),'borg_server')
12
+
13
+ require File.join(File.dirname(__FILE__),'borg_test_unit')
14
+ require File.join(File.dirname(__FILE__),'borg_worker')
15
+
16
+
17
+ module Borg
18
+ class Railtie < Rails::Railtie
19
+ rake_tasks do
20
+ load File.join(File.dirname(__FILE__),'borg_tasks.rake')
21
+ end
22
+ end
23
+ end
data/lib/borg.rb ADDED
@@ -0,0 +1,5 @@
1
+ module Borg
2
+ VERSION = "0.0.1"
3
+ require 'borg/railtie'
4
+ end
5
+
metadata ADDED
@@ -0,0 +1,161 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: borg
3
+ version: !ruby/object:Gem::Version
4
+ hash: 19
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 6
10
+ version: 0.0.6
11
+ platform: ruby
12
+ authors:
13
+ - Hemant Kumar
14
+ - Karunakar
15
+ autorequire:
16
+ bindir: bin
17
+ cert_chain: []
18
+
19
+ date: 2011-02-07 00:00:00 +05:30
20
+ default_executable:
21
+ dependencies:
22
+ - !ruby/object:Gem::Dependency
23
+ prerelease: false
24
+ type: :runtime
25
+ name: eventmachine
26
+ version_requirements: &id001 !ruby/object:Gem::Requirement
27
+ none: false
28
+ requirements:
29
+ - - ">="
30
+ - !ruby/object:Gem::Version
31
+ hash: 3
32
+ segments:
33
+ - 0
34
+ version: "0"
35
+ requirement: *id001
36
+ - !ruby/object:Gem::Dependency
37
+ prerelease: false
38
+ type: :runtime
39
+ name: redis
40
+ version_requirements: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ hash: 3
46
+ segments:
47
+ - 0
48
+ version: "0"
49
+ requirement: *id002
50
+ - !ruby/object:Gem::Dependency
51
+ prerelease: false
52
+ type: :development
53
+ name: bundler
54
+ version_requirements: &id003 !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ~>
58
+ - !ruby/object:Gem::Version
59
+ hash: 23
60
+ segments:
61
+ - 1
62
+ - 0
63
+ - 0
64
+ version: 1.0.0
65
+ requirement: *id003
66
+ - !ruby/object:Gem::Dependency
67
+ prerelease: false
68
+ type: :development
69
+ name: jeweler
70
+ version_requirements: &id004 !ruby/object:Gem::Requirement
71
+ none: false
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ hash: 7
76
+ segments:
77
+ - 1
78
+ - 5
79
+ - 2
80
+ version: 1.5.2
81
+ requirement: *id004
82
+ - !ruby/object:Gem::Dependency
83
+ prerelease: false
84
+ type: :development
85
+ name: rspec
86
+ version_requirements: &id005 !ruby/object:Gem::Requirement
87
+ none: false
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ hash: 3
92
+ segments:
93
+ - 0
94
+ version: "0"
95
+ requirement: *id005
96
+ description: A distributed Test Suite runner for Rails, using Eventmachine and Redis
97
+ email: hkumar@crri.co.in
98
+ executables: []
99
+
100
+ extensions: []
101
+
102
+ extra_rdoc_files:
103
+ - LICENSE.txt
104
+ - README.rdoc
105
+ files:
106
+ - .document
107
+ - Gemfile
108
+ - Gemfile.lock
109
+ - LICENSE.txt
110
+ - README.rdoc
111
+ - Rakefile
112
+ - VERSION
113
+ - borg.gemspec
114
+ - lib/borg.rb
115
+ - lib/borg/borg_abstract_adapter.rb
116
+ - lib/borg/borg_config.rb
117
+ - lib/borg/borg_cucumber.rb
118
+ - lib/borg/borg_git.rb
119
+ - lib/borg/borg_messages.rb
120
+ - lib/borg/borg_requestor.rb
121
+ - lib/borg/borg_server.rb
122
+ - lib/borg/borg_tasks.rake
123
+ - lib/borg/borg_test_unit.rb
124
+ - lib/borg/borg_worker.rb
125
+ - lib/borg/railtie.rb
126
+ has_rdoc: true
127
+ homepage: http://github.com/gnufied/borg
128
+ licenses:
129
+ - MIT
130
+ post_install_message:
131
+ rdoc_options: []
132
+
133
+ require_paths:
134
+ - lib
135
+ required_ruby_version: !ruby/object:Gem::Requirement
136
+ none: false
137
+ requirements:
138
+ - - ">="
139
+ - !ruby/object:Gem::Version
140
+ hash: 3
141
+ segments:
142
+ - 0
143
+ version: "0"
144
+ required_rubygems_version: !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - ">="
148
+ - !ruby/object:Gem::Version
149
+ hash: 3
150
+ segments:
151
+ - 0
152
+ version: "0"
153
+ requirements: []
154
+
155
+ rubyforge_project:
156
+ rubygems_version: 1.3.7
157
+ signing_key:
158
+ specification_version: 3
159
+ summary: A distributed Test Suite runner for Rails, using Eventmachine and Redis
160
+ test_files: []
161
+