class CapistranoMulticonfigParallel::Application
finds app dependencies, shows menu and delegates jobs to celluloid manager
Attributes
application[R]
args[R]
argv[R]
bundler_workers_store[R]
checked_job_paths[R]
condition[R]
default_stage[R]
dependency_tracker[R]
jobs[R]
manager[R]
name[R]
patched_job_paths[RW]
stage[R]
stage_apps[R]
top_level_tasks[R]
Public Class Methods
new()
click to toggle source
# File lib/capistrano_multiconfig_parallel/application.rb, line 25 def initialize celluloid_running = Celluloid.running? rescue false 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 = [] # for deploy end
Public Instance Methods
action_key()
click to toggle source
# File lib/capistrano_multiconfig_parallel/application.rb, line 108 def action_key 'ACTION' end
add_job_to_list_of_jobs(job)
click to toggle source
# File lib/capistrano_multiconfig_parallel/application.rb, line 240 def add_job_to_list_of_jobs(job) @jobs << job unless job_can_tag_staging?(job) end
boxes_key()
click to toggle source
# File lib/capistrano_multiconfig_parallel/application.rb, line 201 def boxes_key 'BOX' end
call_task_deploy_app(options = {})
click to toggle source
# File lib/capistrano_multiconfig_parallel/application.rb, line 205 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?()
click to toggle source
# File lib/capistrano_multiconfig_parallel/application.rb, line 161 def can_tag_staging? wants_deploy_production? && fetch_multi_stages.include?('staging') end
check_before_starting()
click to toggle source
# File lib/capistrano_multiconfig_parallel/application.rb, line 117 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_jobs(options = {}, &_block)
click to toggle source
# File lib/capistrano_multiconfig_parallel/application.rb, line 125 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?()
click to toggle source
# File lib/capistrano_multiconfig_parallel/application.rb, line 68 def custom_command? custom_commands.include?(@top_level_tasks.first) end
deploy_app(options = {})
click to toggle source
# File lib/capistrano_multiconfig_parallel/application.rb, line 165 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)
click to toggle source
# File lib/capistrano_multiconfig_parallel/application.rb, line 60 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)
click to toggle source
# File lib/capistrano_multiconfig_parallel/application.rb, line 316 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)
click to toggle source
# File lib/capistrano_multiconfig_parallel/application.rb, line 306 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()
click to toggle source
# File lib/capistrano_multiconfig_parallel/application.rb, line 150 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)
click to toggle source
# File lib/capistrano_multiconfig_parallel/application.rb, line 173 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()
click to toggle source
# File lib/capistrano_multiconfig_parallel/application.rb, line 88 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[1]) end
job_can_tag_staging?(job)
click to toggle source
# File lib/capistrano_multiconfig_parallel/application.rb, line 278 def job_can_tag_staging?(job) can_tag_staging? && job.stage == 'production' && job.gitflow.present? end
job_path(options)
click to toggle source
# File lib/capistrano_multiconfig_parallel/application.rb, line 282 def job_path(options) path = options["path"].present? ? options["path"] : nil path.present? && File.directory?(path) ? path : detect_root end
job_stage(options)
click to toggle source
# File lib/capistrano_multiconfig_parallel/application.rb, line 291 def job_stage(options) options['stage'] end
job_stage_valid?(options)
click to toggle source
# File lib/capistrano_multiconfig_parallel/application.rb, line 287 def job_stage_valid?(options) stages(job_path(options)).include?(job_stage(options)) end
jobs_restore_application_state()
click to toggle source
# File lib/capistrano_multiconfig_parallel/application.rb, line 322 def jobs_restore_application_state @jobs.each do |job| job.rollback_changes_to_application end end
prepare_job(options)
click to toggle source
# File lib/capistrano_multiconfig_parallel/application.rb, line 244 def prepare_job(options) options = options.stringify_keys app = options.fetch('app', '') path = job_path(options) rescue nil # raise [app, @stage_apps, job_stage(options) , stages(job_path(options))].inspect return raise_invalid_job_config(path) if (app.present? && !@stage_apps.include?(app)) || !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) )) 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) # make sure we have installed the dependencies first for this application end else add_job_to_list_of_jobs(job) end end
prepare_options(options)
click to toggle source
# File lib/capistrano_multiconfig_parallel/application.rb, line 296 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()
click to toggle source
# File lib/capistrano_multiconfig_parallel/application.rb, line 133 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(path = nil)
click to toggle source
# File lib/capistrano_multiconfig_parallel/application.rb, line 77 def raise_invalid_job_config(path = nil) if independent_deploy?(path) puts 'Invalid execution, please call something such as `multi_cap app_name:production deploy`, where production is a stage you have defined and the "app_name" is a name that you defined in your multi_cap.yml file'.red elsif application_supports_multi_apps? puts 'Invalid execution, please call something such as `multi_cap app_name:production deploy`, where production is a stage you have defined and the "app_name" is name that you have defined in your application'.red else puts 'Invalid execution, please call something such as `multi_cap production deploy`, where production is a stage you have defined'.red end exit(false) end
run()
click to toggle source
# File lib/capistrano_multiconfig_parallel/application.rb, line 181 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()
click to toggle source
# File lib/capistrano_multiconfig_parallel/application.rb, line 217 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) # keep current thread alive end return unless @manager.registration_complete @manager.async.process_jobs end wait_jobs_termination end
run_custom_command(options)
click to toggle source
# File lib/capistrano_multiconfig_parallel/application.rb, line 52 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()
click to toggle source
# File lib/capistrano_multiconfig_parallel/application.rb, line 146 def stages_key 'STAGES' end
start()
click to toggle source
# File lib/capistrano_multiconfig_parallel/application.rb, line 37 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?()
click to toggle source
# File lib/capistrano_multiconfig_parallel/application.rb, line 142 def tag_staging_exists? # check exists task from capistrano-gitflow @jobs.find(&:gitflow).present? end
verify_app_dependencies()
click to toggle source
# File lib/capistrano_multiconfig_parallel/application.rb, line 45 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)
click to toggle source
# File lib/capistrano_multiconfig_parallel/application.rb, line 112 def verify_options_custom_command(options) options[:action] = @argv[action_key].present? ? @argv[action_key] : 'deploy' options end
verify_valid_data()
click to toggle source
# File lib/capistrano_multiconfig_parallel/application.rb, line 72 def verify_valid_data return if @top_level_tasks != ['default'] raise_invalid_job_config end
wait_jobs_termination()
click to toggle source
# File lib/capistrano_multiconfig_parallel/application.rb, line 232 def wait_jobs_termination return if configuration.multi_secvential.to_s.downcase == 'true' result = @condition.wait return unless result.present? @manager.terminate #terminate end
wants_deploy_production?()
click to toggle source
# File lib/capistrano_multiconfig_parallel/application.rb, line 157 def wants_deploy_production? (!custom_command? && @stage == 'production') || (custom_command? && fetch_multi_stages.include?('production')) end