capistrano_multiconfig_parallel 0.17.0 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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