cape 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. data/.gitignore +1 -0
  2. data/.travis.yml +1 -1
  3. data/Gemfile +11 -9
  4. data/Guardfile +17 -0
  5. data/History.markdown +10 -0
  6. data/MIT-LICENSE.markdown +1 -1
  7. data/README.markdown +58 -9
  8. data/Rakefile +1 -1
  9. data/cape.gemspec +13 -12
  10. data/features/dsl/each_rake_task/with_defined_namespace_argument.feature +8 -0
  11. data/features/dsl/each_rake_task/with_undefined_argument.feature +25 -1
  12. data/features/dsl/each_rake_task/without_arguments.feature +8 -0
  13. data/features/dsl/mirror_rake_tasks/inside_capistrano_namespace/with_defined_namespace_argument.feature +25 -0
  14. data/features/dsl/mirror_rake_tasks/inside_capistrano_namespace/without_arguments.feature +50 -4
  15. data/features/dsl/mirror_rake_tasks/with_defined_namespace_argument.feature +19 -0
  16. data/features/dsl/mirror_rake_tasks/with_defined_task_and_valid_options_arguments_and_environment_variables.feature +199 -0
  17. data/features/dsl/mirror_rake_tasks/with_valid_options_argument.feature +90 -0
  18. data/features/dsl/mirror_rake_tasks/without_arguments.feature +48 -5
  19. data/features/dsl/rake_executable.feature +10 -6
  20. data/features/step_definitions.rb +3 -0
  21. data/lib/cape/capistrano.rb +70 -40
  22. data/lib/cape/dsl.rb +76 -13
  23. data/lib/cape/rake.rb +30 -6
  24. data/lib/cape/version.rb +1 -1
  25. data/spec/cape/capistrano_spec.rb +16 -0
  26. data/spec/cape/dsl_spec.rb +108 -29
  27. data/spec/cape/rake_spec.rb +40 -0
  28. data/spec/cape/util_spec.rb +2 -2
  29. data/spec/cape/version_spec.rb +0 -1
  30. data/spec/cape_spec.rb +21 -3
  31. metadata +24 -18
  32. data/spec/cape/task_spec.rb +0 -0
data/.gitignore CHANGED
@@ -1,4 +1,5 @@
1
1
  .bundle
2
+ .rbx
2
3
  .rvmrc
3
4
  .yardoc
4
5
  Gemfile.lock
@@ -1,4 +1,4 @@
1
- bundler_args: --without debug doc
1
+ bundler_args: --without debug doc tooling
2
2
  rvm:
3
3
  - 1.8.7
4
4
  - 1.9.3
data/Gemfile CHANGED
@@ -3,16 +3,18 @@ source 'http://rubygems.org'
3
3
  gemspec
4
4
 
5
5
  group :debug do
6
- gem 'ruby-debug', :platforms => :mri_18
7
-
8
- # This is a dependency of ruby-debug. We're specifying it here because its
9
- # v0.45 is incompatible with Ruby v1.8.7.
10
- gem 'linecache', '<= 0.43', :platforms => :mri_18
11
-
12
- gem 'ruby-debug19', :platforms => :mri_19
6
+ gem 'ruby-debug', '~> 0', :platforms => :mri_18
7
+ gem 'ruby-debug19', '~> 0', :platforms => :mri_19, :require => 'ruby-debug'
13
8
  end
14
9
 
15
10
  group :doc do
16
- gem 'yard', :platforms => [:ruby, :mswin, :mingw]
17
- gem 'rdiscount', :platforms => [:ruby, :mswin, :mingw]
11
+ gem 'yard', '~> 0', :platforms => [:ruby, :mswin, :mingw]
12
+ gem 'rdiscount', '~> 1', :platforms => [:ruby, :mswin, :mingw]
13
+ end
14
+
15
+ group :tooling do
16
+ gem 'guard-rspec', '~> 0'
17
+ if RUBY_PLATFORM =~ /darwin/i
18
+ gem 'rb-fsevent', '~> 0', :require => false
19
+ end
18
20
  end
@@ -0,0 +1,17 @@
1
+ guard 'rspec', :cli => '--color', :version => 2 do
2
+ # Run the corresponding spec (or all specs) when code changes.
3
+ watch( %r{^lib/(.+)\.rb$} ) do |match|
4
+ corresponding_spec = "spec/#{match[1]}_spec.rb"
5
+ if File.file?( File.expand_path( "../#{corresponding_spec}", __FILE__ ))
6
+ corresponding_spec
7
+ else
8
+ 'spec'
9
+ end
10
+ end
11
+
12
+ # Run a spec when it changes.
13
+ watch %r{^spec/.+_spec\.rb$}
14
+
15
+ # Run all specs when the bundle changes.
16
+ watch( 'Gemfile.lock' ) { 'spec' }
17
+ end
@@ -1,5 +1,15 @@
1
1
  # Version history for the _Cape_ project
