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 +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
|