capistrano_multiconfig_parallel 0.20.9 → 0.21.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: bb9d81743bb7797aad849b28341801909a634659
4
- data.tar.gz: fdc6ba3368a3cfdede894bb150ac831a17b240c9
3
+ metadata.gz: ba9973965ea61da495ec59d3cd50c8465267532a
4
+ data.tar.gz: ac92a48585d8b7491120f898a38b8a5fc9439316
5
5
  SHA512:
6
- metadata.gz: feebf247d9aa8bccb9d2108e956808aacdbc18190eae4bd27436619339b2aa10a304ecbc3651a0a285980e8ec5ee66f746df25ed32aea9123d59e980c8e3415e
7
- data.tar.gz: 0213a80c1f4b394c508247c0e426d4dd1941352c688bc087fad15de27d29142341d3d7e677b3108d489c95ba7acd5f286aa69846d8ec92003e17c38984e59e36
6
+ metadata.gz: ee5a2f3d237b7eeca37eb51b9358f3cce6b47fec61dcfa1923fa5bf014299b65a238c0a72f03ee3a7eca1b16afb0c6c3747ccd6e00d1f885e9d14fa827f4bf77
7
+ data.tar.gz: 5c70b0cdb8b7a347babfba5fdeaad76c99128d4f66f2b22f5473d628e1c66796148ec17881b9626d21874b7c5bcd1a0cbefa21eb15361bf68eb74dee73b35423
@@ -17,14 +17,14 @@ module CapistranoMulticonfigParallel
17
17
  end
18
18
 
19
19
  def start
20
- verify_app_dependencies if multi_apps? && app_configuration.application_dependencies.present?
20
+ verify_app_dependencies if multi_apps? && configuration.application_dependencies.present?
21
21
  check_before_starting
22
22
  initialize_data
23
23
  run
24
24
  end
25
25
 
26
26
  def verify_app_dependencies
27
- wrong = app_configuration.application_dependencies.find do |hash|
27
+ wrong = configuration.application_dependencies.find do |hash|
28
28
  !@stage_apps.include?(hash[:app]) || (hash[:dependencies].present? && hash[:dependencies].find { |val| !@stage_apps.include?(val) })
29
29
  end
30
30
  raise ArgumentError, "Invalid configuration for #{wrong.inspect}".red if wrong.present?
@@ -93,7 +93,7 @@ module CapistranoMulticonfigParallel
93
93
  def check_before_starting
94
94
  CapistranoMulticonfigParallel.enable_logging
95
95
  @dependency_tracker = CapistranoMulticonfigParallel::DependencyTracker.new(Actor.current)
96
- @default_stage = app_configuration.development_stages.present? ? app_configuration.development_stages.first : 'development'
96
+ @default_stage = configuration.development_stages.present? ? configuration.development_stages.first : 'development'
97
97
  @condition = Celluloid::Condition.new
98
98
  @manager = CapistranoMulticonfigParallel::CelluloidManager.new(Actor.current)
99
99
  end
@@ -110,7 +110,7 @@ module CapistranoMulticonfigParallel
110
110
  def process_jobs
111
111
  return unless @jobs.present?
112
112
  FileUtils.rm Dir["#{log_directory}/worker_*.log"]
113
- if app_configuration.multi_secvential.to_s.downcase == 'true'
113
+ if configuration.multi_secvential.to_s.downcase == 'true'
114
114
  @jobs.each(&:execute_standard_deploy)
115
115
  else
116
116
  run_async_jobs
@@ -177,7 +177,7 @@ module CapistranoMulticonfigParallel
177
177
  options = options.stringify_keys
178
178
  main_box_name = @argv['BOX'].blank? ? '' : @argv['BOX']
179
179
  stage = options.fetch('stage', @default_stage)
180
- if app_configuration.development_stages.include?(stage) && main_box_name.present? && /^[a-z0-9,]+/.match(main_box_name)
180
+ if configuration.development_stages.include?(stage) && main_box_name.present? && /^[a-z0-9,]+/.match(main_box_name)
181
181
  execute_on_multiple_boxes(main_box_name, options)
182
182
  else
183
183
  prepare_job(options)
@@ -198,7 +198,7 @@ module CapistranoMulticonfigParallel
198
198
  end
199
199
 
200
200
  def wait_jobs_termination
201
- return if app_configuration.multi_secvential.to_s.downcase == 'true'
201
+ return if configuration.multi_secvential.to_s.downcase == 'true'
202
202
  result = @condition.wait
203
203
  return unless result.present?
204
204
  @manager.terminate
