Class: CapistranoMulticonfigParallel::Application
- Inherits:
-
Object
- Object
- CapistranoMulticonfigParallel::Application
show all
- Includes:
- ApplicationHelper
- Defined in:
- lib/capistrano_multiconfig_parallel/application.rb
Overview
finds app dependencies, shows menu and delegates jobs to celluloid manager
Instance Attribute Summary collapse
Instance Method Summary
collapse
action_confirmed?, fetch_parsed_string, fetch_remaining_arguments, find_remaining_args, get_question_details, message_from_bundler?, message_is_about_a_task?, message_is_for_stdout?, msg_for_stdin?, parse_json, parse_task_string, percent_of, regex_last_match, setup_command_line_standard, truncate, wrap_string
env_key_format, env_prefix, filtered_env_keys_format, setup_flags_for_job, trace_flag
Methods included from GemHelper
fetch_gem_version, find_loaded_gem, find_loaded_gem_property, format_gem_version, get_parsed_version, verify_gem_version
app_names_from_stages, check_stage_path, checks_paths, fetch_stages_app, fetch_stages_from_file, fetch_stages_paths, independent_deploy?, multi_apps?, sorted_paths, stages, stages_paths, stages_root
check_hash_set, check_numeric, strip_characters_from_string, value_is_array?, verify_array_of_strings, verify_empty_options, warn_array_without_strings
Methods included from CoreHelper
app_debug_enabled?, ask_confirm, ask_stdout_confirmation, check_terminal_tty, debug_websocket?, development_debug?, error_filtered?, execute_with_rescue, find_worker_log, force_confirmation, format_error, log_error, log_output_error, log_to_file, multi_fetch_argv, print_to_log_file, rescue_error, rescue_interrupt, setup_filename_logger, setup_logger_formatter, show_warning, terminal_actor, terminal_errors?, websocket_config, websocket_server_config
arg_is_in_default_config?, check_file, create_log_file, custom_commands, default_config_keys, default_internal_config, default_internal_configuration_params, detect_root, enable_main_log_file, fail_capfile_not_found, fetch_default_internal_config, find_config_type, find_env_multi_cap_root, find_file_by_names, find_file_in_directory, get_current_gem_name, internal_config_directory, internal_config_file, log_directory, main_log_file, multi_level_prop, pathname_is_root?, pwd_directory, pwd_parent_dir, root, setup_default_configuration_types, sliced_default_config, try_detect_file
Constructor Details
Returns a new instance of Application.
25
26
27
28
29
30
31
32
33
34
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 25
def initialize
Celluloid.boot unless Celluloid.running?
CapistranoMulticonfigParallel.enable_logging
@stage_apps = multi_apps? ? app_names_from_stages : []
collect_command_line_tasks(CapistranoMulticonfigParallel.original_args)
@bundler_workers_store = {}
@jobs = []
@checked_job_paths = []
@patched_job_paths = []
end
|
Instance Attribute Details
#application ⇒ Object
Returns the value of attribute application.
7
8
9
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 7
def application
@application
end
|
#args ⇒ Object
Returns the value of attribute args.
7
8
9
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 7
def args
@args
end
|
#argv ⇒ Object
Returns the value of attribute argv.
7
8
9
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 7
def argv
@argv
end
|
#bundler_workers_store ⇒ Object
Returns the value of attribute bundler_workers_store.
7
8
9
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 7
def bundler_workers_store
@bundler_workers_store
end
|
#checked_job_paths ⇒ Object
Returns the value of attribute checked_job_paths.
7
8
9
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 7
def checked_job_paths
@checked_job_paths
end
|
#condition ⇒ Object
Returns the value of attribute condition.
7
8
9
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 7
def condition
@condition
end
|
#default_stage ⇒ Object
Returns the value of attribute default_stage.
7
8
9
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 7
def default_stage
@default_stage
end
|
#dependency_tracker ⇒ Object
Returns the value of attribute dependency_tracker.
7
8
9
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 7
def dependency_tracker
@dependency_tracker
end
|
#jobs ⇒ Object
Returns the value of attribute jobs.
7
8
9
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 7
def jobs
@jobs
end
|
#manager ⇒ Object
Returns the value of attribute manager.
7
8
9
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 7
def manager
@manager
end
|
#name ⇒ Object
Returns the value of attribute name.
7
8
9
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 7
def name
@name
end
|
#patched_job_paths ⇒ Object
Returns the value of attribute patched_job_paths.
7
8
9
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 7
def patched_job_paths
@patched_job_paths
end
|
#stage ⇒ Object
Returns the value of attribute stage.
7
8
9
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 7
def stage
@stage
end
|
#stage_apps ⇒ Object
Returns the value of attribute stage_apps.
7
8
9
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 7
def stage_apps
@stage_apps
end
|
#top_level_tasks ⇒ Object
Returns the value of attribute top_level_tasks.
7
8
9
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 7
def top_level_tasks
@top_level_tasks
end
|
Instance Method Details
#action_key ⇒ Object
101
102
103
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 101
def action_key
'ACTION'
end
|
#add_job_to_list_of_jobs(job) ⇒ Object
233
234
235
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 233
def add_job_to_list_of_jobs(job)
@jobs << job unless job_can_tag_staging?(job)
end
|
#boxes_key ⇒ Object
194
195
196
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 194
def boxes_key
'BOX'
end
|
#call_task_deploy_app(options = {}) ⇒ Object
198
199
200
201
202
203
204
205
206
207
208
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 198
def call_task_deploy_app(options = {})
options = options.stringify_keys
main_box_name = @argv[boxes_key].blank? ? '' : @argv[boxes_key]
boxes = strip_characters_from_string(main_box_name).split(',').compact
stage = options.fetch('stage', @default_stage)
if configuration.development_stages.include?(stage) && boxes.present?
execute_on_multiple_boxes(boxes, options)
else
prepare_job(options)
end
end
|
#can_tag_staging? ⇒ Boolean
154
155
156
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 154
def can_tag_staging?
wants_deploy_production? && fetch_multi_stages.include?('staging')
end
|
#check_before_starting ⇒ Object
110
111
112
113
114
115
116
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 110
def check_before_starting
@dependency_tracker = CapistranoMulticonfigParallel::DependencyTracker.new(self)
@default_stage = configuration.development_stages.present? ? configuration.development_stages.first : 'development'
@condition = Celluloid::Condition.new
@manager = CapistranoMulticonfigParallel::CelluloidManager.new(self)
@manager.start_bundler_supervision_if_needed
end
|
#collect_command_line_tasks(args) ⇒ Object
88
89
90
91
92
93
94
95
96
97
98
99
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 88
def collect_command_line_tasks(args)
@argv = {}
@top_level_tasks = []
args.each do |arg|
if arg =~ /^(\w+)=(.*)$/m
@argv[Regexp.last_match(1)] = Regexp.last_match(2)
else
@top_level_tasks << arg unless arg =~ /^-/
end
end
@top_level_tasks.push(Rake.application.default_task_name) if @top_level_tasks.blank?
end
|
#collect_jobs(options = {}, &_block) ⇒ Object
118
119
120
121
122
123
124
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 118
def collect_jobs(options = {}, &_block)
options = prepare_options(options)
options = options.stringify_keys
apps, app_options = @dependency_tracker.fetch_apps_needed_for_deployment(options['app'], options['action'])
deploy_multiple_apps(apps, options)
deploy_app(options.merge(app_options)) if !custom_command? || !multi_apps?
end
|
#custom_command? ⇒ Boolean
67
68
69
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 67
def custom_command?
custom_commands.include?(@top_level_tasks.first)
end
|
#deploy_app(options = {}) ⇒ Object
158
159
160
161
162
163
164
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 158
def deploy_app(options = {})
options = options.stringify_keys
call_task_deploy_app({
app: options['app'],
action: options['action']
}.reverse_merge(options))
end
|
#deploy_multiple_apps(applications, options) ⇒ Object
59
60
61
62
63
64
65
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 59
def deploy_multiple_apps(applications, options)
options = options.stringify_keys
return unless applications.present?
applications.each do |app|
deploy_app(options.merge('app' => app['app'], 'path' => app.fetch('path', nil)))
end
end
|
#execute_on_multiple_boxes(boxes, options) ⇒ Object
310
311
312
313
314
315
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 310
def execute_on_multiple_boxes(boxes, options)
boxes.each do |box_name|
options['env_options'][boxes_key] = box_name
prepare_job(options)
end
end
|
#fetch_app_additional_env_options(variable) ⇒ Object
300
301
302
303
304
305
306
307
308
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 300
def fetch_app_additional_env_options(variable)
options = {}
return options if variable.blank?
env_options = strip_characters_from_string(variable)
env_options = env_options.split(' ')
options = multi_fetch_argv(env_options)
options.stringify_keys!
options
end
|
#fetch_multi_stages ⇒ Object
143
144
145
146
147
148
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 143
def fetch_multi_stages
custom_stages = @argv[stages_key].blank? ? '' : @argv[stages_key]
custom_stages = strip_characters_from_string(custom_stages).split(',').compact if custom_stages.present?
custom_stages = custom_stages.present? ? custom_stages : [@default_stage]
custom_stages
end
|
#get_app_additional_env_options(app, app_message) ⇒ Object
166
167
168
169
170
171
172
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 166
def get_app_additional_env_options(app, app_message)
app_name = (app.is_a?(Hash) && app[:app].present?) ? app[:app].camelcase : app
app_name = app_name.present? ? app_name : 'current application'
message = "Please write additional ENV options for #{app_name} for #{app_message}"
app_additional_env_options = ask_confirm(message, nil)
fetch_app_additional_env_options(app_additional_env_options)
end
|
#initialize_data ⇒ Object
81
82
83
84
85
86
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 81
def initialize_data
@application = custom_command? ? nil : @top_level_tasks.first.split(':').reverse[1]
@stage = custom_command? ? nil : @top_level_tasks.first.split(':').reverse[0]
@stage = @stage.present? ? @stage : @default_stage
@name, @args = parse_task_string(@top_level_tasks.second)
end
|
#job_can_tag_staging?(job) ⇒ Boolean
272
273
274
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 272
def job_can_tag_staging?(job)
can_tag_staging? && job.stage == 'production' && job.gitflow.present?
end
|
#job_path(options) ⇒ Object
276
277
278
279
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 276
def job_path(options)
path = options["path"].present? ? options["path"] : nil
path.present? && File.directory?(path) ? path : detect_root
end
|
#job_stage(options) ⇒ Object
285
286
287
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 285
def job_stage(options)
multi_apps?(job_path(options)) && options.fetch('app', nil).present? ? "#{options['app']}:#{options['stage']}" : "#{options['stage']}"
end
|
#job_stage_valid?(options) ⇒ Boolean
281
282
283
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 281
def job_stage_valid?(options)
stages(job_path(options)).include?(job_stage(options))
end
|
#jobs_restore_application_state ⇒ Object
316
317
318
319
320
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 316
def jobs_restore_application_state
@jobs.each do |job|
job.rollback_changes_to_application
end
end
|
#prepare_job(options) ⇒ Object
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 237
def prepare_job(options)
options = options.stringify_keys
return raise_invalid_job_config if !job_stage_valid?(options)
app = options.fetch('app', '')
box = options['env_options'][boxes_key]
message = box.present? ? "BOX #{box}:" : "stage #{options['stage']}:"
env_opts = get_app_additional_env_options(app, message)
options['env_options'] = options['env_options'].reverse_merge(env_opts)
env_options = options['env_options']
job_env_options = custom_command? ? env_options.except(action_key) : env_options
job = CapistranoMulticonfigParallel::Job.new(self, options.merge(
action: custom_command? && env_options[action_key].present? ? env_options[action_key] : options['action'],
env_options: job_env_options,
path: job_path(options)
))
raise "Please make sure you have a Gemfile in the project root directory #{job.job_path}" unless job.job_gemfile.present?
if job.find_capfile.blank?
raise "Please make sure you have a Capfile in the project root directory #{job.job_path}"
end
if configuration.check_app_bundler_dependencies.to_s.downcase == 'true' && job.job_gemfile.present?
if !@checked_job_paths.include?(job.job_path)
@checked_job_paths << job.job_path
@manager.bundler_workers.work(job)
end
else
add_job_to_list_of_jobs(job)
end
end
|
#prepare_options(options) ⇒ Object
290
291
292
293
294
295
296
297
298
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 290
def prepare_options(options)
options = options.stringify_keys
options['app'] = options.fetch('app', @application.to_s.clone)
options['action'] = options.fetch('action', @name.to_s.clone)
options['stage'] = options.fetch('stage', @stage.to_s.clone)
options['env_options'] = options.fetch('env_options', @argv.clone)
options['task_arguments'] = options.fetch('task_arguments', @args.clone)
options
end
|
#process_jobs ⇒ Object
126
127
128
129
130
131
132
133
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 126
def process_jobs
return unless @jobs.present?
if configuration.multi_secvential.to_s.downcase == 'true'
@jobs.each(&:execute_standard_deploy)
else
run_async_jobs
end
end
|
#raise_invalid_job_config ⇒ Object
76
77
78
79
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 76
def raise_invalid_job_config
puts 'Invalid execution, please call something such as `multi_cap production deploy`, where production is a stage you have defined'.red
exit(false)
end
|
#run ⇒ Object
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 174
def run
FileUtils.rm Dir["#{log_directory}/worker_*.log"]
FileUtils.rm Dir["#{log_directory}/multi_cap_worker_*.log"]
options = {}
if custom_command?
options = verify_options_custom_command(options)
run_custom_command(options)
else
collect_jobs(options)
end
if configuration.check_app_bundler_dependencies.to_s.downcase == 'true'
loop do
log_to_file("Trying to sleep until all budler workes are done (#{@jobs.size} and #{@bundler_workers_store.size})")
break if @jobs.size == @bundler_workers_store.size
sleep(0.1)
end
end
process_jobs
end
|
#run_async_jobs ⇒ Object
210
211
212
213
214
215
216
217
218
219
220
221
222
223
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 210
def run_async_jobs
return unless @jobs.present?
@jobs.pmap do |job|
@manager.async.delegate_job(job)
end
unless can_tag_staging? && tag_staging_exists?
until @manager.registration_complete
sleep(0.1)
end
return unless @manager.registration_complete
@manager.async.process_jobs
end
wait_jobs_termination
end
|
#run_custom_command(options) ⇒ Object
51
52
53
54
55
56
57
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 51
def run_custom_command(options)
custom_stages = fetch_multi_stages
return if custom_stages.blank?
custom_stages.each do |stage|
collect_jobs(options.merge('stage' => stage))
end
end
|
#stages_key ⇒ Object
139
140
141
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 139
def stages_key
'STAGES'
end
|
#start ⇒ Object
36
37
38
39
40
41
42
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 36
def start
verify_app_dependencies if multi_apps? && configuration.application_dependencies.present?
initialize_data
verify_valid_data
check_before_starting
run
end
|
#tag_staging_exists? ⇒ Boolean
check exists task from capistrano-gitflow
135
136
137
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 135
def tag_staging_exists?
@jobs.find(&:gitflow).present?
end
|
#verify_app_dependencies ⇒ Object
44
45
46
47
48
49
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 44
def verify_app_dependencies
wrong = configuration.application_dependencies.find do |hash|
!@stage_apps.include?(hash[:app]) || (hash[:dependencies].present? && hash[:dependencies].find { |val| !@stage_apps.include?(val) })
end
raise ArgumentError, "Invalid configuration for #{wrong.inspect}".red if wrong.present?
end
|
#verify_options_custom_command(options) ⇒ Object
105
106
107
108
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 105
def verify_options_custom_command(options)
options[:action] = @argv[action_key].present? ? @argv[action_key] : 'deploy'
options
end
|
#verify_valid_data ⇒ Object
71
72
73
74
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 71
def verify_valid_data
return if @top_level_tasks != ['default']
raise_invalid_job_config
end
|
#wait_jobs_termination ⇒ Object
225
226
227
228
229
230
231
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 225
def wait_jobs_termination
return if configuration.multi_secvential.to_s.downcase == 'true'
result = @condition.wait
return unless result.present?
@manager.terminate
end
|
#wants_deploy_production? ⇒ Boolean
150
151
152
|
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 150
def wants_deploy_production?
(!custom_command? && @stage == 'production') || (custom_command? && fetch_multi_stages.include?('production'))
end
|