capistrano-multiconfig 3.0.1 → 3.0.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7a4a01eddf6db929483491f1ab6e8f1bee0c1de0
4
- data.tar.gz: 37b27ad85cb0cdfb72562e666e3886c90a09256d
3
+ metadata.gz: 2c9b7fb215030f53d9d0eff91305889ad41b26a7
4
+ data.tar.gz: 29adfd8cfd8a8864ea0cb39597aa54b46d143428
5
5
  SHA512:
6
- metadata.gz: 4125540d382803fa4f317d7452eeb83229bae15457aaefab91de85b1f5d2c3331d492b6e3dc9441c48c23d63ecd5e3818875f1141aaacc2f71c5811c7442d7a6
7
- data.tar.gz: a1e9b7b9dbad421babef44a1704180a9a8d90156a87ca8e0b76d8f8048ead068cad6b234f80d08df0b335cc1d216d74142f76fbaff4d4256e2d1cc4e71f4be18
6
+ metadata.gz: 6ddd88b0ee9b23fd0f94f26ce880e3ec304fe38c18aa4afd38c27e4a92b63060f43e129a395a9a68ef0fe449cbc7ec7b4241fb71c6f55a9363f45dfc0b3393aa
7
+ data.tar.gz: 9ec37a468dc70b0524814853c5ca2a7edb223f57458285288cded0cc7679020ccc93382be91a79a733652f1401bba103b7f30f66173cd79c8569de3f5ac6071b
data/README.md CHANGED
@@ -9,6 +9,11 @@ But it's not only about 'stage' configurations. It's about any configuration tha
9
9
  Extension recursively builds configuration list from configuration root directory.
10
10
  Each configuration loads recursively configuration from it namespace files and own configuration file.
11
11
 