@@ -21,8 +21,7 @@ module CapistranoMulticonfigParallel
21
21
  Celluloid.task_class = Celluloid::TaskThread
22
22
  Celluloid.exception_handler do |ex|
23
23
  unless ex.is_a?(Interrupt)
24
- puts format_error(ex)
25
- log_error(ex)
24
+ log_error(ex, 'stderr')
26
25
  end
27
26
  end
28
27
  end
@@ -55,12 +55,12 @@ module CapistranoMulticonfigParallel
55
55
  @worker_to_job[worker.mailbox.address] = job
56
56
  log_to_file("worker #{worker.job_id} registed into manager")
57
57
  Actor.current.link worker
58
- worker.async.start_task unless syncronized_confirmation?
58
+ worker.async.start_task if !syncronized_confirmation? || job.failed? || job.rolling_back?
59
59
  @registration_complete = true if @job_manager.jobs.size == @job_to_worker.size
60
60
  end
61
61
 
62
62
  def all_workers_finished?
63
- @job_to_worker.all? { |job_id, _worker| @jobs[job_id].finished? }
63
+ @jobs.all? { |_job_id, job| job.finished? || job.crashed? || job.rolling_back? }
64
64
  end
65
65
 
66
66
  def process_jobs
@@ -80,7 +80,7 @@ module CapistranoMulticonfigParallel
80
80
  end
81
81
 
82
82
  def apply_confirmations?
83
- confirmations = app_configuration.task_confirmations
83
+ confirmations = configuration.task_confirmations
84
84
  confirmations.is_a?(Array) && confirmations.present?
85
85
  end
86
86
 
@@ -89,13 +89,13 @@ module CapistranoMulticonfigParallel
89
89
  end
90
90
 
91
91
  def apply_confirmation_for_job(job)
92
- app_configuration.apply_stage_confirmation.include?(job.stage) && apply_confirmations?
92
+ configuration.apply_stage_confirmation.include?(job.stage) && apply_confirmations?
93
93
  end
94
94
 
95
95
  def setup_worker_conditions(job)
96
96
  return unless apply_confirmation_for_job(job)
97
97
  hash_conditions = {}
98
- app_configuration.task_confirmations.each do |task|
98
+ configuration.task_confirmations.each do |task|
99
99
  hash_conditions[task] = { condition: Celluloid::Condition.new, status: 'unconfirmed' }
100
100
  end
101
101
  @job_to_condition[job.id] = hash_conditions
@@ -103,22 +103,21 @@ module CapistranoMulticonfigParallel
103
103
 
104
104
  def mark_completed_remaining_tasks(job)
105
105
  return unless apply_confirmation_for_job(job)
106
- app_configuration.task_confirmations.each_with_index do |task, _index|
106
+ configuration.task_confirmations.each_with_index do |task, _index|
107
107
  fake_result = proc { |sum| sum }
108
108
  task_confirmation = @job_to_condition[job.id][task]
109
- if task_confirmation[:status] != 'confirmed'
110
- task_confirmation[:status] = 'confirmed'
111
- task_confirmation[:condition].signal(fake_result)
112
- end
109
+ next unless task_confirmation[:status] != 'confirmed'
110
+ log_to_file("worker #{job.id} with action #{job.action} status #{job.status} and exit status #{job.exit_status} tries to mark fake the task #{task} with status #{task_confirmation[:status]}")
111
+ task_confirmation[:status] = 'confirmed'
112
+ task_confirmation[:condition].signal(fake_result)
113
113
  end
114
114
  end
115
115
 
116
116
  def wait_task_confirmations_worker(job)
117
- return unless job.finished? || job.exit_status.present?
118
117
  return if !apply_confirmation_for_job(job) || !syncronized_confirmation?
119
- app_configuration.task_confirmations.each_with_index do |task, _index|
118
+ configuration.task_confirmations.each_with_index do |task, _index|
120
119
  result = wait_condition_for_task(job.id, task)
121
- confirm_task_approval(result, task, job) if result.present?
120
+ confirm_task_approval(result, task, job)
122
121
  end
123
122
  end
124
123
 
@@ -127,9 +126,9 @@ module CapistranoMulticonfigParallel
127
126
  end
128
127
 
129
128
  def wait_task_confirmations
130
- stage_apply = app_configuration.apply_stage_confirmation.include?(@job_manager.stage)
129
+ stage_apply = configuration.apply_stage_confirmation.include?(@job_manager.stage)
131
130
  return if !stage_apply || !syncronized_confirmation?
132
- app_configuration.task_confirmations.each_with_index do |task, _index|
131
+ configuration.task_confirmations.each_with_index do |task, _index|
133
132
  results = []
