capistrano_multiconfig_parallel 0.17.0 → 0.18.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 383ca1a8dd3caa6d1ae38370f3a3f5b7d05c6dbc
4
- data.tar.gz: 4a2bce60bf821d9f65692c40fd133c67e5e77a04
3
+ metadata.gz: a35d2e97aa86ca857d89790da96cfa0378f8c61e
4
+ data.tar.gz: 17f2c290edb9ae3bc40dbede9be2554237982186
5
5
  SHA512:
6
- metadata.gz: a426aff1833349f6862f9aa2bd42f4f3e249df4057659f86f29a1e3c60e2682c4b474c7c0bbf8f4b25ef1f1400351aaf10fd85e6ae9e96ea1c40b2b54fe6f4c0
7
- data.tar.gz: 5b3ed5196838866db3f1b4369785f3eb0fc49dec74665139e4dde7488f9ccf1995dc8542be6045125224c1ea4f724e47b36ddef3cbe2628a0d35ec683e872875
6
+ metadata.gz: f902cda7987cd1c172bb59afce5a1b1f76a85194835508b8522b283ac4b9005772f3c50ac2c6f2aa443544ad32e100d1f22538d0621102139be4023e801899bd
7
+ data.tar.gz: 39602658bd7b01eed3fea2b4c5e2b48aa0db9fc97776ebd154c9773b2895817cf526ac9a4b1dd92d83adac47432afb2e994ed6b8ddcceba762ca2a72a88864a5
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- capistrano_multiconfig_parallel (0.16.2)
4
+ capistrano_multiconfig_parallel (0.17.0)
5
5
  activesupport (~> 4.0, >= 4.0)
6
6
  capistrano (~> 3.0, >= 3.0)
7
7
  celluloid-pmap (~> 0.2, >= 0.2.2)
@@ -18,14 +18,14 @@ module CapistranoMulticonfigParallel
18
18
  end
19
19
 
20
20
  def start
21
- verify_app_dependencies if multi_apps? && configuration.application_dependencies.present?
21
+ verify_app_dependencies if multi_apps? && app_configuration.application_dependencies.present?
22
22
  check_before_starting
23
23
  initialize_data
24
24
  run
25
25
  end
26
26
 
27
27
  def verify_app_dependencies
28
- wrong = configuration.application_dependencies.find do |hash|
28
+ wrong = app_configuration.application_dependencies.find do |hash|
29
29
  !@stage_apps.include?(hash[:app]) || (hash[:dependencies].present? && hash[:dependencies].find { |val| !@stage_apps.include?(val) })
30
30
  end
31
31
  raise ArgumentError, "Invalid configuration for #{wrong.inspect}".red if wrong.present?
@@ -56,25 +56,16 @@ module CapistranoMulticonfigParallel
56
56
 
57
57
  def custom_command?
58
58
  if multi_apps?
59
- !@stages.include?(@top_level_tasks.first) && custom_commands.values.include?(@top_level_tasks.first)
59
+ !@stages.include?(@top_level_tasks.first) && custom_commands.include?(@top_level_tasks.first)
60
60
  else
61
- !@stages.include?(@top_level_tasks.second) && @stages.include?(@top_level_tasks.first) && custom_commands.values.include?(@top_level_tasks.second)
61
+ !@stages.include?(@top_level_tasks.second) && @stages.include?(@top_level_tasks.first) && custom_commands.include?(@top_level_tasks.second)
62
62
  end
63
63
  end
64
64
 
65
- def custom_commands
66
- key = multi_apps? ? CapistranoMulticonfigParallel::MULTI_KEY : CapistranoMulticonfigParallel::SINGLE_KEY
67
- CapistranoMulticonfigParallel::CUSTOM_COMMANDS[key]
68
- end
69
-
70
65
  def multi_apps?
71
66
  @stages.find { |stage| stage.include?(':') }.present?
72
67
  end
73
68
 
74
- def configuration
75
- CapistranoMulticonfigParallel.configuration
76
- end
77
-
78
69
  def initialize_data
79
70
  @application = custom_command? ? nil : @top_level_tasks.first.split(':').reverse[1]
80
71
  @stage = custom_command? ? nil : @top_level_tasks.first.split(':').reverse[0]
@@ -103,7 +94,7 @@ module CapistranoMulticonfigParallel
103
94
  def check_before_starting
104
95
  CapistranoMulticonfigParallel.enable_logging
105
96
  @dependency_tracker = CapistranoMulticonfigParallel::DependencyTracker.new(Actor.current)
106
- @default_stage = CapistranoMulticonfigParallel.configuration.development_stages.present? ? CapistranoMulticonfigParallel.configuration.development_stages.first : 'development'
97
+ @default_stage = app_configuration.development_stages.present? ? app_configuration.development_stages.first : 'development'
107
98
  @condition = Celluloid::Condition.new
108
99
  @manager = CapistranoMulticonfigParallel::CelluloidManager.new(Actor.current)
109
100
  end
@@ -116,13 +107,13 @@ module CapistranoMulticonfigParallel
116
107
  deploy_multiple_apps(apps, options)
117
108
  deploy_app(options) if !custom_command? || !multi_apps?
118
109
  rescue => e
119
- CapistranoMulticonfigParallel.log_message(e)
110
+ log_error(e)
120
111
  end
121
112
 
122
113
  def process_jobs
123
114
  return unless @jobs.present?
124
115
  FileUtils.rm Dir["#{CapistranoMulticonfigParallel.log_directory}/worker_*.log"]
125
- if configuration.multi_secvential.to_s.downcase == 'true'
116
+ if app_configuration.multi_secvential.to_s.downcase == 'true'
126
117
  @jobs.each { |job| CapistranoMulticonfigParallel::StandardDeploy.new(job) }
127
118
  else
128
119
  run_async_jobs
@@ -130,7 +121,7 @@ module CapistranoMulticonfigParallel
130
121
  end
131
122
 
132
123
  def tag_staging_exists? # check exists task from capistrano-gitflow
133
- CapistranoMulticonfigParallel.find_loaded_gem('capistrano-gitflow').present?
124
+ find_loaded_gem('capistrano-gitflow').present?
134
125
  end
135
126
 
136
127
  def fetch_multi_stages
@@ -167,7 +158,7 @@ module CapistranoMulticonfigParallel
167
158
  app_name = (app.is_a?(Hash) && app[:app].present?) ? app[:app].camelcase : app
168
159
  app_name = app_name.present? ? app_name : 'current application'
169
160
  message = "Please write additional ENV options for #{app_name} for #{app_message}"
