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 +4 -4
- data/lib/capistrano_multiconfig_parallel/application.rb +6 -6
- data/lib/capistrano_multiconfig_parallel/base.rb +1 -2
- data/lib/capistrano_multiconfig_parallel/celluloid/celluloid_manager.rb +41 -36
- data/lib/capistrano_multiconfig_parallel/celluloid/celluloid_worker.rb +14 -17
- data/lib/capistrano_multiconfig_parallel/celluloid/child_process.rb +6 -6
- data/lib/capistrano_multiconfig_parallel/celluloid/terminal_table.rb +22 -30
- data/lib/capistrano_multiconfig_parallel/celluloid/web_server.rb +1 -1
- data/lib/capistrano_multiconfig_parallel/classes/dependency_tracker.rb +2 -2
- data/lib/capistrano_multiconfig_parallel/classes/interactive_menu.rb +1 -1
- data/lib/capistrano_multiconfig_parallel/classes/job.rb +33 -6
- data/lib/capistrano_multiconfig_parallel/classes/job_command.rb +1 -1
- data/lib/capistrano_multiconfig_parallel/classes/{rake_hook_actor.rb → rake_task_hooks.rb} +2 -2
- data/lib/capistrano_multiconfig_parallel/cli.rb +3 -2
- data/lib/capistrano_multiconfig_parallel/helpers/application_helper.rb +7 -1
- data/lib/capistrano_multiconfig_parallel/helpers/configuration.rb +1 -1
- data/lib/capistrano_multiconfig_parallel/helpers/core_helper.rb +17 -20
- data/lib/capistrano_multiconfig_parallel/initializers/rake.rb +3 -3
- data/lib/capistrano_multiconfig_parallel/version.rb +2 -2
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ba9973965ea61da495ec59d3cd50c8465267532a
|
4
|
+
data.tar.gz: ac92a48585d8b7491120f898a38b8a5fc9439316
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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? &&
|
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 =
|
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 =
|
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
|
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
|
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
|
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
|
@@ -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
|
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
|
-
@
|
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 =
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
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
|
-
|
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)
|
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 =
|
129
|
+
stage_apply = configuration.apply_stage_confirmation.include?(@job_manager.stage)
|
131
130
|
return if !stage_apply || !syncronized_confirmation?
|
132
|
-
|
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
|
-
|
150
|
-
|
151
|
-
|
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.
|
163
|
-
|
164
|
-
|
165
|
-
|
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
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
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
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
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
|
-
|
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
|
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? &&
|
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
|
-
|
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
|
-
|
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
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
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
|
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
|
-
|
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
|
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
|
-
|
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(
|
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,
|
68
|
-
|
69
|
-
|
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(
|
74
|
+
{ value: worker_state(job_id) }
|
77
75
|
]
|
78
76
|
|
79
77
|
# if worker.alive?
|
80
|
-
# row << { value:
|
81
|
-
# row << { value: worker_progress(
|
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(
|
82
|
+
# row << { value: worker_state(job_id) }
|
85
83
|
# end
|
86
84
|
table.add_row(row)
|
87
|
-
table.add_separator
|
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(
|
96
|
-
#
|
97
|
-
#
|
98
|
-
# current_task
|
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(
|
103
|
-
#
|
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
|
-
#
|
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)
|
@@ -22,7 +22,7 @@ module CapistranoMulticonfigParallel
|
|
22
22
|
private
|
23
23
|
|
24
24
|
def fetch_application_dependencies(application, action)
|
25
|
-
return [] if
|
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 =
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
59
|
-
status.present? && status == '
|
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
|
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
|
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
|
-
|
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
|
-
|
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 =
|
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
|
-
|
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
|
59
|
-
|
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) :
|
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
|
-
|
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
|
-
|
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/
|
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::
|
7
|
-
rake.
|
6
|
+
rake = CapistranoMulticonfigParallel::RakeTaskHooks.new(ENV, self)
|
7
|
+
rake.automatic_hooks do
|
8
8
|
original_execute(*args)
|
9
9
|
end
|
10
10
|
end
|
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.
|
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-
|
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/
|
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
|