pulsar 0.2.3 → 0.3.0

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.
data/README.md CHANGED
@@ -129,6 +129,28 @@ load_recipes do
129
129
  end
130
130
  ```
131
131
 
132
+ ---
133
+
134
+ You can specify some recipes to be loaded only when you run Pulsar from inside a Rack application directory.
135
+ This is useful with recipes that require something inside that directory (like retrieving the database/assets
136
+ from a staging environment).
137
+
138
+ You can do that like this:
139
+
140
+ ```ruby
141
+ #
142
+ # Somewhere inside apps/
143
+ #
144
+
145
+ #
146
+ # These recipes will be available only if you're running
147
+ # Pulsar inside a Rack application (like Rails) directory
148
+ #
149
+ load_recipes(app_only: true) do
150
+ rails :assets_pull, :database_pull
151
+ end
152
+ ```
153
+
132
154
  ### Loading the repository
133
155
 
134
156
  Once the repository is ready, you'll need to tell Pulsar where it is. The repository location can be specified either
@@ -5,7 +5,7 @@ module Pulsar
5
5
  include Pulsar::Options::ConfRepo
6
6
 
7
7
  option [ "-l", "--log-level" ], "LOG LEVEL",
8
- "how much output will Capistrano print out. Can be any of: important, info, debug",
8
+ "how much output will Capistrano print out. Can be any of: important, info, debug, trace",
9
9
  :default => "important"
10
10
 
11
11
  option [ "-s", "--skip-cap-run" ], :flag,
@@ -16,22 +16,19 @@ module Pulsar
16
16
  parameter "APPLICATION", "the application which you would like to deploy. Pass a comma separated list to deploy multiple applications at once"
17
17
  end
18
18
 
19
- parameter "ENVIRONMENT", "the environment on which you would like to deploy" do |env|
20
- %w(production staging development).include?(env) ? env : raise(ArgumentError)
21
- end
19
+ parameter "STAGE", "the stage on which you would like to deploy"
22
20
 
23
21
  parameter "[TASKS] ...", "the arguments and/or options that will be passed to capistrano", :default => "deploy"
24
22
 
25
23
  def execute
26
24
  find_apps.each do |app|
27
- target = "#{app}:#{environment}"
28
-
29
25
  Bundler.with_clean_env do
30
26
  begin
31
27
  fetch_repo
28
+ validate(app, stage)
32
29
  bundle_install
33
30
  create_capfile
34
- build_capfile(target)
31
+ build_capfile(app, stage)
35
32
 
36
33
  unless skip_cap_run?
37
34
  cap_args = [ tasks_list ].flatten.join(" ")
@@ -3,7 +3,7 @@ module Pulsar
3
3
  include Pulsar::Helpers::Clamp
4
4
  include Pulsar::Options::Shared
5
5
 
6
- subcommand "list", "list all available apps and environments which you can deploy", ListCommand
6
+ subcommand "list", "list all available apps and stages which you can deploy", ListCommand
7
7
  subcommand "init", "generate a new configuration repo with some basic recipes to use with pulsar", InitCommand
8
8
  end
9
9
  end
@@ -1,5 +1,6 @@
1
1
  module Pulsar::Helpers
2
2
  autoload :Capistrano, "pulsar/helpers/capistrano"
3
3
  autoload :Clamp, "pulsar/helpers/clamp"
4
+ autoload :Path, "pulsar/helpers/path"
4
5
  autoload :Shell, "pulsar/helpers/shell"
5
6
  end
@@ -2,6 +2,7 @@ module Pulsar
2
2
  module Helpers
3
3
  module Clamp
4
4
  include Pulsar::Helpers::Shell
5
+ include Pulsar::Helpers::Path
5
6
 
6
7
  def self.included(base)
7
8
  base.extend(InstanceAndClassMethods)
@@ -21,9 +22,7 @@ module Pulsar
21
22
  Dir.pwd if from_application_path?
22
23
  end
23
24
 
24
- def build_capfile(args)
25
- app, stage = args.split(":")
26
-
25
+ def build_capfile(app, stage)
27
26
  # Variables
28
27
  set_log_level
29
28
  include_base_conf
@@ -39,20 +38,12 @@ module Pulsar
39
38
  end
40
39
  end
41
40
 
42
- def capfile_path
43
- @capfile_name ||= "#{tmp_dir}/capfile-#{time_to_deploy}"
44
- end
45
-
46
- def config_path
47
- @configuration_path ||= "#{tmp_dir}/conf-repo-#{time_to_deploy}"
48
- end
49
-
50
41
  def create_capfile
51
42
  touch(capfile_path, :verbose => verbose?)
52
43
  end
53
44
 
54
45
  def each_app
55
- Dir["#{config_path}/apps/*"].each do |path|
46
+ Dir["#{config_apps_path}/*"].each do |path|
56
47
  yield(File.basename(path)) if File.directory?(path)
57
48
  end
58
49
  end
@@ -71,46 +62,47 @@ module Pulsar
71
62
 
72
63
  def fetch_directory_repo(repo)
73
64
  if File.directory?("#{repo}/.git")
74
- fetch_git_repo(repo)
65
+ fetch_git_repo(repo, true)
75
66
  else
76
67
  run_cmd("cp -rp #{repo} #{config_path}", :verbose => verbose?)
77
68
  end
78
69
  end
79
70
 
80
- def fetch_git_repo(repo)
81
- git_options = "--quiet --depth=1 --branch #{conf_branch}"
71
+ def fetch_git_repo(repo, local=false)
72
+ git_options = "--quiet --branch #{conf_branch}"
73
+ git_options = "#{git_options} --depth=1" unless local
74
+
82
75
  run_cmd("git clone #{git_options} #{repo} #{config_path}", :verbose => verbose?)
83
76
  end
84
77
 
85
- def include_app(app, stage=nil)
86
- app_file = "#{config_path}/apps/#{app}/defaults.rb"
87
- stage_file = "#{config_path}/apps/#{app}/#{stage}.rb"
78
+ def include_app(app, stage)
79
+ app_file = config_app_defaults_path(app)
80
+ stage_file = config_stage_path(app, stage)
88
81
 
89
82
  if File.exists?(app_file)
90
83
  run_cmd("cat #{app_file} >> #{capfile_path}", :verbose => verbose?)
91
84
  end
92
85
 
93
- if stage
86
+ if File.exists?(stage_file)
94
87
  run_cmd("cat #{stage_file} >> #{capfile_path}", :verbose => verbose?)
95
88
  end
96
89
  end
97
90
 
98
- def include_app_recipes(app, stage=nil)
99
- recipes_dir = "#{config_path}/apps/#{app}/recipes"
91
+ def include_app_recipes(app, stage)
92
+ recipes_dir = config_app_recipes_path(app)
93
+ stage_recipes_dir = config_app_stage_recipes_path(app, stage)
100
94
 
101
95
  Dir.glob("#{recipes_dir}/*.rb").each do |recipe|
102
96
  run_cmd("cat #{recipe} >> #{capfile_path}", :verbose => verbose?)
103
97
  end
104
98
 
105
- if stage
106
- Dir.glob("#{recipes_dir}/#{stage}/*.rb").each do |recipe|
107
- run_cmd("cat #{recipe} >> #{capfile_path}", :verbose => verbose?)
108
- end
99
+ Dir.glob("#{stage_recipes_dir}/*.rb").each do |recipe|
100
+ run_cmd("cat #{recipe} >> #{capfile_path}", :verbose => verbose?)
109
101
  end
110
102
  end
111
103
 
112
104
  def include_base_conf
113
- run_cmd("cat #{config_path}/apps/base.rb >> #{capfile_path}", :verbose => verbose?)
105
+ run_cmd("cat #{config_base_path} >> #{capfile_path}", :verbose => verbose?)
114
106
  end
115
107
 
116
108
  def list_apps
@@ -164,7 +156,7 @@ module Pulsar
164
156
 
165
157
  def set_log_level
166
158
  level = log_level.upcase
167
- levels = %w(IMPORTANT INFO DEBUG)
159
+ levels = %w(IMPORTANT INFO DEBUG TRACE)
168
160
 
169
161
  level = levels.first unless levels.include?(level)
170
162
 
@@ -174,17 +166,20 @@ module Pulsar
174
166
  end
175
167
 
176
168
  def stages_for(app)
177
- environments = %w(development staging production)
169
+ exclude = %w(defaults recipes)
178
170
 
179
- Dir["#{config_path}/apps/#{app}/*"].map do |env|
171
+ Dir["#{config_app_path(app)}/*"].sort.map do |env|
180
172
  env_name = File.basename(env, '.rb')
181
173
 
182
- env_name if environments.include?(env_name)
174
+ env_name unless exclude.include?(env_name)
183
175
  end.compact
184
176
  end
185
177
 
186
- def time_to_deploy
187
- @now ||= Time.now.strftime("%Y-%m-%d-%H%M%S-s#{rand(9999)}")
178
+ def validate(app, stage)
179
+ app_path = config_app_path(app)
180
+ stage_path = config_stage_path(app, stage)
181
+
182
+ raise(ArgumentError) unless File.exists?(app_path) && File.exists?(stage_path)
188
183
  end
189
184
  end
190
185
  end
@@ -0,0 +1,46 @@
1
+ module Pulsar
2
+ module Helpers
3
+ module Path
4
+ def capfile_path
5
+ @capfile_name ||= "#{tmp_dir}/capfile-#{time_to_deploy}"
6
+ end
7
+
8
+ def config_path
9
+ @configuration_path ||= "#{tmp_dir}/conf-repo-#{time_to_deploy}"
10
+ end
11
+
12
+ def config_app_path(app)
13
+ "#{config_apps_path}/#{app}"
14
+ end
15
+
16
+ def config_app_defaults_path(app)
17
+ "#{config_app_path(app)}/defaults.rb"
18
+ end
19
+
20
+ def config_app_recipes_path(app)
21
+ "#{config_app_path(app)}/recipes"
22
+ end
23
+
24
+ def config_app_stage_recipes_path(app, stage)
25
+ "#{config_app_recipes_path(app)}/#{stage}"
26
+ end
27
+
28
+ def config_apps_path
29
+ "#{config_path}/apps"
30
+ end
31
+
32
+ def config_base_path
33
+ "#{config_apps_path}/base.rb"
34
+ end
35
+
36
+ def config_stage_path(app, stage)
37
+ "#{config_app_path(app)}/#{stage}.rb"
38
+ end
39
+
40
+ private
41
+ def time_to_deploy
42
+ @now ||= Time.now.strftime("%Y-%m-%d-%H%M%S-s#{rand(9999)}")
43
+ end
44
+ end
45
+ end
46
+ end
@@ -1,3 +1,3 @@
1
1
  module Pulsar
2
- VERSION = "0.2.3"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -25,8 +25,8 @@ Gem::Specification.new do |gem|
25
25
  gem.add_dependency "bundler", "~> 1.2"
26
26
  gem.add_dependency "colored", "~> 1.2"
27
27
 
28
- gem.add_development_dependency "rake"
29
- gem.add_development_dependency "rspec", "~> 2.12"
30
- gem.add_development_dependency "rr", "~> 1.0"
31
- gem.add_development_dependency "coveralls", "~> 0.6.3"
28
+ gem.add_development_dependency "rake", "10.0.4"
29
+ gem.add_development_dependency "rspec", "2.12.0"
30
+ gem.add_development_dependency "rr", "1.0.4"
31
+ gem.add_development_dependency "coveralls", "0.6.3"
32
32
  end
@@ -23,14 +23,13 @@ describe Pulsar::ListCommand do
23
23
  app_one = Regexp.escape("dummy_app".cyan)
24
24
  app_two = Regexp.escape("other_dummy_app".cyan)
25
25
 
26
- stages = [ "production".magenta, "staging".magenta ]
26
+ stages = [ "custom_stage".magenta, "production".magenta, "staging".magenta ]
27
27
  escaped_stages = Regexp.escape(stages.join(', '))
28
- reversed_stages = Regexp.escape(stages.reverse.join(', '))
29
28
 
30
29
  pulsar.run(full_list_args)
31
30
 
32
- stdout.should match(/#{app_one}: (#{escaped_stages})|(#{reversed_stages})/)
33
- stdout.should match(/#{app_two}: (#{escaped_stages})|(#{reversed_stages})/)
31
+ stdout.should match(/#{app_one}: #{escaped_stages}/)
32
+ stdout.should match(/#{app_two}: #{escaped_stages}/)
34
33
  end
35
34
 
36
35
  it "reads configuration variables from .pulsar file in home" do
@@ -101,6 +101,14 @@ describe Pulsar::MainCommand do
101
101
  end
102
102
  end
103
103
 
104
+ it "errors out if application does not exist in configuration repository" do
105
+ expect { pulsar.run(full_cap_args + %w(non_existant_app production)) }.to raise_error(ArgumentError)
106
+ end
107
+
108
+ it "errors out if stage does not exist in configuration repository" do
109
+ expect { pulsar.run(full_cap_args + dummy_app(:non_existant_stage)) }.to raise_error(ArgumentError)
110
+ end
111
+
104
112
  context "Capfile" do
105
113
  it "uses base.rb in staging stage" do
106
114
  pulsar.run(full_cap_args + dummy_app(:staging))
@@ -259,5 +267,11 @@ describe Pulsar::MainCommand do
259
267
 
260
268
  latest_capfile.should include("logger.level = logger.level = Capistrano::Logger::DEBUG")
261
269
  end
270
+
271
+ it "supports Capistrano TRACE" do
272
+ pulsar.run(full_cap_args + %w(--log-level trace) + dummy_app)
273
+
274
+ latest_capfile.should include("logger.level = logger.level = Capistrano::Logger::TRACE")
275
+ end
262
276
  end
263
277
  end
@@ -0,0 +1,5 @@
1
+ # This is apps/dummy_app/custom_stage.rb
2
+
3
+ server "dummy.it", :db, :web, :app, :primary => true
4
+
5
+ set :stage, "custom_stage"
@@ -0,0 +1,5 @@
1
+ # This is apps/other_dummy_app/custom_stage.rb
2
+
3
+ server "dummy.it", :db, :web, :app, :primary => true
4
+
5
+ set :stage, "custom_stage"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pulsar
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2013-05-12 00:00:00.000000000 Z
13
+ date: 2013-07-23 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: clamp
@@ -65,55 +65,55 @@ dependencies:
65
65
  requirement: !ruby/object:Gem::Requirement
66
66
  none: false
67
67
  requirements:
68
- - - ! '>='
68
+ - - '='
69
69
  - !ruby/object:Gem::Version
70
- version: '0'
70
+ version: 10.0.4
71
71
  type: :development
72
72
  prerelease: false
73
73
  version_requirements: !ruby/object:Gem::Requirement
74
74
  none: false
75
75
  requirements:
76
- - - ! '>='
76
+ - - '='
77
77
  - !ruby/object:Gem::Version
78
- version: '0'
78
+ version: 10.0.4
79
79
  - !ruby/object:Gem::Dependency
80
80
  name: rspec
81
81
  requirement: !ruby/object:Gem::Requirement
82
82
  none: false
83
83
  requirements:
84
- - - ~>
84
+ - - '='
85
85
  - !ruby/object:Gem::Version
86
- version: '2.12'
86
+ version: 2.12.0
87
87
  type: :development
88
88
  prerelease: false
89
89
  version_requirements: !ruby/object:Gem::Requirement
90
90
  none: false
91
91
  requirements:
92
- - - ~>
92
+ - - '='
93
93
  - !ruby/object:Gem::Version
94
- version: '2.12'
94
+ version: 2.12.0
95
95
  - !ruby/object:Gem::Dependency
96
96
  name: rr
97
97
  requirement: !ruby/object:Gem::Requirement
98
98
  none: false
99
99
  requirements:
100
- - - ~>
100
+ - - '='
101
101
  - !ruby/object:Gem::Version
102
- version: '1.0'
102
+ version: 1.0.4
103
103
  type: :development
104
104
  prerelease: false
105
105
  version_requirements: !ruby/object:Gem::Requirement
106
106
  none: false
107
107
  requirements:
108
- - - ~>
108
+ - - '='
109
109
  - !ruby/object:Gem::Version
110
- version: '1.0'
110
+ version: 1.0.4
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: coveralls
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  none: false
115
115
  requirements:
116
- - - ~>
116
+ - - '='
117
117
  - !ruby/object:Gem::Version
118
118
  version: 0.6.3
119
119
  type: :development
@@ -121,7 +121,7 @@ dependencies:
121
121
  version_requirements: !ruby/object:Gem::Requirement
122
122
  none: false
123
123
  requirements:
124
- - - ~>
124
+ - - '='
125
125
  - !ruby/object:Gem::Version
126
126
  version: 0.6.3
127
127
  description: Manage your Capistrano deployments with ease
@@ -165,6 +165,7 @@ files:
165
165
  - lib/pulsar/helpers/all.rb
166
166
  - lib/pulsar/helpers/capistrano.rb
167
167
  - lib/pulsar/helpers/clamp.rb
168
+ - lib/pulsar/helpers/path.rb
168
169
  - lib/pulsar/helpers/shell.rb
169
170
  - lib/pulsar/options/all.rb
170
171
  - lib/pulsar/options/conf_repo.rb
@@ -182,12 +183,14 @@ files:
182
183
  - spec/support/dummies/dummy_app/config.ru
183
184
  - spec/support/dummies/dummy_conf/Gemfile
184
185
  - spec/support/dummies/dummy_conf/apps/base.rb
186
+ - spec/support/dummies/dummy_conf/apps/dummy_app/custom_stage.rb
185
187
  - spec/support/dummies/dummy_conf/apps/dummy_app/defaults.rb
186
188
  - spec/support/dummies/dummy_conf/apps/dummy_app/production.rb
187
189
  - spec/support/dummies/dummy_conf/apps/dummy_app/recipes/custom_recipe.rb
188
190
  - spec/support/dummies/dummy_conf/apps/dummy_app/recipes/production/custom_recipe.rb
189
191
  - spec/support/dummies/dummy_conf/apps/dummy_app/recipes/staging/custom_recipe.rb
190
192
  - spec/support/dummies/dummy_conf/apps/dummy_app/staging.rb
193
+ - spec/support/dummies/dummy_conf/apps/other_dummy_app/custom_stage.rb
191
194
  - spec/support/dummies/dummy_conf/apps/other_dummy_app/defaults.rb
192
195
  - spec/support/dummies/dummy_conf/apps/other_dummy_app/production.rb
193
196
  - spec/support/dummies/dummy_conf/apps/other_dummy_app/staging.rb
@@ -209,7 +212,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
209
212
  version: '0'
210
213
  segments:
211
214
  - 0
212
- hash: 882451203726848959
215
+ hash: 2226446731285894531
213
216
  required_rubygems_version: !ruby/object:Gem::Requirement
214
217
  none: false
215
218
  requirements:
@@ -218,7 +221,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
218
221
  version: '0'
219
222
  segments:
220
223
  - 0
221
- hash: 882451203726848959
224
+ hash: 2226446731285894531
222
225
  requirements: []
223
226
  rubyforge_project:
224
227
  rubygems_version: 1.8.25
@@ -239,12 +242,14 @@ test_files:
239
242
  - spec/support/dummies/dummy_app/config.ru
240
243
  - spec/support/dummies/dummy_conf/Gemfile
241
244
  - spec/support/dummies/dummy_conf/apps/base.rb
245
+ - spec/support/dummies/dummy_conf/apps/dummy_app/custom_stage.rb
242
246
  - spec/support/dummies/dummy_conf/apps/dummy_app/defaults.rb
243
247
  - spec/support/dummies/dummy_conf/apps/dummy_app/production.rb
244
248
  - spec/support/dummies/dummy_conf/apps/dummy_app/recipes/custom_recipe.rb
245
249
  - spec/support/dummies/dummy_conf/apps/dummy_app/recipes/production/custom_recipe.rb
246
250
  - spec/support/dummies/dummy_conf/apps/dummy_app/recipes/staging/custom_recipe.rb
247
251
  - spec/support/dummies/dummy_conf/apps/dummy_app/staging.rb
252
+ - spec/support/dummies/dummy_conf/apps/other_dummy_app/custom_stage.rb
248
253
  - spec/support/dummies/dummy_conf/apps/other_dummy_app/defaults.rb
249
254
  - spec/support/dummies/dummy_conf/apps/other_dummy_app/production.rb
250
255
  - spec/support/dummies/dummy_conf/apps/other_dummy_app/staging.rb