134
133
  @jobs.pmap do |job_id, _job|
135
134
  result = wait_condition_for_task(job_id, task)
@@ -146,11 +145,15 @@ module CapistranoMulticonfigParallel
146
145
  message = "Do you want to continue the deployment and execute #{task.upcase}"
147
146
  message += " for JOB #{job.id}" if job.present?
148
147
  message += '?'
149
- apps_symlink_confirmation = Celluloid::Actor[:terminal_server].show_confirmation(message, 'Y/N')
150
- until apps_symlink_confirmation.present?
151
- sleep(0.1) # keep current thread alive
148
+ if Celluloid::Actor[:terminal_server].present? && Celluloid::Actor[:terminal_server].alive?
149
+ apps_symlink_confirmation = Celluloid::Actor[:terminal_server].show_confirmation(message, 'Y/N')
150
+ until apps_symlink_confirmation.present?
151
+ sleep(0.1) # keep current thread alive
152
+ end
153
+ apps_symlink_confirmation
154
+ else
155
+ 'y'
152
156
  end
153
- apps_symlink_confirmation
154
157
  end
155
158
 
156
159
  def confirm_task_approval(result, task, processed_job = nil)
@@ -159,11 +162,13 @@ module CapistranoMulticonfigParallel
159
162
  return unless action_confirmed?(result)
160
163
  @jobs.pmap do |job_id, job|
161
164
  worker = get_worker_for_job(job_id)
162
- worker.publish_rake_event('approved' => 'yes',
163
- 'action' => 'invoke',
164
- 'job_id' => job.id,
165
- 'task' => task
166
- )
165
+ if worker.alive?
166
+ worker.publish_rake_event('approved' => 'yes',
167
+ 'action' => 'invoke',
168
+ 'job_id' => job.id,
169
+ 'task' => task
170
+ )
171
+ end
167
172
  end
168
173
  end
169
174
 
@@ -185,10 +190,13 @@ module CapistranoMulticonfigParallel
185
190
  end
186
191
 
187
192
  def dispatch_new_job(job, options = {})
188
- env_opts = @job_manager.get_app_additional_env_options(job.app, job.stage)
189
- job.env_options = options.merge(env_opts)
190
- new_job = CapistranoMulticonfigParallel::Job.new(job.to_json)
191
- async.delegate(new_job)
193
+ return unless job.is_a?(CapistranoMulticonfigParallel::Job)
194
+ options.stringify_keys! if options.present?
195
+ env_opts = options['skip_env_options'].present? ? {} : @job_manager.get_app_additional_env_options(job.app, job.stage)
196
+ new_job_options = job.options.merge('env_options' => job.env_options.merge(env_opts))
197
+ new_job = CapistranoMulticonfigParallel::Job.new(new_job_options.merge(options.except(job.job_writer_attributes)))
198
+ new_job.setup_writer_attributes(options)
199
+ async.delegate(new_job) unless job.worker_died?
192
200
  end
193
201
 
194
202
  # lookup status of job by asking actor running it
@@ -208,14 +216,11 @@ module CapistranoMulticonfigParallel
208
216
 
209
217
  def worker_died(worker, reason)
210
218
  job = @worker_to_job[worker.mailbox.address]
211
- log_to_file("worker job #{job} with mailbox #{worker.mailbox.inspect} died for reason: #{reason}")
212
- @worker_to_job.delete(worker.mailbox.address)
213
- return if job.blank? || job.crashed?
214
- return unless job.action == 'deploy'
215
- log_to_file "restarting #{job} on new worker"
216
- job.status = 'worker_died'
217
- job.action = 'deploy:rollback'
218
- dispatch_new_job(job)
219
+ return true if job.blank? || job.worker_died? || job.action != 'deploy'
220
+ mailbox = worker.mailbox
221
+ @worker_to_job.delete(mailbox.address)
222
+ log_to_file("RESTARTING: worker job #{job.inspect} with mailbox #{mailbox.inspect} and #{mailbox.address.inspect} died for reason: #{reason}")
223
+ dispatch_new_job(job, skip_env_options: true, action: 'deploy:rollback', status: 'worker_died')
219
224
  end
220
225
  end
221
226
  end
@@ -43,9 +43,9 @@ module CapistranoMulticonfigParallel
43
43
 
44
44
  def worker_state
45
45
  if Actor.current.alive?
46
- status = @machine.state.to_s
47
- job.crashed? ? status.red : status.green
46
+ @machine.state.to_s.green
48
47
  else
48
+ job.status = 'dead'
49
49
  'dead'.upcase.red
50
50
  end
51
51
  end
