pulsar 0.2.3 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +22 -0
- data/lib/pulsar/commands/main.rb +4 -7
- data/lib/pulsar/commands/utils.rb +1 -1
- data/lib/pulsar/helpers/all.rb +1 -0
- data/lib/pulsar/helpers/clamp.rb +27 -32
- data/lib/pulsar/helpers/path.rb +46 -0
- data/lib/pulsar/version.rb +1 -1
- data/pulsar.gemspec +4 -4
- data/spec/pulsar/commands/list_spec.rb +3 -4
- data/spec/pulsar/commands/main_spec.rb +14 -0
- data/spec/support/dummies/dummy_conf/apps/dummy_app/custom_stage.rb +5 -0
- data/spec/support/dummies/dummy_conf/apps/other_dummy_app/custom_stage.rb +5 -0
- metadata +23 -18
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
|
data/lib/pulsar/commands/main.rb
CHANGED
@@ -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 "
|
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(
|
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
|
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
|
data/lib/pulsar/helpers/all.rb
CHANGED
data/lib/pulsar/helpers/clamp.rb
CHANGED
@@ -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(
|
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["#{
|
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 --
|
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
|
86
|
-
app_file =
|
87
|
-
stage_file =
|
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
|
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
|
99
|
-
recipes_dir =
|
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
|
-
|
106
|
-
|
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 #{
|
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
|
-
|
169
|
+
exclude = %w(defaults recipes)
|
178
170
|
|
179
|
-
Dir["#{
|
171
|
+
Dir["#{config_app_path(app)}/*"].sort.map do |env|
|
180
172
|
env_name = File.basename(env, '.rb')
|
181
173
|
|
182
|
-
env_name
|
174
|
+
env_name unless exclude.include?(env_name)
|
183
175
|
end.compact
|
184
176
|
end
|
185
177
|
|
186
|
-
def
|
187
|
-
|
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
|
data/lib/pulsar/version.rb
CHANGED
data/pulsar.gemspec
CHANGED
@@ -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", "
|
30
|
-
gem.add_development_dependency "rr", "
|
31
|
-
gem.add_development_dependency "coveralls", "
|
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}:
|
33
|
-
stdout.should match(/#{app_two}:
|
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
|
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.
|
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-
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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
|