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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3969bb2312c4d58de611a321420226dd9a556bed
4
- data.tar.gz: 40b5524432fe09ff8240ad910bd784a67e292e91
3
+ metadata.gz: 50bc1ddfa761688a5fd56d8eaf83da2e9a632056
4
+ data.tar.gz: f3a60a12be7b53b63947b199154c6fc20c40c729
5
5
  SHA512:
6
- metadata.gz: 401ef05ba36d18fb6ac2871c7a4287267cb65c6539e573d4d97bc409ed81874dace93abfdba6ca1106b523694edd9aedcb2cb86f707dadbea82695940fed4afa
7
- data.tar.gz: c63ef76946c39e239266876b5166ff20f17cc0aee213d3fd6dcd864f0384ff7a1bdb48b7713a3f48f5749ad4a04db3702f66040ce6ccaa31701eaa2d7791978c
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 please use **-S box=<box_name>,<box_name>**
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.2) Deploying the application to multiple stages ( Using the customized command "deploy_multi_stages")
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.2) Deploying multiple application to multiple stages ( Using the customized command "deploy_multi_stages")
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? ? stages.map { |stage| stage.split(':').reverse[1] }.uniq : []
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 if @top_level_tasks != ['default']
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
- capistrano_version_2? ? 'action' : 'ACTION'
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
- find_loaded_gem('capistrano-gitflow').present?
114
+ @jobs.find(&:gitflow).present?
120
115
  end
121
116
 
122
117
  def stages_key
123
- capistrano_version_2? ? 'stages' : 'STAGES'
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? && tag_staging_exists? && fetch_multi_stages.include?('staging')
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
- capistrano_version_2? ? 'box' : 'BOX'
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)
@@ -30,7 +30,7 @@ module CapistranoMulticonfigParallel
30
30
  end
31
31
 
32
32
  def original_args_hash
33
- multi_fetch_argv(original_args.dup)
33
+ multi_fetch_argv((original_args || ARGV).dup)
34
34
  end
35
35
 
36
36
  def job_id
@@ -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
- !@job_manager.can_tag_staging?
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 new_data.include?('aborted!') || new_data.include?('Terminating')
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.present? && worker_obj.alive? ? worker_obj.worker_state : default
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
- filtered_env_keys_format(%w(STAGES ACTION))
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
- configuration_options = CapistranoMulticonfigParallel.configuration_flags
54
- environment_options = setup_command_line(configuration_options).join(' ')
55
- "cd #{detect_root} && RAILS_ENV=#{stage} bundle exec multi_cap #{job_stage} #{capistrano_action} #{environment_options}"
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: >-
@@ -39,8 +39,7 @@ module CapistranoMulticonfigParallel
39
39
 
40
40
  def setup_command_line_standard(*args)
41
41
  options = args.extract_options!
42
- args.select(&:present?)
43
- [args, options]
42
+ [args.select(&:present?), options]
44
43
  end
45
44
 
46
45
  def wrap_string(string, options = {})
@@ -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 && capistrano_version_2? ? '-S' : ''
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
- capistrano_version_2? ? key.downcase : key
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
- capistrano_version_2? ? '--verbose' : '--trace'
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
- File.join(detect_root.to_s, 'log')
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
- # TODO: find a way to remove this and still be compatible with capistrano 2.x
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
- fetch_stages_paths do |paths|
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 stages_paths
27
- stages_root = File.expand_path(File.join(detect_root, 'config/deploy'))
28
- Dir["#{stages_root}/**/*.rb"].map do |file|
29
- file.slice(stages_root.size + 1..-4).tr('/', ':')
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
@@ -7,8 +7,8 @@ module CapistranoMulticonfigParallel
7
7
  # module used for generating the version
8
8
  module VERSION
9
9
  MAJOR = 1
10
- MINOR = 0
11
- TINY = 7
10
+ MINOR = 1
11
+ TINY = 0
12
12
  PRE = nil
13
13
 
14
14
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: capistrano_multiconfig_parallel
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.7
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-13 00:00:00.000000000 Z
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