capistrano_multiconfig_parallel 0.32.0 → 1.0.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 +14 -8
- data/capistrano_multiconfig_parallel.gemspec +2 -1
- data/img/parallel_demo-min.png +0 -0
- data/lib/capistrano_multiconfig_parallel/all.rb +5 -2
- data/lib/capistrano_multiconfig_parallel/application.rb +25 -24
- data/lib/capistrano_multiconfig_parallel/base.rb +16 -3
- data/lib/capistrano_multiconfig_parallel/celluloid/celluloid_manager.rb +4 -2
- data/lib/capistrano_multiconfig_parallel/celluloid/rake_worker.rb +4 -4
- data/lib/capistrano_multiconfig_parallel/classes/job.rb +1 -1
- data/lib/capistrano_multiconfig_parallel/classes/job_command.rb +8 -8
- data/lib/capistrano_multiconfig_parallel/classes/rake_task_hooks.rb +7 -4
- data/lib/capistrano_multiconfig_parallel/cli.rb +12 -1
- data/lib/capistrano_multiconfig_parallel/helpers/application_helper.rb +8 -42
- data/lib/capistrano_multiconfig_parallel/helpers/capistrano_helper.rb +22 -0
- data/lib/capistrano_multiconfig_parallel/helpers/configuration.rb +69 -70
- data/lib/capistrano_multiconfig_parallel/helpers/core_helper.rb +5 -1
- data/lib/capistrano_multiconfig_parallel/helpers/gem_helper.rb +33 -0
- data/lib/capistrano_multiconfig_parallel/helpers/parse_helper.rb +44 -0
- data/lib/capistrano_multiconfig_parallel/initializers/capistrano2.rb +24 -0
- data/lib/capistrano_multiconfig_parallel/version.rb +2 -2
- metadata +28 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d913f859f09d3474f80d0ebc9df04c6207dbad68
|
4
|
+
data.tar.gz: 0fa7d2ff36d4f718ace5e149e7dec0939fd8479b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 53e7738c4d3b8ff65dc9a2e2758af6880562c6e9482a54de930368d27ec16bfc5e416232aea4e4392d5f918f728bfb0f7011e9c5ae657580cba2f4991abe28fb
|
7
|
+
data.tar.gz: 2f064bbc1b8d6ef2ed23132b8d67ca33bc94964cb2ba2381fbb3dc7e0345d5d5dd32c0d2d05efebe8518eee2c953994cde511a1a9345e66ede2ec74b1ae7feb7
|
data/README.md
CHANGED
@@ -17,6 +17,13 @@ IMPORTANT! The whole reason for this gem was for using [Caphub](https://github.c
|
|
17
17
|
|
18
18
|
CAUTION!! PLEASE READ CAREFULLY!! Capistrano is not thread-safe. However in order to work around this problem, each of the task is executing inside a thread that spawns a new process in order to run capistrano tasks The thread monitors the process. This works well, however if the tasks you are executing is working with files, you might get into deadlocks because multiple proceses try to access same resource. Instead of using files , please consider using StringIO instead.
|
19
19
|
|
20
|
+
NEW Improvements in version 1.0.0
|
21
|
+
---------------------------------
|
22
|
+
|
23
|
+
- added support for Capistrano version 2
|
24
|
+
- a lot of refactoring and bug fixes
|
25
|
+
- removed Branch variable ( this needs to be passed when asked for additional env options for each job!!!).
|
26
|
+
|
20
27
|
Requirements
|
21
28
|
------------
|
22
29
|
|
@@ -29,11 +36,12 @@ Requirements
|
|
29
36
|
7. [colorize >= 0.7](https://github.com/fazibear/colorize)
|
30
37
|
8. [eventmachine >= 1.0.3](https://github.com/eventmachine/eventmachine)
|
31
38
|
9. [right_popen >= 1.1.3](https://github.com/rightscale/right_popen)
|
32
|
-
10. [capistrano >=
|
39
|
+
10. [capistrano >= 2.0](https://github.com/capistrano/capistrano/)
|
33
40
|
11. [configliere >= 0.4](https://github.com/infochimps-platform/configliere)
|
34
41
|
12. [inquirer >= 0.2](https://github.com/arlimus/inquirer.rb)
|
35
42
|
13. [devnull >= 0.1](https://github.com/arlimus/inquirer.rb)
|
36
43
|
14. [rack >= 1.6](http://rack.github.io/)
|
44
|
+
15. [rake >= 10.4](https://github.com/ruby/rake)
|
37
45
|
|
38
46
|
Compatibility
|
39
47
|
-------------
|
@@ -157,13 +165,13 @@ development_stages:
|
|
157
165
|
#<development_stage> - the name of one of the stages you previously configured
|
158
166
|
#<task_name> - the capistrano task that you want to execute ( example: 'deploy' )
|
159
167
|
|
160
|
-
bundle exec multi_cap <development_stage> <task_name> BOX=<box_name>,<box_name>
|
168
|
+
bundle exec multi_cap <development_stage> <task_name> BOX=<box_name>,<box_name>
|
161
169
|
|
162
170
|
```
|
163
171
|
|
164
|
-
|
172
|
+
For Capistrano 2 please use **-S box=<box_name>,<box_name>**
|
165
173
|
|
166
|
-
|
174
|
+
The script will ask if there are any other environment variables that user might want to pass to each of the sandboxes separately.
|
167
175
|
|
168
176
|
### 1.2) Deploying the application to multiple stages ( Using the customized command "deploy_multi_stages")
|
169
177
|
|
@@ -174,9 +182,7 @@ bundle exec multi_cap deploy_multi_stages STAGES=development, staging, producti
|
|
174
182
|
|
175
183
|
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 individually for each task when prompted about additional ENV options
|
176
184
|
|
177
|
-
|
178
|
-
|
179
|
-
Also the script will ask if there are any other environment variables that user might want to pass to each of the stages separately.
|
185
|
+
The script will ask if there are any other environment variables that user might want to pass to each of the stages separately.
|
180
186
|
|
181
187
|
If you use **capistrano-gitflow**, the workers will first deploy to all the other stages and only after staging is tagged , will trigger a new worker to start deploying to production
|
182
188
|
|
@@ -228,7 +234,7 @@ Demo:
|
|
228
234
|
|
229
235
|
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 individually for each task when prompted about additional ENV options
|
230
236
|
|
231
|
-
|
237
|
+
The script will ask for additional ENV options for each stage.
|
232
238
|
|
233
239
|
If you use **capistrano-gitflow**, the workers will first deploy to all the other stages and only after staging is tagged , will trigger a new worker to start deploying to production
|
234
240
|
|
@@ -25,12 +25,13 @@ Gem::Specification.new do |s|
|
|
25
25
|
s.add_runtime_dependency 'colorize', '~> 0.7', '>= 0.7'
|
26
26
|
s.add_runtime_dependency 'eventmachine', '~> 1.0', '>= 1.0.3'
|
27
27
|
s.add_runtime_dependency 'right_popen', '~> 1.1', '>= 1.1.3'
|
28
|
-
s.add_runtime_dependency 'capistrano','
|
28
|
+
s.add_runtime_dependency 'capistrano','>= 2.0','>= 2.0'
|
29
29
|
s.add_runtime_dependency 'activesupport', '~> 4.0','>= 4.0'
|
30
30
|
s.add_runtime_dependency 'configliere', '~> 0.4', '>=0.4'
|
31
31
|
s.add_runtime_dependency 'inquirer', '~> 0.2', '>= 0.2'
|
32
32
|
s.add_runtime_dependency 'devnull','~> 0.1', '>= 0.1'
|
33
33
|
s.add_runtime_dependency 'rack', '~> 1.6', '>= 1.6'
|
34
|
+
s.add_runtime_dependency 'rake', '~> 10.4', '>= 10.4'
|
34
35
|
|
35
36
|
s.add_development_dependency 'rspec-rails', '~> 3.3', '>= 3.3'
|
36
37
|
s.add_development_dependency 'guard', '~> 2.13', '>= 2.13'
|
data/img/parallel_demo-min.png
CHANGED
Binary file
|
@@ -28,15 +28,18 @@ require 'io/console'
|
|
28
28
|
|
29
29
|
# capistrano requirements
|
30
30
|
require 'rake'
|
31
|
-
require 'capistrano/all'
|
32
31
|
|
33
32
|
# fix error with not files that can not be found
|
34
33
|
Gem.find_files('composable_state_machine/**/*.rb').each { |path| require path }
|
35
34
|
|
36
|
-
%w(classes
|
35
|
+
%w(helpers classes celluloid core_ext).each do |folder_name|
|
37
36
|
Gem.find_files("capistrano_multiconfig_parallel/#{folder_name}/**/*.rb").each { |path| require path }
|
38
37
|
end
|
39
38
|
|
40
39
|
require_relative './version'
|
41
40
|
require_relative './base'
|
42
41
|
require_relative './application'
|
42
|
+
|
43
|
+
%w(initializers).each do |folder_name|
|
44
|
+
Gem.find_files("capistrano_multiconfig_parallel/#{folder_name}/**/*.rb").each { |path| require path }
|
45
|
+
end
|
@@ -5,7 +5,7 @@ module CapistranoMulticonfigParallel
|
|
5
5
|
include Celluloid::Logger
|
6
6
|
include CapistranoMulticonfigParallel::ApplicationHelper
|
7
7
|
|
8
|
-
attr_reader :stage_apps, :top_level_tasks, :jobs, :
|
8
|
+
attr_reader :stage_apps, :top_level_tasks, :jobs, :condition, :manager, :dependency_tracker, :application, :stage, :name, :args, :argv, :default_stage
|
9
9
|
|
10
10
|
def initialize
|
11
11
|
Celluloid.boot
|
@@ -47,12 +47,6 @@ module CapistranoMulticonfigParallel
|
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
|
-
def backup_the_branch
|
51
|
-
return if custom_command? || @argv['BRANCH'].blank?
|
52
|
-
@branch_backup = @argv['BRANCH'].to_s
|
53
|
-
@argv['BRANCH'] = nil
|
54
|
-
end
|
55
|
-
|
56
50
|
def custom_command?
|
57
51
|
if multi_apps?
|
58
52
|
!stages.include?(@top_level_tasks.first) && custom_commands.include?(@top_level_tasks.first)
|
@@ -91,8 +85,12 @@ module CapistranoMulticonfigParallel
|
|
91
85
|
@top_level_tasks.push(Rake.application.default_task_name) if @top_level_tasks.blank?
|
92
86
|
end
|
93
87
|
|
88
|
+
def action_key
|
89
|
+
capistrano_version_2? ? 'action' : 'ACTION'
|
90
|
+
end
|
91
|
+
|
94
92
|
def verify_options_custom_command(options)
|
95
|
-
options[:action] = @argv[
|
93
|
+
options[:action] = @argv[action_key].present? ? @argv[action_key] : 'deploy'
|
96
94
|
options
|
97
95
|
end
|
98
96
|
|
@@ -107,7 +105,6 @@ module CapistranoMulticonfigParallel
|
|
107
105
|
options = prepare_options(options)
|
108
106
|
options = options.stringify_keys
|
109
107
|
apps = @dependency_tracker.fetch_apps_needed_for_deployment(options['app'], options['action'])
|
110
|
-
backup_the_branch if multi_apps?
|
111
108
|
deploy_multiple_apps(apps, options)
|
112
109
|
deploy_app(options) if !custom_command? || !multi_apps?
|
113
110
|
end
|
@@ -126,8 +123,12 @@ module CapistranoMulticonfigParallel
|
|
126
123
|
find_loaded_gem('capistrano-gitflow').present?
|
127
124
|
end
|
128
125
|
|
126
|
+
def stages_key
|
127
|
+
capistrano_version_2? ? 'stages' : 'STAGES'
|
128
|
+
end
|
129
|
+
|
129
130
|
def fetch_multi_stages
|
130
|
-
custom_stages = @argv[
|
131
|
+
custom_stages = @argv[stages_key].blank? ? '' : @argv[stages_key]
|
131
132
|
custom_stages = strip_characters_from_string(custom_stages).split(',').compact if custom_stages.present?
|
132
133
|
custom_stages = custom_stages.present? ? custom_stages : [@default_stage]
|
133
134
|
custom_stages
|
@@ -147,9 +148,7 @@ module CapistranoMulticonfigParallel
|
|
147
148
|
|
148
149
|
def deploy_app(options = {})
|
149
150
|
options = options.stringify_keys
|
150
|
-
branch = @branch_backup.present? ? @branch_backup : @argv['BRANCH'].to_s
|
151
151
|
call_task_deploy_app({
|
152
|
-
branch: branch,
|
153
152
|
app: options['app'],
|
154
153
|
action: options['action']
|
155
154
|
}.reverse_merge(options))
|
@@ -178,12 +177,17 @@ module CapistranoMulticonfigParallel
|
|
178
177
|
process_jobs
|
179
178
|
end
|
180
179
|
|
180
|
+
def boxes_key
|
181
|
+
capistrano_version_2? ? 'box' : 'BOX'
|
182
|
+
end
|
183
|
+
|
181
184
|
def call_task_deploy_app(options = {})
|
182
185
|
options = options.stringify_keys
|
183
|
-
main_box_name = @argv[
|
186
|
+
main_box_name = @argv[boxes_key].blank? ? '' : @argv[boxes_key]
|
187
|
+
boxes = strip_characters_from_string(main_box_name).split(',').compact
|
184
188
|
stage = options.fetch('stage', @default_stage)
|
185
|
-
if configuration.development_stages.include?(stage) &&
|
186
|
-
execute_on_multiple_boxes(
|
189
|
+
if configuration.development_stages.include?(stage) && boxes.present?
|
190
|
+
execute_on_multiple_boxes(boxes, options)
|
187
191
|
else
|
188
192
|
prepare_job(options)
|
189
193
|
end
|
@@ -212,21 +216,19 @@ module CapistranoMulticonfigParallel
|
|
212
216
|
terminate
|
213
217
|
end
|
214
218
|
|
215
|
-
# rubocop:disable CyclomaticComplexity
|
216
219
|
def prepare_job(options)
|
217
220
|
options = options.stringify_keys
|
218
|
-
branch_name = options.fetch('branch', {})
|
219
221
|
app = options.fetch('app', '')
|
220
|
-
box = options['env_options'][
|
222
|
+
box = options['env_options'][boxes_key]
|
221
223
|
message = box.present? ? "BOX #{box}:" : "stage #{options['stage']}:"
|
222
224
|
env_opts = get_app_additional_env_options(app, message)
|
223
225
|
|
224
226
|
options['env_options'] = options['env_options'].reverse_merge(env_opts)
|
225
227
|
|
226
|
-
env_options =
|
227
|
-
job_env_options = custom_command?
|
228
|
+
env_options = options['env_options']
|
229
|
+
job_env_options = custom_command? ? env_options.except(action_key) : env_options
|
228
230
|
job = CapistranoMulticonfigParallel::Job.new(Actor.current, options.merge(
|
229
|
-
action: custom_command? && env_options[
|
231
|
+
action: custom_command? && env_options[action_key].present? ? env_options[action_key] : options['action'],
|
230
232
|
env_options: job_env_options
|
231
233
|
|
232
234
|
))
|
@@ -253,10 +255,9 @@ module CapistranoMulticonfigParallel
|
|
253
255
|
options
|
254
256
|
end
|
255
257
|
|
256
|
-
def execute_on_multiple_boxes(
|
257
|
-
boxes = strip_characters_from_string(main_box_name).split(',').compact
|
258
|
+
def execute_on_multiple_boxes(boxes, options)
|
258
259
|
boxes.each do |box_name|
|
259
|
-
options['env_options'][
|
260
|
+
options['env_options'][boxes_key] = box_name
|
260
261
|
prepare_job(options)
|
261
262
|
end
|
262
263
|
end
|
@@ -6,15 +6,28 @@ module CapistranoMulticonfigParallel
|
|
6
6
|
GITFLOW_VERIFY_UPTODATE_TASK = 'gitflow:verify_up_to_date'
|
7
7
|
|
8
8
|
class << self
|
9
|
-
attr_accessor :logger, :original_args
|
9
|
+
attr_accessor :logger, :original_args, :config, :config_keys
|
10
10
|
include CapistranoMulticonfigParallel::Configuration
|
11
|
-
include CapistranoMulticonfigParallel::
|
11
|
+
include CapistranoMulticonfigParallel::GemHelper
|
12
|
+
|
13
|
+
def configuration
|
14
|
+
@config ||= fetch_configuration
|
15
|
+
@config
|
16
|
+
end
|
12
17
|
|
13
18
|
def enable_logging
|
14
19
|
enable_file_logging
|
15
20
|
set_celluloid_exception_handling
|
16
21
|
end
|
17
22
|
|
23
|
+
def capistrano_version
|
24
|
+
find_loaded_gem_property('capistrano', 'version')
|
25
|
+
end
|
26
|
+
|
27
|
+
def capistrano_version_2?
|
28
|
+
verify_gem_version('capistrano', '3.0', operator: '<')
|
29
|
+
end
|
30
|
+
|
18
31
|
private
|
19
32
|
|
20
33
|
def set_celluloid_exception_handling
|
@@ -22,7 +35,7 @@ module CapistranoMulticonfigParallel
|
|
22
35
|
Celluloid.task_class = Celluloid::TaskThread
|
23
36
|
Celluloid.exception_handler do |ex|
|
24
37
|
unless ex.is_a?(Interrupt)
|
25
|
-
|
38
|
+
rescue_error(ex, 'stderr')
|
26
39
|
end
|
27
40
|
end
|
28
41
|
end
|
@@ -16,10 +16,12 @@ module CapistranoMulticonfigParallel
|
|
16
16
|
trap_exit :worker_died
|
17
17
|
|
18
18
|
def initialize(job_manager)
|
19
|
-
# start SupervisionGroup
|
20
|
-
@worker_supervisor = Celluloid::SupervisionGroup.run!
|
21
19
|
@job_manager = job_manager
|
22
20
|
@registration_complete = false
|
21
|
+
return if configuration.multi_secvential.to_s.downcase == 'true'
|
22
|
+
# start SupervisionGroup
|
23
|
+
@worker_supervisor = Celluloid::SupervisionGroup.run!
|
24
|
+
|
23
25
|
# Get a handle on the SupervisionGroup::Member
|
24
26
|
@mutex = Mutex.new
|
25
27
|
# http://rubydoc.info/gems/celluloid/Celluloid/SupervisionGroup/Member
|
@@ -80,7 +80,7 @@ module CapistranoMulticonfigParallel
|
|
80
80
|
elsif msg_for_stdin?(message)
|
81
81
|
stdin_approval(message)
|
82
82
|
else
|
83
|
-
show_warning "unknown
|
83
|
+
show_warning "unknown message: #{message.inspect}"
|
84
84
|
end
|
85
85
|
end
|
86
86
|
|
@@ -103,16 +103,16 @@ module CapistranoMulticonfigParallel
|
|
103
103
|
if @job_id == message['job_id']
|
104
104
|
@stdin_result = message.fetch('result', '')
|
105
105
|
else
|
106
|
-
show_warning "unknown
|
106
|
+
show_warning "unknown stdin_approval #{message.inspect}"
|
107
107
|
end
|
108
108
|
end
|
109
109
|
|
110
110
|
def task_approval(message)
|
111
111
|
return unless msg_for_task?(message)
|
112
|
-
if @job_id == message['job_id'] && message['task'] == task_name && message['approved'] == 'yes'
|
112
|
+
if @job_id == message['job_id'] && message['task'].to_s == task_name.to_s && message['approved'] == 'yes'
|
113
113
|
@task_approved = true
|
114
114
|
else
|
115
|
-
show_warning "unknown
|
115
|
+
show_warning "unknown task_approval #{message.inspect} #{task_data}"
|
116
116
|
end
|
117
117
|
end
|
118
118
|
|
@@ -14,7 +14,7 @@ module CapistranoMulticonfigParallel
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def filtered_env_keys
|
17
|
-
%w(STAGES ACTION)
|
17
|
+
filtered_env_keys_format(%w(STAGES ACTION))
|
18
18
|
end
|
19
19
|
|
20
20
|
def job_stage
|
@@ -27,15 +27,15 @@ module CapistranoMulticonfigParallel
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def env_option_filtered?(key, filtered_keys_array = [])
|
30
|
-
filtered_env_keys.include?(key) || filtered_keys_array.include?(key.to_s)
|
30
|
+
filtered_env_keys.include?(env_key_format(key)) || filtered_keys_array.include?(key.to_s)
|
31
31
|
end
|
32
32
|
|
33
33
|
def setup_env_options(options = {})
|
34
34
|
array_options = []
|
35
35
|
env_options.each do |key, value|
|
36
|
-
array_options << "#{key}=#{value}" if value.present? && !env_option_filtered?(key, options.fetch(:filtered_keys, []))
|
36
|
+
array_options << "#{env_prefix} #{env_key_format(key)}=#{value}" if value.present? && !env_option_filtered?(key, options.fetch(:filtered_keys, []))
|
37
37
|
end
|
38
|
-
array_options <<
|
38
|
+
array_options << trace_flag if app_debug_enabled?
|
39
39
|
array_options
|
40
40
|
end
|
41
41
|
|
@@ -45,8 +45,9 @@ module CapistranoMulticonfigParallel
|
|
45
45
|
end
|
46
46
|
|
47
47
|
def to_s
|
48
|
-
|
49
|
-
|
48
|
+
configuration_options = CapistranoMulticonfigParallel.original_args.select { |arg| arg.include?('--') }
|
49
|
+
environment_options = setup_command_line(configuration_options).join(' ')
|
50
|
+
"cd #{detect_root} && RAILS_ENV=#{stage} bundle exec multi_cap #{job_stage} #{capistrano_action} #{environment_options}"
|
50
51
|
end
|
51
52
|
|
52
53
|
def to_json
|
@@ -54,8 +55,7 @@ module CapistranoMulticonfigParallel
|
|
54
55
|
end
|
55
56
|
|
56
57
|
def execute_standard_deploy(action = nil)
|
57
|
-
|
58
|
-
run_shell_command(command)
|
58
|
+
run_shell_command(to_s)
|
59
59
|
rescue => ex
|
60
60
|
rescue_error(ex, 'stderr')
|
61
61
|
execute_standard_deploy('deploy:rollback') if action.blank? && @name == 'deploy'
|
@@ -1,17 +1,20 @@
|
|
1
1
|
require_relative '../celluloid/rake_worker'
|
2
2
|
require_relative './input_stream'
|
3
3
|
require_relative './output_stream'
|
4
|
+
require_relative '../helpers/application_helper'
|
4
5
|
module CapistranoMulticonfigParallel
|
5
6
|
# class used to handle the rake worker and sets all the hooks before and after running the worker
|
6
7
|
class RakeTaskHooks
|
7
|
-
|
8
|
-
|
8
|
+
include CapistranoMulticonfigParallel::ApplicationHelper
|
9
|
+
attr_accessor :task, :env, :config
|
10
|
+
def initialize(env, task, config = nil)
|
9
11
|
@env = env
|
10
12
|
@task = task
|
13
|
+
@config = config
|
11
14
|
end
|
12
15
|
|
13
16
|
def automatic_hooks(&block)
|
14
|
-
if job_id.present?
|
17
|
+
if configuration.multi_secvential.to_s.downcase == 'false' && job_id.present? && @task.present?
|
15
18
|
actor_start_working
|
16
19
|
actor.wait_execution until actor.task_approved
|
17
20
|
actor_execute_block(&block)
|
@@ -66,7 +69,7 @@ module CapistranoMulticonfigParallel
|
|
66
69
|
end
|
67
70
|
|
68
71
|
def job_id
|
69
|
-
@env[CapistranoMulticonfigParallel::ENV_KEY_JOB_ID]
|
72
|
+
capistrano_version_2? ? @config.fetch(CapistranoMulticonfigParallel::ENV_KEY_JOB_ID, nil) : @env[CapistranoMulticonfigParallel::ENV_KEY_JOB_ID]
|
70
73
|
end
|
71
74
|
|
72
75
|
def rake_actor_id
|
@@ -9,6 +9,7 @@ module CapistranoMulticonfigParallel
|
|
9
9
|
def start
|
10
10
|
before_start
|
11
11
|
arguments = multi_fetch_argv(original_args)
|
12
|
+
configuration_valid?
|
12
13
|
execute_start(arguments)
|
13
14
|
end
|
14
15
|
|
@@ -16,6 +17,17 @@ module CapistranoMulticonfigParallel
|
|
16
17
|
if arguments[CapistranoMulticonfigParallel::ENV_KEY_JOB_ID].blank?
|
17
18
|
run_the_application
|
18
19
|
else
|
20
|
+
ARGV.reject! { |arg| configuration.keys.map(&:to_s).include?(arg.split('=')[0].tr('--', '')) }
|
21
|
+
run_capistrano
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def run_capistrano
|
26
|
+
if capistrano_version_2?
|
27
|
+
require 'capistrano/cli'
|
28
|
+
Capistrano::CLI.execute
|
29
|
+
else
|
30
|
+
require 'capistrano/all'
|
19
31
|
Capistrano::Application.new.run
|
20
32
|
end
|
21
33
|
end
|
@@ -27,7 +39,6 @@ module CapistranoMulticonfigParallel
|
|
27
39
|
|
28
40
|
def run_the_application
|
29
41
|
execute_with_rescue('stderr') do
|
30
|
-
configuration_valid?
|
31
42
|
CapistranoMulticonfigParallel::Application.new.start
|
32
43
|
end
|
33
44
|
end
|
@@ -1,16 +1,24 @@
|
|
1
1
|
require_relative './core_helper'
|
2
2
|
require_relative './internal_helper'
|
3
3
|
require_relative './stages_helper'
|
4
|
+
require_relative './gem_helper'
|
5
|
+
require_relative './parse_helper'
|
6
|
+
require_relative './capistrano_helper'
|
4
7
|
module CapistranoMulticonfigParallel
|
5
8
|
# class that holds the options that are configurable for this gem
|
6
9
|
module ApplicationHelper
|
7
10
|
include CapistranoMulticonfigParallel::InternalHelper
|
8
11
|
include CapistranoMulticonfigParallel::CoreHelper
|
12
|
+
include CapistranoMulticonfigParallel::ParseHelper
|
9
13
|
include CapistranoMulticonfigParallel::StagesHelper
|
14
|
+
include CapistranoMulticonfigParallel::GemHelper
|
15
|
+
include CapistranoMulticonfigParallel::CapistranoHelper
|
10
16
|
|
11
17
|
delegate :logger,
|
12
18
|
:configuration,
|
13
19
|
:configuration_valid?,
|
20
|
+
:capistrano_version_2?,
|
21
|
+
:capistrano_version,
|
14
22
|
:original_args,
|
15
23
|
to: :CapistranoMulticonfigParallel
|
16
24
|
|
@@ -40,10 +48,6 @@ module CapistranoMulticonfigParallel
|
|
40
48
|
string.scan(/.{#{options.fetch('length', 80)}}|.+/).map(&:strip).join(options.fetch('character', $INPUT_RECORD_SEPARATOR))
|
41
49
|
end
|
42
50
|
|
43
|
-
def find_loaded_gem(name)
|
44
|
-
Gem.loaded_specs.values.find { |repo| repo.name == name }
|
45
|
-
end
|
46
|
-
|
47
51
|
def percent_of(index, total)
|
48
52
|
index.to_f / total.to_f * 100.0
|
49
53
|
end
|
@@ -62,44 +66,6 @@ module CapistranoMulticonfigParallel
|
|
62
66
|
result.present? && result.downcase == 'y'
|
63
67
|
end
|
64
68
|
|
65
|
-
def check_numeric(num)
|
66
|
-
/^[0-9]+/.match(num.to_s)
|
67
|
-
end
|
68
|
-
|
69
|
-
def verify_empty_options(options)
|
70
|
-
if options.is_a?(Hash)
|
71
|
-
options.reject { |_key, value| value.blank? }
|
72
|
-
elsif options.is_a?(Array)
|
73
|
-
options.reject(&:blank?)
|
74
|
-
else
|
75
|
-
options
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
def verify_array_of_strings(value)
|
80
|
-
value.reject(&:blank?)
|
81
|
-
warn_array_without_strings(value)
|
82
|
-
end
|
83
|
-
|
84
|
-
def warn_array_without_strings(value)
|
85
|
-
raise ArgumentError, 'the array must contain only task names' if value.find { |row| !row.is_a?(String) }
|
86
|
-
end
|
87
|
-
|
88
|
-
def check_hash_set(hash, props)
|
89
|
-
!Set.new(props).subset?(hash.keys.to_set) || hash.values.find(&:blank?).present?
|
90
|
-
end
|
91
|
-
|
92
|
-
def value_is_array?(value)
|
93
|
-
value.present? && value.is_a?(Array)
|
94
|
-
end
|
95
|
-
|
96
|
-
def strip_characters_from_string(value)
|
97
|
-
return '' if value.blank?
|
98
|
-
value = value.delete("\r\n").delete("\n")
|
99
|
-
value = value.gsub(/\s+/, ' ').strip
|
100
|
-
value
|
101
|
-
end
|
102
|
-
|
103
69
|
def regex_last_match(number)
|
104
70
|
Regexp.last_match(number)
|
105
71
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module CapistranoMulticonfigParallel
|
2
|
+
# helper methods used for capistrano actions
|
3
|
+
module CapistranoHelper
|
4
|
+
module_function
|
5
|
+
|
6
|
+
def filtered_env_keys_format(keys)
|
7
|
+
capistrano_version_2? ? keys.map(&:downcase) : keys
|
8
|
+
end
|
9
|
+
|
10
|
+
def env_prefix
|
11
|
+
capistrano_version_2? ? '-S' : ''
|
12
|
+
end
|
13
|
+
|
14
|
+
def env_key_format(key)
|
15
|
+
capistrano_version_2? ? key.downcase : key
|
16
|
+
end
|
17
|
+
|
18
|
+
def trace_flag
|
19
|
+
capistrano_version_2? ? '--debug' : '--trace'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -1,96 +1,95 @@
|
|
1
|
-
require_relative './
|
1
|
+
require_relative './core_helper'
|
2
|
+
require_relative './internal_helper'
|
3
|
+
require_relative './parse_helper'
|
2
4
|
module CapistranoMulticonfigParallel
|
3
5
|
# class that holds the options that are configurable for this gem
|
4
6
|
module Configuration
|
5
|
-
|
7
|
+
include CapistranoMulticonfigParallel::CoreHelper
|
8
|
+
include CapistranoMulticonfigParallel::InternalHelper
|
9
|
+
include CapistranoMulticonfigParallel::ParseHelper
|
6
10
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
@config ||= fetch_configuration
|
13
|
-
@config
|
14
|
-
end
|
15
|
-
|
16
|
-
def fetch_configuration
|
17
|
-
@fetched_config = Configliere::Param.new
|
18
|
-
setup_default_config
|
19
|
-
setup_configuration
|
20
|
-
end
|
11
|
+
def fetch_configuration
|
12
|
+
@fetched_config = Configliere::Param.new
|
13
|
+
setup_default_config
|
14
|
+
setup_configuration
|
15
|
+
end
|
21
16
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
end
|
17
|
+
def setup_default_config
|
18
|
+
default_internal_config.each do |array_param|
|
19
|
+
@fetched_config.define array_param[0], array_param[1].symbolize_keys
|
26
20
|
end
|
21
|
+
end
|
27
22
|
|
28
|
-
|
29
|
-
|
30
|
-
|
23
|
+
def setup_configuration
|
24
|
+
@fetched_config.read config_file if File.file?(config_file)
|
25
|
+
@fetched_config.use :commandline
|
31
26
|
|
32
|
-
|
33
|
-
|
34
|
-
|
27
|
+
@fetched_config.use :config_block
|
28
|
+
validate_configuration
|
29
|
+
end
|
35
30
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
check_configuration
|
40
|
-
end
|
41
|
-
@fetched_config.process_argv!
|
42
|
-
@fetched_config.resolve!
|
31
|
+
def validate_configuration
|
32
|
+
@fetched_config.finally do |config|
|
33
|
+
check_configuration(config)
|
43
34
|
end
|
35
|
+
@fetched_config.process_argv!
|
36
|
+
@fetched_config.resolve!
|
37
|
+
@fetched_config
|
38
|
+
end
|
44
39
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
40
|
+
def verify_application_dependencies(value, props)
|
41
|
+
return unless value.is_a?(Array)
|
42
|
+
value.reject { |val| val.blank? || !val.is_a?(Hash) }
|
43
|
+
wrong = check_array_of_hash(value, props.map(&:to_sym))
|
44
|
+
raise ArgumentError, "invalid configuration for #{wrong.inspect}" if wrong.present?
|
45
|
+
end
|
51
46
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
end
|
47
|
+
def check_array_of_hash(value, props)
|
48
|
+
value.find do|hash|
|
49
|
+
check_hash_set(hash, props)
|
56
50
|
end
|
51
|
+
end
|
57
52
|
|
58
|
-
|
59
|
-
|
60
|
-
|
53
|
+
def check_boolean(prop)
|
54
|
+
value = get_prop_config(prop)
|
55
|
+
if %w(true false).include?(value.to_s.downcase)
|
56
|
+
true
|
57
|
+
else
|
58
|
+
raise ArgumentError, "the property `#{prop}` must be boolean"
|
61
59
|
end
|
60
|
+
end
|
62
61
|
|
63
|
-
|
64
|
-
|
65
|
-
|
62
|
+
def configuration_valid?
|
63
|
+
configuration
|
64
|
+
end
|
66
65
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
end
|
66
|
+
def check_boolean_props(props)
|
67
|
+
props.each do |prop|
|
68
|
+
@check_config[prop] = get_prop_config(prop) if check_boolean(prop)
|
71
69
|
end
|
70
|
+
end
|
72
71
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
end
|
72
|
+
def check_array_props(props)
|
73
|
+
props.each do |prop|
|
74
|
+
value = get_prop_config(prop)
|
75
|
+
@check_config[prop] = value if value_is_array?(value) && verify_array_of_strings(value)
|
78
76
|
end
|
77
|
+
end
|
79
78
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
end
|
79
|
+
def get_prop_config(prop)
|
80
|
+
config = @check_config
|
81
|
+
if prop.include?('.')
|
82
|
+
multi_level_prop(config, prop)
|
83
|
+
else
|
84
|
+
config[prop]
|
87
85
|
end
|
86
|
+
end
|
88
87
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
88
|
+
def check_configuration(config)
|
89
|
+
@check_config = config.stringify_keys
|
90
|
+
check_boolean_props(%w(multi_debug multi_secvential websocket_server.enable_debug websocket_server.use_redis terminal.clear_screen))
|
91
|
+
check_array_props(%w(task_confirmations development_stages apply_stage_confirmation))
|
92
|
+
verify_application_dependencies(@check_config['application_dependencies'], %w(app priority dependencies))
|
94
93
|
end
|
95
94
|
end
|
96
95
|
end
|
@@ -52,10 +52,14 @@ module CapistranoMulticonfigParallel
|
|
52
52
|
Celluloid::Actor[:terminal_server]
|
53
53
|
end
|
54
54
|
|
55
|
+
def terminal_errors?
|
56
|
+
terminal_actor.present? && terminal_actor.alive? && terminal_actor.errors.is_a?(Array)
|
57
|
+
end
|
58
|
+
|
55
59
|
def log_output_error(error, output, message)
|
56
60
|
return if error_filtered?(error)
|
57
61
|
puts message if output.present?
|
58
|
-
terminal_actor.errors.push(message) if
|
62
|
+
terminal_actor.errors.push(message) if terminal_errors?
|
59
63
|
end
|
60
64
|
|
61
65
|
def format_error(exception)
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module CapistranoMulticonfigParallel
|
2
|
+
# helper used to determine gem versions
|
3
|
+
module GemHelper
|
4
|
+
module_function
|
5
|
+
|
6
|
+
def find_loaded_gem(name)
|
7
|
+
Gem.loaded_specs.values.find { |repo| repo.name == name }
|
8
|
+
end
|
9
|
+
|
10
|
+
def find_loaded_gem_property(gem_name, property = 'version')
|
11
|
+
gem_spec = find_loaded_gem(gem_name)
|
12
|
+
gem_spec.respond_to?(property) ? gem_spec.send(property) : nil
|
13
|
+
end
|
14
|
+
|
15
|
+
def fetch_gem_version(gem_name)
|
16
|
+
version = find_loaded_gem_property(gem_name)
|
17
|
+
version.blank? ? nil : get_parsed_version(version)
|
18
|
+
end
|
19
|
+
|
20
|
+
def get_parsed_version(version)
|
21
|
+
version = version.to_s.split('.')
|
22
|
+
version.pop until version.size == 2
|
23
|
+
version.join('.').to_f
|
24
|
+
end
|
25
|
+
|
26
|
+
def verify_gem_version(gem_name, version, options = {})
|
27
|
+
options.stringify_keys!
|
28
|
+
version = get_parsed_version(version)
|
29
|
+
gem_version = fetch_gem_version(gem_name)
|
30
|
+
gem_version.blank? ? false : gem_version.send(options.fetch('operator', '<='), version)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module CapistranoMulticonfigParallel
|
2
|
+
# module used for parsing numbers, strings , arrays and hashes
|
3
|
+
module ParseHelper
|
4
|
+
module_function
|
5
|
+
|
6
|
+
def check_numeric(num)
|
7
|
+
/^[0-9]+/.match(num.to_s)
|
8
|
+
end
|
9
|
+
|
10
|
+
def verify_empty_options(options)
|
11
|
+
if options.is_a?(Hash)
|
12
|
+
options.reject { |_key, value| value.blank? }
|
13
|
+
elsif options.is_a?(Array)
|
14
|
+
options.reject(&:blank?)
|
15
|
+
else
|
16
|
+
options
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def verify_array_of_strings(value)
|
21
|
+
value = verify_empty_options(value)
|
22
|
+
value.find { |row| !row.is_a?(String) }.present? ? warn_array_without_strings(value) : true
|
23
|
+
end
|
24
|
+
|
25
|
+
def warn_array_without_strings(value)
|
26
|
+
raise ArgumentError, "the array #{value} must contain only task names"
|
27
|
+
end
|
28
|
+
|
29
|
+
def check_hash_set(hash, props)
|
30
|
+
!Set.new(props).subset?(hash.keys.to_set) || hash.values.find(&:blank?).present?
|
31
|
+
end
|
32
|
+
|
33
|
+
def value_is_array?(value)
|
34
|
+
value.present? && value.is_a?(Array)
|
35
|
+
end
|
36
|
+
|
37
|
+
def strip_characters_from_string(value)
|
38
|
+
return '' if value.blank?
|
39
|
+
value = value.delete("\r\n").delete("\n")
|
40
|
+
value = value.gsub(/\s+/, ' ').strip
|
41
|
+
value
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
if CapistranoMulticonfigParallel.capistrano_version_2?
|
2
|
+
require 'capistrano/cli'
|
3
|
+
Capistrano::Configuration::Execution.class_eval do
|
4
|
+
alias_method :original_execute_task, :execute_task
|
5
|
+
|
6
|
+
def execute_task(task)
|
7
|
+
rake = CapistranoMulticonfigParallel::RakeTaskHooks.new(ENV, task, self)
|
8
|
+
rake.automatic_hooks do
|
9
|
+
original_execute_task(task)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
Capistrano::Configuration::Callbacks.class_eval do
|
15
|
+
alias_method :original_trigger, :trigger
|
16
|
+
|
17
|
+
def trigger(event, task = nil)
|
18
|
+
rake = CapistranoMulticonfigParallel::RakeTaskHooks.new(ENV, task, self)
|
19
|
+
rake.automatic_hooks do
|
20
|
+
original_trigger(event, task)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
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: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- bogdanRada
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-01-
|
11
|
+
date: 2016-01-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: celluloid-pmap
|
@@ -174,22 +174,16 @@ dependencies:
|
|
174
174
|
name: capistrano
|
175
175
|
requirement: !ruby/object:Gem::Requirement
|
176
176
|
requirements:
|
177
|
-
- - "~>"
|
178
|
-
- !ruby/object:Gem::Version
|
179
|
-
version: '3.0'
|
180
177
|
- - ">="
|
181
178
|
- !ruby/object:Gem::Version
|
182
|
-
version: '
|
179
|
+
version: '2.0'
|
183
180
|
type: :runtime
|
184
181
|
prerelease: false
|
185
182
|
version_requirements: !ruby/object:Gem::Requirement
|
186
183
|
requirements:
|
187
|
-
- - "~>"
|
188
|
-
- !ruby/object:Gem::Version
|
189
|
-
version: '3.0'
|
190
184
|
- - ">="
|
191
185
|
- !ruby/object:Gem::Version
|
192
|
-
version: '
|
186
|
+
version: '2.0'
|
193
187
|
- !ruby/object:Gem::Dependency
|
194
188
|
name: activesupport
|
195
189
|
requirement: !ruby/object:Gem::Requirement
|
@@ -290,6 +284,26 @@ dependencies:
|
|
290
284
|
- - ">="
|
291
285
|
- !ruby/object:Gem::Version
|
292
286
|
version: '1.6'
|
287
|
+
- !ruby/object:Gem::Dependency
|
288
|
+
name: rake
|
289
|
+
requirement: !ruby/object:Gem::Requirement
|
290
|
+
requirements:
|
291
|
+
- - "~>"
|
292
|
+
- !ruby/object:Gem::Version
|
293
|
+
version: '10.4'
|
294
|
+
- - ">="
|
295
|
+
- !ruby/object:Gem::Version
|
296
|
+
version: '10.4'
|
297
|
+
type: :runtime
|
298
|
+
prerelease: false
|
299
|
+
version_requirements: !ruby/object:Gem::Requirement
|
300
|
+
requirements:
|
301
|
+
- - "~>"
|
302
|
+
- !ruby/object:Gem::Version
|
303
|
+
version: '10.4'
|
304
|
+
- - ">="
|
305
|
+
- !ruby/object:Gem::Version
|
306
|
+
version: '10.4'
|
293
307
|
- !ruby/object:Gem::Dependency
|
294
308
|
name: rspec-rails
|
295
309
|
requirement: !ruby/object:Gem::Requirement
|
@@ -659,10 +673,14 @@ files:
|
|
659
673
|
- lib/capistrano_multiconfig_parallel/cli.rb
|
660
674
|
- lib/capistrano_multiconfig_parallel/configuration/default.yml
|
661
675
|
- lib/capistrano_multiconfig_parallel/helpers/application_helper.rb
|
676
|
+
- lib/capistrano_multiconfig_parallel/helpers/capistrano_helper.rb
|
662
677
|
- lib/capistrano_multiconfig_parallel/helpers/configuration.rb
|
663
678
|
- lib/capistrano_multiconfig_parallel/helpers/core_helper.rb
|
679
|
+
- lib/capistrano_multiconfig_parallel/helpers/gem_helper.rb
|
664
680
|
- lib/capistrano_multiconfig_parallel/helpers/internal_helper.rb
|
681
|
+
- lib/capistrano_multiconfig_parallel/helpers/parse_helper.rb
|
665
682
|
- lib/capistrano_multiconfig_parallel/helpers/stages_helper.rb
|
683
|
+
- lib/capistrano_multiconfig_parallel/initializers/capistrano2.rb
|
666
684
|
- lib/capistrano_multiconfig_parallel/initializers/rake.rb
|
667
685
|
- lib/capistrano_multiconfig_parallel/initializers/websocket.rb
|
668
686
|
- lib/capistrano_multiconfig_parallel/version.rb
|