capistrano_multiconfig_parallel 0.20.9 → 0.21.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: 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