@@ -76,6 +76,7 @@ module CapistranoMulticonfigParallel
76
76
 
77
77
  def execute_after_succesfull_subscription
78
78
  async.execute_deploy
79
+ @manager.async.wait_task_confirmations_worker(@job)
79
80
  end
80
81
 
81
82
  def rake_tasks
@@ -91,7 +92,6 @@ module CapistranoMulticonfigParallel
91
92
  check_child_proces
92
93
  log_to_file("worker #{@job_id} executes: #{@job.build_capistrano_task}")
93
94
  @child_process.async.work(@job, @job.build_capistrano_task, actor: Actor.current, silent: true)
94
- @manager.wait_task_confirmations_worker(@job)
95
95
  end
96
96
 
97
97
  def check_child_proces
@@ -110,8 +110,7 @@ module CapistranoMulticonfigParallel
110
110
 
111
111
  def check_gitflow
112
112
  return if @job.stage != 'staging' || !@manager.can_tag_staging? || !executed_task?(CapistranoMulticonfigParallel::GITFLOW_TAG_STAGING_TASK)
113
- @job.stage = 'production'
114
- @manager.dispatch_new_job(@job)
113
+ @manager.dispatch_new_job(@job, stage: 'production')
115
114
  end
116
115
 
117
116
  def handle_subscription(message)
@@ -143,7 +142,7 @@ module CapistranoMulticonfigParallel
143
142
 
144
143
  def task_approval(message)
145
144
  job_conditions = @manager.job_to_condition[@job_id]
146
- if job_conditions.present? && app_configuration.task_confirmations.include?(message['task']) && message['action'] == 'invoke'
145
+ if job_conditions.present? && configuration.task_confirmations.include?(message['task']) && message['action'] == 'invoke'
147
146
  task_confirmation = job_conditions[message['task']]
148
147
  task_confirmation[:status] = 'confirmed'
149
148
  task_confirmation[:condition].signal(message['task'])
@@ -161,28 +160,26 @@ module CapistranoMulticonfigParallel
161
160
  def update_machine_state(name)
162
161
  log_to_file("worker #{@job_id} triest to transition from #{@machine.state} to #{name}")
163
162
  @machine.go_to_transition(name.to_s)
164
- abort(CapistranoMulticonfigParallel::CelluloidWorker::TaskFailed.new("task #{@action} failed ")) if name == 'deploy:failed' # force worker to rollback
163
+ error_message = "worker #{@job_id} task #{name} failed "
164
+ raise(CapistranoMulticonfigParallel::CelluloidWorker::TaskFailed.new(error_message), error_message) if job.failed? # force worker to rollback
165
165
  end
166
166
 
167
167
  def send_msg(channel, message = nil)
168
168
  publish channel, message.present? && message.is_a?(Hash) ? { job_id: @job_id }.merge(message) : { job_id: @job_id, time: Time.now }
169
169
  end
170
170
 
171
- def finish_worker
171
+ def finish_worker(exit_status)
172
+ log_to_file("worker #{job_id} tries to terminate with exit_status #{exit_status}")
172
173
  @manager.mark_completed_remaining_tasks(@job)
173
- @job.status = 'finished'
174
+ update_machine_state('FINISHED')
174
175
  @manager.workers_terminated.signal('completed') if @manager.alive? && @manager.all_workers_finished?
175
176
  end
176
177
 
177
178
  def notify_finished(exit_status)
178
- if exit_status != 0
179
- log_to_file("worker #{job_id} tries to terminate")
180
- abort(CapistranoMulticonfigParallel::CelluloidWorker::TaskFailed.new("task failed with exit status #{exit_status.inspect} ")) # force worker to rollback
181
- else
182
- async.update_machine_state('FINISHED')
183
- log_to_file("worker #{job_id} notifies manager has finished")
184
- async.finish_worker
185
- end
179
+ finish_worker(exit_status)
180
+ return if exit_status == 0
181
+ error_message = "worker #{@job_id} task failed with exit status #{exit_status.inspect} "
182
+ raise(CapistranoMulticonfigParallel::CelluloidWorker::TaskFailed.new(error_message), error_message)
186
183
  end
187
184
  end
188
185
  end
@@ -7,7 +7,7 @@ module CapistranoMulticonfigParallel
7
7
  include Celluloid::Logger
8
8
  include CapistranoMulticonfigParallel::ApplicationHelper
9
9
 
10
- attr_accessor :options, :actor, :job_id, :exit_status, :pid, :process, :job
10
+ attr_accessor :options, :job, :actor, :job_id, :exit_status, :pid, :process
11
11
 
12
12
  finalizer :process_finalizer
13
13
 