2
2
 
3
+ ## <a name="v1.2.0"></a>v1.2.0, Mon 1/30/2012
4
+
5
+ * Add support in the DSL for specifying remote environment variables and Capistrano recipe options
6
+ * Add support for Rake tasks that overlap with (have the same full name as) namespaces
7
+ * Match Rake tasks properly: by the full name of the task rather than a substring thereof
8
+ * Don’t choke on unexpected output from Rake
9
+ * Silence Rake stderr output while enumerating Rake tasks
10
+ * Tweak the wording of generated Capistrano recipe descriptions
11
+ * Tighten RubyGem dependency specifications in an effort to avoid potential compatibility issues
12
+
3
13
  ## <a name="v1.1.0"></a>v1.1.0, Thu 12/29/2011
4
14
 
5
15
  * Allow environment variables for Rake task arguments to be optional
@@ -1,6 +1,6 @@
1
1
  # The MIT License
2
2
 
3
- Source code for _Cape_ is Copyright © 2011 [Nils Jonsson](mailto:cape@nilsjonsson.com) and [contributors](http://github.com/njonsson/cape/contributors "Cape contributors at GitHub").
3
+ Source code for _Cape_ is Copyright © 2011–2012 [Nils Jonsson](mailto:cape@nilsjonsson.com) and [contributors](http://github.com/njonsson/cape/contributors "Cape contributors at GitHub").
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
6
 
@@ -29,7 +29,7 @@
29
29
  <hNNBNBh=(. / \ `
30
30
  ..
31
31
 
32
- # [<img align="right" src="https://secure.travis-ci.org/njonsson/cape.png?branch=master" title="Travis CI build status" />](http://travis-ci.org/njonsson/cape) Cape
32
+ # [<img align="right" src="https://gemnasium.com/njonsson/cape.png" title="Gemnasium build status" />](http://gemnasium.com/njonsson/cape) [<img align="right" src="https://secure.travis-ci.org/njonsson/cape.png?branch=master" title="Travis CI build status" />](http://travis-ci.org/njonsson/cape) Cape
33
33
 
34
34
  If
35
35
 
@@ -124,7 +124,7 @@ Let’s use Capistrano to view the unabbreviated description of a Rake task reci
124
124
  ------------------------------------------------------------
125
125
  Bags the leaves.
126
126
 
127
- Set environment variable PAPER_OR_PLASTIC to pass a Rake task argument.
127
+ Set environment variable PAPER_OR_PLASTIC if you want to pass a Rake task argument.
128
128
 
129
129
  Here’s how to invoke a task/recipe with arguments. On the local computer, via Rake:
130
130
 
@@ -137,7 +137,7 @@ On remote computers, via Capistrano:
137
137
 
138
138
  $ cap bag_leaves PAPER_OR_PLASTIC=plastic
139
139
  * executing `bag_leaves'
140
- * executing "cd /path/to/currently/deployed/version/of/your/app && rake bag_leaves[plastic]"
140
+ * executing "cd /path/to/currently/deployed/version/of/your/app && /usr/bin/env rake bag_leaves[plastic]"
141
141
  servers: ["your.server.name"]
142
142
  [your.server.name] executing command
143
143
  ** [out :: your.server.name] (in /path/to/currently/deployed/version/of/your/app)
@@ -154,13 +154,45 @@ Cape lets you filter the Rake tasks to be mirrored. Note that Cape statements mu
154
154
  require 'cape'
155
155
 
156
156
  Cape do
157
- # Create Capistrano recipes for the Rake task 'foo' or for the tasks in the
157
+ # Create Capistrano recipes for the Rake task 'foo' and/or for the tasks in the
158
158
  # 'foo' namespace.
159
159
  mirror_rake_tasks :foo
160
+ end
161
+
162
+ ### Mirror Rake tasks that require Capistrano recipe options and/or environment variables
163
+
164
+ Cape lets you specify options used for defining Capistrano recipes. You can also specify remote environment variables to be set when running Rake tasks. Note that Cape statements must be executed within a `Cape` block.
165
+
166
+ # config/deploy.rb
167
+
168
+ require 'cape'
169
+
170
+ Cape do
171
+ # Display defined Rails routes on application server remote machines only.
172
+ mirror_rake_tasks :routes, :roles => :app
173
+
174
+ # Execute database migration on application server remote machines only,
175
+ # and set the 'RAILS_ENV' environment variable to the value of the
176
+ # Capistrano variable 'rails_env'.
177
+ mirror_rake_tasks 'db:migrate', :roles => :app do |env|
178
+ env['RAILS_ENV'] = rails_env
179
+ end
180
+ end
181
+
182
+ The above is equivalent to the following manually-defined Capistrano recipes.
183
+
184
+ # config/deploy.rb
185
+
186
+ # These translations to Capistrano are just for illustration.
160
187
 
161
- # Create Capistrano recipes only for the Rake task 'bar:baz' or for the
162
- # tasks in the 'bar:baz' namespace.
163
- mirror_rake_tasks 'bar:baz'
188
+ task :routes, :roles => :app do
189
+ run "cd #{current_path} && /usr/bin/env rake routes"
190
+ end
191
+
192
+ namespace :db do
193
+ task :migrate, :roles => :app do
194
+ run "cd #{current_path} && /usr/bin/env rake db:migrate RAILS_ENV=#{rails_env}"
195
+ end
164
196
  end
165
197
 
166
198
  ### Mirror Rake tasks into a Capistrano namespace
@@ -195,13 +227,30 @@ Cape lets you enumerate Rake tasks, optionally filtering them by task name or na
195
227
  # * t[:description] -- documentation on the task, including parameters
196
228
  end
197
229
 
198
- # Enumerate the Rake task 'foo' or the tasks in the 'foo' namespace.
230
+ # Enumerate the Rake task 'foo' and/or the tasks in the 'foo' namespace.
199
231
  each_rake_task 'foo' do |t|
200
232
  # ...
201
233
  end
202
234
  end
203
235
 
204
- ## Limitations
236
+ ### Configure Rake execution
237
+
238
+ Cape lets you specify how Rake should be executed on the local computer and on remote computers. Note that Cape statements must be executed within a `Cape` block.
239
+
240
+ # config/deploy.rb
241
+
242
+ require 'cape'
243
+
244
+ # Configure Cape to execute Rake via Bundler, both locally and remotely.
245
+ Cape.local_rake_executable = '/usr/bin/env bundle exec rake'
246
+ Cape.remote_rake_executable = '/usr/bin/env bundle exec rake'
247
+
248
+ Cape do
249
+ # Create Capistrano recipes for all Rake tasks.
250
+ mirror_rake_tasks
251
+ end
252
+
253
+ ## Known issues
205
254
 
206
255
  For now, only Rake tasks that have descriptions can be mirrored or enumerated.
207
256
 
data/Rakefile CHANGED
@@ -30,7 +30,7 @@ def define_spec_task(name, options={})
30
30
  t.rspec_opts << '--debug'
31
31
  end
32
32
  end
33
- t.pattern = "spec/**/*_spec.rb"
33
+ t.pattern = %w(spec/*_spec.rb spec/**/*_spec.rb)
34
34
  end
35
35
  end
36
36
 
@@ -5,19 +5,20 @@ require 'cape/version'
5
5
  Gem::Specification.new do |s|
6
6
  s.name = 'cape'
7
7
  s.version = Cape::VERSION
8
+ s.summary = 'Dynamically generates Capistrano recipes for Rake tasks'
9
+ s.description = <<-end_description.gsub(/^\s+/, '').chomp
10
+ Cape dynamically generates Capistrano recipes for Rake tasks.
11
+ It provides a DSL for reflecting on Rake tasks and mirroring
12
+ them as documented Capistrano recipes. You can pass Rake task
13
+ arguments via environment variables.
14
+ end_description
8
15
  s.platform = Gem::Platform::RUBY
9
16
  s.authors = ['Nils Jonsson']
10
17
  s.email = %w(cape@nilsjonsson.com)
11
- s.homepage = ''
12
- s.summary = 'Dynamically generates Capistrano recipes for Rake tasks'
13
- s.description = 'Cape provides a simple DSL for selecting Rake tasks to be ' +
14
- 'made available as documented Capistrano recipes. You can ' +
15
- 'pass required arguments to Rake tasks via environment ' +
16
- 'variables.'
18
+ s.homepage = 'http://github.com/njonsson/cape'
17
19
  s.license = 'MIT'
18
20
 
19
- # TODO: Apply for RubyForge project
20
- # s.rubyforge_project = 'cape'
21
+ s.rubyforge_project = 'cape'
21
22
 
22
23
  s.required_ruby_version = '>= 1.8.7'
23
24
 
@@ -29,8 +30,8 @@ Gem::Specification.new do |s|
29
30
  s.require_paths = %w(lib)
30
31
  s.has_rdoc = true
31
32
 
32
- s.add_development_dependency 'aruba'
33
- s.add_development_dependency 'capistrano'
34
- s.add_development_dependency 'rake'
35
- s.add_development_dependency 'rspec', '~> 2.7'
33
+ s.add_development_dependency 'aruba', '~> 0'
34
+ s.add_development_dependency 'capistrano', '~> 2'
35
+ s.add_development_dependency 'rake', '~> 0'
36
+ s.add_development_dependency 'rspec', '~> 2'
36
37
  end
@@ -17,6 +17,7 @@ Feature: The #each_rake_task DSL method with an argument of a defined namespace
17
17
  if t[:description]
18
18
  $stdout.puts "Description: #{t[:description].inspect}"
19
19
  end
20
+ $stdout.puts 'Default' if t[:default]
20
21
  end
21
22
  end
22
23
  """
@@ -30,6 +31,13 @@ Feature: The #each_rake_task DSL method with an argument of a defined namespace
30
31
  And the output should contain:
31
32
  """
32
33
 
34
+ Name: "my_namespace"
35
+ Description: "A task that shadows a namespace"
36
+ Default
37
+ """
38
+ And the output should contain:
39
+ """
40
+
33
41
  Name: "my_namespace:in_a_namespace"
34
42
  Description: "My task in a namespace"
35
43
  """
@@ -4,7 +4,7 @@ Feature: The #each_rake_task DSL method with an undefined argument
4
4
  As a developer using Cape,
5
5
  I want to use the Cape DSL.
6
6
 
7
- Scenario: do not enumerate any Rake tasks
7
+ Scenario: do not enumerate any Rake tasks for a completely unrecognized argument
8
8
  Given a full-featured Rakefile
9
9
  And a Capfile with:
10
10
  """
@@ -27,3 +27,27 @@ Feature: The #each_rake_task DSL method with an undefined argument
27
27
  Name: "with_period"
28
28
  Description: "Ends with period."
29
29
  """
30
+
31
+ Scenario: do not enumerate any Rake tasks for a partially recognized argument
32
+ Given a full-featured Rakefile
33
+ And a Capfile with:
34
+ """
35
+ Cape do
36
+ each_rake_task :period do |t|
37
+ $stdout.puts '', "Name: #{t[:name].inspect}"
38
+ if t[:parameters]
39
+ $stdout.puts "Parameters: #{t[:parameters].inspect}"
40
+ end
41
+ if t[:description]
42
+ $stdout.puts "Description: #{t[:description].inspect}"
43
+ end
44
+ end
45
+ end
46
+ """
47
+ When I run `cap -T`
48
+ Then the output should not contain:
49
+ """
50
+
51
+ Name: "with_period"
52
+ Description: "Ends with period."
53
+ """
@@ -17,6 +17,7 @@ Feature: The #each_rake_task DSL method without arguments
17
17
  if t[:description]
18
18
  $stdout.puts "Description: #{t[:description].inspect}"
19
19
  end
20
+ $stdout.puts 'Default' if t[:default]
20
21
  end
21
22
  end
22
23
  """
@@ -49,6 +50,13 @@ Feature: The #each_rake_task DSL method without arguments
49
50
  And the output should contain:
50
51
  """
51
52
 
53
+ Name: "my_namespace"
54
+ Description: "A task that shadows a namespace"
55
+ Default
56
+ """
57
+ And the output should contain:
58
+ """
59
+
52
60
  Name: "my_namespace:in_a_namespace"
53
61
  Description: "My task in a namespace"
54
62
  """
@@ -16,6 +16,10 @@ Feature: The #mirror_rake_tasks DSL method, inside a Capistrano namespace, with
16
16
  """
17
17
  When I run `cap -T`
18
18
  Then the output should not contain "cap ns:with_period"
19
+ And the output should contain:
20
+ """
21
+ cap ns:my_namespace # A task that shadows a names...
22
+ """
19
23
  And the output should contain:
20
24
  """
21
25
  cap ns:my_namespace:in_a_namespace # My task in a namespace.
@@ -40,6 +44,27 @@ Feature: The #mirror_rake_tasks DSL method, inside a Capistrano namespace, with
40
44
  """
41
45
  The task `ns:with_period' does not exist.
42
46
 
47
+ """
48
+
49
+ Scenario: mirror Rake task 'my_namespace' with its description
50
+ Given a full-featured Rakefile
51
+ And a Capfile with:
52
+ """
53
+ namespace :ns do
54
+ Cape do |cape|
55
+ cape.mirror_rake_tasks :my_namespace
56
+ end
57
+ end
58
+ """
59
+ When I run `cap -e ns:my_namespace`
60
+ Then the output should contain exactly:
61
+ """
62
+ ------------------------------------------------------------
63
+ cap ns:my_namespace
64
+ ------------------------------------------------------------
65
+ A task that shadows a namespace.
66
+
67
+
43
68
  """
44
69
 
45
70
  Scenario: mirror Rake task 'my_namespace:in_a_namespace' with its description
@@ -31,6 +31,10 @@ Feature: The #mirror_rake_tasks DSL method, inside a Capistrano namespace, witho
31
31
  """
32
32
  cap ns:with_one_arg # My task with one argument.
33
33
  """
34
+ And the output should contain:
35
+ """
36
+ cap ns:my_namespace # A task that shadows a names...
37
+ """
34
38
  And the output should contain:
35
39
  """
36
40
  cap ns:my_namespace:in_a_namespace # My task in a namespace.
@@ -85,6 +89,7 @@ Feature: The #mirror_rake_tasks DSL method, inside a Capistrano namespace, witho
85
89
  When I run `cap ns:with_period`
86
90
  Then the output should contain:
87
91
  """
92
+ * executing `ns:with_period'
88
93
  * executing "cd /path/to/current/deployed/application && /usr/bin/env rake with_period"
89
94
  """
90
95
 
@@ -150,11 +155,51 @@ Feature: The #mirror_rake_tasks DSL method, inside a Capistrano namespace, witho
150
155
  ------------------------------------------------------------
151
156
  My task with one argument.
152
157
 
153
- Set environment variable THE_ARG to pass a Rake task argument.
158
+ Set environment variable THE_ARG if you want to pass a Rake task argument.
154
159
 
155
160
 
156
161
  """
157
162
 
163
+ Scenario: mirror Rake task 'my_namespace' with its description
164
+ Given a full-featured Rakefile
165
+ And a Capfile with:
166
+ """
167
+ namespace :ns do
168
+ Cape do |cape|
169
+ cape.mirror_rake_tasks
170
+ end
171
+ end
172
+ """
173
+ When I run `cap -e ns:my_namespace`
174
+ Then the output should contain exactly:
175
+ """
176
+ ------------------------------------------------------------
177
+ cap ns:my_namespace
178
+ ------------------------------------------------------------
179
+ A task that shadows a namespace.
180
+
181
+
182
+ """
183
+
184
+ Scenario: mirror Rake task 'my_namespace' with its implementation
185
+ Given a full-featured Rakefile
186
+ And a Capfile with:
187
+ """
188
+ set :current_path, '/path/to/current/deployed/application'
189
+
190
+ namespace :ns do
191
+ Cape do |cape|
192
+ cape.mirror_rake_tasks
193
+ end
194
+ end
195
+ """
196
+ When I run `cap ns:my_namespace`
197
+ Then the output should contain:
198
+ """
199
+ * executing `ns:my_namespace'
200
+ * executing "cd /path/to/current/deployed/application && /usr/bin/env rake my_namespace"
201
+ """
202
+
158
203
  Scenario: mirror Rake task 'my_namespace:in_a_namespace' with its description
159
204
  Given a full-featured Rakefile
160
205
  And a Capfile with:
@@ -215,7 +260,8 @@ Feature: The #mirror_rake_tasks DSL method, inside a Capistrano namespace, witho
215
260
  ------------------------------------------------------------
216
261
  My task with two arguments.
217
262
 
218
- Set environment variables MY_ARG1 and MY_ARG2 to pass Rake task arguments.
263
+ Set environment variables MY_ARG1 and MY_ARG2 if you want to pass Rake task
264
+ arguments.
219
265
 
220
266
 
221
267
  """
@@ -238,8 +284,8 @@ Feature: The #mirror_rake_tasks DSL method, inside a Capistrano namespace, witho
238
284
  ------------------------------------------------------------
239
285
  My task with three arguments.
240
286
 
241
- Set environment variables AN_ARG1, AN_ARG2, and AN_ARG3 to pass Rake task
242
- arguments.
287
+ Set environment variables AN_ARG1, AN_ARG2, and AN_ARG3 if you want to pass Rake
288
+ task arguments.
243
289
 
244
290
 
245
291
  """