capistrano_multiconfig_parallel 0.6.3 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +5 -5
- data/capistrano_multiconfig_parallel.gemspec +8 -8
- data/img/parallel_demo.png +0 -0
- data/lib/capistrano_multiconfig_parallel/all.rb +1 -0
- data/lib/capistrano_multiconfig_parallel/base.rb +4 -6
- data/lib/capistrano_multiconfig_parallel/celluloid/celluloid_manager.rb +46 -40
- data/lib/capistrano_multiconfig_parallel/celluloid/celluloid_worker.rb +18 -16
- data/lib/capistrano_multiconfig_parallel/celluloid/child_process.rb +1 -1
- data/lib/capistrano_multiconfig_parallel/celluloid/terminal_table.rb +30 -21
- data/lib/capistrano_multiconfig_parallel/configuration.rb +8 -4
- data/lib/capistrano_multiconfig_parallel/helpers/base_manager.rb +47 -46
- data/lib/capistrano_multiconfig_parallel/helpers/multi_app_manager.rb +3 -3
- data/lib/capistrano_multiconfig_parallel/initializers/helper.rb +0 -1
- data/lib/capistrano_multiconfig_parallel/multi_app_helpers/interactive_menu.rb +1 -1
- data/lib/capistrano_multiconfig_parallel/version.rb +2 -2
- metadata +19 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8f0f8c07848c290c54be6147ed565365c4f5d9b6
|
4
|
+
data.tar.gz: 6e2a75cf93aee7cb7bbe1a6f484c53f3bf003db5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bf0d3c5f0d5453bece121ff9c6886e16e7f063a11772683188a396f528f88698f75cb874a08cf5f357ae1b22100dba2e5af994957eab1e46432d7c4bc48a139d
|
7
|
+
data.tar.gz: 06d957bbd180bc92b34ab03dfa0b31ec3af13f81fd4f8829d7ae750e4be9561e4bd2ad374fbe7179c374b7871b3aa2b25dee24ee70bce96155fd0dcc65ad9d37
|
data/README.md
CHANGED
@@ -183,7 +183,7 @@ bundle exec multi_cap <development_stage> <task_name> BOX=<box_name>,<box_nam
|
|
183
183
|
|
184
184
|
```
|
185
185
|
|
186
|
-
If a branch is specified using
|
186
|
+
If a branch is specified using **BRANCH=name** it will deploy same branch to all sandboxes
|
187
187
|
The branch environment variable is then passed to the capistrano task
|
188
188
|
|
189
189
|
Also the script will ask if there are any other environment variables that user might want to pass to each of the sandboxes separately.
|
@@ -195,10 +195,10 @@ Also the script will ask if there are any other environment variables that user
|
|
195
195
|
|
196
196
|
bundle exec multi_cap deploy_multi_stages STAGES=development, staging, production
|
197
197
|
```
|
198
|
-
NOTE: IF you want to execute a different command on all stages, you can specify environment variable **ACTION
|
198
|
+
NOTE: IF you want to execute a different command on all stages, you can specify environment variable **ACTION=task_name** either when you specify the STAGES, or can be done
|
199
199
|
individually for each task when prompted about additional ENV options
|
200
200
|
|
201
|
-
If a branch is specified using
|
201
|
+
If a branch is specified using **BRANCH=name** it will deploy same branch to all stages.The branch environment variable is then passed to the capistrano task
|
202
202
|
|
203
203
|
Also the script will ask if there are any other environment variables that user might want to pass to each of the stages separately.
|
204
204
|
|
@@ -256,10 +256,10 @@ Will ask user if he wants to deploy the apps "foo" and "bar" , since they appear
|
|
256
256
|
bundle exec multi_cap deploy_multi_stages STAGES=development, staging, production
|
257
257
|
```
|
258
258
|
|
259
|
-
NOTE: IF you want to execute a different command on all stages, you can specify environment variable **ACTION
|
259
|
+
NOTE: IF you want to execute a different command on all stages, you can specify environment variable **ACTION=task_name** either when you specify the STAGES, or can be done
|
260
260
|
individually for each task when prompted about additional ENV options
|
261
261
|
|
262
|
-
If a branch is specified using **BRANCH
|
262
|
+
If a branch is specified using **BRANCH=branch_name** it will deploy same branch to all stages.The branch environment variable is then passed to the capistrano task
|
263
263
|
If you want different branches , capistrano will ask for additional ENV options for each stage, and can be specified then for each stage
|
264
264
|
|
265
265
|
If you use **capistrano-gitflow**, the workers will first deploy to all the other stages
|
@@ -41,12 +41,12 @@ Gem::Specification.new do |s|
|
|
41
41
|
s.add_development_dependency 'coveralls', '~> 0.7', '>= 0.7'
|
42
42
|
s.add_development_dependency 'rvm-tester', '~> 1.1', '>= 1.1'
|
43
43
|
|
44
|
-
s.add_development_dependency 'rubocop', '0
|
45
|
-
s.add_development_dependency 'phare', '~> 0
|
46
|
-
s.add_development_dependency 'yard', '~> 0
|
47
|
-
s.add_development_dependency 'yard-rspec', '~> 0
|
48
|
-
s.add_development_dependency 'redcarpet', '~> 3
|
49
|
-
s.add_development_dependency 'github-markup', '~> 1
|
50
|
-
s.add_development_dependency 'inch', '~> 0
|
51
|
-
s.add_development_dependency 'guard-inch', '~> 0
|
44
|
+
s.add_development_dependency 'rubocop', '~> 0', '>= 0.29'
|
45
|
+
s.add_development_dependency 'phare', '~> 0', '>= 0.6'
|
46
|
+
s.add_development_dependency 'yard', '~> 0', '>= 0.8.7'
|
47
|
+
s.add_development_dependency 'yard-rspec', '~> 0', '>= 0.1'
|
48
|
+
s.add_development_dependency 'redcarpet', '~> 3', '>= 3.2.2'
|
49
|
+
s.add_development_dependency 'github-markup', '~> 1', '>= 1.3.3'
|
50
|
+
s.add_development_dependency 'inch', '~> 0', '>= 0.5.10'
|
51
|
+
s.add_development_dependency 'guard-inch', '~> 0', '>= 0.1.0'
|
52
52
|
end
|
data/img/parallel_demo.png
CHANGED
Binary file
|
@@ -5,10 +5,10 @@ module CapistranoMulticonfigParallel
|
|
5
5
|
ENV_KEY_JOB_ID = 'multi_cap_job_id'
|
6
6
|
MULTI_KEY = 'multi'
|
7
7
|
SINGLE_KEY = 'single'
|
8
|
-
GITFLOW_TAG_STAGING_TASK =
|
8
|
+
GITFLOW_TAG_STAGING_TASK = 'gitflow:tag_staging'
|
9
9
|
GITFLOW_CALCULATE_TAG_TASK = 'gitflow:calculate_tag'
|
10
10
|
GITFLOW_VERIFY_UPTODATE_TASK = 'gitflow:verify_up_to_date'
|
11
|
-
|
11
|
+
|
12
12
|
CUSTOM_COMMANDS = {
|
13
13
|
CapistranoMulticonfigParallel::MULTI_KEY => {
|
14
14
|
stages: 'deploy_multi_stages'
|
@@ -26,11 +26,9 @@ module CapistranoMulticonfigParallel
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def ask_confirm(message, default)
|
29
|
-
begin
|
30
29
|
Ask.input message, default: default
|
31
30
|
rescue
|
32
31
|
return nil
|
33
|
-
end
|
34
32
|
end
|
35
33
|
|
36
34
|
def log_directory
|
@@ -48,7 +46,7 @@ module CapistranoMulticonfigParallel
|
|
48
46
|
def enable_logging
|
49
47
|
CapistranoMulticonfigParallel.configuration_valid?
|
50
48
|
FileUtils.mkdir_p(log_directory) unless File.directory?(log_directory)
|
51
|
-
if
|
49
|
+
if CapistranoMulticonfigParallel::CelluloidManager.debug_enabled.to_s.downcase == 'true'
|
52
50
|
FileUtils.touch(main_log_file) unless File.file?(main_log_file)
|
53
51
|
if ENV[CapistranoMulticonfigParallel::ENV_KEY_JOB_ID].blank?
|
54
52
|
log_file = File.open(main_log_file, 'w')
|
@@ -56,7 +54,7 @@ module CapistranoMulticonfigParallel
|
|
56
54
|
end
|
57
55
|
self.logger = ::Logger.new(main_log_file)
|
58
56
|
else
|
59
|
-
self.logger =
|
57
|
+
self.logger = ::Logger.new(DevNull.new)
|
60
58
|
end
|
61
59
|
Celluloid.logger = CapistranoMulticonfigParallel.logger
|
62
60
|
Celluloid.task_class = Celluloid::TaskThread
|
@@ -79,18 +79,21 @@ module CapistranoMulticonfigParallel
|
|
79
79
|
debug("job id not found. delegating again the job #{job.inspect}") if self.class.debug_enabled?
|
80
80
|
delegate(job)
|
81
81
|
else
|
82
|
-
|
83
|
-
@job_to_worker[job['id']] = worker
|
84
|
-
@worker_to_job[worker.mailbox.address] = job
|
85
|
-
debug("worker #{worker.job_id} registed into manager") if self.class.debug_enabled?
|
86
|
-
Actor.current.link worker
|
87
|
-
worker.async.start_task unless syncronized_confirmation?
|
88
|
-
if @job_manager.jobs.size == @job_to_worker.size
|
89
|
-
@registration_complete = true
|
90
|
-
end
|
82
|
+
start_worker(job, worker)
|
91
83
|
end
|
92
84
|
end
|
93
85
|
|
86
|
+
def start_worker(job, worker)
|
87
|
+
worker.job_id = job['id'] if worker.job_id.blank?
|
88
|
+
@job_to_worker[job['id']] = worker
|
89
|
+
@worker_to_job[worker.mailbox.address] = job
|
90
|
+
debug("worker #{worker.job_id} registed into manager") if self.class.debug_enabled?
|
91
|
+
Actor.current.link worker
|
92
|
+
worker.async.start_task unless syncronized_confirmation?
|
93
|
+
return unless @job_manager.jobs.size != @job_to_worker.size
|
94
|
+
@registration_complete = true
|
95
|
+
end
|
96
|
+
|
94
97
|
def process_jobs
|
95
98
|
if syncronized_confirmation?
|
96
99
|
@job_to_worker.pmap do |_job_id, worker|
|
@@ -105,18 +108,18 @@ module CapistranoMulticonfigParallel
|
|
105
108
|
debug("all jobs have completed #{condition}") if self.class.debug_enabled?
|
106
109
|
@job_manager.condition.signal('completed') if condition
|
107
110
|
end
|
108
|
-
|
111
|
+
|
109
112
|
def apply_confirmations?
|
110
|
-
|
113
|
+
CapistranoMulticonfigParallel.configuration.task_confirmation_active.to_s.downcase == 'true'
|
111
114
|
end
|
112
|
-
|
115
|
+
|
113
116
|
def syncronized_confirmation?
|
114
|
-
|
115
|
-
|
117
|
+
(CapistranoMulticonfigParallel.configuration.syncronize_confirmation.to_s.downcase == 'true' && !@job_manager.executes_deploy_stages?) ||
|
118
|
+
(@job_manager.executes_deploy_stages? && @job_manager.confirmation_applies_to_all_workers?)
|
116
119
|
end
|
117
120
|
|
118
121
|
def apply_confirmation_for_worker(worker)
|
119
|
-
worker.alive? &&
|
122
|
+
worker.alive? && CapistranoMulticonfigParallel.configuration.apply_stage_confirmation.include?(worker.env_name)
|
120
123
|
end
|
121
124
|
|
122
125
|
def setup_worker_conditions(worker)
|
@@ -129,7 +132,7 @@ module CapistranoMulticonfigParallel
|
|
129
132
|
end
|
130
133
|
|
131
134
|
def mark_completed_remaining_tasks(worker)
|
132
|
-
return if !apply_confirmation_for_worker(worker)
|
135
|
+
return if !apply_confirmation_for_worker(worker) || !apply_confirmations?
|
133
136
|
CapistranoMulticonfigParallel.configuration.task_confirmations.each_with_index do |task, _index|
|
134
137
|
fake_result = proc { |sum| sum }
|
135
138
|
task_confirmation = @job_to_condition[worker.job_id][task]
|
@@ -141,20 +144,20 @@ module CapistranoMulticonfigParallel
|
|
141
144
|
end
|
142
145
|
|
143
146
|
def wait_task_confirmations_worker(worker)
|
144
|
-
return if !apply_confirmations? ||
|
147
|
+
return if !apply_confirmations? || !apply_confirmation_for_worker(worker) || syncronized_confirmation?
|
145
148
|
CapistranoMulticonfigParallel.configuration.task_confirmations.each_with_index do |task, _index|
|
146
149
|
result = wait_condition_for_task(worker.job_id, task)
|
147
150
|
confirm_task_approval(result, task, worker) if result.present?
|
148
151
|
end
|
149
|
-
|
152
|
+
end
|
150
153
|
|
151
154
|
def wait_condition_for_task(job_id, task)
|
152
155
|
@job_to_condition[job_id][task][:condition].wait
|
153
156
|
end
|
154
157
|
|
155
158
|
def wait_task_confirmations
|
156
|
-
|
157
|
-
return
|
159
|
+
stage_apply = CapistranoMulticonfigParallel.configuration.apply_stage_confirmation.include?(@job_manager.stage)
|
160
|
+
return if !apply_confirmations? || !stage_apply || !syncronized_confirmation?
|
158
161
|
CapistranoMulticonfigParallel.configuration.task_confirmations.each_with_index do |task, _index|
|
159
162
|
results = []
|
160
163
|
@jobs.pmap do |job_id, _job|
|
@@ -167,17 +170,20 @@ module CapistranoMulticonfigParallel
|
|
167
170
|
end
|
168
171
|
end
|
169
172
|
|
173
|
+
def print_confirm_task_approvall(result, task, worker = nil)
|
174
|
+
return if result.is_a?(Proc)
|
175
|
+
message = "Do you want to continue the deployment and execute #{task.upcase}"
|
176
|
+
message += " for JOB #{worker.job_id}" if worker.present?
|
177
|
+
message += '?'
|
178
|
+
set :apps_symlink_confirmation, CapistranoMulticonfigParallel.ask_confirm(message, 'Y/N')
|
179
|
+
until fetch(:apps_symlink_confirmation).present?
|
180
|
+
sleep(0.1) # keep current thread alive
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
170
184
|
def confirm_task_approval(result, task, worker = nil)
|
171
185
|
return unless result.present?
|
172
|
-
|
173
|
-
message = "Do you want to continue the deployment and execute #{task.upcase}"
|
174
|
-
message += " for JOB #{worker.job_id}" if worker.present?
|
175
|
-
message += '?'
|
176
|
-
set :apps_symlink_confirmation, CapistranoMulticonfigParallel.ask_confirm(message, 'Y/N')
|
177
|
-
until fetch(:apps_symlink_confirmation).present?
|
178
|
-
sleep(0.1) # keep current thread alive
|
179
|
-
end
|
180
|
-
end
|
186
|
+
print_confirm_task_approvall(result, task, worker = nil)
|
181
187
|
return if fetch(:apps_symlink_confirmation).blank? || fetch(:apps_symlink_confirmation).downcase != 'y'
|
182
188
|
@jobs.pmap do |job_id, job|
|
183
189
|
worker = get_worker_for_job(job_id)
|
@@ -185,7 +191,7 @@ module CapistranoMulticonfigParallel
|
|
185
191
|
'action' => 'invoke',
|
186
192
|
'job_id' => job['id'],
|
187
193
|
'task' => task
|
188
|
-
|
194
|
+
)
|
189
195
|
end
|
190
196
|
end
|
191
197
|
|
@@ -203,17 +209,17 @@ module CapistranoMulticonfigParallel
|
|
203
209
|
end
|
204
210
|
|
205
211
|
def can_tag_staging?
|
206
|
-
|
207
|
-
|
212
|
+
@job_manager.can_tag_staging? &&
|
213
|
+
@jobs.find { |_job_id, job| job['env'] == 'production' }.blank?
|
208
214
|
end
|
209
|
-
|
215
|
+
|
210
216
|
def dispatch_new_job(job)
|
211
217
|
original_env = job['env_options']
|
212
218
|
env_opts = @job_manager.get_app_additional_env_options(job['app_name'], job['stage'])
|
213
|
-
job['env_options'] =
|
219
|
+
job['env_options'] = original_env.merge(env_opts)
|
214
220
|
async.delegate(job)
|
215
221
|
end
|
216
|
-
|
222
|
+
|
217
223
|
def process_job(job)
|
218
224
|
env_options = {}
|
219
225
|
job['env_options'].each do |key, value|
|
@@ -222,13 +228,13 @@ module CapistranoMulticonfigParallel
|
|
222
228
|
{
|
223
229
|
'job_id' => job['id'],
|
224
230
|
'app_name' => job['app'],
|
225
|
-
'env_name' =>
|
226
|
-
'action_name' =>
|
231
|
+
'env_name' => job['env'],
|
232
|
+
'action_name' => job['action'],
|
227
233
|
'env_options' => env_options,
|
228
|
-
'task_arguments' => job['task_arguments']
|
234
|
+
'task_arguments' => job['task_arguments']
|
229
235
|
}
|
230
236
|
end
|
231
|
-
|
237
|
+
|
232
238
|
# lookup status of job by asking actor running it
|
233
239
|
def get_job_status(job)
|
234
240
|
status = nil
|
@@ -244,7 +250,7 @@ module CapistranoMulticonfigParallel
|
|
244
250
|
end
|
245
251
|
status
|
246
252
|
end
|
247
|
-
|
253
|
+
|
248
254
|
def job_failed?(job)
|
249
255
|
job['worker_action'].present? && job['worker_action'] == 'worker_died'
|
250
256
|
end
|
@@ -23,9 +23,9 @@ module CapistranoMulticonfigParallel
|
|
23
23
|
class TaskFailed < StandardError; end
|
24
24
|
|
25
25
|
attr_accessor :job, :manager, :job_id, :app_name, :env_name, :action_name, :env_options, :machine, :client, :task_argv, :execute_deploy, :executed_dry_run,
|
26
|
-
|
27
|
-
|
28
|
-
|
26
|
+
:rake_tasks, :current_task_number, # tracking tasks
|
27
|
+
:successfull_subscription, :subscription_channel, :publisher_channel, # for subscriptions and publishing events
|
28
|
+
:job_termination_condition, :worker_state
|
29
29
|
|
30
30
|
def work(job, manager)
|
31
31
|
@job = job
|
@@ -38,7 +38,7 @@ module CapistranoMulticonfigParallel
|
|
38
38
|
@machine = CapistranoMulticonfigParallel::StateMachine.new(job, Actor.current)
|
39
39
|
manager.register_worker_for_job(job, Actor.current)
|
40
40
|
end
|
41
|
-
|
41
|
+
|
42
42
|
def debug_enabled?
|
43
43
|
@manager.class.debug_enabled?
|
44
44
|
end
|
@@ -88,18 +88,17 @@ module CapistranoMulticonfigParallel
|
|
88
88
|
def rake_tasks
|
89
89
|
@rake_tasks ||= []
|
90
90
|
end
|
91
|
-
|
92
|
-
|
91
|
+
|
93
92
|
def cd_working_directory
|
94
|
-
"cd #{CapistranoMulticonfigParallel.detect_root
|
93
|
+
"cd #{CapistranoMulticonfigParallel.detect_root}"
|
95
94
|
end
|
96
|
-
|
95
|
+
|
97
96
|
def generate_command
|
98
97
|
<<-CMD
|
99
98
|
#{cd_working_directory} && RAILS_ENV=#{@env_name} bundle exec multi_cap #{@task_argv.join(' ')}
|
100
99
|
CMD
|
101
100
|
end
|
102
|
-
|
101
|
+
|
103
102
|
def execute_deploy
|
104
103
|
@execute_deploy = true
|
105
104
|
debug("invocation chain #{@job_id} is : #{@rake_tasks.inspect}") if debug_enabled? && CapistranoMulticonfigParallel.show_task_progress
|
@@ -124,11 +123,14 @@ module CapistranoMulticonfigParallel
|
|
124
123
|
debug("worker #{@job_id} websocket connection closed: #{code.inspect}, #{reason.inspect}") if debug_enabled?
|
125
124
|
end
|
126
125
|
|
126
|
+
def check_gitflow
|
127
|
+
return if !@env_name == 'staging' || !@manager.can_tag_staging? || !executed_task?(CapistranoMulticonfigParallel::GITFLOW_VERIFY_UPTODATE_TASK)
|
128
|
+
@manager.dispatch_new_job(@job.merge('env' => 'production'))
|
129
|
+
end
|
130
|
+
|
127
131
|
def handle_subscription(message)
|
128
132
|
if message_is_about_a_task?(message)
|
129
|
-
|
130
|
-
@manager.dispatch_new_job(@job.merge('env' => 'production'))
|
131
|
-
end
|
133
|
+
check_gitflow
|
132
134
|
save_tasks_to_be_executed(message)
|
133
135
|
update_machine_state(message['task']) # if message['action'] == 'invoke'
|
134
136
|
debug("worker #{@job_id} state is #{@machine.state}") if debug_enabled?
|
@@ -141,8 +143,8 @@ module CapistranoMulticonfigParallel
|
|
141
143
|
def message_is_about_a_task?(message)
|
142
144
|
message.present? && message.is_a?(Hash) && message['action'].present? && message['job_id'].present? && message['task'].present?
|
143
145
|
end
|
144
|
-
|
145
|
-
def
|
146
|
+
|
147
|
+
def executed_task?(task)
|
146
148
|
@rake_tasks.present? && @rake_tasks[task].present?
|
147
149
|
end
|
148
150
|
|
@@ -203,9 +205,9 @@ module CapistranoMulticonfigParallel
|
|
203
205
|
@env_options = processed_job['env_options']
|
204
206
|
@task_arguments = processed_job['task_arguments']
|
205
207
|
end
|
206
|
-
|
208
|
+
|
207
209
|
def crashed?
|
208
|
-
@action_name == 'deploy:rollback' || @action_name == 'deploy:failed'
|
210
|
+
@action_name == 'deploy:rollback' || @action_name == 'deploy:failed' || @manager.job_failed?(@job)
|
209
211
|
end
|
210
212
|
|
211
213
|
def finish_worker
|
@@ -28,7 +28,7 @@ module CapistranoMulticonfigParallel
|
|
28
28
|
def set_worker_log
|
29
29
|
FileUtils.mkdir_p(CapistranoMulticonfigParallel.log_directory) unless File.directory?(CapistranoMulticonfigParallel.log_directory)
|
30
30
|
@filename = File.join(CapistranoMulticonfigParallel.log_directory, "worker_#{@actor.job_id}.log")
|
31
|
-
FileUtils.rm_rf(@filename) if File.file?(@filename) && !@actor.crashed? &&
|
31
|
+
FileUtils.rm_rf(@filename) if File.file?(@filename) && !@actor.crashed? && (@options[:dry_run] || @actor.executed_dry_run != true)
|
32
32
|
@worker_log = ::Logger.new(@filename)
|
33
33
|
@worker_log.level = ::Logger::Severity::DEBUG
|
34
34
|
@worker_log.formatter = proc do |severity, datetime, progname, msg|
|
@@ -50,42 +50,52 @@ module CapistranoMulticonfigParallel
|
|
50
50
|
puts "\n"
|
51
51
|
sleep(1)
|
52
52
|
end
|
53
|
-
|
54
|
-
def
|
55
|
-
job = @manager.jobs[job_id]
|
56
|
-
processed_job = @manager.process_job(job)
|
57
|
-
worker = @manager.get_worker_for_job(job_id)
|
53
|
+
|
54
|
+
def worker_state(worker)
|
58
55
|
if worker.alive?
|
59
56
|
state = worker.machine.state.to_s
|
60
|
-
|
57
|
+
worker.crashed? ? state.red : state.green
|
61
58
|
else
|
62
|
-
|
59
|
+
'dead'.upcase.red
|
63
60
|
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def worker_env_options(processed_job)
|
64
64
|
worker_optons = ''
|
65
65
|
processed_job['env_options'].each do |key, value|
|
66
66
|
worker_optons << "#{key}=#{value}\n"
|
67
67
|
end
|
68
|
-
|
69
|
-
|
68
|
+
worker_optons
|
69
|
+
end
|
70
|
+
|
71
|
+
def worker_action(processed_job)
|
72
|
+
processed_job['task_arguments'].present? ? "#{processed_job['action_name']}[#{processed_job['task_arguments'].join(',')}]" : processed_job['action_name']
|
73
|
+
end
|
74
|
+
|
75
|
+
def get_worker_details(job_id)
|
76
|
+
job = @manager.jobs[job_id]
|
77
|
+
processed_job = @manager.process_job(job)
|
78
|
+
worker = @manager.get_worker_for_job(job_id)
|
79
|
+
|
70
80
|
{
|
71
81
|
'job_id' => job_id,
|
72
|
-
'app_name' =>processed_job['app_name'],
|
73
|
-
'env_name' =>processed_job['env_name'],
|
74
|
-
'action_name' =>
|
75
|
-
'env_options' =>
|
82
|
+
'app_name' => processed_job['app_name'],
|
83
|
+
'env_name' => processed_job['env_name'],
|
84
|
+
'action_name' => worker_action(processed_job),
|
85
|
+
'env_options' => worker_env_options(processed_job),
|
76
86
|
'task_arguments' => job['task_arguments'],
|
77
|
-
'state' =>
|
87
|
+
'state' => worker_state(worker)
|
78
88
|
}
|
79
89
|
end
|
80
|
-
|
90
|
+
|
81
91
|
def add_job_to_table(table, job_id)
|
82
92
|
details = get_worker_details(job_id)
|
83
93
|
row = [{ value: job_id.to_s },
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
94
|
+
{ value: "#{details['app_name']}\n#{details['env_name']}" },
|
95
|
+
{ value: details['action_name'] },
|
96
|
+
{ value: details['env_options'] },
|
97
|
+
{ value: "#{details['state']}" }
|
98
|
+
]
|
89
99
|
if CapistranoMulticonfigParallel.show_task_progress
|
90
100
|
row << { value: worker.rake_tasks.size }
|
91
101
|
row << { value: worker_progress(worker) }
|
@@ -98,7 +108,6 @@ module CapistranoMulticonfigParallel
|
|
98
108
|
system('cls') || system('clear') || puts("\e[H\e[2J")
|
99
109
|
end
|
100
110
|
|
101
|
-
|
102
111
|
def worker_progress(worker)
|
103
112
|
tasks = worker.rake_tasks
|
104
113
|
current_task = worker.machine.state
|
@@ -27,7 +27,7 @@ module CapistranoMulticonfigParallel
|
|
27
27
|
|
28
28
|
def default_config
|
29
29
|
@default_config ||= Configliere::Param.new
|
30
|
-
@default_config.read File.join(
|
30
|
+
@default_config.read File.join(internal_config_directory, 'default.yml')
|
31
31
|
@default_config.resolve!
|
32
32
|
end
|
33
33
|
|
@@ -35,7 +35,11 @@ module CapistranoMulticonfigParallel
|
|
35
35
|
File.join(CapistranoMulticonfigParallel.detect_root.to_s, 'config', 'multi_cap.yml')
|
36
36
|
end
|
37
37
|
|
38
|
-
|
38
|
+
def internal_config_directory
|
39
|
+
File.join(CapistranoMulticonfigParallel.root.to_s, 'capistrano_multiconfig_parallel', 'initializers')
|
40
|
+
end
|
41
|
+
|
42
|
+
def command_line_params
|
39
43
|
[
|
40
44
|
{
|
41
45
|
name: 'multi_debug',
|
@@ -122,7 +126,7 @@ module CapistranoMulticonfigParallel
|
|
122
126
|
default: default_config[:application_dependencies]
|
123
127
|
}
|
124
128
|
]
|
125
|
-
|
129
|
+
end
|
126
130
|
|
127
131
|
def capistrano_options
|
128
132
|
command_line_params.map do |param|
|
@@ -181,5 +185,5 @@ module CapistranoMulticonfigParallel
|
|
181
185
|
CapistranoMulticonfigParallel.execute_in_sequence = true if c[:multi_secvential].to_s.downcase == 'true'
|
182
186
|
end
|
183
187
|
end
|
184
|
-
end
|
188
|
+
end
|
185
189
|
end
|
@@ -5,7 +5,7 @@ module CapistranoMulticonfigParallel
|
|
5
5
|
class BaseManager
|
6
6
|
include Celluloid
|
7
7
|
include Celluloid::Logger
|
8
|
-
|
8
|
+
|
9
9
|
attr_accessor :condition, :manager, :deps, :application, :stage, :name, :args, :argv, :jobs, :job_registered_condition, :default_stage, :original_argv
|
10
10
|
|
11
11
|
def initialize(cap_app, top_level_tasks, stages)
|
@@ -40,11 +40,15 @@ module CapistranoMulticonfigParallel
|
|
40
40
|
def configuration
|
41
41
|
CapistranoMulticonfigParallel.configuration
|
42
42
|
end
|
43
|
-
|
43
|
+
|
44
44
|
def start(&block)
|
45
|
-
CapistranoMulticonfigParallel.configuration_valid?
|
46
|
-
@default_stage = CapistranoMulticonfigParallel.configuration.development_stages.present? ? CapistranoMulticonfigParallel.configuration.development_stages.first : 'development'
|
47
45
|
check_before_starting
|
46
|
+
initialize_data
|
47
|
+
block.call if block_given?
|
48
|
+
run
|
49
|
+
end
|
50
|
+
|
51
|
+
def initialize_data
|
48
52
|
@application = custom_command? ? nil : @top_level_tasks.first.split(':').reverse[1]
|
49
53
|
@stage = custom_command? ? nil : @top_level_tasks.first.split(':').reverse[0]
|
50
54
|
@stage = @stage.present? ? @stage : @default_stage
|
@@ -52,21 +56,21 @@ module CapistranoMulticonfigParallel
|
|
52
56
|
@argv = @cap_app.handle_options.delete_if { |arg| arg == @stage || arg == @name || arg == @top_level_tasks.first }
|
53
57
|
@argv = multi_fetch_argv(@argv)
|
54
58
|
@original_argv = @argv.clone
|
55
|
-
block.call if block_given?
|
56
|
-
run
|
57
59
|
end
|
58
|
-
|
60
|
+
|
59
61
|
def verify_options_custom_command(options)
|
60
62
|
options[:action] = @argv['ACTION'].present? ? @argv['ACTION'] : 'deploy'
|
61
63
|
@argv = @argv['ACTION'].present? ? @argv.except('ACTION') : @argv
|
62
64
|
options
|
63
65
|
end
|
64
|
-
|
66
|
+
|
65
67
|
def check_before_starting
|
68
|
+
CapistranoMulticonfigParallel.configuration_valid?
|
69
|
+
@default_stage = CapistranoMulticonfigParallel.configuration.development_stages.present? ? CapistranoMulticonfigParallel.configuration.development_stages.first : 'development'
|
66
70
|
@condition = Celluloid::Condition.new
|
67
71
|
@manager = CapistranoMulticonfigParallel::CelluloidManager.new(Actor.current)
|
68
72
|
end
|
69
|
-
|
73
|
+
|
70
74
|
def collect_jobs(options = {}, &block)
|
71
75
|
options = prepare_options(options)
|
72
76
|
block.call(options) if block_given?
|
@@ -82,48 +86,50 @@ module CapistranoMulticonfigParallel
|
|
82
86
|
run_async_jobs
|
83
87
|
end
|
84
88
|
end
|
85
|
-
|
89
|
+
|
86
90
|
def tag_staging_exists? # check exists task from capistrano-gitflow
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
91
|
+
rake1 = Rake::Task[CapistranoMulticonfigParallel::GITFLOW_TAG_STAGING_TASK]
|
92
|
+
rake2 = Rake::Task[GITFLOW_CALCULATE_TAG_TASK]
|
93
|
+
rake3 = Rake::Task[GITFLOW_VERIFY_UPTODATE_TASK]
|
94
|
+
check_giflow_tasks(rake1, rake2, rake3)
|
95
|
+
rescue
|
96
|
+
return false
|
97
|
+
end
|
98
|
+
|
99
|
+
def check_giflow_tasks(rake1, rake2, rake3)
|
100
|
+
rake1.present? && rake2.present? && rake3.present? && rake2.prerequisites.present? && rake2.actions.present? && rake3.prerequisites.present?
|
95
101
|
end
|
96
102
|
|
97
103
|
def fetch_multi_stages
|
98
104
|
stages = @argv['STAGES'].blank? ? '' : @argv['STAGES']
|
99
105
|
@argv = @argv['STAGES'].present? ? @argv.except('STAGES') : @argv
|
100
106
|
stages = parse_inputted_value(value: stages).split(',').compact if stages.present?
|
101
|
-
stages.present? ? stages :
|
107
|
+
stages.present? ? stages : [@default_stage]
|
102
108
|
end
|
103
109
|
|
104
110
|
def wants_deploy_production?
|
105
|
-
|
111
|
+
(!custom_command? && @stage == 'production') || (custom_command? && fetch_multi_stages.include?('production'))
|
106
112
|
end
|
107
|
-
|
108
|
-
|
109
|
-
|
113
|
+
|
114
|
+
def can_tag_staging?
|
115
|
+
using_git? && wants_deploy_production? && tag_staging_exists?
|
116
|
+
end
|
117
|
+
|
118
|
+
def check_multi_stages(stages)
|
119
|
+
can_tag_staging? ? stages.reject { |u| u == 'production' } : stages
|
110
120
|
end
|
111
|
-
|
112
|
-
def check_multi_stages(stages)
|
113
|
-
can_tag_staging? ? stages.reject{|u| u == 'production'} : stages
|
114
|
-
end
|
115
|
-
|
121
|
+
|
116
122
|
def deploy_app(options = {})
|
117
123
|
options = options.stringify_keys
|
118
124
|
app = options['app'].is_a?(Hash) ? options['app'] : { 'app' => options['app'] }
|
119
125
|
branch = @branch_backup.present? ? @branch_backup : @argv['BRANCH'].to_s
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
126
|
+
call_task_deploy_app({
|
127
|
+
branch: branch,
|
128
|
+
app: app,
|
129
|
+
action: options['action']
|
130
|
+
}.reverse_merge(options))
|
125
131
|
end
|
126
|
-
|
132
|
+
|
127
133
|
def get_app_additional_env_options(app, app_message)
|
128
134
|
app_name = (app.is_a?(Hash) && app[:app].present?) ? app[:app].camelcase : app
|
129
135
|
app_name = app_name.present? ? app_name : 'current application'
|
@@ -133,11 +139,11 @@ module CapistranoMulticonfigParallel
|
|
133
139
|
end
|
134
140
|
|
135
141
|
def confirmation_applies_to_all_workers?
|
136
|
-
environments = @jobs.map{|job| job['env']}
|
142
|
+
environments = @jobs.map { |job| job['env'] }
|
137
143
|
CapistranoMulticonfigParallel.configuration.apply_stage_confirmation.all? { |e| environments.include?(e) }
|
138
144
|
end
|
139
|
-
|
140
|
-
|
145
|
+
|
146
|
+
private
|
141
147
|
|
142
148
|
def call_task_deploy_app(options = {})
|
143
149
|
options = options.stringify_keys
|
@@ -183,9 +189,8 @@ module CapistranoMulticonfigParallel
|
|
183
189
|
options['env_options'] = options['env_options'].reverse_merge(env_opts.except('BOX'))
|
184
190
|
|
185
191
|
env_options = branch_name.present? ? { 'BRANCH' => branch_name }.merge(options['env_options']) : options['env_options']
|
186
|
-
job_env_options =
|
187
|
-
|
188
|
-
|
192
|
+
job_env_options = custom_command? && env_options['ACTION'].present? ? env_options.except('ACTION') : env_options
|
193
|
+
|
189
194
|
job = {
|
190
195
|
app: app,
|
191
196
|
env: options['stage'],
|
@@ -196,8 +201,6 @@ module CapistranoMulticonfigParallel
|
|
196
201
|
job = job.stringify_keys
|
197
202
|
@jobs << job
|
198
203
|
end
|
199
|
-
|
200
|
-
|
201
204
|
|
202
205
|
def prepare_options(options)
|
203
206
|
options = options.stringify_keys
|
@@ -222,13 +225,11 @@ module CapistranoMulticonfigParallel
|
|
222
225
|
return ''
|
223
226
|
end
|
224
227
|
end
|
225
|
-
|
228
|
+
|
226
229
|
def using_git?
|
227
|
-
|
230
|
+
fetch(:scm, :git).to_sym == :git
|
228
231
|
end
|
229
232
|
|
230
|
-
|
231
|
-
|
232
233
|
def fetch_app_additional_env_options
|
233
234
|
options = {}
|
234
235
|
return options if fetch(:app_additional_env_options).blank?
|
@@ -23,7 +23,7 @@ module CapistranoMulticonfigParallel
|
|
23
23
|
end
|
24
24
|
raise ArgumentError, "invalid configuration for #{wrong.inspect}" if wrong.present?
|
25
25
|
end
|
26
|
-
|
26
|
+
|
27
27
|
def run
|
28
28
|
options = {}
|
29
29
|
if custom_command?
|
@@ -39,7 +39,7 @@ module CapistranoMulticonfigParallel
|
|
39
39
|
CapistranoMulticonfigParallel.interactive_menu = true
|
40
40
|
options = verify_options_custom_command(options)
|
41
41
|
action_name = @name
|
42
|
-
if
|
42
|
+
if action_name == custom_commands[:stages]
|
43
43
|
multi_stage_deploy(options)
|
44
44
|
else
|
45
45
|
raise "Custom command #{@name} not available for multi apps"
|
@@ -66,7 +66,7 @@ module CapistranoMulticonfigParallel
|
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
69
|
-
|
69
|
+
private
|
70
70
|
|
71
71
|
def multi_collect_and_run_jobs(options = {}, &block)
|
72
72
|
collect_jobs(options) do |new_options|
|
@@ -49,7 +49,7 @@ module CapistranoMulticonfigParallel
|
|
49
49
|
num = number_option.to_i
|
50
50
|
if /^[0-9]+/.match(num.to_s) && ((num.to_i > 0 && num.to_i <= applications.size))
|
51
51
|
num -= 1
|
52
|
-
msg += "#{applications[num]} was #{choices[num].present? ? 'un' : ''
|
52
|
+
msg += "#{applications[num]} was #{choices[num].present? ? 'un' : ''}checked\n"
|
53
53
|
choices[num] = choices[num].blank? ? '+' : ' '
|
54
54
|
else
|
55
55
|
msg = "Invalid option: #{num}\n"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: capistrano_multiconfig_parallel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- bogdanRada
|
@@ -454,9 +454,9 @@ dependencies:
|
|
454
454
|
name: rubocop
|
455
455
|
requirement: !ruby/object:Gem::Requirement
|
456
456
|
requirements:
|
457
|
-
- -
|
457
|
+
- - "~>"
|
458
458
|
- !ruby/object:Gem::Version
|
459
|
-
version: '0
|
459
|
+
version: '0'
|
460
460
|
- - ">="
|
461
461
|
- !ruby/object:Gem::Version
|
462
462
|
version: '0.29'
|
@@ -464,9 +464,9 @@ dependencies:
|
|
464
464
|
prerelease: false
|
465
465
|
version_requirements: !ruby/object:Gem::Requirement
|
466
466
|
requirements:
|
467
|
-
- -
|
467
|
+
- - "~>"
|
468
468
|
- !ruby/object:Gem::Version
|
469
|
-
version: '0
|
469
|
+
version: '0'
|
470
470
|
- - ">="
|
471
471
|
- !ruby/object:Gem::Version
|
472
472
|
version: '0.29'
|
@@ -476,7 +476,7 @@ dependencies:
|
|
476
476
|
requirements:
|
477
477
|
- - "~>"
|
478
478
|
- !ruby/object:Gem::Version
|
479
|
-
version: '0
|
479
|
+
version: '0'
|
480
480
|
- - ">="
|
481
481
|
- !ruby/object:Gem::Version
|
482
482
|
version: '0.6'
|
@@ -486,7 +486,7 @@ dependencies:
|
|
486
486
|
requirements:
|
487
487
|
- - "~>"
|
488
488
|
- !ruby/object:Gem::Version
|
489
|
-
version: '0
|
489
|
+
version: '0'
|
490
490
|
- - ">="
|
491
491
|
- !ruby/object:Gem::Version
|
492
492
|
version: '0.6'
|
@@ -496,7 +496,7 @@ dependencies:
|
|
496
496
|
requirements:
|
497
497
|
- - "~>"
|
498
498
|
- !ruby/object:Gem::Version
|
499
|
-
version: '0
|
499
|
+
version: '0'
|
500
500
|
- - ">="
|
501
501
|
- !ruby/object:Gem::Version
|
502
502
|
version: 0.8.7
|
@@ -506,7 +506,7 @@ dependencies:
|
|
506
506
|
requirements:
|
507
507
|
- - "~>"
|
508
508
|
- !ruby/object:Gem::Version
|
509
|
-
version: '0
|
509
|
+
version: '0'
|
510
510
|
- - ">="
|
511
511
|
- !ruby/object:Gem::Version
|
512
512
|
version: 0.8.7
|
@@ -516,7 +516,7 @@ dependencies:
|
|
516
516
|
requirements:
|
517
517
|
- - "~>"
|
518
518
|
- !ruby/object:Gem::Version
|
519
|
-
version: '0
|
519
|
+
version: '0'
|
520
520
|
- - ">="
|
521
521
|
- !ruby/object:Gem::Version
|
522
522
|
version: '0.1'
|
@@ -526,7 +526,7 @@ dependencies:
|
|
526
526
|
requirements:
|
527
527
|
- - "~>"
|
528
528
|
- !ruby/object:Gem::Version
|
529
|
-
version: '0
|
529
|
+
version: '0'
|
530
530
|
- - ">="
|
531
531
|
- !ruby/object:Gem::Version
|
532
532
|
version: '0.1'
|
@@ -536,7 +536,7 @@ dependencies:
|
|
536
536
|
requirements:
|
537
537
|
- - "~>"
|
538
538
|
- !ruby/object:Gem::Version
|
539
|
-
version: '3
|
539
|
+
version: '3'
|
540
540
|
- - ">="
|
541
541
|
- !ruby/object:Gem::Version
|
542
542
|
version: 3.2.2
|
@@ -546,7 +546,7 @@ dependencies:
|
|
546
546
|
requirements:
|
547
547
|
- - "~>"
|
548
548
|
- !ruby/object:Gem::Version
|
549
|
-
version: '3
|
549
|
+
version: '3'
|
550
550
|
- - ">="
|
551
551
|
- !ruby/object:Gem::Version
|
552
552
|
version: 3.2.2
|
@@ -556,7 +556,7 @@ dependencies:
|
|
556
556
|
requirements:
|
557
557
|
- - "~>"
|
558
558
|
- !ruby/object:Gem::Version
|
559
|
-
version: '1
|
559
|
+
version: '1'
|
560
560
|
- - ">="
|
561
561
|
- !ruby/object:Gem::Version
|
562
562
|
version: 1.3.3
|
@@ -566,7 +566,7 @@ dependencies:
|
|
566
566
|
requirements:
|
567
567
|
- - "~>"
|
568
568
|
- !ruby/object:Gem::Version
|
569
|
-
version: '1
|
569
|
+
version: '1'
|
570
570
|
- - ">="
|
571
571
|
- !ruby/object:Gem::Version
|
572
572
|
version: 1.3.3
|
@@ -576,7 +576,7 @@ dependencies:
|
|
576
576
|
requirements:
|
577
577
|
- - "~>"
|
578
578
|
- !ruby/object:Gem::Version
|
579
|
-
version: '0
|
579
|
+
version: '0'
|
580
580
|
- - ">="
|
581
581
|
- !ruby/object:Gem::Version
|
582
582
|
version: 0.5.10
|
@@ -586,7 +586,7 @@ dependencies:
|
|
586
586
|
requirements:
|
587
587
|
- - "~>"
|
588
588
|
- !ruby/object:Gem::Version
|
589
|
-
version: '0
|
589
|
+
version: '0'
|
590
590
|
- - ">="
|
591
591
|
- !ruby/object:Gem::Version
|
592
592
|
version: 0.5.10
|
@@ -596,7 +596,7 @@ dependencies:
|
|
596
596
|
requirements:
|
597
597
|
- - "~>"
|
598
598
|
- !ruby/object:Gem::Version
|
599
|
-
version: '0
|
599
|
+
version: '0'
|
600
600
|
- - ">="
|
601
601
|
- !ruby/object:Gem::Version
|
602
602
|
version: 0.1.0
|
@@ -606,7 +606,7 @@ dependencies:
|
|
606
606
|
requirements:
|
607
607
|
- - "~>"
|
608
608
|
- !ruby/object:Gem::Version
|
609
|
-
version: '0
|
609
|
+
version: '0'
|
610
610
|
- - ">="
|
611
611
|
- !ruby/object:Gem::Version
|
612
612
|
version: 0.1.0
|