170
- app_additional_env_options = CapistranoMulticonfigParallel.ask_confirm(message, nil)
161
+ app_additional_env_options = ask_confirm(message, nil)
171
162
  fetch_app_additional_env_options(app_additional_env_options)
172
163
  end
173
164
 
@@ -190,7 +181,7 @@ module CapistranoMulticonfigParallel
190
181
  options = options.stringify_keys
191
182
  main_box_name = @argv['BOX'].blank? ? '' : @argv['BOX']
192
183
  stage = options.fetch('stage', @default_stage)
193
- if CapistranoMulticonfigParallel.configuration.development_stages.include?(stage) && main_box_name.present? && /^[a-z0-9,]+/.match(main_box_name)
184
+ if app_configuration.development_stages.include?(stage) && main_box_name.present? && /^[a-z0-9,]+/.match(main_box_name)
194
185
  execute_on_multiple_boxes(main_box_name, options)
195
186
  else
196
187
  prepare_job(options)
@@ -211,7 +202,7 @@ module CapistranoMulticonfigParallel
211
202
  end
212
203
 
213
204
  def wait_jobs_termination
214
- return if configuration.multi_secvential.to_s.downcase == 'true'
205
+ return if app_configuration.multi_secvential.to_s.downcase == 'true'
215
206
  result = @condition.wait
216
207
  return unless result.present?
217
208
  @manager.terminate
@@ -7,36 +7,56 @@ module CapistranoMulticonfigParallel
7
7
 
8
8
  class << self
9
9
  attr_accessor :logger, :original_args
10
-
11
10
  include CapistranoMulticonfigParallel::Configuration
12
- include CapistranoMulticonfigParallel::ApplicationHelper
13
- include CapistranoMulticonfigParallel::CoreHelper
14
11
 
15
12
  def enable_logging
16
13
  enable_file_logging
17
- self.logger ||= ::Logger.new(DevNull.new)
18
- Celluloid.logger = CapistranoMulticonfigParallel.logger
14
+ Celluloid.logger = logger
19
15
  Celluloid.task_class = Celluloid::TaskThread
20
16
  end
21
17
 
18
+ def detect_root
19
+ if find_env_multi_cap_root
20
+ Pathname.new(find_env_multi_cap_root)
21
+ elsif defined?(::Rails)
22
+ ::Rails.root
23
+ else
24
+ try_detect_capfile
25
+ end
26
+ end
27
+
28
+ def config_file
29
+ File.join(detect_root.to_s, 'config', 'multi_cap.yml')
30
+ end
31
+
32
+ def log_directory
33
+ File.join(detect_root.to_s, 'log')
34
+ end
35
+
36
+ def main_log_file
37
+ File.join(log_directory, 'multi_cap.log')
38
+ end
39
+
40
+ def custom_commands
41
+ ['deploy_multi_stages']
42
+ end
43
+
44
+ private
45
+
22
46
  def enable_file_logging
23
- return if configuration.multi_debug.to_s.downcase != 'true'
47
+ if configuration.multi_debug.to_s.downcase == 'true'
48
+ enable_main_log_file
49
+ self.logger = ::Logger.new(main_log_file)
50
+ else
51
+ self.logger ||= ::Logger.new(DevNull.new)
52
+ end
53
+ end
54
+
55
+ def enable_main_log_file
24
56
  FileUtils.mkdir_p(log_directory) unless File.directory?(log_directory)
25
57
  FileUtils.touch(main_log_file) unless File.file?(main_log_file)
26
58
  log_file = File.open(main_log_file, 'w')
27
59
  log_file.sync = true
28
- self.logger = ::Logger.new(main_log_file)
29
- end
30
-
31
- def custom_commands
32
- {
33
- 'multi ' => {
34
- stages: 'deploy_multi_stages'
35
- },
36
- 'single' => {
37
- stages: 'deploy_multi_stages'
38
- }
39
- }
40
60
  end
41
61
  end
42
62
  end
@@ -1,14 +1,14 @@
1
1
  require_relative './celluloid_worker'
2
2
  require_relative './terminal_table'
3
3
  require_relative './web_server'
4
+ require_relative '../helpers/application_helper'
4
5
  module CapistranoMulticonfigParallel
5
6
  # rubocop:disable ClassLength
6
7
  class CelluloidManager
7
8
  include Celluloid
8
9
  include Celluloid::Notifications
9
10
  include Celluloid::Logger
10
-
11
- cattr_accessor :debug_enabled
11
+ include CapistranoMulticonfigParallel::ApplicationHelper
12
12
 
13
13
  attr_accessor :jobs, :job_to_worker, :worker_to_job, :job_to_condition, :mutex, :registration_complete, :workers_terminated
14
14
 
@@ -34,19 +34,15 @@ module CapistranoMulticonfigParallel
34
34
  @worker_to_job = {}
35
35
  @job_to_condition = {}
36
36
  @worker_supervisor.supervise_as(:terminal_server, CapistranoMulticonfigParallel::TerminalTable, Actor.current, @job_manager)
37
- @worker_supervisor.supervise_as(:web_server, CapistranoMulticonfigParallel::WebServer, self.class.websocket_config)
38
- end
39
-
40
- def self.debug_enabled?
41
- debug_enabled
37
+ @worker_supervisor.supervise_as(:web_server, CapistranoMulticonfigParallel::WebServer, websocket_config)
42
38
  end
43
39
 
44
- def self.debug_websocket?
40
+ def debug_websocket?
45
41
  websocket_config['enable_debug'].to_s == 'true'
46
42
  end
47
43
 
48
- def self.websocket_config
49
- config = CapistranoMulticonfigParallel.configuration[:websocket_server]
44
+ def websocket_config
45
+ config = app_configuration[:websocket_server]
50
46
  config.present? && config.is_a?(Hash) ? config.stringify_keys : {}
51
47
  config['enable_debug'] = config.fetch('enable_debug', '').to_s == 'true'
52
48
  config
@@ -74,7 +70,7 @@ module CapistranoMulticonfigParallel
74
70
  def register_worker_for_job(job, worker)
75
71
  job = job.stringify_keys
76
72
  if job['id'].blank?
77
- debug("job id not found. delegating again the job #{job.inspect}") if self.class.debug_enabled?
73
+ log_to_file("job id not found. delegating again the job #{job.inspect}")
78
74
  delegate(job)
79
75
  else
80
76
  start_worker(job, worker)
@@ -85,7 +81,7 @@ module CapistranoMulticonfigParallel
85
81
  worker.job_id = job['id'] if worker.job_id.blank?
86
82
  @job_to_worker[job['id']] = worker
87
83
  @worker_to_job[worker.mailbox.address] = job
88
- debug("worker #{worker.job_id} registed into manager") if self.class.debug_enabled?
84
+ log_to_file("worker #{worker.job_id} registed into manager")
89
85
  Actor.current.link worker
90
86
  worker.async.start_task unless syncronized_confirmation?
91
87
  @registration_complete = true if @job_manager.jobs.size == @job_to_worker.size
@@ -107,12 +103,12 @@ module CapistranoMulticonfigParallel
107
103
  until condition.present?
108
104
  sleep(0.1) # keep current thread alive
109
105
  end
110
- debug("all jobs have completed #{condition}") if self.class.debug_enabled?
106
+ log_to_file("all jobs have completed #{condition}")
111
107
  Celluloid::Actor[:terminal_server].async.notify_time_change(CapistranoMulticonfigParallel::TerminalTable.topic, type: 'output') if Celluloid::Actor[:terminal_server].alive?
112
108
  end
113
109
 
114
110
  def apply_confirmations?
115
- confirmations = CapistranoMulticonfigParallel.configuration.task_confirmations
111
+ confirmations = app_configuration.task_confirmations
116
112
  confirmations.is_a?(Array) && confirmations.present?
117
113
  end
118
114
 
@@ -121,13 +117,13 @@ module CapistranoMulticonfigParallel
121
117
  end
122
118
 
123
119
  def apply_confirmation_for_worker(worker)
124
- worker.alive? && CapistranoMulticonfigParallel.configuration.apply_stage_confirmation.include?(worker.env_name) && apply_confirmations?
120
+ worker.alive? && app_configuration.apply_stage_confirmation.include?(worker.env_name) && apply_confirmations?
125
121
  end
126
122
 
127
123
  def setup_worker_conditions(worker)
128
124
  return unless apply_confirmation_for_worker(worker)
129
125
  hash_conditions = {}
130
- CapistranoMulticonfigParallel.configuration.task_confirmations.each do |task|
126
+ app_configuration.task_confirmations.each do |task|
131
127
  hash_conditions[task] = { condition: Celluloid::Condition.new, status: 'unconfirmed' }
132
128
  end
133
129
  @job_to_condition[worker.job_id] = hash_conditions
@@ -135,7 +131,7 @@ module CapistranoMulticonfigParallel
135
131
 
136
132
  def mark_completed_remaining_tasks(worker)
137
133
  return unless apply_confirmation_for_worker(worker)
138
- CapistranoMulticonfigParallel.configuration.task_confirmations.each_with_index do |task, _index|
134
+ app_configuration.task_confirmations.each_with_index do |task, _index|
139
135
  fake_result = proc { |sum| sum }
140
136
  task_confirmation = @job_to_condition[worker.job_id][task]
141
137
  if task_confirmation[:status] != 'confirmed'
@@ -147,7 +143,7 @@ module CapistranoMulticonfigParallel
147
143
 
148
144
  def wait_task_confirmations_worker(worker)
149
145
  return if !apply_confirmation_for_worker(worker) || !syncronized_confirmation?
150
- CapistranoMulticonfigParallel.configuration.task_confirmations.each_with_index do |task, _index|
146
+ app_configuration.task_confirmations.each_with_index do |task, _index|
151
147
  result = wait_condition_for_task(worker.job_id, task)
152
148
  confirm_task_approval(result, task, worker) if result.present?
153
149
  end
@@ -158,9 +154,9 @@ module CapistranoMulticonfigParallel
158
154
  end
159
155
 
160
156
  def wait_task_confirmations
161
- stage_apply = CapistranoMulticonfigParallel.configuration.apply_stage_confirmation.include?(@job_manager.stage)
157
+ stage_apply = app_configuration.apply_stage_confirmation.include?(@job_manager.stage)
162
158
  return if !stage_apply || !syncronized_confirmation?
163
- CapistranoMulticonfigParallel.configuration.task_confirmations.each_with_index do |task, _index|
159
+ app_configuration.task_confirmations.each_with_index do |task, _index|
164
160
  results = []
165
161
  @jobs.pmap do |job_id, _job|
166
162
  result = wait_condition_for_task(job_id, task)
@@ -269,11 +265,11 @@ module CapistranoMulticonfigParallel
269
265
 
270
266
  def worker_died(worker, reason)
271
267
  job = @worker_to_job[worker.mailbox.address]
272
- debug("worker job #{job} with mailbox #{worker.mailbox.inspect} died for reason: #{reason}") if self.class.debug_enabled?
268
+ log_to_file("worker job #{job} with mailbox #{worker.mailbox.inspect} died for reason: #{reason}")
273
269
  @worker_to_job.delete(worker.mailbox.address)
274
270
  return if job.blank? || job_failed?(job)
275
271
  return unless job['action_name'] == 'deploy'
276
- debug "restarting #{job} on new worker" if self.class.debug_enabled?
272
+ log_to_file "restarting #{job} on new worker"
277
273
  job = job.merge(:action => 'deploy:rollback', 'worker_action' => 'worker_died')
278
274
  delegate(job)
279
275
  end
@@ -1,5 +1,6 @@
1
1
  require_relative './child_process'
2
2
  require_relative './state_machine'
3
+ require_relative '../helpers/application_helper'
3
4
  module CapistranoMulticonfigParallel
4
5
  # rubocop:disable ClassLength
5
6
  # worker that will spawn a child process in order to execute a capistrano job and monitor that process
@@ -20,12 +21,13 @@ module CapistranoMulticonfigParallel
20
21
  include Celluloid
21
22
  include Celluloid::Notifications
22
23
  include Celluloid::Logger
24
+ include CapistranoMulticonfigParallel::ApplicationHelper
23
25
  class TaskFailed < StandardError; end
24
26
 
25
27
  attr_accessor :job, :manager, :job_id, :app_name, :env_name, :action_name, :env_options, :machine, :client, :task_argv,
26
28
  :rake_tasks, :current_task_number, # tracking tasks
27
29
  :successfull_subscription, :subscription_channel, :publisher_channel, # for subscriptions and publishing events
28
- :job_termination_condition, :worker_state, :invocation_chain
30
+ :job_termination_condition, :worker_state, :invocation_chain, :filename, :worker_log
29
31
 
30
32
  def work(job, manager)
31
33
  @job = job
@@ -33,20 +35,16 @@ module CapistranoMulticonfigParallel
33
35
  @manager = manager
34
36
  @job_confirmation_conditions = []
35
37
  process_job(job) if job.present?
36
- debug("worker #{@job_id} received #{job.inspect}") if debug_enabled?
38
+ log_to_file("worker #{@job_id} received #{job.inspect}")
37
39
  @subscription_channel = "worker_#{@job_id}"
38
40
  @machine = CapistranoMulticonfigParallel::StateMachine.new(job, Actor.current)
39
41
  manager.register_worker_for_job(job, Actor.current)
40
42
  end
41
43
 
42
- def debug_enabled?
43
- @manager.class.debug_enabled?
44
- end
45
-
46
44
  def start_task
47
45
  @manager.setup_worker_conditions(Actor.current)
48
- debug("exec worker #{@job_id} starts task with #{@job.inspect}") if debug_enabled?
49
- @client = CelluloidPubsub::Client.connect(actor: Actor.current, enable_debug: @manager.class.debug_websocket?, channel: subscription_channel)
46
+ log_to_file("exec worker #{@job_id} starts task with #{@job.inspect}")
47
+ @client = CelluloidPubsub::Client.connect(actor: Actor.current, enable_debug: @manager.debug_websocket?, channel: subscription_channel)
50
48
  end
51
49
 
52
50
  def publish_rake_event(data)
@@ -58,7 +56,7 @@ module CapistranoMulticonfigParallel
58
56
  end
59
57
 
60
58
  def on_message(message)
61
- debug("worker #{@job_id} received: #{message.inspect}") if debug_enabled?
59
+ log_to_file("worker #{@job_id} received: #{message.inspect}")
62
60
  if @client.succesfull_subscription?(message)
63
61
  @successfull_subscription = true
64
62
  execute_after_succesfull_subscription
@@ -96,10 +94,10 @@ module CapistranoMulticonfigParallel
96
94
  end
97
95
 
98
96
  def execute_deploy
99
- debug("invocation chain #{@job_id} is : #{@rake_tasks.inspect}") if debug_enabled?
97
+ log_to_file("invocation chain #{@job_id} is : #{@rake_tasks.inspect}")
100
98
  check_child_proces
101
99
  setup_task_arguments
102
- debug("worker #{@job_id} executes: #{generate_command}") if debug_enabled?
100
+ log_to_file("worker #{@job_id} executes: #{generate_command}")
103
101
  @child_process.async.work(generate_command, actor: Actor.current, silent: true)
104
102
  @manager.wait_task_confirmations_worker(Actor.current)
105
103
  end
@@ -115,7 +113,7 @@ module CapistranoMulticonfigParallel
115
113
  end
116
114
 
117
115
  def on_close(code, reason)
118
- debug("worker #{@job_id} websocket connection closed: #{code.inspect}, #{reason.inspect}") if debug_enabled?
116
+ log_to_file("worker #{@job_id} websocket connection closed: #{code.inspect}, #{reason.inspect}")
119
117
  end
120
118
 
121
119
  def check_gitflow
@@ -128,13 +126,13 @@ module CapistranoMulticonfigParallel
128
126
  check_gitflow
129
127
  save_tasks_to_be_executed(message)
130
128
  update_machine_state(message['task']) # if message['action'] == 'invoke'
131
- debug("worker #{@job_id} state is #{@machine.state}") if debug_enabled?
129
+ log_to_file("worker #{@job_id} state is #{@machine.state}")
132
130
  task_approval(message)
133
131
  elsif message_is_for_stdout?(message)
134
132
  result = Celluloid::Actor[:terminal_server].show_confirmation(message['question'], message['default'])
135
133
  publish_rake_event(message.merge('action' => 'stdin', 'result' => result, 'client_action' => 'stdin'))
136
134
  else
137
- debug("worker #{@job_id} could not handle #{message}") if debug_enabled?
135
+ log_to_file(message, @job_id)
138
136
  end
139
137
  end
140
138
 
@@ -152,7 +150,7 @@ module CapistranoMulticonfigParallel
152
150
 
153
151
  def task_approval(message)
154
152
  job_conditions = @manager.job_to_condition[@job_id]
155
- if job_conditions.present? && CapistranoMulticonfigParallel.configuration.task_confirmations.include?(message['task']) && message['action'] == 'invoke'
153
+ if job_conditions.present? && app_configuration.task_confirmations.include?(message['task']) && message['action'] == 'invoke'
156
154
  task_confirmation = job_conditions[message['task']]
157
155
  task_confirmation[:status] = 'confirmed'
158
156
  task_confirmation[:condition].signal(message['task'])
@@ -162,13 +160,13 @@ module CapistranoMulticonfigParallel
162
160
  end
163
161
 
164
162
  def save_tasks_to_be_executed(message)
165
- debug("worler #{@job_id} current invocation chain : #{rake_tasks.inspect}") if debug_enabled?
163
+ log_to_file("worler #{@job_id} current invocation chain : #{rake_tasks.inspect}")
166
164
  rake_tasks << message['task'] if rake_tasks.last != message['task']
167
165
  invocation_chain << message['task'] if invocation_chain.last != message['task']
168
166
  end
169
167
 
170
168
  def update_machine_state(name)
171
- debug("worker #{@job_id} triest to transition from #{@machine.state} to #{name}") if debug_enabled?
169
+ log_to_file("worker #{@job_id} triest to transition from #{@machine.state} to #{name}")
172
170
  @machine.transitions.on(name.to_s, @machine.state => name.to_s)
173
171
  @machine.go_to_transition(name.to_s)
174
172
  raise(CapistranoMulticonfigParallel::CelluloidWorker::TaskFailed, "task #{@action} failed ") if name == 'deploy:failed' # force worker to rollback
@@ -196,7 +194,7 @@ module CapistranoMulticonfigParallel
196
194
  @env_options.each do |key, value|
197
195
  array_options << "#{key}=#{value}" if value.present?
198
196
  end
199
- array_options << '--trace' if debug_enabled?
197
+ array_options << '--trace' if app_debug_enabled?
200
198
  args.each do |arg|
201
199
  array_options << arg
202
200
  end
@@ -236,11 +234,11 @@ module CapistranoMulticonfigParallel
236
234
 
237
235
  def notify_finished(exit_status)
238
236
  if exit_status.exitstatus != 0
239
- debug("worker #{job_id} tries to terminate") if debug_enabled?
237
+ log_to_file("worker #{job_id} tries to terminate")
240
238
  raise(CapistranoMulticonfigParallel::CelluloidWorker::TaskFailed, "task failed with exit status #{exit_status.inspect} ") # force worker to rollback
241
239
  else
242
240
  update_machine_state('FINISHED')
243
- debug("worker #{job_id} notifies manager has finished") if debug_enabled?
241
+ log_to_file("worker #{job_id} notifies manager has finished")
244
242
  finish_worker
245
243
  end
246
244
  end
@@ -1,10 +1,13 @@
1
+ require_relative '../helpers/application_helper'
2
+ require_relative '../helpers/core_helper'
1
3
  module CapistranoMulticonfigParallel
2
4
  # class that is used to execute the capistrano tasks and it is invoked by the celluloid worker
3
5
  class ChildProcess
4
6
  include Celluloid
5
7
  include Celluloid::Logger
8
+ include CapistranoMulticonfigParallel::ApplicationHelper
6
9
 
7
- attr_accessor :actor, :pid, :exit_status, :process, :filename, :worker_log, :job_id, :debug_enabled
10
+ attr_accessor :actor, :pid, :exit_status, :process, :job_id
8
11
 
9
12
  finalizer :process_finalizer
10
13
 
@@ -12,8 +15,6 @@ module CapistranoMulticonfigParallel
12
15
  @options = options
13
16
  @actor = @options.fetch(:actor, nil)
14
17
  @job_id = @actor.job_id
15
- @debug_enabled = @actor.debug_enabled?
16
- set_worker_log
17
18
  EM.run do
18
19
  EM.next_tick do
19
20
  start_async_deploy(cmd, options)
@@ -23,24 +24,12 @@ module CapistranoMulticonfigParallel
23
24
  end
24
25
  end
25
26
  EM.error_handler do|e|
26
- @worker_log.debug "Error during event loop for worker #{@job_id}: #{e.inspect}" if @debug_enabled
27
- @worker_log.debug e.backtrace if @debug_enabled
27
+ log_to_file("Error during event loop for worker #{@job_id}: #{e.inspect}", @job_id)
28
+ log_to_file(e.backtrace, @job_id)
28
29
  EM.stop
29
30
  end
30
31
  end
31
32
 
32
- def set_worker_log
33
- FileUtils.mkdir_p(CapistranoMulticonfigParallel.log_directory) unless File.directory?(CapistranoMulticonfigParallel.log_directory)
34
- @filename = File.join(CapistranoMulticonfigParallel.log_directory, "worker_#{@actor.job_id}.log")
35
- FileUtils.rm_rf(@filename) if File.file?(@filename) && !@actor.crashed?
36
- @worker_log = ::Logger.new(@filename)
37
- @worker_log.level = ::Logger::Severity::DEBUG
38
- @worker_log.formatter = proc do |severity, datetime, progname, msg|
39
- date_format = datetime.strftime('%Y-%m-%d %H:%M:%S')
40
- "[#{date_format}] #{severity} (#{progname}): #{msg}\n"
41
- end
42
- end
43
-
44
33
  def process_finalizer
45
34
  @timer.cancel
46
35
  EM.stop if EM.reactor_running?
@@ -83,12 +72,12 @@ module CapistranoMulticonfigParallel
83
72
  end
84
73
 
85
74
  def on_exit(status)
86
- @worker_log.debug "Child process for worker #{@job_id} on_exit disconnected due to error #{status.inspect}" if @debug_enabled
75
+ log_to_file "Child process for worker #{@job_id} on_exit disconnected due to error #{status.inspect}"
87
76
  @exit_status = status
88
77
  end
89
78
 
90
79
  def async_exception_handler(*data)
91
- @worker_log.debug "Child process for worker #{@job_id} async_exception_handler disconnected due to error #{data.inspect}" if @debug_enabled
80
+ log_to_file "Child process for worker #{@job_id} async_exception_handler disconnected due to error #{data.inspect}"
92
81
  io_callback('stderr', data)
93
82
  @exit_status = 1
94
83
  end
@@ -98,7 +87,7 @@ module CapistranoMulticonfigParallel
98
87
  end
99
88
 
100
89
  def io_callback(io, data)
101
- @worker_log.debug("#{io.upcase} ---- #{data}")
90
+ log_to_file("#{io.upcase} ---- #{data}", @job_id)
102
91
  end
103
92
  end
104
93
  end
@@ -1,9 +1,11 @@
1
+ require_relative '../helpers/application_helper'
1
2
  module CapistranoMulticonfigParallel
2
3
  # class that handles the rake task and waits for approval from the celluloid worker
3
4
  # rubocop:disable ClassLength
4
5
  class RakeWorker
5
6
  include Celluloid
6
7
  include Celluloid::Logger
8
+ include CapistranoMulticonfigParallel::ApplicationHelper
7
9
 
8
10
  attr_accessor :env, :client, :job_id, :action, :task,
9
11
  :task_approved, :successfull_subscription,
@@ -50,11 +52,7 @@ module CapistranoMulticonfigParallel
50
52
 
51
53
  def initialize_subscription
52
54
  return if defined?(@client) && @client.present?
53
- @client = CelluloidPubsub::Client.connect(actor: Actor.current, enable_debug: debug_enabled?, channel: @subscription_channel)
54
- end
55
-
56
- def debug_enabled?
57
- CapistranoMulticonfigParallel::CelluloidManager.debug_websocket?
55
+ @client = CelluloidPubsub::Client.connect(actor: Actor.current, enable_debug: false, channel: @subscription_channel)
58
56
  end
59
57
 
60
58
  def task_name
@@ -82,12 +80,12 @@ module CapistranoMulticonfigParallel
82
80
  task_approval(message)
83
81
  stdin_approval(message)
84
82
  else
85
- warn "unknown action: #{message.inspect}" if debug_enabled?
83
+ show_warning "unknown action: #{message.inspect}"
86
84
  end
87
85
  end
88
86
 
89
87
  def log_debug(action, message)
90
- debug("Rake worker #{@job_id} received after #{action}: #{message}") if debug_enabled?
88
+ log_to_file("Rake worker #{@job_id} received after #{action}: #{message}")
91
89
  end
92
90
 
93
91
  def msg_for_stdin?(message)
@@ -117,7 +115,7 @@ module CapistranoMulticonfigParallel
117
115
  if @job_id.to_i == message['job_id'].to_i && message['result'].present?
118
116
  @stdin_result = message['result']
119
117
  else
120
- warn "unknown invocation #{message.inspect}" if debug_enabled?
118
+ show_warning "unknown invocation #{message.inspect}"
121
119
  end
122
120
  end
123
121
 
@@ -126,12 +124,12 @@ module CapistranoMulticonfigParallel
126
124
  if @job_id.to_i == message['job_id'].to_i && message['task'] == task_name && message['approved'] == 'yes'
127
125
  @task_approved = true
128
126
  else
129
- warn "unknown invocation #{message.inspect}" if debug_enabled?
127
+ show_warning "unknown invocation #{message.inspect}"
130
128
  end
131
129
  end
132
130
 
133
131
  def on_close(code, reason)
134
- debug("websocket connection closed: #{code.inspect}, #{reason.inspect}") if debug_enabled?
132
+ log_to_file("websocket connection closed: #{code.inspect}, #{reason.inspect}")
135
133
  terminate
136
134
  end
137
135
 
@@ -1,3 +1,4 @@
1
+ require_relative '../helpers/application_helper'
1
2
  module CapistranoMulticonfigParallel
2
3
  # class used to display the progress of each worker on terminal screen using a table
3
4
  # rubocop:disable ClassLength
@@ -5,7 +6,7 @@ module CapistranoMulticonfigParallel
5
6
  include Celluloid
6
7
  include Celluloid::Notifications
7
8
  include Celluloid::Logger
8
-
9
+ include CapistranoMulticonfigParallel::ApplicationHelper
9
10
  def self.topic
10
11
  'sshkit_terminal'
11
12
  end
@@ -44,7 +45,7 @@ module CapistranoMulticonfigParallel
44
45
 
45
46
  def show_confirmation(message, default)
46
47
  exclusive do
47
- CapistranoMulticonfigParallel.ask_confirm(message, default)
48
+ ask_confirm(message, default)
48
49
  end
49
50
  end
50
51
 
@@ -1,10 +1,12 @@
1
+ require_relative '../helpers/application_helper'
1
2
  module CapistranoMulticonfigParallel
2
3
  # class used to start the web server for websockets
3
4
  class WebServer < CelluloidPubsub::WebServer
5
+ include CapistranoMulticonfigParallel::ApplicationHelper
4
6
  def initialize(*args)
5
7
  super(*args)
6
8
  rescue => exc
7
- CapistranoMulticonfigParallel.log_message(exc)
9
+ log_error(exc)
8
10
  # fails silently
9
11
  end
10
12
  end
@@ -1,8 +1,9 @@
1
1
  require_relative './interactive_menu'
2
-
2
+ require_relative '../helpers/application_helper'
3
3
  module CapistranoMulticonfigParallel
4
4
  # class used to find application dependencies
5
5
  class DependencyTracker
6
+ include CapistranoMulticonfigParallel::ApplicationHelper
6
7
  attr_accessor :job_manager
7
8
 
8
9
  def initialize(job_manager)
@@ -15,7 +16,7 @@ module CapistranoMulticonfigParallel
15
16
  if @job_manager.custom_command?
16
17
  apps_selected = all_websites_return_applications_selected
17
18
  applications = get_applications_to_deploy(action, apps_selected)
18
- elsif CapistranoMulticonfigParallel.configuration.application_dependencies.present?
19
+ elsif app_configuration.application_dependencies.present?
19
20
  if application.present?
20
21
  applications = get_applications_to_deploy(action, [application.camelcase])
21
22
  applications = applications.delete_if { |hash| hash['app'] == application }
@@ -31,7 +32,7 @@ module CapistranoMulticonfigParallel
31
32
  private
32
33
 
33
34
  def application_dependencies
34
- deps = CapistranoMulticonfigParallel.configuration.application_dependencies
35
+ deps = app_configuration.application_dependencies
35
36
  deps.present? && deps.is_a?(Array) ? deps.map(&:stringify_keys) : []
36
37
  end
37
38
 
@@ -68,7 +69,7 @@ module CapistranoMulticonfigParallel
68
69
 
69
70
  def check_app_dependency_unique(applications_selected, apps_dependencies, applications_to_deploy, action)
70
71
  return applications_to_deploy if applications_selected.blank? || apps_dependencies.blank? || (apps_dependencies.map { |app| app['app'] } - applications_to_deploy.map { |app| app['app'] }).blank?
71
- apps_dependency_confirmation = CapistranoMulticonfigParallel.ask_confirm("Do you want to #{action} all dependencies also ?", 'Y/N')
72
+ apps_dependency_confirmation = ask_confirm("Do you want to #{action} all dependencies also ?", 'Y/N')
72
73
  applications_to_deploy = applications_to_deploy.concat(apps_dependencies) if apps_dependency_confirmation.present? && apps_dependency_confirmation.downcase == 'y'
73
74
  applications_to_deploy
74
75
  end
@@ -102,7 +103,7 @@ module CapistranoMulticonfigParallel
102
103
 
103
104
  def print_frameworks_used(app_names, applications_to_deploy, action)
104
105
  app_names.each { |app| puts "#{app}" }
105
- apps_deploy_confirmation = CapistranoMulticonfigParallel.ask_confirm("Are you sure you want to #{action} these apps?", 'Y/N')
106
+ apps_deploy_confirmation = ask_confirm("Are you sure you want to #{action} these apps?", 'Y/N')
106
107
  if apps_deploy_confirmation.blank? || (apps_deploy_confirmation.present? && apps_deploy_confirmation.downcase != 'y')
107
108
  return []
108
109
  elsif apps_deploy_confirmation.present? && apps_deploy_confirmation.downcase == 'y'
@@ -23,18 +23,26 @@ module CapistranoMulticonfigParallel
23
23
 
24
24
  private
25
25
 
26
+ def output_stream
27
+ CapistranoMulticonfigParallel::OutputStream
28
+ end
29
+
30
+ def input_stream
31
+ CapistranoMulticonfigParallel::InputStream
32
+ end
33
+
26
34
  def actor_execute_block(&block)
27
35
  stringio = StringIO.new
28
- CapistranoMulticonfigParallel::OutputStream.hook(stringio)
29
- CapistranoMulticonfigParallel::InputStream.hook(actor, stringio)
36
+ output_stream.hook(stringio)
37
+ input_stream.hook(actor, stringio)
30
38
  block.call
31
- CapistranoMulticonfigParallel::InputStream.unhook
32
- CapistranoMulticonfigParallel::OutputStream.unhook
39
+ input_stream.unhook
40
+ output_stream.unhook
33
41
  end
34
42
 
35
43
  def actor_start_working
36
44
  if actor.blank?
37
- CapistranoMulticonfigParallel::RakeWorker.supervise_as rake_actor_id
45
+ supervise_actor
38
46
  actor.work(@env, actor_id: rake_actor_id, job_id: job_id, task: @task)
39
47
  else
40
48
  actor.publish_new_work(@env, task: @task)
@@ -42,9 +50,8 @@ module CapistranoMulticonfigParallel
42
50
  end
43
51
 
44
52
  def supervise_actor
45
- CapistranoMulticonfigParallel::RakeWorker.supervise_as(rake_actor_id,
46
- actor_id: rake_actor_id,
47
- job_id: job_id) if actor.blank?
53
+ return unless actor.blank?
54
+ CapistranoMulticonfigParallel::RakeWorker.supervise_as(rake_actor_id)
48
55
  end