@@ -23,6 +23,7 @@ module CapistranoMulticonfigParallel
23
23
  end
24
24
  @timer = EM::PeriodicTimer.new(0.1) do
25
25
  check_exit_status
26
+ @timer.cancel if @exit_status.present?
26
27
  end
27
28
  end
28
29
  EM.error_handler do|e|
@@ -37,12 +38,11 @@ module CapistranoMulticonfigParallel
37
38
  end
38
39
 
39
40
  def check_exit_status
40
- log_to_file("worker #{@job_id} checking exit status #{@exit_status.inspect}") if @exit_status.present?
41
41
  return if @exit_status.blank?
42
+ @timer.cancel
42
43
  @job.exit_status = @exit_status
43
- log_to_file("worker #{@job_id} startsnotify finished")
44
+ log_to_file("worker #{@job_id} startsnotify finished with exit status #{@exit_status.inspect}")
44
45
  @actor.async.notify_finished(@exit_status)
45
- @timer.cancel
46
46
  end
47
47
 
48
48
  def start_async_deploy(cmd, options)
@@ -76,9 +76,8 @@ module CapistranoMulticonfigParallel
76
76
  end
77
77
 
78
78
  def on_exit(status)
79
+ log_to_file "Child process for worker #{@job_id} on_exit disconnected due to error #{status.inspect}"
79
80
  @exit_status = status.exitstatus
80
- log_to_file "Child process for worker #{@job_id} on_exit disconnected due to error #{status.inspect} and #{@exit_status.inspect}"
81
- check_exit_status
82
81
  end
83
82
 
84
83
  def async_exception_handler(*data)
@@ -90,6 +89,7 @@ module CapistranoMulticonfigParallel
90
89
 
91
90
  def watch_handler(process)
92
91
  @process ||= process
92
+ check_exit_status
93
93
  end
94
94
 
95
95
  def io_callback(io, data)
@@ -25,19 +25,18 @@ module CapistranoMulticonfigParallel
25
25
  # default_headings << 'Total'
26
26
  # default_headings << 'Progress'
27
27
  table = Terminal::Table.new(title: 'Deployment Status Table', headings: default_headings)
28
- jobs = @manager.alive? ? @manager.jobs : []
28
+ jobs = @manager.alive? ? @manager.jobs.dup : []
29
29
  if jobs.present?
30
30
  count = 0
31
- last_job_id = jobs.keys.last.to_i
32
- jobs.each do |_job_id, job|
31
+ jobs.pmap do |job_id, job|
33
32
  count += 1
34
- add_job_to_table(table, job, count, last_job_id)
33
+ add_job_to_table(table, job_id, job, count)
35
34
  end
36
35
  end
37
36
  show_terminal_screen(table)
38
37
  rescue => ex
39
38
  log_to_file("Terminal Table client disconnected due to error #{ex.inspect}")
40
- log_to_file(ex.backtrace)
39
+ log_error(ex, 'stderr')
41
40
  terminate
42
41
  end
43
42
 
@@ -56,7 +55,9 @@ module CapistranoMulticonfigParallel
56
55
  @job_manager.condition.signal('completed') if @manager.all_workers_finished?
57
56
  end
58
57
 
59
- def worker_state(worker)
58
+ def worker_state(job_id)
59
+ return unless @manager.alive?
60
+ worker = @manager.get_worker_for_job(job_id)
60
61
  worker.alive? ? worker.worker_state : 'dead'.upcase.red
61
62
  end
62
63
 
@@ -64,27 +65,24 @@ module CapistranoMulticonfigParallel
64
65
  %w(STAGES ACTION)
65
66
  end
66
67
 
