capistrano_multiconfig_parallel 0.15.6 → 0.16.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.
- checksums.yaml +4 -4
- data/.codeclimate.yml +25 -0
- data/.gitignore +0 -1
- data/Gemfile.lock +327 -0
- data/README.md +1 -1
- data/lib/capistrano_multiconfig_parallel/all.rb +16 -1
- data/lib/capistrano_multiconfig_parallel/application.rb +340 -11
- data/lib/capistrano_multiconfig_parallel/base.rb +8 -8
- data/lib/capistrano_multiconfig_parallel/celluloid/celluloid_manager.rb +3 -6
- data/lib/capistrano_multiconfig_parallel/celluloid/celluloid_worker.rb +6 -0
- data/lib/capistrano_multiconfig_parallel/cli.rb +8 -1
- data/lib/capistrano_multiconfig_parallel/configuration.rb +8 -30
- data/lib/capistrano_multiconfig_parallel/extensions/rake.rb +1 -1
- data/lib/capistrano_multiconfig_parallel/{multi_app_helpers → helpers}/dependency_tracker.rb +5 -5
- data/lib/capistrano_multiconfig_parallel/helpers/helper.rb +9 -0
- data/lib/capistrano_multiconfig_parallel/{extensions → helpers}/rake_hook_actor.rb +0 -1
- data/lib/capistrano_multiconfig_parallel/initializers/conf.rb +2 -3
- data/lib/capistrano_multiconfig_parallel/initializers/default.yml +3 -3
- data/lib/capistrano_multiconfig_parallel/version.rb +2 -2
- metadata +11 -9
- data/lib/capistrano_multiconfig_parallel/managers/base_manager.rb +0 -348
- /data/lib/capistrano_multiconfig_parallel/{extensions → helpers}/input_stream.rb +0 -0
- /data/lib/capistrano_multiconfig_parallel/{multi_app_helpers → helpers}/interactive_menu.rb +0 -0
- /data/lib/capistrano_multiconfig_parallel/{extensions → helpers}/output_stream.rb +0 -0
- /data/lib/capistrano_multiconfig_parallel/{managers → helpers}/standard_deploy.rb +0 -0
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: capistrano_multiconfig_parallel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.16.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- bogdanRada
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-12-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: celluloid-pmap
|
@@ -599,6 +599,7 @@ executables:
|
|
599
599
|
extensions: []
|
600
600
|
extra_rdoc_files: []
|
601
601
|
files:
|
602
|
+
- ".codeclimate.yml"
|
602
603
|
- ".coveralls.yml"
|
603
604
|
- ".gitignore"
|
604
605
|
- ".rspec"
|
@@ -606,6 +607,7 @@ files:
|
|
606
607
|
- ".travis.yml"
|
607
608
|
- CONTRIBUTING.md
|
608
609
|
- Gemfile
|
610
|
+
- Gemfile.lock
|
609
611
|
- Guardfile
|
610
612
|
- LICENSE
|
611
613
|
- README.md
|
@@ -627,16 +629,16 @@ files:
|
|
627
629
|
- lib/capistrano_multiconfig_parallel/celluloid/web_server.rb
|
628
630
|
- lib/capistrano_multiconfig_parallel/cli.rb
|
629
631
|
- lib/capistrano_multiconfig_parallel/configuration.rb
|
630
|
-
- lib/capistrano_multiconfig_parallel/extensions/input_stream.rb
|
631
|
-
- lib/capistrano_multiconfig_parallel/extensions/output_stream.rb
|
632
632
|
- lib/capistrano_multiconfig_parallel/extensions/rake.rb
|
633
|
-
- lib/capistrano_multiconfig_parallel/
|
633
|
+
- lib/capistrano_multiconfig_parallel/helpers/dependency_tracker.rb
|
634
|
+
- lib/capistrano_multiconfig_parallel/helpers/helper.rb
|
635
|
+
- lib/capistrano_multiconfig_parallel/helpers/input_stream.rb
|
636
|
+
- lib/capistrano_multiconfig_parallel/helpers/interactive_menu.rb
|
637
|
+
- lib/capistrano_multiconfig_parallel/helpers/output_stream.rb
|
638
|
+
- lib/capistrano_multiconfig_parallel/helpers/rake_hook_actor.rb
|
639
|
+
- lib/capistrano_multiconfig_parallel/helpers/standard_deploy.rb
|
634
640
|
- lib/capistrano_multiconfig_parallel/initializers/conf.rb
|
635
641
|
- lib/capistrano_multiconfig_parallel/initializers/default.yml
|
636
|
-
- lib/capistrano_multiconfig_parallel/managers/base_manager.rb
|
637
|
-
- lib/capistrano_multiconfig_parallel/managers/standard_deploy.rb
|
638
|
-
- lib/capistrano_multiconfig_parallel/multi_app_helpers/dependency_tracker.rb
|
639
|
-
- lib/capistrano_multiconfig_parallel/multi_app_helpers/interactive_menu.rb
|
640
642
|
- lib/capistrano_multiconfig_parallel/version.rb
|
641
643
|
homepage: http://github.com/bogdanRada/capistrano_multiconfig_parallel/
|
642
644
|
licenses:
|
@@ -1,348 +0,0 @@
|
|
1
|
-
require_relative './standard_deploy'
|
2
|
-
require_relative '../celluloid/celluloid_manager'
|
3
|
-
require_relative '../multi_app_helpers/dependency_tracker'
|
4
|
-
module CapistranoMulticonfigParallel
|
5
|
-
# finds app dependencies, shows menu and delegates jobs to celluloid manager
|
6
|
-
# rubocop:disable ClassLength
|
7
|
-
class BaseManager
|
8
|
-
include Celluloid
|
9
|
-
include Celluloid::Logger
|
10
|
-
|
11
|
-
attr_accessor :stages, :top_level_tasks, :jobs, :branch_backup, :condition, :manager, :dependency_tracker, :application, :stage, :name, :args, :argv, :default_stage
|
12
|
-
|
13
|
-
def initialize
|
14
|
-
@stages = fetch_stages
|
15
|
-
collect_command_line_tasks(CapistranoMulticonfigParallel.original_args)
|
16
|
-
@jobs = []
|
17
|
-
end
|
18
|
-
|
19
|
-
def fetch_stages
|
20
|
-
fetch_stages_paths do |paths|
|
21
|
-
paths.reject! { |path| check_stage_path(paths, path) }.sort
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def check_stage_path(paths, path)
|
26
|
-
paths.any? { |another| another != path && another.start_with?(path + ':') }
|
27
|
-
end
|
28
|
-
|
29
|
-
def stages_paths
|
30
|
-
stages_root = 'config/deploy'
|
31
|
-
Dir["#{stages_root}/**/*.rb"].map do |file|
|
32
|
-
file.slice(stages_root.size + 1..-4).tr('/', ':')
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def fetch_stages_paths
|
37
|
-
stages_paths.tap { |paths| yield paths if block_given? }
|
38
|
-
end
|
39
|
-
|
40
|
-
def run
|
41
|
-
options = {}
|
42
|
-
if custom_command?
|
43
|
-
options = verify_options_custom_command(options)
|
44
|
-
run_custom_command(options)
|
45
|
-
else
|
46
|
-
collect_jobs(options)
|
47
|
-
end
|
48
|
-
process_jobs
|
49
|
-
end
|
50
|
-
|
51
|
-
def run_custom_command(options)
|
52
|
-
custom_stages = fetch_multi_stages
|
53
|
-
return if custom_stages.blank?
|
54
|
-
custom_stages = check_multi_stages(custom_stages)
|
55
|
-
custom_stages.each do |stage|
|
56
|
-
collect_jobs(options.merge('stage' => stage))
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
def deploy_multiple_apps(applications, options)
|
61
|
-
options = options.stringify_keys
|
62
|
-
return unless applications.present?
|
63
|
-
applications.each do |app|
|
64
|
-
deploy_app(options.merge('app' => app))
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def backup_the_branch
|
69
|
-
return if custom_command? || @argv['BRANCH'].blank?
|
70
|
-
@branch_backup = @argv['BRANCH'].to_s
|
71
|
-
@argv['BRANCH'] = nil
|
72
|
-
end
|
73
|
-
|
74
|
-
def can_start?
|
75
|
-
@top_level_tasks.size >= 1 && (@stages.include?(@top_level_tasks.first) || custom_command?) && ENV[CapistranoMulticonfigParallel::ENV_KEY_JOB_ID].blank?
|
76
|
-
end
|
77
|
-
|
78
|
-
def custom_command?
|
79
|
-
if multi_apps?
|
80
|
-
!@stages.include?(@top_level_tasks.first) && custom_commands.values.include?(@top_level_tasks.first)
|
81
|
-
else
|
82
|
-
!@stages.include?(@top_level_tasks.second) && @stages.include?(@top_level_tasks.first) && custom_commands.values.include?(@top_level_tasks.second)
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
def custom_commands
|
87
|
-
key = multi_apps? ? CapistranoMulticonfigParallel::MULTI_KEY : CapistranoMulticonfigParallel::SINGLE_KEY
|
88
|
-
CapistranoMulticonfigParallel::CUSTOM_COMMANDS[key]
|
89
|
-
end
|
90
|
-
|
91
|
-
def multi_apps?
|
92
|
-
@stages.find { |stage| stage.include?(':') }.present?
|
93
|
-
end
|
94
|
-
|
95
|
-
def configuration
|
96
|
-
CapistranoMulticonfigParallel.configuration
|
97
|
-
end
|
98
|
-
|
99
|
-
def start(&block)
|
100
|
-
check_before_starting
|
101
|
-
initialize_data
|
102
|
-
block.call if block_given?
|
103
|
-
run
|
104
|
-
end
|
105
|
-
|
106
|
-
def initialize_data
|
107
|
-
@application = custom_command? ? nil : @top_level_tasks.first.split(':').reverse[1]
|
108
|
-
@stage = custom_command? ? nil : @top_level_tasks.first.split(':').reverse[0]
|
109
|
-
@stage = @stage.present? ? @stage : @default_stage
|
110
|
-
@name, @args = parse_task_string(@top_level_tasks.second)
|
111
|
-
end
|
112
|
-
|
113
|
-
def collect_command_line_tasks(args) # :nodoc:
|
114
|
-
@argv = {}
|
115
|
-
@top_level_tasks = []
|
116
|
-
args.each do |arg|
|
117
|
-
if arg =~ /^(\w+)=(.*)$/m
|
118
|
-
@argv[Regexp.last_match(1)] = Regexp.last_match(2)
|
119
|
-
else
|
120
|
-
@top_level_tasks << arg unless arg =~ /^-/
|
121
|
-
end
|
122
|
-
end
|
123
|
-
@top_level_tasks.push(Rake.application.default_task_name) if @top_level_tasks.blank?
|
124
|
-
end
|
125
|
-
|
126
|
-
def parse_task_string(string) # :nodoc:
|
127
|
-
/^([^\[]+)(?:\[(.*)\])$/ =~ string.to_s
|
128
|
-
|
129
|
-
name = Regexp.last_match(1)
|
130
|
-
remaining_args = Regexp.last_match(2)
|
131
|
-
|
132
|
-
return string, [] unless name
|
133
|
-
return name, [] if remaining_args.empty?
|
134
|
-
|
135
|
-
args = []
|
136
|
-
|
137
|
-
loop do
|
138
|
-
/((?:[^\\,]|\\.)*?)\s*(?:,\s*(.*))?$/ =~ remaining_args
|
139
|
-
|
140
|
-
remaining_args = Regexp.last_match(2)
|
141
|
-
args << Regexp.last_match(1).gsub(/\\(.)/, '\1')
|
142
|
-
break if remaining_args.blank?
|
143
|
-
end
|
144
|
-
|
145
|
-
[name, args]
|
146
|
-
end
|
147
|
-
|
148
|
-
def verify_options_custom_command(options)
|
149
|
-
options[:action] = @argv['ACTION'].present? ? @argv['ACTION'] : 'deploy'
|
150
|
-
options
|
151
|
-
end
|
152
|
-
|
153
|
-
def check_before_starting
|
154
|
-
CapistranoMulticonfigParallel.configuration_valid?(@stages)
|
155
|
-
CapistranoMulticonfigParallel.enable_logging
|
156
|
-
@dependency_tracker = CapistranoMulticonfigParallel::DependencyTracker.new(Actor.current)
|
157
|
-
@default_stage = CapistranoMulticonfigParallel.configuration.development_stages.present? ? CapistranoMulticonfigParallel.configuration.development_stages.first : 'development'
|
158
|
-
@condition = Celluloid::Condition.new
|
159
|
-
@manager = CapistranoMulticonfigParallel::CelluloidManager.new(Actor.current)
|
160
|
-
end
|
161
|
-
|
162
|
-
def collect_jobs(options = {}, &_block)
|
163
|
-
options = prepare_options(options)
|
164
|
-
options = options.stringify_keys
|
165
|
-
apps = @dependency_tracker.fetch_apps_needed_for_deployment(options['app'], options['action'])
|
166
|
-
backup_the_branch if multi_apps?
|
167
|
-
deploy_multiple_apps(apps, options)
|
168
|
-
deploy_app(options) if !custom_command? || !multi_apps?
|
169
|
-
rescue => e
|
170
|
-
CapistranoMulticonfigParallel.log_message(e)
|
171
|
-
end
|
172
|
-
|
173
|
-
def process_jobs
|
174
|
-
return unless @jobs.present?
|
175
|
-
if configuration.multi_secvential.to_s.downcase == 'true'
|
176
|
-
@jobs.each { |job| CapistranoMulticonfigParallel::StandardDeploy.new(job) }
|
177
|
-
else
|
178
|
-
run_async_jobs
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
|
-
def tag_staging_exists? # check exists task from capistrano-gitflow
|
183
|
-
check_giflow_tasks(
|
184
|
-
CapistranoMulticonfigParallel::GITFLOW_TAG_STAGING_TASK,
|
185
|
-
CapistranoMulticonfigParallel::GITFLOW_CALCULATE_TAG_TASK,
|
186
|
-
CapistranoMulticonfigParallel::GITFLOW_VERIFY_UPTODATE_TASK
|
187
|
-
)
|
188
|
-
rescue
|
189
|
-
return false
|
190
|
-
end
|
191
|
-
|
192
|
-
def check_giflow_tasks(*tasks)
|
193
|
-
tasks.all? { |t| Rake::Task[t].present? }
|
194
|
-
end
|
195
|
-
|
196
|
-
def fetch_multi_stages
|
197
|
-
custom_stages = @argv['STAGES'].blank? ? '' : @argv['STAGES']
|
198
|
-
custom_stages = parse_inputted_value('value' => custom_stages).split(',').compact if custom_stages.present?
|
199
|
-
custom_stages = custom_stages.present? ? custom_stages : [@default_stage]
|
200
|
-
custom_stages
|
201
|
-
end
|
202
|
-
|
203
|
-
def wants_deploy_production?
|
204
|
-
(!custom_command? && @stage == 'production') || (custom_command? && fetch_multi_stages.include?('production'))
|
205
|
-
end
|
206
|
-
|
207
|
-
def can_tag_staging?
|
208
|
-
wants_deploy_production? && tag_staging_exists? && fetch_multi_stages.include?('staging')
|
209
|
-
end
|
210
|
-
|
211
|
-
def check_multi_stages(custom_stages)
|
212
|
-
can_tag_staging? ? custom_stages.reject { |u| u == 'production' } : custom_stages
|
213
|
-
end
|
214
|
-
|
215
|
-
def deploy_app(options = {})
|
216
|
-
options = options.stringify_keys
|
217
|
-
app = options['app'].is_a?(Hash) ? options['app'] : { 'app' => options['app'] }
|
218
|
-
branch = @branch_backup.present? ? @branch_backup : @argv['BRANCH'].to_s
|
219
|
-
call_task_deploy_app({
|
220
|
-
branch: branch,
|
221
|
-
app: app,
|
222
|
-
action: options['action']
|
223
|
-
}.reverse_merge(options))
|
224
|
-
end
|
225
|
-
|
226
|
-
def get_app_additional_env_options(app, app_message)
|
227
|
-
app_name = (app.is_a?(Hash) && app[:app].present?) ? app[:app].camelcase : app
|
228
|
-
app_name = app_name.present? ? app_name : 'current application'
|
229
|
-
message = "Please write additional ENV options for #{app_name} for #{app_message}"
|
230
|
-
set :app_additional_env_options, CapistranoMulticonfigParallel.ask_confirm(message, nil)
|
231
|
-
fetch_app_additional_env_options
|
232
|
-
end
|
233
|
-
|
234
|
-
def worker_environments
|
235
|
-
@jobs.map { |job| job['env'] }
|
236
|
-
end
|
237
|
-
|
238
|
-
private
|
239
|
-
|
240
|
-
def call_task_deploy_app(options = {})
|
241
|
-
options = options.stringify_keys
|
242
|
-
main_box_name = @argv['BOX'].blank? ? '' : @argv['BOX']
|
243
|
-
stage = options.fetch('stage', @default_stage)
|
244
|
-
if CapistranoMulticonfigParallel.configuration.development_stages.include?(stage) && main_box_name.present? && /^[a-z0-9,]+/.match(main_box_name)
|
245
|
-
execute_on_multiple_boxes(main_box_name, options)
|
246
|
-
else
|
247
|
-
prepare_job(options)
|
248
|
-
end
|
249
|
-
end
|
250
|
-
|
251
|
-
def run_async_jobs
|
252
|
-
return unless @jobs.present?
|
253
|
-
@jobs.pmap do |job|
|
254
|
-
@manager.async.delegate(job)
|
255
|
-
end
|
256
|
-
until @manager.registration_complete
|
257
|
-
sleep(0.1) # keep current thread alive
|
258
|
-
end
|
259
|
-
return unless @manager.registration_complete
|
260
|
-
@manager.async.process_jobs
|
261
|
-
wait_jobs_termination
|
262
|
-
end
|
263
|
-
|
264
|
-
def wait_jobs_termination
|
265
|
-
return if configuration.multi_secvential.to_s.downcase == 'true'
|
266
|
-
result = @condition.wait
|
267
|
-
return unless result.present?
|
268
|
-
@manager.terminate
|
269
|
-
terminate
|
270
|
-
end
|
271
|
-
|
272
|
-
def prepare_job(options)
|
273
|
-
options = options.stringify_keys
|
274
|
-
branch_name = options.fetch('branch', {})
|
275
|
-
app = options.fetch('app', {})
|
276
|
-
app = app.fetch('app', '')
|
277
|
-
box = options['env_options']['BOX']
|
278
|
-
message = box.present? ? "BOX #{box}:" : "stage #{options['stage']}:"
|
279
|
-
env_opts = get_app_additional_env_options(app, message)
|
280
|
-
|
281
|
-
options['env_options'] = options['env_options'].reverse_merge(env_opts)
|
282
|
-
|
283
|
-
env_options = branch_name.present? ? { 'BRANCH' => branch_name }.merge(options['env_options']) : options['env_options']
|
284
|
-
job_env_options = custom_command? && env_options['ACTION'].present? ? env_options.except('ACTION') : env_options
|
285
|
-
|
286
|
-
job = {
|
287
|
-
app: app,
|
288
|
-
env: options['stage'],
|
289
|
-
action: custom_command? && env_options['ACTION'].present? ? env_options['ACTION'] : options['action'],
|
290
|
-
task_arguments: options['task_arguments'],
|
291
|
-
env_options: job_env_options
|
292
|
-
}
|
293
|
-
@jobs << job.stringify_keys
|
294
|
-
end
|
295
|
-
|
296
|
-
def prepare_options(options)
|
297
|
-
options = options.stringify_keys
|
298
|
-
options['app'] = options.fetch('app', @application.to_s.clone)
|
299
|
-
options['action'] = options.fetch('action', @name.to_s.clone)
|
300
|
-
options['stage'] = options.fetch('stage', @stage.to_s.clone)
|
301
|
-
options['env_options'] = options.fetch('env_options', @argv.clone)
|
302
|
-
options['task_arguments'] = options.fetch('task_arguments', @args.clone)
|
303
|
-
options
|
304
|
-
end
|
305
|
-
|
306
|
-
def parse_inputted_value(options = {})
|
307
|
-
options = options.stringify_keys
|
308
|
-
value = options['value'].present? ? options['value'] : fetch(options.fetch('key', :app_branch_name))
|
309
|
-
if value.present?
|
310
|
-
branch = value.gsub("\r\n", '')
|
311
|
-
branch = branch.delete("\n") if branch.present?
|
312
|
-
branch = branch.gsub(/\s+/, ' ') if branch.present?
|
313
|
-
branch = branch.strip if branch.present?
|
314
|
-
return branch
|
315
|
-
else
|
316
|
-
return ''
|
317
|
-
end
|
318
|
-
end
|
319
|
-
|
320
|
-
def fetch_app_additional_env_options
|
321
|
-
options = {}
|
322
|
-
return options if fetch(:app_additional_env_options).blank?
|
323
|
-
env_options = parse_inputted_value('key' => :app_additional_env_options)
|
324
|
-
env_options = env_options.split(' ')
|
325
|
-
options = multi_fetch_argv(env_options)
|
326
|
-
options.stringify_keys!
|
327
|
-
options
|
328
|
-
end
|
329
|
-
|
330
|
-
def multi_fetch_argv(args)
|
331
|
-
options = {}
|
332
|
-
args.each do |arg|
|
333
|
-
if arg =~ /^(\w+)=(.*)$/m
|
334
|
-
options[Regexp.last_match(1)] = Regexp.last_match(2)
|
335
|
-
end
|
336
|
-
end
|
337
|
-
options
|
338
|
-
end
|
339
|
-
|
340
|
-
def execute_on_multiple_boxes(main_box_name, options)
|
341
|
-
boxes = parse_inputted_value('value' => main_box_name).split(',').compact
|
342
|
-
boxes.each do |box_name|
|
343
|
-
options['env_options']['BOX'] = box_name
|
344
|
-
prepare_job(options)
|
345
|
-
end
|
346
|
-
end
|
347
|
-
end
|
348
|
-
end
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|