49
56
 
50
57
  def actor
@@ -1,8 +1,10 @@
1
1
  require 'fileutils'
2
+ require_relative '../helpers/application_helper'
2
3
  module CapistranoMulticonfigParallel
3
4
  # class used to find application dependencies
4
5
  class StandardDeploy
5
6
  include FileUtils
7
+ include CapistranoMulticonfigParallel::ApplicationHelper
6
8
 
7
9
  attr_reader :app, :stage, :action, :task_arguments, :env_options
8
10
  def initialize(options)
@@ -40,9 +42,9 @@ module CapistranoMulticonfigParallel
40
42
  command = build_capistrano_task(action)
41
43
  puts("\n\n\n Executing '#{command}' \n\n\n .")
42
44
  sh("#{command}")
43
- # rescue => ex
44
- # CapistranoMulticonfigParallel.log_message(ex)
45
- # execute_standard_deploy('deploy:rollback') if action.blank? && @name == 'deploy'
45
+ rescue => ex
46
+ log_error(ex)
47
+ execute_standard_deploy('deploy:rollback') if action.blank? && @name == 'deploy'
46
48
  end
47
49
  end
48
50
  end
@@ -4,6 +4,8 @@ module CapistranoMulticonfigParallel
4
4
  # this is the class that will be invoked from terminal , and willl use the invoke task as the primary function.
5
5
  class CLI
6
6
  class << self
7
+ include CapistranoMulticonfigParallel::ApplicationHelper
8
+
7
9
  # method used to start
8
10
  def start
9
11
  verify_validation
@@ -26,7 +28,7 @@ module CapistranoMulticonfigParallel
26
28
  end
27
29
 
28
30
  def verify_validation
29
- CapistranoMulticonfigParallel.check_terminal_tty
31
+ check_terminal_tty
30
32
  CapistranoMulticonfigParallel.original_args = ARGV.dup
31
33
  CapistranoMulticonfigParallel.configuration_valid?
32
34
  end
@@ -2,44 +2,37 @@ require_relative './core_helper'
2
2
  module CapistranoMulticonfigParallel
3
3
  # class that holds the options that are configurable for this gem
4
4
  module ApplicationHelper
5
- extend ActiveSupport::Concern
6
- included do
7
- def app_configuration
8
- CapistranoMulticonfigParallel.configuration
9
- end
10
-
11
- def change_config_type(type)
12
- ['boolean'].include?(type) ? type.delete(':').to_sym : type.constantize
13
- end
5
+ include CapistranoMulticonfigParallel::CoreHelper
14
6
 
15
- def strip_characters_from_string(value)
16
- return unless value.present?
17
- value = value.delete("\r\n").delete("\n")
18
- value = value.gsub(/\s+/, ' ').strip if value.present?
19
- value
20
- end
7
+ module_function
21
8
 