67
- def add_job_to_table(table, job, count, last_job_id)
68
- return unless @manager.alive?
69
- worker = @manager.get_worker_for_job(job.id)
70
-
71
- row = [{ value: count.to_s },
72
- { value: job.id.to_s },
68
+ def add_job_to_table(table, job_id, job, index)
69
+ row = [{ value: index.to_s },
70
+ { value: job_id.to_s },
73
71
  { value: job.job_stage },
74
72
  { value: job.capistrano_action },
75
73
  { value: job.setup_command_line_standard(filtered_keys: [CapistranoMulticonfigParallel::ENV_KEY_JOB_ID]).join("\n") },
76
- { value: worker_state(worker) }
74
+ { value: worker_state(job_id) }
77
75
  ]
78
76
 
79
77
  # if worker.alive?
80
- # row << { value: worker.rake_tasks.size }
81
- # row << { value: worker_progress(details['processed_job'], worker) }
78
+ # row << { value: job.rake_tasks.size }
79
+ # row << { value: worker_progress(job_id, job) }
82
80
  # else
83
81
  # row << { value: 0 }
84
- # row << { value: worker_state(worker) }
82
+ # row << { value: worker_state(job_id) }
85
83
  # end
86
84
  table.add_row(row)
87
- table.add_separator if last_job_id.to_i != job.id.to_i
85
+ table.add_separator
88
86
  table
89
87
  end
90
88
 
@@ -92,23 +90,17 @@ module CapistranoMulticonfigParallel
92
90
  system('cls') || system('clear') || puts("\e[H\e[2J")
93
91
  end
94
92
 
95
- # def worker_progress(processed_job, worker)
96
- # return worker_state(worker) unless worker.alive?
97
- # tasks = worker.alive? ? worker.invocation_chain : []
98
- # current_task = worker.alive? ? worker.machine.state.to_s : ''
99
- # show_worker_percent(worker, tasks, current_task, processed_job)
93
+ # def worker_progress(job)
94
+ # tasks = job.rake_tasks.size
95
+ # current_task = job.status
96
+ # show_worker_percent(tasks, current_task, job)
100
97
  # end
101
98
  #
102
- # def show_worker_percent(worker, tasks, current_task, processed_job)
103
- # total_tasks = worker.alive? ? tasks.size : nil
104
- # task_index = worker.alive? ? tasks.index(current_task.to_s).to_i + 1 : 0
99
+ # def show_worker_percent(tasks, current_task, job)
100
+ # task_index = tasks.index(current_task.to_s).to_i + 1
105
101
  # percent = percent_of(task_index, total_tasks)
106
102
  # result = "Progress [#{format('%.2f', percent)}%] (executed #{task_index} of #{total_tasks})"
107
- # if worker.alive?
108
- # processed_job.crashed? ? result.red : result.green
109
- # else
110
- # worker_state(worker)
111
- # end
103
+ # job.crashed? ? result.red : result.green
112
104
  # end
113
105
  #
114
106
  # def percent_of(index, total)
@@ -6,7 +6,7 @@ module CapistranoMulticonfigParallel
6
6
  def initialize(*args)
7
7
  super(*args)
8
8
  rescue => exc
9
- log_error(exc)
9
+ log_error(exc, 'stderr')
10
10
  # fails silently
11
11
  end
12
12
  end
@@ -22,7 +22,7 @@ module CapistranoMulticonfigParallel
22
22
  private
23
23
 
24
24
  def fetch_application_dependencies(application, action)
25
- return [] if app_configuration.application_dependencies.blank? || application.blank?
25
+ return [] if configuration.application_dependencies.blank? || application.blank?
26
26
  applications = get_applications_to_deploy(action, [application.camelcase])
27
27
  applications.delete_if { |hash| hash['app'] == application }
28
28
  end
@@ -33,7 +33,7 @@ module CapistranoMulticonfigParallel
33
33
  end
34
34
 
35
35
  def application_dependencies
36
- deps = app_configuration.application_dependencies
36
+ deps = configuration.application_dependencies
37
37
  value_is_array?(deps) ? deps.map(&:stringify_keys) : []
38
38
  end
39
39
 
@@ -43,7 +43,7 @@ module CapistranoMulticonfigParallel
43
43
  end
44
44
 
45
45
  def confirm_option_selected
46
- print "Enter a comma-separated list of option numbers or one single option number (again to uncheck, ENTER when done): "
46
+ print 'Enter a comma-separated list of option numbers or one single option number (again to uncheck, ENTER when done): '
47
47
  $stdin.gets.squeeze(' ').strip
48
48
  end
49
49
 
@@ -17,7 +17,20 @@ module CapistranoMulticonfigParallel
17
17
 
18
18
  def initialize(options)
19
19
  @options = options
20
- @command = CapistranoMulticonfigParallel::JobCommand.new(self)
20
+ end
21
+
22
+ def command
23
+ @command ||= CapistranoMulticonfigParallel::JobCommand.new(self)
24
+ end
25
+
26
+ def job_writer_attributes
27
+ %w(status exit_status)
28
+ end
29
+
30
+ def setup_writer_attributes(options)
31
+ job_writer_attributes.each do |attribute|
32
+ send("#{attribute}=", options.fetch("#{attribute}", send(attribute)))
33
+ end
21
34
  end
22
35
 
23
36
  def id
@@ -44,19 +57,33 @@ module CapistranoMulticonfigParallel
44
57
  value["#{CapistranoMulticonfigParallel::ENV_KEY_JOB_ID}"] = id if hash[:name] == 'env_options'
45
58
  verify_empty_options(value)
46
59
  end
60
+ # define_method "#{hash[:name]}=" do |value|
61
+ # self.send("#{hash[:name]}=", value)
62
+ # end
47
63
  end
48
64
 
49
65
  def finished?
50
- @status == 'finished'
66
+ status == 'finished'
67
+ end
68
+
69
+ def failed?
70
+ ['deploy:failed'].include?(status)
71
+ end
72
+
73
+ def rolling_back?
74
+ ['deploy:rollback'].include?(action)
51
75
  end
52
76
 
53
77
  def crashed?
54
- crashing_actions = ['deploy:rollback', 'deploy:failed']
55
- crashing_actions.include?(action) || crashing_actions.include?(status) || failed?
78
+ failed? || dead? || worker_died? || exit_status.to_i != 0
56
79
  end
57
80
 
58
- def failed?
59
- status.present? && status == 'worker_died'
81
+ def dead?
82
+ status.present? && status.to_s.downcase == 'dead'
83
+ end
84
+
85
+ def worker_died?
86
+ status.present? && status.to_s.downcase == 'worker_died'
60
87
  end
61
88
  end
62
89
  end
@@ -55,7 +55,7 @@ module CapistranoMulticonfigParallel
55
55
  command = build_capistrano_task(action)
56
56
  run_shell_command(command)
57
57
  rescue => ex
58
- log_error(ex)
58
+ log_error(ex, 'stderr')
59
59
  execute_standard_deploy('deploy:rollback') if action.blank? && @name == 'deploy'
60
60
  end
61
61
 
@@ -3,14 +3,14 @@ require_relative './input_stream'
3
3
  require_relative './output_stream'
4
4
  module CapistranoMulticonfigParallel
5
5
  # class used to handle the rake worker and sets all the hooks before and after running the worker
6
- class RakeHookActor
6
+ class RakeTaskHooks
7
7
  attr_accessor :task, :env
8
8
  def initialize(env, task)
9
9
  @env = env
10
10
  @task = task
11
11
  end
12
12
 
13
- def work(&block)
13
+ def automatic_hooks(&block)
14
14
  if job_id.present?
15
15
  actor_start_working
16
16
  actor.wait_execution until actor.task_approved
@@ -9,7 +9,8 @@ module CapistranoMulticonfigParallel
9
9
  # method used to start
10
10
  def start
11
11
  check_terminal_tty
12
- arguments = multi_fetch_argv(ARGV.dup)
12
+ CapistranoMulticonfigParallel.original_args = ARGV.dup
13
+ arguments = multi_fetch_argv(original_args)
13
14
  if arguments[CapistranoMulticonfigParallel::ENV_KEY_JOB_ID].blank?
14
15
  run_the_application
15
16
  else
@@ -19,7 +20,7 @@ module CapistranoMulticonfigParallel
19
20
 
20
21
  def run_the_application
21
22
  execute_with_rescue('stderr') do
22
- verify_validation
23
+ configuration_valid?
23
24
  CapistranoMulticonfigParallel::Application.new.start
24
25
  end
25
26
  end
@@ -8,6 +8,12 @@ module CapistranoMulticonfigParallel
8
8
  include CapistranoMulticonfigParallel::CoreHelper
9
9
  include CapistranoMulticonfigParallel::StagesHelper
10
10
 
11
+ delegate :logger,
12
+ :configuration,
13
+ :configuration_valid?,
14
+ :original_args,
15
+ to: :CapistranoMulticonfigParallel
16
+
11
17
  module_function
12
18
 
13
19
  def multi_fetch_argv(args)
@@ -75,7 +81,7 @@ module CapistranoMulticonfigParallel
75
81
  return string, [] unless name
76
82
  return name, [] if remaining_args.empty?
77
83
 
78
- args = find_remaaining_args(remaining_args)
84
+ args = find_remaining_args(remaining_args)
79
85
  [name, args]
80
86
  end
81
87
 
@@ -3,9 +3,9 @@ module CapistranoMulticonfigParallel
3
3
  # class that holds the options that are configurable for this gem
4
4
  module Configuration
5
5
  extend ActiveSupport::Concern
6
- include CapistranoMulticonfigParallel::ApplicationHelper
7
6
 
8
7
  included do
8
+ include CapistranoMulticonfigParallel::ApplicationHelper
9
9
  attr_reader :configuration
10
10
 
11
11
  def configuration
@@ -4,26 +4,13 @@ module CapistranoMulticonfigParallel
4
4
  module_function
5
5
 
6
6
  def app_debug_enabled?
7
- app_configuration.multi_debug.to_s.downcase == 'true'
7
+ configuration.multi_debug.to_s.downcase == 'true'
8
8
  end
9
9
 
10
10
  def show_warning(message)
11
11
  warn message if app_debug_enabled?
12
12
  end
13
13
 
14
- def app_configuration
15
- CapistranoMulticonfigParallel.configuration
16
- end
17
-
18
- def app_logger
19
- CapistranoMulticonfigParallel.logger
20
- end
21
-
22
- def verify_validation
23
- CapistranoMulticonfigParallel.original_args = ARGV.dup
24
- CapistranoMulticonfigParallel.configuration_valid?
25
- end
26
-
27
14
  def check_terminal_tty
28
15
  $stdin.sync = true if $stdin.isatty
29
16
  $stdout.sync = true if $stdout.isatty
@@ -55,8 +42,19 @@ module CapistranoMulticonfigParallel
55
42
  result
56
43
  end
57
44
 
58
- def log_error(error)
59
- log_to_file(format_error(error))
45
+ def filtered_errors
46
+ [CapistranoMulticonfigParallel::CelluloidWorker::TaskFailed, Celluloid::DeadActorError, Celluloid::Task::TerminatedError]
47
+ end
48
+
49
+ def error_filtered?(error)
50
+ filtered_errors.find { |class_name| error.is_a?(class_name) }.present?
51
+ end
52
+
53
+ def log_error(error, output = nil)
54
+ return if error_filtered?(error)
55
+ message = format_error(error)
56
+ puts(message) if output.present?
57
+ log_to_file(message)
60
58
  end
61
59
 
62
60
  def format_error(error)
@@ -66,7 +64,7 @@ module CapistranoMulticonfigParallel
66
64
  end
67
65
 
68
66
  def log_to_file(message, job_id = nil)
69
- worker_log = job_id.present? ? find_worker_log(job_id) : app_logger
67
+ worker_log = job_id.present? ? find_worker_log(job_id) : logger
70
68
  worker_log.debug(message) if worker_log.present? && app_debug_enabled?
71
69
  end
72
70
 
@@ -96,7 +94,7 @@ module CapistranoMulticonfigParallel
96
94
  end
97
95
 
98
96
  def websocket_server_config
99
- app_configuration.fetch(:websocket_server, {}).stringify_keys
97
+ configuration.fetch(:websocket_server, {}).stringify_keys
100
98
  end
101
99
 
102
100
  def websocket_config
@@ -112,8 +110,7 @@ module CapistranoMulticonfigParallel
112
110
  end
113
111
 
114
112
  def rescue_error(error, output = nil)
115
- puts(format_error(error)) if output.present?
116
- log_error(error)
113
+ log_error(error, output)
117
114
  exit(1)
118
115
  end
119
116
 
@@ -1,10 +1,10 @@
1
- require_relative '../classes/rake_hook_actor'
1
+ require_relative '../classes/rake_task_hooks'
2
2
  Rake::Task.class_eval do
3
3
  alias_method :original_execute, :execute
4
4
 
5
5
  def execute(*args)
6
- rake = CapistranoMulticonfigParallel::RakeHookActor.new(ENV, self)
7
- rake.work do
6
+ rake = CapistranoMulticonfigParallel::RakeTaskHooks.new(ENV, self)
7
+ rake.automatic_hooks do
8
8
  original_execute(*args)
9
9
  end
10
10
  end
@@ -7,8 +7,8 @@ module CapistranoMulticonfigParallel
7
7
  # module used for generating the version
8
8
  module VERSION
9
9
  MAJOR = 0
10
- MINOR = 20
11
- TINY = 9
10
+ MINOR = 21
11
+ TINY = 0
12
12
  PRE = nil
13
13
 
14
14
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: capistrano_multiconfig_parallel
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.20.9
4
+ version: 0.21.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - bogdanRada
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-12-08 00:00:00.000000000 Z
11
+ date: 2015-12-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: celluloid-pmap
@@ -634,7 +634,7 @@ files:
634
634
  - lib/capistrano_multiconfig_parallel/classes/job.rb
635
635
  - lib/capistrano_multiconfig_parallel/classes/job_command.rb
636
636
  - lib/capistrano_multiconfig_parallel/classes/output_stream.rb
637
- - lib/capistrano_multiconfig_parallel/classes/rake_hook_actor.rb
637
+ - lib/capistrano_multiconfig_parallel/classes/rake_task_hooks.rb
638
638
  - lib/capistrano_multiconfig_parallel/cli.rb
639
639
  - lib/capistrano_multiconfig_parallel/configuration/default.yml
640
640
  - lib/capistrano_multiconfig_parallel/helpers/application_helper.rb