1
0
Fork 0
mirror of https://github.com/capistrano/capistrano synced 2023-03-27 23:21:18 -04:00

Support loading stage configs from additional directories

**This is an epic commit message. TL;DR - add a `file_in_load_path?`
method to determine if a file is in the Capistrano load_paths, and
change the multistage extension to use `file_in_load_path?` instead of
`File.exists?` when loading stage configs.**

I am working on a private Capistrano gem to consolidate our deploys into
one project. We are deploying to EC2 and use tags on the instances to
determine where to deploy each application to. Therefore the Capistrano
configuration for all of our applications is almost identical with the
only difference being the application name, and things that can be
derived from the application name. I want to be able to use the
Capistrano multistage extension to configure our different environments.
While testing this I discovered that I can not load the stage configs
from within my gem.

I tried the following config:

```ruby
set :stage_dir, 'stages/aws'
set :stages, %w(production staging)
set :default_stage, 'staging'
```

This config would not load the proper configs because stages/aws was not
found by the `File.exists?` call on
[multistage.rb#18](https://github.com/capistrano/capistrano/blob/master/lib/capistrano/ext/multistage.rb#L18)

Then I tried this config:

```ruby
set :stage_dir, File.join(File.dirname(__FILE__), 'stages', 'aws')
set :stages, %w(production staging)
set :default_stage, 'staging'
```

The multistage gem found the file in this example, but failed due to the
path not being in the Capistrano load_path. I tried adding the
`File.dirname(__FILE__)` to the load_path, but that did not work because
I still had to set
`:stage_dir` to `File.join(File.dirname(__FILE__), 'stages', 'aws')`
in order for load to be called.

To fix this I added a method to loading.rb to scan the load_paths for
the file requested, and updated the multistage extension to use the new
method.
This commit is contained in:
Ryan Sullivan 2013-05-18 14:09:02 -07:00
parent cb2efe876f
commit 6146985a80
3 changed files with 27 additions and 1 deletions

View file

@ -163,6 +163,14 @@ module Capistrano
end
end
def file_in_load_path?(file)
begin
!!find_file_in_load_path(file)
rescue LoadError
false
end
end
private
# Load a recipe from the named file. If +name+ is given, the file will

View file

@ -15,7 +15,9 @@ Capistrano::Configuration.instance.load do
desc "Set the target stage to `#{name}'."
task(name) do
set :stage, name.to_sym
load "#{location}/#{stage}" if File.exist?(File.join(location, "#{stage}.rb"))
file = "#{location}/#{stage}"
load file if file_in_load_path?(file)
end
end

View file

@ -129,4 +129,20 @@ class ConfigurationLoadingTest < Test::Unit::TestCase
assert_equal :custom, @config.ping
assert_equal :custom, config2.ping
end
def test_file_in_load_path_returns_true_when_file_is_in_load_path
File.stubs(:file?).returns(false)
File.stubs(:file?).with("custom/path/for/file.rb").returns(true)
@config.load_paths << "custom/path/for"
assert_equal true, @config.file_in_load_path?("file")
end
def test_file_in_load_path_returns_false_when_file_is_not_in_load_path
File.stubs(:file?).returns(false)
File.stubs(:file?).with("custom/path/for/file.rb").returns(false)
@config.load_paths << "custom/path/for"
assert_equal false, @config.file_in_load_path?("file")
end
end