hydra 0.9.0 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. data/README.rdoc +26 -0
  2. data/VERSION +1 -1
  3. data/hydra.gemspec +2 -2
  4. data/lib/hydra/tasks.rb +119 -17
  5. metadata +2 -2
@@ -32,6 +32,26 @@ Run:
32
32
  Hydra defaults to Single Core mode, so you may want to configure it
33
33
  to use two (or more) of your cores if you have a multi-processing machine.
34
34
 
35
+ == Running Remote Tasks
36
+
37
+ You can run tasks across all of your remote workers easily with Hydra. In your rake file, add:
38
+
39
+ Hydra::RemoteTask.new('db:reset')
40
+
41
+ Then you can run:
42
+
43
+ rake hydra:remote:db:reset
44
+
45
+ == Running Global Tasks
46
+
47
+ A Global task is a task run locally *and* remotely. It's used in the same way as RemoteTask:
48
+
49
+ Hydra::GlobalTask.new('db:reset')
50
+
51
+ But it is invoked in a higher namespace:
52
+
53
+ rake hydra:db:reset
54
+
35
55
  == Configuration
36
56
 
37
57
  Place the config file in the main project directory as
@@ -112,6 +132,12 @@ Use ssh_opts to set the port or compression options.
112
132
  The *directory* option is the path for the project directory
113
133
  where the tests should be run.
114
134
 
135
+ == More Information
136
+
137
+ For more information on Hydra, check out the rdocs:
138
+
139
+ http://rdoc.info/projects/ngauthier/hydra
140
+
115
141
  == Copyright
116
142
 
117
143
  Copyright (c) 2010 Nick Gauthier. See LICENSE for details.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.9.0
1
+ 0.10.0
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{hydra}
8
- s.version = "0.9.0"
8
+ s.version = "0.10.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Nick Gauthier"]
12
- s.date = %q{2010-02-09}
12
+ s.date = %q{2010-02-10}
13
13
  s.description = %q{Spread your tests over multiple machines to test your code faster.}
14
14
  s.email = %q{nick@smartlogicsolutions.com}