22
- def parse_task_string(string) # :nodoc:
23
- /^([^\[]+)(?:\[(.*)\])$/ =~ string.to_s
9
+ def strip_characters_from_string(value)
10
+ return unless value.present?
11
+ value = value.delete("\r\n").delete("\n")
12
+ value = value.gsub(/\s+/, ' ').strip if value.present?
13
+ value
14
+ end
24
15
 
25
- name = Regexp.last_match(1)
26
- remaining_args = Regexp.last_match(2)
16
+ def parse_task_string(string) # :nodoc:
17
+ /^([^\[]+)(?:\[(.*)\])$/ =~ string.to_s
27
18
 
28
- return string, [] unless name
29
- return name, [] if remaining_args.empty?
19
+ name = Regexp.last_match(1)
20
+ remaining_args = Regexp.last_match(2)
30
21
 
31
- args = []
22
+ return string, [] unless name
23
+ return name, [] if remaining_args.empty?
32
24
 
33
- loop do
34
- /((?:[^\\,]|\\.)*?)\s*(?:,\s*(.*))?$/ =~ remaining_args
25
+ args = []
35
26
 
36
- remaining_args = Regexp.last_match(2)
37
- args << Regexp.last_match(1).gsub(/\\(.)/, '\1')
38
- break if remaining_args.blank?
39
- end
27
+ loop do
28
+ /((?:[^\\,]|\\.)*?)\s*(?:,\s*(.*))?$/ =~ remaining_args
40
29
 
41
- [name, args]
30
+ remaining_args = Regexp.last_match(2)
31
+ args << Regexp.last_match(1).gsub(/\\(.)/, '\1')
32
+ break if remaining_args.blank?
42
33
  end
34
+
35
+ [name, args]
43
36
  end
44
37
  end
45
38
  end
@@ -1,7 +1,9 @@
1
+ require_relative './application_helper'
1
2
  module CapistranoMulticonfigParallel
2
3
  # class that holds the options that are configurable for this gem
3
4
  module Configuration
4
5
  extend ActiveSupport::Concern
6
+ include CapistranoMulticonfigParallel::ApplicationHelper
5
7
 
6
8
  included do
7
9
  attr_reader :configuration
@@ -13,8 +15,8 @@ module CapistranoMulticonfigParallel
13
15
 
14
16
  def fetch_configuration
15
17
  @fetched_config = Configliere::Param.new
16
- command_line_params.each do |param|
17
- param_type = change_config_type(param['type'].to_s)
18
+ default_internal_config.each do |param|
19
+ param_type = find_config_type(param['type'])
18
20
  @fetched_config.define param['name'], type: param_type, description: param['description'], default: param['default']
19
21
  end
20
22
 
@@ -32,11 +34,6 @@ module CapistranoMulticonfigParallel
32
34
  @fetched_config.resolve!
33
35
  end
34
36
 
35
- def command_line_params
36
- @default_config ||= YAML.load_file(File.join(internal_config_directory, 'default.yml'))['default_config']
37
- @default_config
38
- end
39
-
40
37
  def verify_array_of_strings(value)
41
38
  return true if value.blank?
42
39
  value.reject(&:blank?)
@@ -82,7 +79,6 @@ module CapistranoMulticonfigParallel
82
79
  check_boolean_props(c, %w(multi_debug multi_secvential websocket_server.enable_debug))
83
80
  check_array_props(c, %w(task_confirmations development_stages apply_stage_confirmation))
84
81
  verify_application_dependencies(c, 'application_dependencies', %w(app priority dependencies))
85
- CapistranoMulticonfigParallel::CelluloidManager.debug_enabled = true if c[:multi_debug].to_s.downcase == 'true'
86
82
  end
87
83
  end
88
84
  end
@@ -1,82 +1,105 @@
1
1
  module CapistranoMulticonfigParallel
2
2
  # class that holds the options that are configurable for this gem
3
3
  module CoreHelper
4
- extend ActiveSupport::Concern
5
- included do
6
- def config_file
7
- File.join(detect_root.to_s, 'config', 'multi_cap.yml')
8
- end
4
+ module_function
9
5
 
10
- def internal_config_directory
11
- File.join(root.to_s, 'capistrano_multiconfig_parallel', 'configuration')
12
- end
6
+ def internal_config_directory
7
+ File.join(root.to_s, 'capistrano_multiconfig_parallel', 'configuration')
8
+ end
13
9
 
14
- def find_env_multi_cap_root
15
- ENV['MULTI_CAP_ROOT']
16
- end
10
+ def internal_config_file
11
+ File.join(internal_config_directory, 'default.yml')
12
+ end
17
13
 
18
- def detect_root
19
- if find_env_multi_cap_root
20
- Pathname.new(find_env_multi_cap_root)
21
- elsif defined?(::Rails)
22
- ::Rails.root
23
- else
24
- try_detect_capfile
25
- end
26
- end
14
+ def default_internal_config
15
+ @default_config ||= YAML.load_file(internal_config_file)['default_config']
16
+ @default_config
17
+ end
27
18
 
28
- def log_directory
29
- File.join(detect_root.to_s, 'log')
30
- end
19
+ def find_env_multi_cap_root
20
+ ENV['MULTI_CAP_ROOT']
21
+ end
31
22
 
32
- def main_log_file
33
- File.join(log_directory, 'multi_cap.log')
34
- end
23
+ def root
24
+ File.expand_path(File.dirname(File.dirname(__dir__)))
25
+ end
35
26
 
36
- def websokect_log_file
37
- File.join(log_directory, 'multi_cap_websocket.log')
38
- end
27
+ def find_config_type(type)
28
+ ['boolean'].include?(type.to_s) ? type.to_s.delete(':').to_sym : type.to_s.constantize
29
+ end
39
30
 
40
- def root
41
- File.expand_path(File.dirname(File.dirname(__dir__)))
42
- end
31
+ def try_detect_capfile
32
+ root = Pathname.new(FileUtils.pwd)
33
+ root = root.parent unless root.directory?
34
+ root = root.parent until root.children.find { |f| f.file? && f.basename.to_s.downcase == 'capfile' }.present? || root.root?
35
+ fail "Can't detect Capfile in the application root".red if root.root?
36
+ root
37
+ end
43
38
 
44
- def check_terminal_tty
45
- $stdin.sync = true if $stdin.isatty
46
- $stdout.sync = true if $stdout.isatty
47
- end
39
+ def app_debug_enabled?
40
+ app_configuration.multi_debug.to_s.downcase == 'true'
41
+ end
48
42
 
49
- def ask_confirm(message, default)
50
- `stty -raw echo`
51
- check_terminal_tty
52
- result = Ask.input message, default: default
53
- $stdout.flush
54
- `stty -raw echo`
55
- return result
56
- rescue
57
- return nil
58
- end
43
+ def show_warning(message)
44
+ warn message if app_debug_enabled?
45
+ end
59
46
 
60
- def log_message(message)
61
- return unless logger.present?
62
- logger.debug(
63
- class_name: message.class,
64
- message: message.respond_to?(:message) ? message.message : message.inspect,
65
- backtrace: message.respond_to?(:backtrace) ? message.backtrace.join("\n\n") : ''
66
- )
67
- end
47
+ def app_configuration
48
+ CapistranoMulticonfigParallel.configuration
49
+ end
68
50
 
69
- def try_detect_capfile
70
- root = Pathname.new(FileUtils.pwd)
71
- root = root.parent unless root.directory?
72
- root = root.parent until root.children.find { |f| f.file? && f.basename.to_s.downcase == 'capfile' }.present? || root.root?
73
- fail "Can't detect Capfile in the application root".red if root.root?
74
- root
75
- end
51
+ def custom_commands
52
+ CapistranoMulticonfigParallel.custom_commands
53
+ end
54
+
55
+ def app_logger
56
+ CapistranoMulticonfigParallel.logger
57
+ end
58
+
59
+ def check_terminal_tty
60
+ $stdin.sync = true if $stdin.isatty
61
+ $stdout.sync = true if $stdout.isatty
62
+ end
63
+
64
+ def find_loaded_gem(name)
65
+ Gem.loaded_specs.values.find { |repo| repo.name == name }
66
+ end
67
+
68
+ def ask_confirm(message, default)
69
+ `stty -raw echo`
70
+ check_terminal_tty
71
+ result = Ask.input message, default: default
72
+ $stdout.flush
73
+ `stty -raw echo`
74
+ return result
75
+ rescue
76
+ return nil
77
+ end
78
+
79
+ def log_error(message)
80
+ log_to_file(
81
+ class_name: message.class,
82
+ message: message.respond_to?(:message) ? message.message : message.inspect,
83
+ backtrace: message.respond_to?(:backtrace) ? message.backtrace.join("\n\n") : ''
84
+ )
85
+ end
86
+
87
+ def log_to_file(message, job_id = nil)
88
+ worker_log = job_id.present? ? find_worker_log(job_id) : app_logger
89
+ worker_log.debug(message) if worker_log.present? && app_debug_enabled?
90
+ end
76
91
 
77
- def find_loaded_gem(name)
78
- Gem.loaded_specs.values.find { |repo| repo.name == name }
92
+ def find_worker_log(job_id)
93
+ return if job_id.blank?
94
+ FileUtils.mkdir_p(CapistranoMulticonfigParallel.log_directory) unless File.directory?(CapistranoMulticonfigParallel.log_directory)
95
+ filename = File.join(CapistranoMulticonfigParallel.log_directory, "worker_#{job_id}.log")
96
+ worker_log = ::Logger.new(filename)
97
+ worker_log.level = ::Logger::Severity::DEBUG
98
+ worker_log.formatter = proc do |severity, datetime, progname, msg|
99
+ date_format = datetime.strftime('%Y-%m-%d %H:%M:%S')
100
+ "[#{date_format}] #{severity} (#{progname}): #{msg}\n"
79
101
  end
102
+ worker_log
80
103
  end
81
104
  end
82
105
  end
@@ -7,7 +7,7 @@ module CapistranoMulticonfigParallel
7
7
  # module used for generating the version
8
8
  module VERSION
9
9
  MAJOR = 0
10
- MINOR = 17
10
+ MINOR = 18
11
11
  TINY = 0
12
12
  PRE = nil
13
13
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: capistrano_multiconfig_parallel
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.17.0
4
+ version: 0.18.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - bogdanRada