Class: CapistranoMulticonfigParallel::Application
- Inherits:
-
Object
- Object
- CapistranoMulticonfigParallel::Application
- Includes:
- BaseActorHelper
- Defined in:
- lib/capistrano_multiconfig_parallel/application.rb
Overview
finds app dependencies, shows menu and delegates jobs to celluloid manager
Instance Attribute Summary collapse
-
#application ⇒ Object
readonly
Returns the value of attribute application.
-
#args ⇒ Object
readonly
Returns the value of attribute args.
-
#argv ⇒ Object
readonly
Returns the value of attribute argv.
-
#bundler_workers_store ⇒ Object
readonly
Returns the value of attribute bundler_workers_store.
-
#checked_job_paths ⇒ Object
readonly
Returns the value of attribute checked_job_paths.
-
#condition ⇒ Object
readonly
Returns the value of attribute condition.
-
#default_stage ⇒ Object
readonly
Returns the value of attribute default_stage.
-
#dependency_tracker ⇒ Object
readonly
Returns the value of attribute dependency_tracker.
-
#jobs ⇒ Object
readonly
Returns the value of attribute jobs.
-
#manager ⇒ Object
readonly
Returns the value of attribute manager.
-
#name ⇒ Object
readonly
Returns the value of attribute name.
-
#patched_job_paths ⇒ Object
Returns the value of attribute patched_job_paths.
-
#stage ⇒ Object
readonly
Returns the value of attribute stage.
-
#stage_apps ⇒ Object
readonly
Returns the value of attribute stage_apps.
-
#top_level_tasks ⇒ Object
readonly
Returns the value of attribute top_level_tasks.
Instance Method Summary collapse
- #action_key ⇒ Object
- #boxes_key ⇒ Object
- #call_task_deploy_app(options = {}) ⇒ Object
- #can_tag_staging? ⇒ Boolean
- #check_before_starting ⇒ Object
-
#collect_command_line_tasks(args) ⇒ Object
:nodoc:.
- #collect_jobs(options = {}, &_block) ⇒ Object
- #custom_command? ⇒ Boolean
- #deploy_app(options = {}) ⇒ Object
- #deploy_multiple_apps(applications, options) ⇒ Object
- #execute_on_multiple_boxes(boxes, options) ⇒ Object
- #fetch_app_additional_env_options(variable) ⇒ Object
- #fetch_multi_stages ⇒ Object
- #get_app_additional_env_options(app, app_message) ⇒ Object
-
#initialize ⇒ Application
constructor
A new instance of Application.
- #initialize_data ⇒ Object
- #job_can_tag_staging?(job) ⇒ Boolean
- #job_path(options) ⇒ Object
- #job_stage(options) ⇒ Object
- #job_stage_valid?(options) ⇒ Boolean
- #jobs_restore_application_state ⇒ Object
- #prepare_job(options) ⇒ Object
- #prepare_options(options) ⇒ Object
- #process_jobs ⇒ Object
- #raise_invalid_job_config ⇒ Object
- #run ⇒ Object
- #run_async_jobs ⇒ Object
- #run_custom_command(options) ⇒ Object
- #stages_key ⇒ Object
- #start ⇒ Object
- #start_bundler_supervision_if_needed ⇒ Object
-
#tag_staging_exists? ⇒ Boolean
check exists task from capistrano-gitflow.
- #verify_app_dependencies ⇒ Object
- #verify_options_custom_command(options) ⇒ Object
- #verify_valid_data ⇒ Object
- #wait_jobs_termination ⇒ Object
- #wants_deploy_production? ⇒ Boolean
Methods included from BaseActorHelper
Constructor Details
#initialize ⇒ Application
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 = [] # for deploy end |
Instance Attribute Details
#application ⇒ Object (readonly)
Returns the value of attribute application.
7 8 9 |
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 7 def application @application end |
#args ⇒ Object (readonly)
Returns the value of attribute args.
7 8 9 |
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 7 def args @args end |
#argv ⇒ Object (readonly)
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 (readonly)
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 (readonly)
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 (readonly)
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 (readonly)
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 (readonly)
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 (readonly)
Returns the value of attribute jobs.
7 8 9 |
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 7 def jobs @jobs end |
#manager ⇒ Object (readonly)
Returns the value of attribute manager.
7 8 9 |
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 7 def manager @manager end |
#name ⇒ Object (readonly)
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 (readonly)
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 (readonly)
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 (readonly)
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 |
#boxes_key ⇒ Object
199 200 201 |
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 199 def boxes_key 'BOX' end |
#call_task_deploy_app(options = {}) ⇒ Object
203 204 205 206 207 208 209 210 211 212 213 |
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 203 def call_task_deploy_app( = {}) = .stringify_keys main_box_name = @argv[boxes_key].blank? ? '' : @argv[boxes_key] boxes = strip_characters_from_string(main_box_name).split(',').compact stage = .fetch('stage', @default_stage) if configuration.development_stages.include?(stage) && boxes.present? execute_on_multiple_boxes(boxes, ) else prepare_job() end end |
#can_tag_staging? ⇒ Boolean
163 164 165 |
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 163 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(Actor.current) @default_stage = configuration.development_stages.present? ? configuration.development_stages.first : 'development' @condition = Celluloid::Condition.new @manager = CapistranoMulticonfigParallel::CelluloidManager.new(Actor.current) start_bundler_supervision_if_needed end |
#collect_command_line_tasks(args) ⇒ Object
:nodoc:
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) # :nodoc: @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
127 128 129 130 131 132 133 |
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 127 def collect_jobs( = {}, &_block) = () = .stringify_keys apps, = @dependency_tracker.fetch_apps_needed_for_deployment(['app'], ['action']) deploy_multiple_apps(apps, ) deploy_app(.merge()) 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
167 168 169 170 171 172 173 |
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 167 def deploy_app( = {}) = .stringify_keys call_task_deploy_app({ app: ['app'], action: ['action'] }.reverse_merge()) 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, ) = .stringify_keys return unless applications.present? applications.each do |app| deploy_app(.merge('app' => app['app'], 'path' => app.fetch('path', nil))) end end |
#execute_on_multiple_boxes(boxes, options) ⇒ Object
318 319 320 321 322 323 |
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 318 def execute_on_multiple_boxes(boxes, ) boxes.each do |box_name| ['env_options'][boxes_key] = box_name prepare_job() end end |
#fetch_app_additional_env_options(variable) ⇒ Object
308 309 310 311 312 313 314 315 316 |
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 308 def (variable) = {} return if variable.blank? = strip_characters_from_string(variable) = .split(' ') = multi_fetch_argv() .stringify_keys! end |
#fetch_multi_stages ⇒ Object
152 153 154 155 156 157 |
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 152 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
175 176 177 178 179 180 181 |
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 175 def (app, ) app_name = (app.is_a?(Hash) && app[:app].present?) ? app[:app].camelcase : app app_name = app_name.present? ? app_name : 'current application' = "Please write additional ENV options for #{app_name} for #{}" = ask_confirm(, nil) () 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
280 281 282 |
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 280 def job_can_tag_staging?(job) can_tag_staging? && job.stage == 'production' && job.gitflow.present? end |
#job_path(options) ⇒ Object
284 285 286 287 |
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 284 def job_path() path = ["path"].present? ? ["path"] : nil path.present? && File.directory?(path) ? path : detect_root end |
#job_stage(options) ⇒ Object
293 294 295 |
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 293 def job_stage() multi_apps?(job_path()) && .fetch('app', nil).present? ? "#{['app']}:#{['stage']}" : "#{['stage']}" end |
#job_stage_valid?(options) ⇒ Boolean
289 290 291 |
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 289 def job_stage_valid?() stages(job_path()).include?(job_stage()) end |
#jobs_restore_application_state ⇒ Object
324 325 326 327 328 |
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 324 def jobs_restore_application_state @jobs.each do |job| job.rollback_changes_to_application end end |
#prepare_job(options) ⇒ Object
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 271 272 273 274 275 276 277 278 |
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 238 def prepare_job() = .stringify_keys return raise_invalid_job_config if !job_stage_valid?() app = .fetch('app', '') box = ['env_options'][boxes_key] = box.present? ? "BOX #{box}:" : "stage #{['stage']}:" env_opts = (app, ) ['env_options'] = ['env_options'].reverse_merge(env_opts) = ['env_options'] = custom_command? ? .except(action_key) : job = CapistranoMulticonfigParallel::Job.new(Actor.current, .merge( action: custom_command? && [action_key].present? ? [action_key] : ['action'], env_options: , path: job_path() )) bundler_callback = lambda { |job| 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 unless job.capistrano_sentinel_needs_updating? raise "Please consider upgrading the gem #{job.capistrano_sentinel_name} to version #{job.loaded_capistrano_sentinel_version} from #{job.job_capistrano_sentinel_version} in #{job.job_path} " end log_to_file("bundler callback called with #{job.inspect}") job.application.jobs << job unless job.application.job_can_tag_staging?(job) } 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 @bundler_workers.work(job, &bundler_callback) # make sure we have installed the dependencies first for this application end else bundler_callback.call(job) end end |
#prepare_options(options) ⇒ Object
298 299 300 301 302 303 304 305 306 |
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 298 def () = .stringify_keys ['app'] = .fetch('app', @application.to_s.clone) ['action'] = .fetch('action', @name.to_s.clone) ['stage'] = .fetch('stage', @stage.to_s.clone) ['env_options'] = .fetch('env_options', @argv.clone) ['task_arguments'] = .fetch('task_arguments', @args.clone) end |
#process_jobs ⇒ Object
135 136 137 138 139 140 141 142 |
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 135 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
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 |
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 183 def run FileUtils.rm Dir["#{log_directory}/worker_*.log"] FileUtils.rm Dir["#{log_directory}/multi_cap_worker_*.log"] = {} if custom_command? = () run_custom_command() else collect_jobs() end if configuration.check_app_bundler_dependencies.to_s.downcase == 'true' sleep(0.1) until @jobs.size == @bundler_workers_store.size end process_jobs end |
#run_async_jobs ⇒ Object
215 216 217 218 219 220 221 222 223 224 225 226 227 228 |
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 215 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) ⇒ Object
51 52 53 54 55 56 57 |
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 51 def run_custom_command() custom_stages = fetch_multi_stages return if custom_stages.blank? custom_stages.each do |stage| collect_jobs(.merge('stage' => stage)) end end |
#stages_key ⇒ Object
148 149 150 |
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 148 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 |
#start_bundler_supervision_if_needed ⇒ Object
118 119 120 121 122 123 124 125 |
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 118 def start_bundler_supervision_if_needed return if configuration.check_app_bundler_dependencies.to_s.downcase != 'true' @bundler_worker_supervisor = setup_supervision_group @mutex = Mutex.new @bundler_workers = setup_pool_of_actor(@bundler_worker_supervisor, actor_name: :bundler_workers, type: CapistranoMulticonfigParallel::BundlerWorker, size: 10) Actor.current.link @bundler_workers setup_actor_supervision(@bundler_worker_supervisor, actor_name: :bundler_terminal_server, type: CapistranoMulticonfigParallel::BundlerTerminalTable, args: [@manager, Actor.current, configuration.fetch(:terminal, {})]) end |
#tag_staging_exists? ⇒ Boolean
check exists task from capistrano-gitflow
144 145 146 |
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 144 def tag_staging_exists? # check exists task from capistrano-gitflow @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 () [:action] = @argv[action_key].present? ? @argv[action_key] : 'deploy' 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
230 231 232 233 234 235 236 |
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 230 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? ⇒ Boolean
159 160 161 |
# File 'lib/capistrano_multiconfig_parallel/application.rb', line 159 def wants_deploy_production? (!custom_command? && @stage == 'production') || (custom_command? && fetch_multi_stages.include?('production')) end |