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.
Files changed (25) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +25 -0
  3. data/.gitignore +0 -1
  4. data/Gemfile.lock +327 -0
  5. data/README.md +1 -1
  6. data/lib/capistrano_multiconfig_parallel/all.rb +16 -1
  7. data/lib/capistrano_multiconfig_parallel/application.rb +340 -11
  8. data/lib/capistrano_multiconfig_parallel/base.rb +8 -8
  9. data/lib/capistrano_multiconfig_parallel/celluloid/celluloid_manager.rb +3 -6
  10. data/lib/capistrano_multiconfig_parallel/celluloid/celluloid_worker.rb +6 -0
  11. data/lib/capistrano_multiconfig_parallel/cli.rb +8 -1
  12. data/lib/capistrano_multiconfig_parallel/configuration.rb +8 -30
  13. data/lib/capistrano_multiconfig_parallel/extensions/rake.rb +1 -1
  14. data/lib/capistrano_multiconfig_parallel/{multi_app_helpers → helpers}/dependency_tracker.rb +5 -5
  15. data/lib/capistrano_multiconfig_parallel/helpers/helper.rb +9 -0
  16. data/lib/capistrano_multiconfig_parallel/{extensions → helpers}/rake_hook_actor.rb +0 -1
  17. data/lib/capistrano_multiconfig_parallel/initializers/conf.rb +2 -3
  18. data/lib/capistrano_multiconfig_parallel/initializers/default.yml +3 -3
  19. data/lib/capistrano_multiconfig_parallel/version.rb +2 -2
  20. metadata +11 -9
  21. data/lib/capistrano_multiconfig_parallel/managers/base_manager.rb +0 -348
  22. /data/lib/capistrano_multiconfig_parallel/{extensions → helpers}/input_stream.rb +0 -0
  23. /data/lib/capistrano_multiconfig_parallel/{multi_app_helpers → helpers}/interactive_menu.rb +0 -0
  24. /data/lib/capistrano_multiconfig_parallel/{extensions → helpers}/output_stream.rb +0 -0
  25. /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.15.6
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-25 00:00:00.000000000 Z
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/extensions/rake_hook_actor.rb
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