15
15
  s.extra_rdoc_files = [
@@ -1,8 +1,7 @@
1
+ require 'open3'
1
2
  module Hydra #:nodoc:
2
- # Define a test task that uses hydra to test the files.
3
- #
4
- # TODO: examples
5
- class TestTask
3
+ # Hydra Task Common attributes and methods
4
+ class Task
6
5
  # Name of the task. Default 'hydra'
7
6
  attr_accessor :name
8
7
 
@@ -19,6 +18,35 @@ module Hydra #:nodoc:
19
18
  # Path to the hydra config file.
20
19
  # If not set, it will check 'hydra.yml' and 'config/hydra.yml'
21
20
  attr_accessor :config
21
+ #
22
+ # Search for the hydra config file
23
+ def find_config_file
24
+ @config ||= 'hydra.yml'
25
+ return @config if File.exists?(@config)
26
+ @config = File.join('config', 'hydra.yml')
27
+ return @config if File.exists?(@config)
28
+ @config = nil
29
+ end
30
+
31
+ # Add files to test by passing in a string to be run through Dir.glob.
32
+ # For example:
33
+ #
34
+ # t.add_files 'test/units/*.rb'
35
+ def add_files(pattern)
36
+ @files += Dir.glob(pattern)
37
+ end
38
+
39
+ end
40
+
41
+ # Define a test task that uses hydra to test the files.
42
+ #
43
+ # Hydra::TestTask.new('hydra') do |t|
44
+ # t.add_files 'test/unit/**/*_test.rb'
45
+ # t.add_files 'test/functional/**/*_test.rb'
46
+ # t.add_files 'test/integration/**/*_test.rb'
47
+ # t.verbose = false # optionally set to true for lots of debug messages
48
+ # end
49
+ class TestTask < Hydra::Task
22
50
 
23
51
  # Create a new HydraTestTask
24
52
  def initialize(name = :hydra)
@@ -45,6 +73,7 @@ module Hydra #:nodoc:
45
73
  define
46
74
  end
47
75
 
76
+ private
48
77
  # Create the rake task defined by this HydraTestTask
49
78
  def define
50
79
  desc "Hydra Tests" + (@name == :hydra ? "" : " for #{@name}")
@@ -55,22 +84,95 @@ module Hydra #:nodoc:
55
84
  exit(0) #bypass test on_exit output
56
85
  end
57
86
  end
87
+ end
58
88
 
59
- # Add files to test by passing in a string to be run through Dir.glob.
60
- # For example:
61
- #
62
- # t.add_files 'test/units/*.rb'
63
- def add_files(pattern)
64
- @files += Dir.glob(pattern)
89
+ # Setup a task that will be run across all remote workers
90
+ # Hydra::RemoteTask.new('db:reset')
91
+ #
92
+ # Then you can run:
93
+ # rake hydra:remote:db:reset
94
+ class RemoteTask < Hydra::Task
95
+ include Open3
96
+ # Create a new hydra remote task with the given name.
97
+ # The task will be named hydra:remote:<name>
98
+ def initialize(name)
99
+ @name = name
100
+ yield self if block_given?
101
+ @config = find_config_file
102
+
103
+ unless @config
104
+ $stderr.write "No config file. Can't run a remote task without remote workers\n"
105
+ return
106
+ end
107
+
108
+ define
65
109
  end
66
110
 
67
- # Search for the hydra config file
68
- def find_config_file
69
- @config ||= 'hydra.yml'
70
- return @config if File.exists?(@config)
71
- @config = File.join('config', 'hydra.yml')
72
- return @config if File.exists?(@config)
73
- @config = nil
111
+ private
112
+ def define
113
+ desc "Run #{@name} remotely on all workers"
114
+ task "hydra:remote:#{@name}" do
115
+ config = YAML.load_file(@config)
116
+ workers = config.fetch('workers') { [] }
117
+ workers = workers.select{|w| w['type'] == 'ssh'}
118
+ raise "No remote workers" if workers.empty?
119
+ workers.each do |worker|
120
+ $stdout.write "==== Hydra Running #{@name} on #{worker['connect']} ====\n"
121
+ ssh_opts = worker.fetch('ssh_opts') { '' }
122
+ writer, reader, error = popen3("ssh -tt #{ssh_opts} #{worker['connect']} ")
123
+ writer.write("cd #{worker['directory']}\n")
124
+ writer.write "echo BEGIN HYDRA\n"
125
+ writer.write("RAILS_ENV=test rake #{@name}\n")
126
+ writer.write "echo END HYDRA\n"
127
+ writer.write("exit\n")
128
+ writer.close
129
+ ignoring = true
130
+ while line = reader.gets
131
+ line.chomp!
132
+ if line =~ /echo END HYDRA$/
133
+ ignoring = true
134
+ end
135
+ $stdout.write "#{line}\n" unless ignoring
136
+ if line == 'BEGIN HYDRA'
137
+ ignoring = false
138
+ end
139
+ end
140
+ $stdout.write "\n==== Hydra Running #{@name} COMPLETE ====\n\n"
141
+ end
142
+ end
143
+ end
144
+ end
145
+
146
+ # A Hydra global task is a task that is run both locally and remotely.
147
+ #
148
+ # For example:
149
+ #
150
+ # Hydra::GlobalTask.new('db:reset')
151
+ #
152
+ # Allows you to run:
153
+ #
154
+ # rake hydra:db:reset
155
+ #
156
+ # Then, db:reset will be run locally and on all remote workers. This
157
+ # makes it easy to setup your workers and run tasks all in a row.
158
+ #
159
+ # For example:
160
+ #
161
+ # rake hydra:db:reset hydra:factories hydra:tests
162
+ #
163
+ # Assuming you setup hydra:db:reset and hydra:db:factories as global
164
+ # tasks and hydra:tests as a Hydra::TestTask for all your tests
165
+ class GlobalTask < Hydra::Task
166
+ def initialize(name)
167
+ @name = name
168
+ define
169
+ end
170
+
171
+ private
172
+ def define
173
+ Hydra::RemoteTask.new(@name)
174
+ desc "Run #{@name.to_s} Locally and Remotely across all Workers"
175
+ task "hydra:#{@name.to_s}" => [@name.to_s, "hydra:remote:#{@name.to_s}"]
74
176
  end
75
177
  end
76
178
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hydra
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nick Gauthier
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-02-09 00:00:00 -05:00
12
+ date: 2010-02-10 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency