Remote and Global tasks
This commit is contained in:
parent
9b428bcf95
commit
6544e9eec3
|
@ -9,7 +9,7 @@ Gem::Specification.new do |s|
|
||||||
|
|
||||||
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
||||||
s.authors = ["Nick Gauthier"]
|
s.authors = ["Nick Gauthier"]
|
||||||
s.date = %q{2010-02-09}
|
s.date = %q{2010-02-10}
|
||||||
s.description = %q{Spread your tests over multiple machines to test your code faster.}
|
s.description = %q{Spread your tests over multiple machines to test your code faster.}
|
||||||
s.email = %q{nick@smartlogicsolutions.com}
|
s.email = %q{nick@smartlogicsolutions.com}
|
||||||
s.extra_rdoc_files = [
|
s.extra_rdoc_files = [
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
|
require 'open3'
|
||||||
module Hydra #:nodoc:
|
module Hydra #:nodoc:
|
||||||
# Define a test task that uses hydra to test the files.
|
# Hydra Task Common attributes and methods
|
||||||
#
|
class Task
|
||||||
# TODO: examples
|
|
||||||
class TestTask
|
|
||||||
# Name of the task. Default 'hydra'
|
# Name of the task. Default 'hydra'
|
||||||
attr_accessor :name
|
attr_accessor :name
|
||||||
|
|
||||||
|
@ -19,6 +18,35 @@ module Hydra #:nodoc:
|
||||||
# Path to the hydra config file.
|
# Path to the hydra config file.
|
||||||
# If not set, it will check 'hydra.yml' and 'config/hydra.yml'
|
# If not set, it will check 'hydra.yml' and 'config/hydra.yml'
|
||||||
attr_accessor :config
|
attr_accessor :config
|
||||||
|
#
|
||||||
|
# Search for the hydra config file
|
||||||
|
def find_config_file
|
||||||
|
@config ||= 'hydra.yml'
|
||||||
|
return @config if File.exists?(@config)
|
||||||
|
@config = File.join('config', 'hydra.yml')
|
||||||
|
return @config if File.exists?(@config)
|
||||||
|
@config = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
# Add files to test by passing in a string to be run through Dir.glob.
|
||||||
|
# For example:
|
||||||
|
#
|
||||||
|
# t.add_files 'test/units/*.rb'
|
||||||
|
def add_files(pattern)
|
||||||
|
@files += Dir.glob(pattern)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
# Define a test task that uses hydra to test the files.
|
||||||
|
#
|
||||||
|
# Hydra::TestTask.new('hydra') do |t|
|
||||||
|
# t.add_files 'test/unit/**/*_test.rb'
|
||||||
|
# t.add_files 'test/functional/**/*_test.rb'
|
||||||
|
# t.add_files 'test/integration/**/*_test.rb'
|
||||||
|
# t.verbose = false # optionally set to true for lots of debug messages
|
||||||
|
# end
|
||||||
|
class TestTask < Hydra::Task
|
||||||
|
|
||||||
# Create a new HydraTestTask
|
# Create a new HydraTestTask
|
||||||
def initialize(name = :hydra)
|
def initialize(name = :hydra)
|
||||||
|
@ -45,6 +73,7 @@ module Hydra #:nodoc:
|
||||||
define
|
define
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
# Create the rake task defined by this HydraTestTask
|
# Create the rake task defined by this HydraTestTask
|
||||||
def define
|
def define
|
||||||
desc "Hydra Tests" + (@name == :hydra ? "" : " for #{@name}")
|
desc "Hydra Tests" + (@name == :hydra ? "" : " for #{@name}")
|
||||||
|
@ -55,22 +84,95 @@ module Hydra #:nodoc:
|
||||||
exit(0) #bypass test on_exit output
|
exit(0) #bypass test on_exit output
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Add files to test by passing in a string to be run through Dir.glob.
|
# Setup a task that will be run across all remote workers
|
||||||
# For example:
|
# Hydra::RemoteTask.new('db:reset')
|
||||||
#
|
#
|
||||||
# t.add_files 'test/units/*.rb'
|
# Then you can run:
|
||||||
def add_files(pattern)
|
# rake hydra:remote:db:reset
|
||||||
@files += Dir.glob(pattern)
|
class RemoteTask < Hydra::Task
|
||||||
|
include Open3
|
||||||
|
# Create a new hydra remote task with the given name.
|
||||||
|
# The task will be named hydra:remote:<name>
|
||||||
|
def initialize(name)
|
||||||
|
@name = name
|
||||||
|
yield self if block_given?
|
||||||
|
@config = find_config_file
|
||||||
|
|
||||||
|
unless @config
|
||||||
|
$stderr.write "No config file. Can't run a remote task without remote workers\n"
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
define
|
||||||
end
|
end
|
||||||
|
|
||||||
# Search for the hydra config file
|
private
|
||||||
def find_config_file
|
def define
|
||||||
@config ||= 'hydra.yml'
|
desc "Run #{@name} remotely on all workers"
|
||||||
return @config if File.exists?(@config)
|
task "hydra:remote:#{@name}" do
|
||||||
@config = File.join('config', 'hydra.yml')
|
config = YAML.load_file(@config)
|
||||||
return @config if File.exists?(@config)
|
workers = config.fetch('workers') { [] }
|
||||||
@config = nil
|
workers = workers.select{|w| w['type'] == 'ssh'}
|
||||||
|
raise "No remote workers" if workers.empty?
|
||||||
|
workers.each do |worker|
|
||||||
|
$stdout.write "==== Hydra Running #{@name} on #{worker['connect']} ====\n"
|
||||||
|
ssh_opts = worker.fetch('ssh_opts') { '' }
|
||||||
|
writer, reader, error = popen3("ssh -tt #{ssh_opts} #{worker['connect']} ")
|
||||||
|
writer.write("cd #{worker['directory']}\n")
|
||||||
|
writer.write "echo BEGIN HYDRA\n"
|
||||||
|
writer.write("RAILS_ENV=test rake #{@name}\n")
|
||||||
|
writer.write "echo END HYDRA\n"
|
||||||
|
writer.write("exit\n")
|
||||||
|
writer.close
|
||||||
|
ignoring = true
|
||||||
|
while line = reader.gets
|
||||||
|
line.chomp!
|
||||||
|
if line =~ /echo END HYDRA$/
|
||||||
|
ignoring = true
|
||||||
|
end
|
||||||
|
$stdout.write "#{line}\n" unless ignoring
|
||||||
|
if line == 'BEGIN HYDRA'
|
||||||
|
ignoring = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
$stdout.write "\n==== Hydra Running #{@name} COMPLETE ====\n\n"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# A Hydra global task is a task that is run both locally and remotely.
|
||||||
|
#
|
||||||
|
# For example:
|
||||||
|
#
|
||||||
|
# Hydra::GlobalTask.new('db:reset')
|
||||||
|
#
|
||||||
|
# Allows you to run:
|
||||||
|
#
|
||||||
|
# rake hydra:db:reset
|
||||||
|
#
|
||||||
|
# Then, db:reset will be run locally and on all remote workers. This
|
||||||
|
# makes it easy to setup your workers and run tasks all in a row.
|
||||||
|
#
|
||||||
|
# For example:
|
||||||
|
#
|
||||||
|
# rake hydra:db:reset hydra:factories hydra:tests
|
||||||
|
#
|
||||||
|
# Assuming you setup hydra:db:reset and hydra:db:factories as global
|
||||||
|
# tasks and hydra:tests as a Hydra::TestTask for all your tests
|
||||||
|
class GlobalTask < Hydra::Task
|
||||||
|
def initialize(name)
|
||||||
|
@name = name
|
||||||
|
define
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def define
|
||||||
|
Hydra::RemoteTask.new(@name)
|
||||||
|
desc "Run #{@name.to_s} Locally and Remotely across all Workers"
|
||||||
|
task "hydra:#{@name.to_s}" => [@name.to_s, "hydra:remote:#{@name.to_s}"]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue