capistrano_multiconfig_parallel 1.0.7 → 1.1.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 +52 -3
- data/capistrano_multiconfig_parallel.gemspec +0 -3
- data/lib/capistrano_multiconfig_parallel/application.rb +18 -26
- data/lib/capistrano_multiconfig_parallel/base.rb +1 -1
- data/lib/capistrano_multiconfig_parallel/celluloid/celluloid_manager.rb +7 -2
- data/lib/capistrano_multiconfig_parallel/celluloid/state_machine.rb +1 -1
- data/lib/capistrano_multiconfig_parallel/classes/dependency_tracker.rb +7 -4
- data/lib/capistrano_multiconfig_parallel/classes/job.rb +5 -3
- data/lib/capistrano_multiconfig_parallel/classes/job_command.rb +37 -9
- data/lib/capistrano_multiconfig_parallel/configuration/default.yml +16 -0
- data/lib/capistrano_multiconfig_parallel/helpers/application_helper.rb +1 -2
- data/lib/capistrano_multiconfig_parallel/helpers/capistrano_helper.rb +8 -8
- data/lib/capistrano_multiconfig_parallel/helpers/configuration.rb +18 -3
- data/lib/capistrano_multiconfig_parallel/helpers/gem_helper.rb +3 -1
- data/lib/capistrano_multiconfig_parallel/helpers/internal_helper.rb +2 -5
- data/lib/capistrano_multiconfig_parallel/helpers/stages_helper.rb +34 -9
- data/lib/capistrano_multiconfig_parallel/version.rb +2 -2
- metadata +2 -62
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 50bc1ddfa761688a5fd56d8eaf83da2e9a632056
|
4
|
+
data.tar.gz: f3a60a12be7b53b63947b199154c6fc20c40c729
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a253a2b2d5e22482b69b9ff2aa7f4a8051cddaacffe45a60e580e16e5d6a25460557d00dee87fbebbcc4af261264102d4e83771afab11949a4281802d161339b
|
7
|
+
data.tar.gz: 95db1686f2850e55b7650e4caec8757aabdc3b79834de84220909ec2b92897eff153a26aedbb4c6d2597dfb538380d0be0f792874bbedde4b67cfda961e56b45
|
data/README.md
CHANGED
@@ -17,6 +17,12 @@ 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.1.0
|
21
|
+
---------------------------------
|
22
|
+
|
23
|
+
- a lot of refactoring and bug fixes
|
24
|
+
- added posibility to run the deployments from a single directory and is described at section **[2.2) Deploying multiple applications from a central location](#22-deploying-multiple-applications-from-a-central-location)**
|
25
|
+
|
20
26
|
NEW Improvements in version 1.0.5
|
21
27
|
---------------------------------
|
22
28
|
|
@@ -169,11 +175,11 @@ bundle exec multi_cap <development_stage> <task_name> BOX=<box_name>,<box_nam
|
|
169
175
|
|
170
176
|
```
|
171
177
|
|
172
|
-
For Capistrano 2
|
178
|
+
For Capistrano 2 application, the jobs will receive **-S box=<box_name>,<box_name>**, although you will use **BOX** when running the command. This so that i can maintain compatibility between versions
|
173
179
|
|
174
180
|
The script will ask if there are any other environment variables that user might want to pass to each of the sandboxes separately.
|
175
181
|
|
176
|
-
### 1
|
182
|
+
### 2.1) Deploying the application to multiple stages ( Using the customized command "deploy_multi_stages")
|
177
183
|
|
178
184
|
```shell
|
179
185
|
|
@@ -221,7 +227,7 @@ bundle exec multi_cap foo2:development deploy
|
|
221
227
|
|
222
228
|
Will ask user if he wants to deploy the apps "foo" and "bar" , since they appear in the dependencies list for the application "foo2"
|
223
229
|
|
224
|
-
### 1
|
230
|
+
### 2.1) Deploying multiple application to multiple stages ( Using the customized command "deploy_multi_stages")
|
225
231
|
|
226
232
|
```shell
|
227
233
|
|
@@ -238,6 +244,49 @@ The script will ask for additional ENV options for each stage.
|
|
238
244
|
|
239
245
|
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
|
240
246
|
|
247
|
+
### 2.2) [Deploying multiple applications from a central location](#deploy-from-central-location)
|
248
|
+
|
249
|
+
This works like described in section **[2) Multiple applications](#2-multiple-apps--like-caphub-)** ), but now the **application_dependencies** Array can also have a **path** key inside each item that should point to the DocumentRoot of that application, and the configuration now accepts two new arguments **config_dir** ( this should point to the directory where the file **multi_cap.yml** resides) and **log_dir**( this can be used if you want your logs created in different directory)
|
250
|
+
|
251
|
+
This will only work if all applications listed in the configuration file have the gem **capistrano_multiconfig_parallel** as part of their Gemfile.
|
252
|
+
|
253
|
+
Example of configuration: - create a directory anywhere (e.g.**mkdir /tmp/app**\) - create a Gemfile and add only this two lines:
|
254
|
+
|
255
|
+
```ruby
|
256
|
+
source 'http://rubygems.org'
|
257
|
+
|
258
|
+
gem 'capistrano_multiconfig_parallel'
|
259
|
+
```
|
260
|
+
|
261
|
+
Then create a file called **multi_cap.yml** in the root folder and create a configuration like this.
|
262
|
+
|
263
|
+
```yaml
|
264
|
+
---
|
265
|
+
application_dependencies:
|
266
|
+
- app: foo'
|
267
|
+
priority: 1
|
268
|
+
path: /some/path/to/foo
|
269
|
+
dependencies: []
|
270
|
+
- app: bar
|
271
|
+
priority: 1
|
272
|
+
path: /some/path/to/bar
|
273
|
+
dependencies:
|
274
|
+
- foo
|
275
|
+
- app: foo2
|
276
|
+
priority: 1
|
277
|
+
path: /some/path/to/foo2
|
278
|
+
dependencies:
|
279
|
+
- foo
|
280
|
+
- bar
|
281
|
+
---
|
282
|
+
```
|
283
|
+
|
284
|
+
and then you can run like you would normally do
|
285
|
+
|
286
|
+
```shell
|
287
|
+
bundle exec multi_cap foo2:development deploy
|
288
|
+
```
|
289
|
+
|
241
290
|
Known Limitations
|
242
291
|
-----------------
|
243
292
|
|
@@ -34,8 +34,6 @@ Gem::Specification.new do |s|
|
|
34
34
|
s.add_runtime_dependency 'rake', '~> 10.4', '>= 10.4'
|
35
35
|
|
36
36
|
s.add_development_dependency 'rspec-rails', '~> 3.3', '>= 3.3'
|
37
|
-
s.add_development_dependency 'guard', '~> 2.13', '>= 2.13'
|
38
|
-
s.add_development_dependency 'guard-rspec', '~> 4.6', '>= 4.6'
|
39
37
|
s.add_development_dependency 'simplecov', '~> 0.10', '>= 0.10'
|
40
38
|
s.add_development_dependency 'simplecov-summary', '~> 0.0.4', '>= 0.0.4'
|
41
39
|
s.add_development_dependency 'mocha', '~> 1.1', '>= 1.1'
|
@@ -49,5 +47,4 @@ Gem::Specification.new do |s|
|
|
49
47
|
s.add_development_dependency 'redcarpet', '~> 3.3', '>= 3.3'
|
50
48
|
s.add_development_dependency 'github-markup', '~> 1.3', '>= 1.3.3'
|
51
49
|
s.add_development_dependency 'inch', '~> 0.6', '>= 0.6'
|
52
|
-
s.add_development_dependency 'guard-inch', '~> 0.1', '>= 0.1.0'
|
53
50
|
end
|
@@ -10,7 +10,7 @@ module CapistranoMulticonfigParallel
|
|
10
10
|
def initialize
|
11
11
|
Celluloid.boot
|
12
12
|
CapistranoMulticonfigParallel.enable_logging
|
13
|
-
@stage_apps = multi_apps? ?
|
13
|
+
@stage_apps = multi_apps? ? app_names_from_stages : []
|
14
14
|
collect_command_line_tasks(CapistranoMulticonfigParallel.original_args)
|
15
15
|
@jobs = []
|
16
16
|
end
|
@@ -33,7 +33,6 @@ module CapistranoMulticonfigParallel
|
|
33
33
|
def run_custom_command(options)
|
34
34
|
custom_stages = fetch_multi_stages
|
35
35
|
return if custom_stages.blank?
|
36
|
-
custom_stages = check_multi_stages(custom_stages)
|
37
36
|
custom_stages.each do |stage|
|
38
37
|
collect_jobs(options.merge('stage' => stage))
|
39
38
|
end
|
@@ -43,7 +42,7 @@ module CapistranoMulticonfigParallel
|
|
43
42
|
options = options.stringify_keys
|
44
43
|
return unless applications.present?
|
45
44
|
applications.each do |app|
|
46
|
-
deploy_app(options.merge('app' => app['app']))
|
45
|
+
deploy_app(options.merge('app' => app['app'], 'path' => app.fetch('path', nil)))
|
47
46
|
end
|
48
47
|
end
|
49
48
|
|
@@ -51,12 +50,8 @@ module CapistranoMulticonfigParallel
|
|
51
50
|
custom_commands.include?(@top_level_tasks.first)
|
52
51
|
end
|
53
52
|
|
54
|
-
def multi_apps?
|
55
|
-
stages.find { |stage| stage.include?(':') }.present?
|
56
|
-
end
|
57
|
-
|
58
53
|
def verify_valid_data
|
59
|
-
return
|
54
|
+
return if @top_level_tasks != ['default']
|
60
55
|
puts 'Invalid execution, please call something such as `multi_cap production deploy`, where production is a stage you have defined'.red
|
61
56
|
exit(false)
|
62
57
|
end
|
@@ -82,7 +77,7 @@ module CapistranoMulticonfigParallel
|
|
82
77
|
end
|
83
78
|
|
84
79
|
def action_key
|
85
|
-
|
80
|
+
'ACTION'
|
86
81
|
end
|
87
82
|
|
88
83
|
def verify_options_custom_command(options)
|
@@ -100,9 +95,9 @@ module CapistranoMulticonfigParallel
|
|
100
95
|
def collect_jobs(options = {}, &_block)
|
101
96
|
options = prepare_options(options)
|
102
97
|
options = options.stringify_keys
|
103
|
-
apps = @dependency_tracker.fetch_apps_needed_for_deployment(options['app'], options['action'])
|
98
|
+
apps, app_options = @dependency_tracker.fetch_apps_needed_for_deployment(options['app'], options['action'])
|
104
99
|
deploy_multiple_apps(apps, options)
|
105
|
-
deploy_app(options) if !custom_command? || !multi_apps?
|
100
|
+
deploy_app(options.merge(app_options)) if !custom_command? || !multi_apps?
|
106
101
|
end
|
107
102
|
|
108
103
|
def process_jobs
|
@@ -116,11 +111,11 @@ module CapistranoMulticonfigParallel
|
|
116
111
|
end
|
117
112
|
|
118
113
|
def tag_staging_exists? # check exists task from capistrano-gitflow
|
119
|
-
|
114
|
+
@jobs.find(&:gitflow).present?
|
120
115
|
end
|
121
116
|
|
122
117
|
def stages_key
|
123
|
-
|
118
|
+
'STAGES'
|
124
119
|
end
|
125
120
|
|
126
121
|
def fetch_multi_stages
|
@@ -135,11 +130,7 @@ module CapistranoMulticonfigParallel
|
|
135
130
|
end
|
136
131
|
|
137
132
|
def can_tag_staging?
|
138
|
-
wants_deploy_production? &&
|
139
|
-
end
|
140
|
-
|
141
|
-
def check_multi_stages(custom_stages)
|
142
|
-
can_tag_staging? ? custom_stages.reject { |u| u == 'production' } : custom_stages
|
133
|
+
wants_deploy_production? && fetch_multi_stages.include?('staging')
|
143
134
|
end
|
144
135
|
|
145
136
|
def deploy_app(options = {})
|
@@ -158,10 +149,6 @@ module CapistranoMulticonfigParallel
|
|
158
149
|
fetch_app_additional_env_options(app_additional_env_options)
|
159
150
|
end
|
160
151
|
|
161
|
-
def worker_environments
|
162
|
-
@jobs.map(&:stage)
|
163
|
-
end
|
164
|
-
|
165
152
|
def run
|
166
153
|
options = {}
|
167
154
|
if custom_command?
|
@@ -174,7 +161,7 @@ module CapistranoMulticonfigParallel
|
|
174
161
|
end
|
175
162
|
|
176
163
|
def boxes_key
|
177
|
-
|
164
|
+
'BOX'
|
178
165
|
end
|
179
166
|
|
180
167
|
def call_task_deploy_app(options = {})
|
@@ -194,7 +181,7 @@ module CapistranoMulticonfigParallel
|
|
194
181
|
@jobs.pmap do |job|
|
195
182
|
@manager.async.delegate_job(job)
|
196
183
|
end
|
197
|
-
unless can_tag_staging?
|
184
|
+
unless can_tag_staging? && tag_staging_exists?
|
198
185
|
until @manager.registration_complete
|
199
186
|
sleep(0.1) # keep current thread alive
|
200
187
|
end
|
@@ -225,10 +212,15 @@ module CapistranoMulticonfigParallel
|
|
225
212
|
job_env_options = custom_command? ? env_options.except(action_key) : env_options
|
226
213
|
job = CapistranoMulticonfigParallel::Job.new(Actor.current, options.merge(
|
227
214
|
action: custom_command? && env_options[action_key].present? ? env_options[action_key] : options['action'],
|
228
|
-
env_options: job_env_options
|
215
|
+
env_options: job_env_options,
|
216
|
+
path: options.fetch('path', nil)
|
229
217
|
|
230
218
|
))
|
231
|
-
@jobs << job
|
219
|
+
@jobs << job unless job_can_tag_staging?(job)
|
220
|
+
end
|
221
|
+
|
222
|
+
def job_can_tag_staging?(job)
|
223
|
+
can_tag_staging? && job.stage == 'production' && job.gitflow.present?
|
232
224
|
end
|
233
225
|
|
234
226
|
def prepare_options(options)
|
@@ -74,11 +74,16 @@ module CapistranoMulticonfigParallel
|
|
74
74
|
end
|
75
75
|
wait_task_confirmations
|
76
76
|
end
|
77
|
+
terminal_show
|
77
78
|
condition = @workers_terminated.wait
|
78
79
|
until condition.present?
|
79
80
|
sleep(0.1) # keep current thread alive
|
80
81
|
end
|
81
82
|
log_to_file("all jobs have completed #{condition}")
|
83
|
+
terminal_show
|
84
|
+
end
|
85
|
+
|
86
|
+
def terminal_show
|
82
87
|
Celluloid::Actor[:terminal_server].async.notify_time_change(CapistranoMulticonfigParallel::TerminalTable.topic, type: 'output') if Celluloid::Actor[:terminal_server].alive?
|
83
88
|
end
|
84
89
|
|
@@ -88,7 +93,7 @@ module CapistranoMulticonfigParallel
|
|
88
93
|
end
|
89
94
|
|
90
95
|
def syncronized_confirmation?
|
91
|
-
|
96
|
+
!can_tag_staging?
|
92
97
|
end
|
93
98
|
|
94
99
|
def apply_confirmation_for_job(job)
|
@@ -188,7 +193,7 @@ module CapistranoMulticonfigParallel
|
|
188
193
|
end
|
189
194
|
|
190
195
|
def can_tag_staging?
|
191
|
-
@job_manager.can_tag_staging? &&
|
196
|
+
@job_manager.can_tag_staging? && @job_manager.tag_staging_exists? &&
|
192
197
|
@jobs.find { |_job_id, job| job.stage == 'production' }.blank?
|
193
198
|
end
|
194
199
|
|
@@ -45,7 +45,7 @@ module CapistranoMulticonfigParallel
|
|
45
45
|
private
|
46
46
|
|
47
47
|
def actor_notify_state_change(current_state, event, new_state)
|
48
|
-
@actor.send_msg(CapistranoMulticonfigParallel::TerminalTable.topic, type: 'event', message: "Going from #{current_state} to #{new_state} due to a #{event} event")
|
48
|
+
@actor.send_msg(CapistranoMulticonfigParallel::TerminalTable.topic, type: 'event', new_state: new_state, message: "Going from #{current_state} to #{new_state} due to a #{event} event")
|
49
49
|
end
|
50
50
|
end
|
51
51
|
end
|
@@ -11,7 +11,7 @@ module CapistranoMulticonfigParallel
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def fetch_apps_needed_for_deployment(application, action)
|
14
|
-
return [] unless @job_manager.multi_apps?
|
14
|
+
return [[], {}] unless @job_manager.multi_apps?
|
15
15
|
if @job_manager.custom_command?
|
16
16
|
show_interactive_menu(action)
|
17
17
|
else
|
@@ -22,14 +22,17 @@ module CapistranoMulticonfigParallel
|
|
22
22
|
private
|
23
23
|
|
24
24
|
def fetch_application_dependencies(application, action)
|
25
|
-
return [] if configuration.application_dependencies.blank? || application.blank?
|
25
|
+
return [[], {}] if configuration.application_dependencies.blank? || application.blank?
|
26
26
|
applications = get_applications_to_deploy(action, [application.camelcase])
|
27
|
+
app_options = applications.find { |hash| hash['app'] == application }.dup
|
27
28
|
applications.delete_if { |hash| hash['app'] == application }
|
29
|
+
[applications, app_options]
|
28
30
|
end
|
29
31
|
|
30
32
|
def show_interactive_menu(action)
|
31
33
|
apps_selected = CapistranoMulticonfigParallel::InteractiveMenu.new(available_apps).fetch_menu
|
32
|
-
get_applications_to_deploy(action, apps_selected)
|
34
|
+
apps = get_applications_to_deploy(action, apps_selected)
|
35
|
+
[apps, {}]
|
33
36
|
end
|
34
37
|
|
35
38
|
def application_dependencies
|
@@ -103,7 +106,7 @@ module CapistranoMulticonfigParallel
|
|
103
106
|
if action_confirmed?(apps_deploy_confirmation)
|
104
107
|
return applications_to_deploy
|
105
108
|
else
|
106
|
-
return
|
109
|
+
return applications_to_deploy
|
107
110
|
end
|
108
111
|
end
|
109
112
|
end
|
@@ -10,9 +10,9 @@ module CapistranoMulticonfigParallel
|
|
10
10
|
|
11
11
|
delegate :job_stage,
|
12
12
|
:capistrano_action,
|
13
|
-
:build_capistrano_task,
|
14
13
|
:execute_standard_deploy,
|
15
14
|
:setup_command_line,
|
15
|
+
:gitflow,
|
16
16
|
to: :command
|
17
17
|
|
18
18
|
delegate :stderr_buffer,
|
@@ -25,10 +25,11 @@ module CapistranoMulticonfigParallel
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def save_stderr_error(data)
|
28
|
+
return unless @manager.alive?
|
28
29
|
stderr_buffer.rewind
|
29
30
|
old_data = stderr_buffer.read.dup
|
30
31
|
new_data = old_data.to_s + data
|
31
|
-
stderr_buffer.write(new_data) if
|
32
|
+
stderr_buffer.write(new_data) if ['aborted!', 'Terminating', 'Error'].any? { |word| new_data.include?(word) }
|
32
33
|
end
|
33
34
|
|
34
35
|
def env_variable
|
@@ -68,7 +69,7 @@ module CapistranoMulticonfigParallel
|
|
68
69
|
def worker_state
|
69
70
|
worker_obj = worker
|
70
71
|
default = status.to_s.upcase.red
|
71
|
-
worker_obj.
|
72
|
+
worker_obj.alive? ? worker_obj.worker_state : default
|
72
73
|
end
|
73
74
|
|
74
75
|
def id
|
@@ -81,6 +82,7 @@ module CapistranoMulticonfigParallel
|
|
81
82
|
{ name: 'action', default: '' },
|
82
83
|
{ name: 'task_arguments', default: [] },
|
83
84
|
{ name: 'env_options', default: {} },
|
85
|
+
{ name: 'path', default: nil },
|
84
86
|
{ name: 'status', default: :unstarted },
|
85
87
|
{ name: 'exit_status', default: nil }
|
86
88
|
].each do |hash|
|
@@ -6,19 +6,29 @@ module CapistranoMulticonfigParallel
|
|
6
6
|
include FileUtils
|
7
7
|
include CapistranoMulticonfigParallel::ApplicationHelper
|
8
8
|
|
9
|
-
attr_reader :job
|
10
|
-
delegate :app, :stage, :action, :task_arguments, :env_options, to: :job
|
9
|
+
attr_reader :job, :job_capistrano_version, :legacy_capistrano
|
10
|
+
delegate :app, :stage, :action, :task_arguments, :env_options, :path, to: :job
|
11
11
|
|
12
12
|
def initialize(job)
|
13
13
|
@job = job
|
14
|
+
@legacy_capistrano = legacy_capistrano? ? true : false
|
14
15
|
end
|
15
16
|
|
16
17
|
def filtered_env_keys
|
17
|
-
|
18
|
+
%w(STAGES ACTION)
|
19
|
+
end
|
20
|
+
|
21
|
+
def bundle_gemfile_env
|
22
|
+
"BUNDLE_GEMFILE=#{job_path}/Gemfile"
|
23
|
+
end
|
24
|
+
|
25
|
+
def gitflow
|
26
|
+
gitflow = `#{command_prefix} && #{bundle_gemfile_env} bundle show capistrano-gitflow`
|
27
|
+
@gitflow ||= gitflow.include?('Could not find') ? false : true
|
18
28
|
end
|
19
29
|
|
20
30
|
def job_stage
|
21
|
-
app.present? ? "#{app}:#{stage}" : "#{stage}"
|
31
|
+
multi_apps?(job_path) && app.present? ? "#{app}:#{stage}" : "#{stage}"
|
22
32
|
end
|
23
33
|
|
24
34
|
def capistrano_action
|
@@ -34,13 +44,13 @@ module CapistranoMulticonfigParallel
|
|
34
44
|
array_options = []
|
35
45
|
filtered_keys = options.delete(:filtered_keys) || []
|
36
46
|
env_options.each do |key, value|
|
37
|
-
array_options << "#{env_prefix(key)} #{env_key_format(key)}=#{value}" if value.present? && !env_option_filtered?(key, filtered_keys)
|
47
|
+
array_options << "#{env_prefix(key, @legacy_capistrano)} #{env_key_format(key, @legacy_capistrano)}=#{value}" if value.present? && !env_option_filtered?(key, filtered_keys)
|
38
48
|
end
|
39
49
|
setup_remaining_flags(array_options, options)
|
40
50
|
end
|
41
51
|
|
42
52
|
def setup_remaining_flags(array_options, options)
|
43
|
-
array_options << trace_flag if app_debug_enabled?
|
53
|
+
array_options << trace_flag(@legacy_capistrano) if app_debug_enabled?
|
44
54
|
array_options.concat(setup_flags_for_job(options))
|
45
55
|
end
|
46
56
|
|
@@ -49,10 +59,28 @@ module CapistranoMulticonfigParallel
|
|
49
59
|
setup_env_options(options).concat(new_arguments)
|
50
60
|
end
|
51
61
|
|
62
|
+
def job_capistrano_version
|
63
|
+
@job_capistrano_version ||= `#{command_prefix} && #{bundle_gemfile_env} bundle show capistrano | grep -Po 'capistrano-([0-9.]+)' | grep -Po '([0-9.]+)'`
|
64
|
+
@job_capistrano_version = strip_characters_from_string(@job_capistrano_version)
|
65
|
+
end
|
66
|
+
|
67
|
+
def legacy_capistrano?
|
68
|
+
verify_gem_version(job_capistrano_version, '3.0', operator: '<')
|
69
|
+
end
|
70
|
+
|
71
|
+
def job_path
|
72
|
+
path || detect_root
|
73
|
+
end
|
74
|
+
|
75
|
+
def command_prefix
|
76
|
+
bundle_install = path.present? ? "&& #{bundle_gemfile_env} bundle install" : ''
|
77
|
+
"cd #{job_path} #{bundle_install}"
|
78
|
+
end
|
79
|
+
|
52
80
|
def to_s
|
53
|
-
|
54
|
-
environment_options = setup_command_line(
|
55
|
-
"
|
81
|
+
config_flags = CapistranoMulticonfigParallel.configuration_flags
|
82
|
+
environment_options = setup_command_line(config_flags).join(' ')
|
83
|
+
"#{command_prefix} && #{bundle_gemfile_env} RAILS_ENV=#{stage} bundle exec multi_cap #{job_stage} #{capistrano_action} #{environment_options}"
|
56
84
|
end
|
57
85
|
|
58
86
|
def to_json
|
@@ -34,6 +34,22 @@ default_config:
|
|
34
34
|
default: './log/multi_cap_websocket.log'
|
35
35
|
required: false
|
36
36
|
|
37
|
+
- name: 'config_dir'
|
38
|
+
type: 'filename'
|
39
|
+
description: >-
|
40
|
+
The path where the config file is located. If file is not provided,
|
41
|
+
will raise exception if Capfile is not found in the current directory
|
42
|
+
from where the script is running
|
43
|
+
default: ''
|
44
|
+
required: false
|
45
|
+
|
46
|
+
- name: 'log_dir'
|
47
|
+
type: 'filename'
|
48
|
+
description: >-
|
49
|
+
The path where the log files will be created
|
50
|
+
default: ''
|
51
|
+
required: false
|
52
|
+
|
37
53
|
- name: 'development_stages'
|
38
54
|
type: 'Array'
|
39
55
|
description: >-
|
@@ -3,20 +3,20 @@ module CapistranoMulticonfigParallel
|
|
3
3
|
module CapistranoHelper
|
4
4
|
module_function
|
5
5
|
|
6
|
-
def filtered_env_keys_format(keys)
|
7
|
-
keys.map { |key| env_key_format(key) }
|
6
|
+
def filtered_env_keys_format(keys, version = capistrano_version_2?)
|
7
|
+
keys.map { |key| env_key_format(key, version) }
|
8
8
|
end
|
9
9
|
|
10
|
-
def env_prefix(key)
|
11
|
-
key != CapistranoMulticonfigParallel::ENV_KEY_JOB_ID &&
|
10
|
+
def env_prefix(key, version = capistrano_version_2?)
|
11
|
+
key != CapistranoMulticonfigParallel::ENV_KEY_JOB_ID && version == true ? '-S' : ''
|
12
12
|
end
|
13
13
|
|
14
|
-
def env_key_format(key)
|
15
|
-
|
14
|
+
def env_key_format(key, version = capistrano_version_2?)
|
15
|
+
version == true ? key.downcase : key
|
16
16
|
end
|
17
17
|
|
18
|
-
def trace_flag
|
19
|
-
|
18
|
+
def trace_flag(version = capistrano_version_2?)
|
19
|
+
version == true ? '--verbose' : '--trace'
|
20
20
|
end
|
21
21
|
|
22
22
|
def setup_flags_for_job(options)
|
@@ -21,9 +21,9 @@ module CapistranoMulticonfigParallel
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def setup_configuration
|
24
|
-
@fetched_config.read config_file if File.file?(config_file)
|
25
24
|
@fetched_config.use :commandline
|
26
|
-
|
25
|
+
@fetched_config.process_argv!
|
26
|
+
read_config_file
|
27
27
|
@fetched_config.use :config_block
|
28
28
|
validate_configuration
|
29
29
|
end
|
@@ -32,11 +32,18 @@ module CapistranoMulticonfigParallel
|
|
32
32
|
@fetched_config.finally do |config|
|
33
33
|
check_configuration(config)
|
34
34
|
end
|
35
|
-
@fetched_config.process_argv!
|
36
35
|
@fetched_config.resolve!
|
37
36
|
@fetched_config
|
38
37
|
end
|
39
38
|
|
39
|
+
def read_config_file
|
40
|
+
@fetched_config.config_dir = @fetched_config.config_dir.present? ? File.expand_path(@fetched_config.config_dir) : try_detect_file('multi_cap.yml')
|
41
|
+
config_file_path = @fetched_config.config_dir.present? ? File.join(@fetched_config.config_dir, 'multi_cap.yml') : nil
|
42
|
+
config_file = File.expand_path(config_file_path || File.join(detect_root.to_s, 'config', 'multi_cap.yml'))
|
43
|
+
@fetched_config.log_dir = config_file_path.present? ? File.dirname(config_file) : File.dirname(File.dirname(config_file))
|
44
|
+
@fetched_config.read config_file if File.file?(config_file)
|
45
|
+
end
|
46
|
+
|
40
47
|
def verify_application_dependencies(value, props)
|
41
48
|
return unless value.is_a?(Array)
|
42
49
|
value.reject { |val| val.blank? || !val.is_a?(Hash) }
|
@@ -84,10 +91,18 @@ module CapistranoMulticonfigParallel
|
|
84
91
|
end
|
85
92
|
end
|
86
93
|
|
94
|
+
def check_directories(props)
|
95
|
+
props.each do |prop|
|
96
|
+
value = get_prop_config(prop)
|
97
|
+
@check_config[prop] = value if value.present? && File.directory?(value)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
87
101
|
def check_configuration(config)
|
88
102
|
@check_config = config.stringify_keys
|
89
103
|
check_boolean_props(%w(multi_debug multi_secvential websocket_server.enable_debug websocket_server.use_redis terminal.clear_screen))
|
90
104
|
check_array_props(%w(task_confirmations development_stages apply_stage_confirmation))
|
105
|
+
check_directories(%w(log_dir config_dir))
|
91
106
|
verify_application_dependencies(@check_config['application_dependencies'], %w(app priority dependencies))
|
92
107
|
end
|
93
108
|
end
|
@@ -5,7 +5,7 @@ module CapistranoMulticonfigParallel
|
|
5
5
|
|
6
6
|
def find_loaded_gem(name, property = nil)
|
7
7
|
gem_spec = Gem.loaded_specs.values.find { |repo| repo.name == name }
|
8
|
-
property.present? ? gem_spec.send(property) : gem_spec
|
8
|
+
gem_spec.present? && property.present? ? gem_spec.send(property) : gem_spec
|
9
9
|
end
|
10
10
|
|
11
11
|
def find_loaded_gem_property(gem_name, property = 'version')
|
@@ -18,12 +18,14 @@ module CapistranoMulticonfigParallel
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def get_parsed_version(version)
|
21
|
+
return 0 if version.blank?
|
21
22
|
version = version.to_s.split('.')
|
22
23
|
version.pop until version.size == 2
|
23
24
|
version.join('.').to_f
|
24
25
|
end
|
25
26
|
|
26
27
|
def verify_gem_version(gem_version, version, options = {})
|
28
|
+
options.stringify_keys!
|
27
29
|
version = get_parsed_version(version)
|
28
30
|
get_parsed_version(gem_version).send(options.fetch('operator', '<='), version)
|
29
31
|
end
|
@@ -111,12 +111,9 @@ module CapistranoMulticonfigParallel
|
|
111
111
|
end
|
112
112
|
end
|
113
113
|
|
114
|
-
def config_file
|
115
|
-
File.join(detect_root.to_s, 'config', 'multi_cap.yml')
|
116
|
-
end
|
117
|
-
|
118
114
|
def log_directory
|
119
|
-
|
115
|
+
log_dir = configuration.log_dir || detect_root.to_s
|
116
|
+
File.join(log_dir.to_s, 'log')
|
120
117
|
end
|
121
118
|
|
122
119
|
def main_log_file
|
@@ -1,11 +1,32 @@
|
|
1
1
|
module CapistranoMulticonfigParallel
|
2
2
|
# module used to fetch the stages (code taken from https://github.com/railsware/capistrano-multiconfig)
|
3
|
-
#
|
3
|
+
# but refactored to be able to detect stages from multiple paths
|
4
4
|
module StagesHelper
|
5
5
|
module_function
|
6
6
|
|
7
|
-
def stages
|
8
|
-
|
7
|
+
def stages(path = nil)
|
8
|
+
path.blank? && independent_deploy? ? fetch_stages_from_file : fetch_stages_app(path)
|
9
|
+
end
|
10
|
+
|
11
|
+
def multi_apps?(path = nil)
|
12
|
+
path.blank? && independent_deploy? ? true : stages(path).find { |stage| stage.include?(':') }.present?
|
13
|
+
end
|
14
|
+
|
15
|
+
def fetch_stages_from_file
|
16
|
+
configuration.application_dependencies.map { |hash| hash[:app] }
|
17
|
+
end
|
18
|
+
|
19
|
+
def app_names_from_stages
|
20
|
+
independent_deploy? ? fetch_stages_from_file : stages.map { |stage| stage.split(':').reverse[1] }.uniq
|
21
|
+
end
|
22
|
+
|
23
|
+
def independent_deploy?
|
24
|
+
app_with_no_path = configuration.application_dependencies.find { |hash| hash[:path].blank? }
|
25
|
+
configuration.config_dir.present? && app_with_no_path.blank? ? true : false
|
26
|
+
end
|
27
|
+
|
28
|
+
def fetch_stages_app(path)
|
29
|
+
fetch_stages_paths(path) do |paths|
|
9
30
|
checks_paths(paths)
|
10
31
|
end
|
11
32
|
end
|
@@ -23,15 +44,19 @@ module CapistranoMulticonfigParallel
|
|
23
44
|
paths.any? { |another| another != path && another.start_with?(path + ':') }
|
24
45
|
end
|
25
46
|
|
26
|
-
def
|
27
|
-
|
28
|
-
|
29
|
-
|
47
|
+
def stages_root(path)
|
48
|
+
File.expand_path(File.join(path || detect_root, 'config/deploy'))
|
49
|
+
end
|
50
|
+
|
51
|
+
def stages_paths(path)
|
52
|
+
root_stages = stages_root(path)
|
53
|
+
Dir["#{root_stages}/**/*.rb"].map do |file|
|
54
|
+
file.slice(root_stages.size + 1..-4).tr('/', ':')
|
30
55
|
end
|
31
56
|
end
|
32
57
|
|
33
|
-
def fetch_stages_paths
|
34
|
-
stages_paths.tap { |paths| yield paths if block_given? }
|
58
|
+
def fetch_stages_paths(path)
|
59
|
+
stages_paths(path).tap { |paths| yield paths if block_given? }
|
35
60
|
end
|
36
61
|
end
|
37
62
|
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: 1.0
|
4
|
+
version: 1.1.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-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: celluloid-pmap
|
@@ -324,46 +324,6 @@ dependencies:
|
|
324
324
|
- - ">="
|
325
325
|
- !ruby/object:Gem::Version
|
326
326
|
version: '3.3'
|
327
|
-
- !ruby/object:Gem::Dependency
|
328
|
-
name: guard
|
329
|
-
requirement: !ruby/object:Gem::Requirement
|
330
|
-
requirements:
|
331
|
-
- - "~>"
|
332
|
-
- !ruby/object:Gem::Version
|
333
|
-
version: '2.13'
|
334
|
-
- - ">="
|
335
|
-
- !ruby/object:Gem::Version
|
336
|
-
version: '2.13'
|
337
|
-
type: :development
|
338
|
-
prerelease: false
|
339
|
-
version_requirements: !ruby/object:Gem::Requirement
|
340
|
-
requirements:
|
341
|
-
- - "~>"
|
342
|
-
- !ruby/object:Gem::Version
|
343
|
-
version: '2.13'
|
344
|
-
- - ">="
|
345
|
-
- !ruby/object:Gem::Version
|
346
|
-
version: '2.13'
|
347
|
-
- !ruby/object:Gem::Dependency
|
348
|
-
name: guard-rspec
|
349
|
-
requirement: !ruby/object:Gem::Requirement
|
350
|
-
requirements:
|
351
|
-
- - "~>"
|
352
|
-
- !ruby/object:Gem::Version
|
353
|
-
version: '4.6'
|
354
|
-
- - ">="
|
355
|
-
- !ruby/object:Gem::Version
|
356
|
-
version: '4.6'
|
357
|
-
type: :development
|
358
|
-
prerelease: false
|
359
|
-
version_requirements: !ruby/object:Gem::Requirement
|
360
|
-
requirements:
|
361
|
-
- - "~>"
|
362
|
-
- !ruby/object:Gem::Version
|
363
|
-
version: '4.6'
|
364
|
-
- - ">="
|
365
|
-
- !ruby/object:Gem::Version
|
366
|
-
version: '4.6'
|
367
327
|
- !ruby/object:Gem::Dependency
|
368
328
|
name: simplecov
|
369
329
|
requirement: !ruby/object:Gem::Requirement
|
@@ -604,26 +564,6 @@ dependencies:
|
|
604
564
|
- - ">="
|
605
565
|
- !ruby/object:Gem::Version
|
606
566
|
version: '0.6'
|
607
|
-
- !ruby/object:Gem::Dependency
|
608
|
-
name: guard-inch
|
609
|
-
requirement: !ruby/object:Gem::Requirement
|
610
|
-
requirements:
|
611
|
-
- - "~>"
|
612
|
-
- !ruby/object:Gem::Version
|
613
|
-
version: '0.1'
|
614
|
-
- - ">="
|
615
|
-
- !ruby/object:Gem::Version
|
616
|
-
version: 0.1.0
|
617
|
-
type: :development
|
618
|
-
prerelease: false
|
619
|
-
version_requirements: !ruby/object:Gem::Requirement
|
620
|
-
requirements:
|
621
|
-
- - "~>"
|
622
|
-
- !ruby/object:Gem::Version
|
623
|
-
version: '0.1'
|
624
|
-
- - ">="
|
625
|
-
- !ruby/object:Gem::Version
|
626
|
-
version: 0.1.0
|
627
567
|
description: CapistranoMulticonfigParallel is a simple ruby implementation that allows
|
628
568
|
you to run multiple tasks in parallel for single or multiple applications and uses
|
629
569
|
websockets for inter-process communication and has a interactive menu
|