12
+ ## Purpose
13
+
14
+ Extension was specially created to implement [Caphub](https://github.com/railsware/caphub) concept.
15
+ [Read more](http://railsware.com/blog/2011/11/18/caphub-multiple-applications-deployment-with-capistrano/).
16
+
12
17
  ## Usage
13
18
 
14
19
  Install gem
@@ -51,7 +56,6 @@ Create configuration files:
51
56
 
52
57
  Add to `Capfile`:
53
58
 
54
- set :config_root, 'config/deploy'
55
59
  require 'capistrano/multiconfig'
56
60
 
57
61
  Put related capistrano configuration to each file according to file meaning.
@@ -89,7 +93,7 @@ So we must provide configuration as first task:
89
93
  Configuration task loads not only configuration associated with it filename.
90
94
  It also recursively load configurations from all namespaces.
91
95
 
92
- For example for *:config_root* `config/deploy` task `cap apps/blog/qa.rb` loads with **order** next configuration files (if they exist):
96
+ For example task `cap apps/blog/qa.rb` loads with **order** next configuration files (if they exist):
93
97
 
94
98
  * config/deploy/apps.rb
95
99
  * config/deploy/apps/blog.rb
@@ -97,6 +101,12 @@ For example for *:config_root* `config/deploy` task `cap apps/blog/qa.rb` loads
97
101
 
98
102
  So it's easy to put shared configuration.
99
103
 
104
+ ## Custom stages configuration location
105
+
106
+ Specify in `Capfile`:
107
+
108
+ set :stages_root, 'deployment'
109
+ require 'capistrano/multiconfig'
100
110
 
101
111
  ## Testing
102
112
 
@@ -107,3 +117,9 @@ So it's easy to put shared configuration.
107
117
 
108
118
  * Copyright (c) 2013 Railsware [www.railsware.com](http://www.railsware.com)
109
119
  * [MIT](www.opensource.org/licenses/MIT)
120
+
121
+ ## References
122
+
123
+ * [capistrano](https://github.com/capistrano/capistrano)
124
+ * [caphub](https://github.com/railsware/caphub)
125
+
@@ -3,7 +3,7 @@ $:.push File.expand_path("../lib", __FILE__)
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "capistrano-multiconfig"
6
- s.version = "3.0.1"
6
+ s.version = "3.0.2"
7
7
  s.authors = ["Andriy Yanko"]
8
8
  s.email = ["andriy.yanko@gmail.com"]
9
9
  s.homepage = "https://github.com/railsware/multiconfig"
data/fixtures/Capfile CHANGED
@@ -1,7 +1,9 @@
1
- set :config_root, ENV.fetch('CONFIG_ROOT')
1
+ set :stages_root, ENV.fetch('STAGES_ROOT')
2
2
 
3
3
  require 'capistrano/multiconfig'
4
4
 
5
5
  task :hello_world do
6
6
  puts fetch(:message, "hello")
7
7
  end
8
+
9
+ # vim syntax=ruby
@@ -1,33 +1,85 @@
1
- require 'capistrano/multiconfig/configurations'
2
-
3
1
  include Capistrano::DSL
4
2
 
5
- config_root_path = File.expand_path(fetch(:config_root, "config/deploy"))
3
+ def stages_root
4
+ fetch(:stages_root, 'config/deploy')
5
+ end
6
+
7
+ # Build stages with nested configurations
8
+ #
9
+ # @example simple stages
10
+ #
11
+ # config
12
+ # ├── deploy
13
+ # │   ├── production.rb
14
+ # │   └── staging.rb
15
+ # └── deploy.rb
16
+ #
17
+ # * cap production
18
+ # * cap staging
19
+ #
20
+ # @example stages with nested configurations
21
+ #
22
+ # config
23
+ # ├── deploy
24
+ # │   ├── soa
25
+ # │   │   ├── blog
26
+ # │   │   │   ├── production.rb
27
+ # │   │   │   └── staging.rb
28
+ # │   │   └── wiki
29
+ # │   │   └── qa.rb
30
+ # │   └── soa.rb
31
+ # └── deploy.rb
32
+ #
33
+ # * cap soa:blog:production
34
+ # * cap soa:blog:staging
35
+ # * cap soa:wiki:qa
36
+ def stages
37
+ Dir["#{stages_root}/**/*.rb"].map { |file|
38
+ file.slice(stages_root.size + 1 .. -4).tr('/', ':')
39
+ }.tap { |paths|
40
+ paths.reject! { |path|
41
+ paths.any? { |another| another != path && another.start_with?(path) }
42
+ }
43
+ }.sort
44
+ end
6
45
 
7
- config_names = Capistrano::Multiconfig::Configurations.find_names(config_root_path)
46
+ stages.each do |stage|
47
+ Rake::Task.define_task(stage) do
8
48
 
9
- config_names.each do |config_name|
10
- Rake::Task.define_task(config_name) do
11
- set(:config_name, config_name)
49
+ # Set stage variable
50
+ set(:stage, stage)
12
51
 
52
+ # Load defaults variables
13
53
  load "capistrano/defaults.rb"
14
54
 
15
- paths = [ config_root_path + '.rb' ]
16
-
17
- (segments = config_name.split(":")).size.times do |i|
18
- paths << File.join([config_root_path] + segments[0..i]) + '.rb'
55
+ # Load stage configuration(s).
56
+ #
57
+ # For stage 'production' will be loaded next configurations:
58
+ #
59
+ # * config/deploy.rb
60
+ # * config/deploy/production.rb
61
+ #
62
+ # For stage 'soa:blog:production' will be loaded next configurations:
63
+ #
64
+ # * config/deploy.rb
65
+ # * config/deploy/soa.rb
66
+ # * config/deploy/soa/blog.rb
67
+ # * config/deploy/soa/blog/production.rb
68
+ stage.split(':').inject([stages_root]) do |paths, segment|
69
+ paths << File.join(paths.last, segment)
70
+ end.each do |path|
71
+ file = "#{path}.rb"
72
+ load(file) if File.exists?(file)
19
73
  end
20
74
 
21
- paths.each { |path| load(path) if File.exists?(path) }
22
-
75
+ # Load SCM tasks
23
76
  load "capistrano/#{fetch(:scm)}.rb"
77
+
78
+ # Set locale
24
79
  I18n.locale = fetch(:locale, :en)
25
- configure_backend
26
- end.add_description("Load #{config_name} configuration")
27
- end
28
80
 
29
- set(:config_names, config_names)
81
+ # configure core backend
82
+ configure_backend
30
83
 
31
- def stages
32
- fetch(:config_names)
84
+ end.add_description("Load #{stage} configuration")
33
85
  end
@@ -1,7 +1,7 @@
1
1
  describe "integration" do
2
2
  def run_cap(args)
3
3
  Dir.chdir 'fixtures' do
4
- `env CONFIG_ROOT=#{config_root} bundle exec cap #{args}`
4
+ `env STAGES_ROOT=#{stages_root} bundle exec cap #{args}`
5
5
  end
6
6
  end
7
7
 
@@ -10,8 +10,13 @@ describe "integration" do
10
10
  run_cap("-T")
11
11
  end
12
12
 
13
+ context "empty root" do
14
+ let(:stages_root) { 'config/empty' }
15
+ it { should == "" }
16
+ end
17
+
13
18
  context "two files root" do
14
- let(:config_root) { "config/two_files" }
19
+ let(:stages_root) { 'config/two_files' }
15
20
 
16
21
  it "should display configurations" do
17
22
  subject.should == <<-TEXT
@@ -21,24 +26,90 @@ TEXT
21
26
  end
22
27
  end
23
28
 
29
+ context "root with nested directory and two files inside" do
30
+ let(:stages_root) { 'config/nested' }
31
+ it {
32
+ should == <<-TEXT
33
+ cap app:production # Load app:production configuration
34
+ cap app:staging # Load app:staging configuration
35
+ TEXT
36
+ }
37
+ end
38
+
39
+ context "root with two nested directories and two files inside" do
40
+ let(:stages_root) { 'config/two_nested' }
41
+ it {
42
+ should == <<-TEXT
43
+ cap api:production # Load api:production configuration
44
+ cap api:staging # Load api:staging configuration
45
+ cap app:production # Load app:production configuration
46
+ cap app:staging # Load app:staging configuration
47
+ TEXT
48
+ }
49
+ end
50
+
51
+ context "root nested with shared file" do
52
+ let(:stages_root) { 'config/nested_with_shared_file' }
53
+ it {
54
+ should == <<-TEXT
55
+ cap app:production # Load app:production configuration
56
+ cap app:staging # Load app:staging configuration
57
+ TEXT
58
+ }
59
+ end
60
+
61
+ context "root nested with another file" do
62
+ let(:stages_root) { 'config/nested_with_another_file' }
63
+ it {
64
+ should == <<-TEXT
65
+ cap app:production # Load app:production configuration
66
+ cap app:staging # Load app:staging configuration
67
+ cap deploy # Load deploy configuration
68
+ TEXT
69
+ }
70
+ end
71
+
72
+ context "root nested with shared and another file" do
73
+ let(:stages_root) { 'config/nested_with_shared_and_another_file' }
74
+ it {
75
+ should == <<-TEXT
76
+ cap app:production # Load app:production configuration
77
+ cap app:staging # Load app:staging configuration
78
+ cap deploy # Load deploy configuration
79
+ TEXT
80
+ }
81
+ end
82
+
83
+ context "root with foreign file" do
84
+ let(:stages_root) { 'config/with_foreign_file' }
85
+ it {
86
+ should == <<-TEXT
87
+ cap production # Load production configuration
88
+ cap staging # Load staging configuration
89
+ TEXT
90
+ }
91
+ end
92
+
24
93
  context "third level nested root" do
25
- let(:config_root) { "config/third_level_nested" }
94
+ let(:stages_root) { "config/third_level_nested" }
26
95
 
27
- it "should display configurations" do
28
- subject.should == <<-TEXT
96
+ it {
97
+ should == <<-TEXT
29
98
  cap app:blog:production # Load app:blog:production configuration
30
99
  cap app:blog:staging # Load app:blog:staging configuration
31
100
  cap app:wiki:production # Load app:wiki:production configuration
32
101
  cap app:wiki:qa # Load app:wiki:qa configuration
33
102
  TEXT
34
- end
103
+ }
35
104
  end
36
105
  end
37
106
 
107
+
108
+
38
109
  describe "task invocation" do
39
110
 
40
111
  context "sample configurations" do
41
- let(:config_root) { 'config/sample' }
112
+ let(:stages_root) { 'config/sample' }
42
113
 
43
114
  context "without configuration" do
44
115
  subject { run_cap("hello_world") }
@@ -65,7 +136,7 @@ TEXT
65
136
  end
66
137
 
67
138
  context "configurations with shared file" do
68
- let(:config_root) { 'config/nested_with_shared_file' }
139
+ let(:stages_root) { 'config/nested_with_shared_file' }
69
140
  context "with app:production" do
70
141
  subject { run_cap("app:production hello_world") }
71
142
  it "should display certain message" do
@@ -81,7 +152,7 @@ TEXT
81
152
  end
82
153
 
83
154
  context "configuration with double nested shared file" do
84
- let(:config_root) { 'config/double_nested_shared_file' }
155
+ let(:stages_root) { 'config/double_nested_shared_file' }
85
156
  subject { run_cap("level0:level1:config hello_world") }
86
157
  it "should display nested message from all levels" do
87
158
  subject.should == "hello from level0 level1 world\n"
@@ -89,7 +160,7 @@ TEXT
89
160
  end
90
161
 
91
162
  context "configuration with root and nested" do
92
- let(:config_root) { 'config/root_with_nested' }
163
+ let(:stages_root) { 'config/root_with_nested' }
93
164
  subject { run_cap("app:config hello_world") }
94
165
  it "should display nested message from root" do
95
166
  subject.should == "hello from root world\n"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: capistrano-multiconfig
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.1
4
+ version: 3.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andriy Yanko
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-10-16 00:00:00.000000000 Z
11
+ date: 2013-10-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: capistrano
@@ -76,8 +76,6 @@ files:
76
76
  - fixtures/config/with_foreign_file/readme.md
77
77
  - fixtures/config/with_foreign_file/staging.rb
78
78
  - lib/capistrano/multiconfig.rb
79
- - lib/capistrano/multiconfig/configurations.rb
80
- - spec/capistrano/multiconfig/configurations_spec.rb
81
79
  - spec/integration_spec.rb
82
80
  homepage: https://github.com/railsware/multiconfig
83
81
  licenses: []
@@ -103,5 +101,4 @@ signing_key:
103
101
  specification_version: 4
104
102
  summary: Capistrano extension that allows to use multiple configurations
105
103
  test_files:
106
- - spec/capistrano/multiconfig/configurations_spec.rb
107
104
  - spec/integration_spec.rb
@@ -1,49 +0,0 @@
1
- module Capistrano
2
- module Multiconfig
3
- class Configurations
4
- def self.find_names(root_path)
5
- new(root_path).find_names
6
- end
7
-
8
- attr_reader :root_path
9
-
10
- def initialize(root_path)
11
- @root_path = root_path
12
- end
13
-
14
- # find configuration names
15
- def find_names
16
- files = scan_files
17
- files.sort!
18
- remove_shared_files!(files)
19
- build_names(files)
20
- end
21
-
22
- private
23
-
24
- # Scan recursively root path
25
- def scan_files
26
- Dir["#{root_path}/**/*.rb"]
27
- end
28
-
29
- # Remove path when there is the same directory with child.
30
- #
31
- # app/staging.rb (is shared configuration for 'alpha' and 'beta')
32
- # app/staging/alpha.rb
33
- # app/staging/beta.rb
34
- def remove_shared_files!(files)
35
- files.reject! do |file|
36
- dir = file.gsub(/\.rb$/, '/')
37
- files.any? { |f| f[0, dir.size] == dir }
38
- end
39
- end
40
-
41
- # Convert "app/blog/production" to "app:blog:production"
42
- def build_names(files)
43
- files.map do |file|
44
- file.sub("#{root_path}/", '').sub(/\.rb$/, '').gsub('/', ':')
45
- end
46
- end
47
- end
48
- end
49
- end
@@ -1,100 +0,0 @@
1
- require 'capistrano/multiconfig/configurations'
2
-
3
- describe Capistrano::Multiconfig::Configurations do
4
-
5
- describe ".find_names" do
6
- subject { described_class.find_names(config_root) }
7
-
8
- context "empty root" do
9
- let(:config_root) { 'fixtures/config/empty' }
10
- it { should == [] }
11
- end
12
-
13
- context "root with two files" do
14
- let(:config_root) { 'fixtures/config/two_files' }
15
- it {
16
- should == [
17
- 'production',
18
- 'staging'
19
- ]
20
- }
21
- end
22
-
23
- context "root with nested directory and two files inside" do
24
- let(:config_root) { 'fixtures/config/nested' }
25
- it {
26
- should == [
27
- 'app:production',
28
- 'app:staging'
29
- ]
30
- }
31
- end
32
-
33
- context "root with two nested directories and two files inside" do
34
- let(:config_root) { 'fixtures/config/two_nested' }
35
- it {
36
- should == [
37
- 'api:production',
38
- 'api:staging',
39
- 'app:production',
40
- 'app:staging'
41
- ]
42
- }
43
- end
44
-
45
- context "root with third nested directories" do
46
- let(:config_root) { 'fixtures/config/third_level_nested' }
47
- it {
48
- should == [
49
- 'app:blog:production',
50
- 'app:blog:staging',
51
- 'app:wiki:production',
52
- 'app:wiki:qa'
53
- ]
54
- }
55
- end
56
-
57
- context "root nested with shared file" do
58
- let(:config_root) { 'fixtures/config/nested_with_shared_file' }
59
- it {
60
- should == [
61
- 'app:production',
62
- 'app:staging',
63
- ]
64
- }
65
- end
66
-
67
- context "root nested with another file" do
68
- let(:config_root) { 'fixtures/config/nested_with_another_file' }
69
- it {
70
- should == [
71
- 'app:production',
72
- 'app:staging',
73
- 'deploy'
74
- ]
75
- }
76
- end
77
-
78
- context "root nested with shared and another file" do
79
- let(:config_root) { 'fixtures/config/nested_with_shared_and_another_file' }
80
- it {
81
- should == [
82
- 'app:production',
83
- 'app:staging',
84
- 'deploy'
85
- ]
86
- }
87
- end
88
-
89
- context "root with foreign file" do
90
- let(:config_root) { 'fixtures/config/with_foreign_file' }
91
- it {
92
- should == [
93
- 'production',
94
- 'staging'
95
- ]
96
- }
97
- end
98
-
99
- end
100
- end