capistrano-shared_config 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +80 -0
- data/Rakefile +1 -0
- data/capistrano-shared_config.gemspec +26 -0
- data/examples/config/deploy.rb +16 -0
- data/examples/config/nginx.conf.erb +23 -0
- data/examples/config/staging.settings.local.yml +3 -0
- data/lib/capistrano/shared_config.rb +7 -0
- data/lib/capistrano/shared_config/config_file.rb +55 -0
- data/lib/capistrano/shared_config/integration.rb +74 -0
- data/lib/capistrano/shared_config/version.rb +5 -0
- data/spec/capistrano/shared_config/config_file_spec.rb +127 -0
- data/spec/capistrano/shared_config/integration_spec.rb +168 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/support/configuration_extension.rb +9 -0
- data/spec/support/matchers.rb +75 -0
- metadata +139 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c572eaf23a01611ed2e3b3cdf70d1fd0da4e4e00
|
4
|
+
data.tar.gz: d727fa80d40d93c9baecee7fb52f5735cb51feb8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f37094b90296b405e671b0022461c556f178a4e28d8697322bd4f377c35534be2604ce53255ac0f145bc035e5e03c2d2b09cdeac7610584954a3813b17deca2d
|
7
|
+
data.tar.gz: b717f1c764eca18541d609f519a81b0893dd3f0072207340cfb93009a2bcef4b1e7fab0ba04852bc395f17b5f226eb4ab207c7f9f155493ad63813563ebc965e
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Alexander Stanko
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
# Capistrano::SharedConfig
|
2
|
+
|
3
|
+
This gem provides some capistrano tasks for config files management during deploy.
|
4
|
+
With it you can:
|
5
|
+
|
6
|
+
* Create symlinks to config files in shared directory on each deploy
|
7
|
+
* Upload config files to shared directory from local machine on each deploy
|
8
|
+
* Use erb and capistrano tasks binding in your config files (it will compile before uploading to server)
|
9
|
+
* Make separate config files for each rails environment
|
10
|
+
* Automatically create shared_path/config directory on deploy:setup
|
11
|
+
|
12
|
+
## Installation
|
13
|
+
|
14
|
+
Add this line to your application's Gemfile:
|
15
|
+
|
16
|
+
```ruby
|
17
|
+
gem 'capistrano-shared_config'
|
18
|
+
```
|
19
|
+
|
20
|
+
And then execute:
|
21
|
+
```
|
22
|
+
$ bundle install
|
23
|
+
```
|
24
|
+
|
25
|
+
## Usage
|
26
|
+
|
27
|
+
Configure variables in config/deploy.rb, then require capistrano/shared_config:
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
set :shared_config_files, %w[settings.local nginx.conf]
|
31
|
+
set :shared_config_symlinks, %w[database, settings.local newrelic.yml] # default is same as shared_config_files
|
32
|
+
|
33
|
+
require 'capistrano/shared_config'
|
34
|
+
```
|
35
|
+
|
36
|
+
Notice, you may skip `.yml` extension when configuring configs lists (Known extensions are: `.rb`, `.conf` and `.yml`).
|
37
|
+
|
38
|
+
Make sure, you require capistrano/shared\_config after desired `shared_config_files` set
|
39
|
+
|
40
|
+
You can also configure, when to run provided tasks:
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
# set :run_shared_config_symlinks, [:after, 'deploy:update_code']
|
44
|
+
# set :run_shared_config_sync, [:after, 'deploy:update_code']
|
45
|
+
# set :run_early_shared_config_check, [:before, 'deploy:update_code']
|
46
|
+
|
47
|
+
require 'capistrano/shared_config'
|
48
|
+
```
|
49
|
+
|
50
|
+
## Advanced Usage
|
51
|
+
|
52
|
+
You can call particular cap task with FILE env variable specified to upload or check only one file:
|
53
|
+
```bash
|
54
|
+
$ cap shared_config:sync FILE=newrelic
|
55
|
+
```
|
56
|
+
|
57
|
+
Or you can inspect content generated in config file with `show` task like this:
|
58
|
+
```bash
|
59
|
+
$ cap shared_config:show FILE=settings.local
|
60
|
+
```
|
61
|
+
It will output content of specified file surrounded by `=====` lines
|
62
|
+
|
63
|
+
## Config Files Lookup
|
64
|
+
|
65
|
+
For uploading to server, provided task `sync` use files from `config` directory.
|
66
|
+
For every file_name in `shared_config_files` (after adding default `.yml` if needed)
|
67
|
+
it try to find the following files in order:
|
68
|
+
|
69
|
+
1. `config/rails_env.file_name.erb`
|
70
|
+
2. `config/rails_env.file_name`
|
71
|
+
3. `config/file_name.erb`
|
72
|
+
4. `config/file_name`
|
73
|
+
|
74
|
+
## Contributing
|
75
|
+
|
76
|
+
1. Fork it
|
77
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
78
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
79
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
80
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'capistrano/shared_config/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'capistrano-shared_config'
|
8
|
+
spec.version = Capistrano::SharedConfig::VERSION
|
9
|
+
spec.authors = ['Alexander Stanko']
|
10
|
+
spec.email = ['rakoth3d@gmail.com']
|
11
|
+
spec.description = %q{This gem provides several capistrano tasks for config files uploading and symlinking during deploy}
|
12
|
+
spec.summary = %q{Config files management during capistrano deploy}
|
13
|
+
spec.homepage = 'https://github.com/Rakoth/capistrano-shared_config'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
|
21
|
+
spec.add_development_dependency 'bundler', '~> 1.3'
|
22
|
+
spec.add_development_dependency 'rake'
|
23
|
+
spec.add_development_dependency 'capistrano'
|
24
|
+
spec.add_development_dependency 'capistrano-spec'
|
25
|
+
spec.add_development_dependency 'rspec'
|
26
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
set :application, 'app.example.com'
|
2
|
+
|
3
|
+
# Used in settings.local.yml. Usefull if you have many staging servers with same rails env.
|
4
|
+
set :redis_db, 5
|
5
|
+
|
6
|
+
# This files will be compiled from local template files and upload to shared folder on server on each deploy.
|
7
|
+
set :shared_config_files, %w[nginx.conf settings.local]
|
8
|
+
|
9
|
+
# For this files symlinks to shared folder will be created on each deploy.
|
10
|
+
set :shared_config_symlinks, %w[database settings.local]
|
11
|
+
|
12
|
+
# Change shared_config:symlinks tack position in deploy.
|
13
|
+
set :run_shared_config_symlinks, [:before, 'deploy:assets:precompile']
|
14
|
+
|
15
|
+
# Put require after configuring shared_config_* and run_shared_config_* variables.
|
16
|
+
require 'capistrano/shared_config'
|
@@ -0,0 +1,23 @@
|
|
1
|
+
upstream app-<%= stage %>-unicorn {
|
2
|
+
server unix:<%= deploy_to %>/current/tmp/sockets/unicorn.sock fail_timeout=30;
|
3
|
+
}
|
4
|
+
|
5
|
+
server {
|
6
|
+
listen 80;
|
7
|
+
server_name <%= application %>;
|
8
|
+
|
9
|
+
charset utf-8;
|
10
|
+
root <%= deploy_to %>/current/public;
|
11
|
+
|
12
|
+
location @unicorn {
|
13
|
+
proxy_set_header X-Real-IP $remote_addr;
|
14
|
+
proxy_set_header Host $host;
|
15
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
16
|
+
proxy_redirect off;
|
17
|
+
proxy_pass http://app-<%= stage %>-unicorn;
|
18
|
+
}
|
19
|
+
|
20
|
+
try_files $uri $uri/index.html $uri.html @unicorn;
|
21
|
+
|
22
|
+
error_page 500 502 503 504 /500.html;
|
23
|
+
}
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'erb'
|
3
|
+
|
4
|
+
module Capistrano
|
5
|
+
module SharedConfig
|
6
|
+
class ConfigFile
|
7
|
+
def initialize name, capistrano_binding
|
8
|
+
@name = self.class.name(name)
|
9
|
+
@capistrano_binding = capistrano_binding
|
10
|
+
end
|
11
|
+
|
12
|
+
attr_reader :name, :capistrano_binding, :error
|
13
|
+
|
14
|
+
def env
|
15
|
+
@env ||= eval('rails_env', capistrano_binding)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.name name
|
19
|
+
name += '.yml' unless name =~ /\.(yml|conf|rb)$/
|
20
|
+
name
|
21
|
+
end
|
22
|
+
|
23
|
+
def location
|
24
|
+
@location ||= [
|
25
|
+
File.join('.', 'config', [env, name, 'erb'].join(?.)),
|
26
|
+
File.join('.', 'config', [env, name].join(?.)),
|
27
|
+
File.join('.', 'config', [name, 'erb'].join(?.)),
|
28
|
+
File.join('.', 'config', name)
|
29
|
+
].detect(&File.method(:exists?))
|
30
|
+
end
|
31
|
+
|
32
|
+
def content
|
33
|
+
@content ||= ERB.new(File.read(location)).result(capistrano_binding)
|
34
|
+
end
|
35
|
+
|
36
|
+
def valid?
|
37
|
+
begin
|
38
|
+
case name
|
39
|
+
when /\.yml$/
|
40
|
+
YAML.load content
|
41
|
+
when /\.rb$/
|
42
|
+
eval("BEGIN {return true}\n#{content}", nil, name, 0)
|
43
|
+
else
|
44
|
+
# hope it is valid
|
45
|
+
end
|
46
|
+
|
47
|
+
true
|
48
|
+
rescue Exception => exception
|
49
|
+
@error = "Error in config file: #{exception.inspect}\n#{exception.message}"
|
50
|
+
false
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'capistrano'
|
2
|
+
require 'capistrano/version'
|
3
|
+
require 'capistrano/shared_config/config_file'
|
4
|
+
|
5
|
+
module Capistrano
|
6
|
+
module SharedConfig
|
7
|
+
class Integration
|
8
|
+
def self.load_into(capistrano_config)
|
9
|
+
capistrano_config.load do
|
10
|
+
set(:shared_config_files, fetch(:shared_config_files, []))
|
11
|
+
set(:shared_config_symlinks, fetch(:shared_config_symlinks, shared_config_files))
|
12
|
+
|
13
|
+
set(:run_shared_config_symlinks, fetch(:run_shared_config_symlinks, [:after, 'deploy:update_code']))
|
14
|
+
set(:run_shared_config_sync, fetch(:run_shared_config_sync, [:after, 'deploy:update_code']))
|
15
|
+
set(:run_early_shared_config_check, fetch(:run_early_shared_config_check, [:before, 'deploy:update_code']))
|
16
|
+
|
17
|
+
set(:_shared_config_files, (ENV['FILE'] ? [ENV['FILE']] : shared_config_files).
|
18
|
+
map{|name| ConfigFile.new(name, binding)}
|
19
|
+
)
|
20
|
+
|
21
|
+
namespace :shared_config do
|
22
|
+
desc 'Create shared config folder'
|
23
|
+
task :setup do
|
24
|
+
run "mkdir #{File.join(shared_path, 'config')}"
|
25
|
+
end
|
26
|
+
after 'deploy:setup', 'shared_config:setup'
|
27
|
+
|
28
|
+
desc 'Create symlinks for config files from shared_config_symlinks array'
|
29
|
+
task :symlinks do
|
30
|
+
next if shared_config_symlinks.empty?
|
31
|
+
commands = shared_config_symlinks.map do |name|
|
32
|
+
full_name = ConfigFile.name(name)
|
33
|
+
"ln -nfs #{File.join(shared_path, 'config', full_name)} #{File.join(latest_release, 'config', full_name)}"
|
34
|
+
end
|
35
|
+
|
36
|
+
run commands.join(' && ')
|
37
|
+
end
|
38
|
+
on run_shared_config_symlinks.first, 'shared_config:symlinks', only: run_shared_config_symlinks.last
|
39
|
+
|
40
|
+
desc 'Sync all config files'
|
41
|
+
task :sync do
|
42
|
+
_shared_config_files.each do |file|
|
43
|
+
put(file.content, File.join(shared_path, 'config', file.name))
|
44
|
+
end
|
45
|
+
end
|
46
|
+
on run_shared_config_sync.first, 'shared_config:sync', only: run_shared_config_sync.last
|
47
|
+
|
48
|
+
desc 'Check all config files'
|
49
|
+
task :check do
|
50
|
+
_shared_config_files.each do |file|
|
51
|
+
raise Capistrano::CommandError.new(file.error) unless file.valid?
|
52
|
+
end
|
53
|
+
end
|
54
|
+
on run_early_shared_config_check.first, 'shared_config:check', only: run_early_shared_config_check.last
|
55
|
+
before 'shared_config:sync', 'shared_config:check'
|
56
|
+
|
57
|
+
task :show do
|
58
|
+
_shared_config_files.each do |file|
|
59
|
+
puts '', file.name
|
60
|
+
puts ?= * 80
|
61
|
+
puts file.content
|
62
|
+
puts ?= * 80
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
if Capistrano::Configuration.instance
|
73
|
+
Capistrano::SharedConfig::Integration.load_into(Capistrano::Configuration.instance)
|
74
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'capistrano/shared_config/config_file'
|
3
|
+
|
4
|
+
describe Capistrano::SharedConfig::ConfigFile do
|
5
|
+
describe '.name' do
|
6
|
+
it 'should use .yml extension by default' do
|
7
|
+
described_class.name('test').should == 'test.yml'
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should not override known extensions' do
|
11
|
+
described_class.name('test.yml').should == 'test.yml'
|
12
|
+
described_class.name('test.rb').should == 'test.rb'
|
13
|
+
described_class.name('test.conf').should == 'test.conf'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe '#location' do
|
18
|
+
before do
|
19
|
+
File.stub(:exists?).and_return(false)
|
20
|
+
File.stub(:exists?).with('./config/production.config.yml').and_return(true)
|
21
|
+
File.stub(:exists?).with('./config/development.config.yml.erb').and_return(true)
|
22
|
+
File.stub(:exists?).with('./config/config.yml').and_return(true)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should find local config with given environment' do
|
26
|
+
rails_env = 'staging'
|
27
|
+
described_class.new('config.yml', binding).location.should == './config/config.yml'
|
28
|
+
|
29
|
+
rails_env = 'production'
|
30
|
+
described_class.new('config.yml', binding).location.should == './config/production.config.yml'
|
31
|
+
|
32
|
+
rails_env = 'development'
|
33
|
+
described_class.new('config.yml', binding).location.should == './config/development.config.yml.erb'
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe '#content' do
|
38
|
+
let(:file_content) do
|
39
|
+
<<-YAML
|
40
|
+
staging:
|
41
|
+
test: 1
|
42
|
+
path: <%= deploy_to %>
|
43
|
+
YAML
|
44
|
+
end
|
45
|
+
|
46
|
+
before do
|
47
|
+
File.stub(:read).and_return(file_content)
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'should eval erb template with given binding' do
|
51
|
+
deploy_to = 'test/path'
|
52
|
+
rails_env = 'staging'
|
53
|
+
described_class.new('test', binding).content.should == <<-YAML
|
54
|
+
staging:
|
55
|
+
test: 1
|
56
|
+
path: test/path
|
57
|
+
YAML
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe '#valid?' do
|
62
|
+
context 'yaml file' do
|
63
|
+
subject{described_class.new('test.yml', double(rails_env: 'staging'))}
|
64
|
+
|
65
|
+
it 'should return true for valid file' do
|
66
|
+
subject.stub(:content).and_return <<-YAML
|
67
|
+
test:
|
68
|
+
valid: yaml
|
69
|
+
YAML
|
70
|
+
|
71
|
+
subject.should be_valid
|
72
|
+
subject.error.should be_nil
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'should return false for invalid file and set error' do
|
76
|
+
subject.stub(:content).and_return <<-YAML
|
77
|
+
test:
|
78
|
+
invalid: yaml
|
79
|
+
valid: yaml
|
80
|
+
YAML
|
81
|
+
|
82
|
+
subject.should_not be_valid
|
83
|
+
subject.error.should be
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
context 'rb file' do
|
88
|
+
subject{described_class.new('test.rb', double(rails_env: 'staging'))}
|
89
|
+
|
90
|
+
it 'should return true for valid file' do
|
91
|
+
subject.stub(:content).and_return <<-CODE
|
92
|
+
god.watch do
|
93
|
+
test
|
94
|
+
end
|
95
|
+
CODE
|
96
|
+
|
97
|
+
subject.should be_valid
|
98
|
+
subject.error.should be_nil
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'should return false for invalid file and set error' do
|
102
|
+
subject.stub(:content).and_return <<-CODE
|
103
|
+
god.watch do
|
104
|
+
(test
|
105
|
+
end
|
106
|
+
CODE
|
107
|
+
|
108
|
+
subject.should_not be_valid
|
109
|
+
subject.error.should be
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
context 'other files' do
|
114
|
+
subject{described_class.new('test.conf', double(rails_env: 'staging'))}
|
115
|
+
|
116
|
+
it 'should return true' do
|
117
|
+
subject.stub(:content).and_return <<-CONFIG
|
118
|
+
test = 1
|
119
|
+
conf.test = 1
|
120
|
+
CONFIG
|
121
|
+
|
122
|
+
subject.should be_valid
|
123
|
+
subject.error.should be_nil
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
@@ -0,0 +1,168 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'capistrano/shared_config/integration'
|
3
|
+
|
4
|
+
describe Capistrano::SharedConfig::Integration do
|
5
|
+
let(:cap) do
|
6
|
+
Capistrano::Configuration.new.tap do |config|
|
7
|
+
config.extend(Capistrano::Spec::ConfigurationExtension)
|
8
|
+
config.extend(ConfigurationExtension)
|
9
|
+
config.load do
|
10
|
+
namespace :deploy do
|
11
|
+
task(:default){}
|
12
|
+
task(:update_code){}
|
13
|
+
task(:assets_precompile){}
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe 'set config files variables' do
|
20
|
+
before do
|
21
|
+
cap.set(:rails_env, 'staging')
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should should set empty config files set for default' do
|
25
|
+
Capistrano::SharedConfig::Integration.load_into(cap)
|
26
|
+
|
27
|
+
cap.fetch(:shared_config_files).should == []
|
28
|
+
cap.fetch(:shared_config_symlinks).should == []
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should should use predefined shared_config_files' do
|
32
|
+
cap.set(:shared_config_files, ['test'])
|
33
|
+
Capistrano::SharedConfig::Integration.load_into(cap)
|
34
|
+
|
35
|
+
cap.fetch(:shared_config_files).should == ['test']
|
36
|
+
cap.fetch(:shared_config_symlinks).should == ['test']
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should should use predefined shared_config_symlinks' do
|
40
|
+
cap.set(:shared_config_files, ['test', 'test_1'])
|
41
|
+
cap.set(:shared_config_symlinks, ['test'])
|
42
|
+
Capistrano::SharedConfig::Integration.load_into(cap)
|
43
|
+
|
44
|
+
cap.fetch(:shared_config_files).should == ['test', 'test_1']
|
45
|
+
cap.fetch(:shared_config_symlinks).should == ['test']
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should set _shared_config_files for internal use' do
|
49
|
+
cap.set(:shared_config_files, ['test', 'test_1'])
|
50
|
+
Capistrano::SharedConfig::Integration.load_into(cap)
|
51
|
+
|
52
|
+
cap.fetch(:_shared_config_files).should have(2).items
|
53
|
+
cap.fetch(:_shared_config_files).first.name.should == 'test.yml'
|
54
|
+
cap.fetch(:_shared_config_files).last.name.should == 'test_1.yml'
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'should set _shared_config_files for internal use when ENV[FILE] is present' do
|
58
|
+
begin
|
59
|
+
ENV['FILE'] = 'test_env'
|
60
|
+
cap.set(:shared_config_files, ['test', 'test_1'])
|
61
|
+
Capistrano::SharedConfig::Integration.load_into(cap)
|
62
|
+
|
63
|
+
cap.fetch(:_shared_config_files).should have(1).item
|
64
|
+
cap.fetch(:_shared_config_files).first.name.should == 'test_env.yml'
|
65
|
+
ensure
|
66
|
+
ENV.delete('FILE')
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe 'callbacks' do
|
72
|
+
context 'default' do
|
73
|
+
before do
|
74
|
+
Capistrano::SharedConfig::Integration.load_into(cap)
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'should run shared_config:symlinks after deploy:update_code' do
|
78
|
+
cap.should callback('shared_config:symlinks').after('deploy:update_code')
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'should run shared_config:sync after deploy:update_code' do
|
82
|
+
cap.should callback('shared_config:sync').after('deploy:update_code')
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'should run early shared_config:check before deploy:update_code' do
|
86
|
+
cap.should callback('shared_config:check').before('deploy:update_code')
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'should run shared_config:check before shared_config:sync' do
|
90
|
+
cap.should callback('shared_config:check').before('shared_config:sync')
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
context 'configured' do
|
95
|
+
it 'should run configured shared_config:symlinks' do
|
96
|
+
cap.set(:run_shared_config_symlinks, [:before, 'deploy:assets_precompile'])
|
97
|
+
Capistrano::SharedConfig::Integration.load_into(cap)
|
98
|
+
|
99
|
+
cap.should callback('shared_config:symlinks').before('deploy:assets_precompile')
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'should run configured shared_config:sync' do
|
103
|
+
cap.set(:run_shared_config_sync, [:after, 'deploy:assets_precompile'])
|
104
|
+
Capistrano::SharedConfig::Integration.load_into(cap)
|
105
|
+
|
106
|
+
cap.should callback('shared_config:sync').after('deploy:assets_precompile')
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'should run configured early shared_config:check' do
|
110
|
+
cap.set(:run_early_shared_config_check, [:before, 'deploy'])
|
111
|
+
Capistrano::SharedConfig::Integration.load_into(cap)
|
112
|
+
cap.should callback('shared_config:check').before('deploy')
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
describe 'tasks' do
|
118
|
+
before do
|
119
|
+
cap.set(:rails_env, 'production')
|
120
|
+
cap.set(:shared_path, '/shared')
|
121
|
+
cap.set(:shared_config_files, %w[database settings.local])
|
122
|
+
Capistrano::SharedConfig::Integration.load_into(cap)
|
123
|
+
end
|
124
|
+
|
125
|
+
describe 'shared_config:symlinks' do
|
126
|
+
before do
|
127
|
+
cap.set(:latest_release, '/release')
|
128
|
+
cap.find_and_execute_task('shared_config:symlinks')
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'should create symlinks for all config files' do
|
132
|
+
cap.should have_run(
|
133
|
+
'ln -nfs /shared/config/database.yml /release/config/database.yml && ' +
|
134
|
+
'ln -nfs /shared/config/settings.local.yml /release/config/settings.local.yml'
|
135
|
+
)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
describe 'shared_config:check' do
|
140
|
+
let(:files){cap.fetch(:_shared_config_files)}
|
141
|
+
|
142
|
+
it 'should pass silently if all configs are valid' do
|
143
|
+
files.each{|file| file.stub(:valid?).and_return(true)}
|
144
|
+
expect{cap.find_and_execute_task('shared_config:check')}.to_not raise_error
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'should rollback deploy if config is invalid' do
|
148
|
+
files.first.stub(:valid?).and_return(true)
|
149
|
+
files.last.stub(valid?: false, error: 'test')
|
150
|
+
expect{cap.find_and_execute_task('shared_config:check')}.to raise_error(Capistrano::CommandError, 'test')
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
describe 'shared_config:sync' do
|
155
|
+
let(:files){cap.fetch(:_shared_config_files)}
|
156
|
+
|
157
|
+
it 'should upload all config files on server' do
|
158
|
+
files.first.stub(:content).and_return('test')
|
159
|
+
files.last.stub(:content).and_return('test_1')
|
160
|
+
|
161
|
+
cap.find_and_execute_task('shared_config:sync')
|
162
|
+
|
163
|
+
cap.should have_putted('/shared/config/database.yml').with('test')
|
164
|
+
cap.should have_putted('/shared/config/settings.local.yml').with('test_1')
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'capistrano-spec'
|
2
|
+
|
3
|
+
#TODO make pull-request into capistrano-spec gem
|
4
|
+
require 'support/matchers'
|
5
|
+
require 'support/configuration_extension'
|
6
|
+
|
7
|
+
RSpec.configure do |config|
|
8
|
+
config.include Capistrano::Spec::Matchers
|
9
|
+
config.include Capistrano::Spec::Helpers
|
10
|
+
config.include Matchers
|
11
|
+
config.order = :random
|
12
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module Matchers
|
2
|
+
extend ::Spec::Matchers::DSL
|
3
|
+
|
4
|
+
define :callback do |task_name|
|
5
|
+
extend Capistrano::Spec::Helpers
|
6
|
+
|
7
|
+
match do |configuration|
|
8
|
+
@task = configuration.find_task(task_name)
|
9
|
+
callbacks = find_callback(configuration, @on, @task)
|
10
|
+
|
11
|
+
if callbacks
|
12
|
+
callbacks.any? do |callback|
|
13
|
+
if callback && @trigger_task_name
|
14
|
+
@trigger_task = configuration.find_task(@trigger_task_name)
|
15
|
+
@trigger_task && callback.applies_to?(@trigger_task)
|
16
|
+
else
|
17
|
+
callback
|
18
|
+
end
|
19
|
+
end
|
20
|
+
else
|
21
|
+
false
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def on(on)
|
26
|
+
@on = on
|
27
|
+
self
|
28
|
+
end
|
29
|
+
|
30
|
+
def before(before_task_name)
|
31
|
+
@on = :before
|
32
|
+
@trigger_task_name = before_task_name
|
33
|
+
self
|
34
|
+
end
|
35
|
+
|
36
|
+
def after(after_task_name)
|
37
|
+
@on = :after
|
38
|
+
@trigger_task_name = after_task_name
|
39
|
+
self
|
40
|
+
end
|
41
|
+
|
42
|
+
failure_message_for_should do |actual|
|
43
|
+
if @trigger_task_name
|
44
|
+
"expected configuration to callback #{task_name.inspect} #{@on} #{@trigger_task_name.inspect}, but did not"
|
45
|
+
else
|
46
|
+
"expected configuration to callback #{task_name.inspect} on #{@on}, but did not"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
define :have_putted do |path|
|
53
|
+
match do |configuration|
|
54
|
+
upload = configuration.puttes[path]
|
55
|
+
if @content
|
56
|
+
upload && upload[:content] == @content
|
57
|
+
else
|
58
|
+
upload
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def with(content)
|
63
|
+
@content = content
|
64
|
+
self
|
65
|
+
end
|
66
|
+
|
67
|
+
failure_message_for_should do |actual|
|
68
|
+
if @content
|
69
|
+
"expected configuration to put #{path} with content '#{@content}', but did not"
|
70
|
+
else
|
71
|
+
"expected configuration to put #{path}, but did not"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
metadata
ADDED
@@ -0,0 +1,139 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: capistrano-shared_config
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Alexander Stanko
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-06-17 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: capistrano
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: capistrano-spec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: This gem provides several capistrano tasks for config files uploading
|
84
|
+
and symlinking during deploy
|
85
|
+
email:
|
86
|
+
- rakoth3d@gmail.com
|
87
|
+
executables: []
|
88
|
+
extensions: []
|
89
|
+
extra_rdoc_files: []
|
90
|
+
files:
|
91
|
+
- .gitignore
|
92
|
+
- .rspec
|
93
|
+
- Gemfile
|
94
|
+
- LICENSE.txt
|
95
|
+
- README.md
|
96
|
+
- Rakefile
|
97
|
+
- capistrano-shared_config.gemspec
|
98
|
+
- examples/config/deploy.rb
|
99
|
+
- examples/config/nginx.conf.erb
|
100
|
+
- examples/config/staging.settings.local.yml
|
101
|
+
- lib/capistrano/shared_config.rb
|
102
|
+
- lib/capistrano/shared_config/config_file.rb
|
103
|
+
- lib/capistrano/shared_config/integration.rb
|
104
|
+
- lib/capistrano/shared_config/version.rb
|
105
|
+
- spec/capistrano/shared_config/config_file_spec.rb
|
106
|
+
- spec/capistrano/shared_config/integration_spec.rb
|
107
|
+
- spec/spec_helper.rb
|
108
|
+
- spec/support/configuration_extension.rb
|
109
|
+
- spec/support/matchers.rb
|
110
|
+
homepage: https://github.com/Rakoth/capistrano-shared_config
|
111
|
+
licenses:
|
112
|
+
- MIT
|
113
|
+
metadata: {}
|
114
|
+
post_install_message:
|
115
|
+
rdoc_options: []
|
116
|
+
require_paths:
|
117
|
+
- lib
|
118
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
119
|
+
requirements:
|
120
|
+
- - '>='
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: '0'
|
123
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
124
|
+
requirements:
|
125
|
+
- - '>='
|
126
|
+
- !ruby/object:Gem::Version
|
127
|
+
version: '0'
|
128
|
+
requirements: []
|
129
|
+
rubyforge_project:
|
130
|
+
rubygems_version: 2.0.3
|
131
|
+
signing_key:
|
132
|
+
specification_version: 4
|
133
|
+
summary: Config files management during capistrano deploy
|
134
|
+
test_files:
|
135
|
+
- spec/capistrano/shared_config/config_file_spec.rb
|
136
|
+
- spec/capistrano/shared_config/integration_spec.rb
|
137
|
+
- spec/spec_helper.rb
|
138
|
+
- spec/support/configuration_extension.rb
|
139
|
+
- spec/support/matchers.rb
|