capistrano_multiconfig_parallel 0.18.1 → 0.18.2

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: 90467fb1e95571ff800390c44e68f08d7d4b9b2f
4
- data.tar.gz: a9fa1498b21325d91a363c0b15c92e9b33ad3aac
3
+ metadata.gz: 636e8807495e7cc5082a737fddaf6de9eb132d50
4
+ data.tar.gz: 77409e0a2196ce97e32fc12f9d9feffd54972bda
5
5
  SHA512:
6
- metadata.gz: 735c86753f6a6af76c9c339e5b5c14e8b655eb92216daafeba8034930e87d7ece4b9bcbb38f7ddc168ab6dc44d6ee0cb014fdda9551759edc9fbdde26f506d86
7
- data.tar.gz: 7bfd74cfa40521cb0a8bf8508624e54d9fa2f0a005f9a36470492e7f2f49f9e25f1e9f91215dc3d52008b79c480e9892576641999a14a2c921c39e76a03401c6
6
+ metadata.gz: 524ffa981d6cfc38698300d0334ec049a384002ed9b0b31eed239ca4d02047fce155a3211e53a720d533e2b911aa320fea0e789d934dd7728fb1c239c54d2f4c
7
+ data.tar.gz: d8b40b726fb03873c14d720604bbd99ee74e676d177b1778ab2cfa791d1645b86f473abd701d124f56779414ededec03c5dce0da0af7c81cb9cd61485752920f
data/.reek ADDED
@@ -0,0 +1,3 @@
1
+ ---
2
+ Attribute:
3
+ enabled: false
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- capistrano_multiconfig_parallel (0.17.0)
4
+ capistrano_multiconfig_parallel (0.18.1)
5
5
  activesupport (~> 4.0, >= 4.0)
6
6
  capistrano (~> 3.0, >= 3.0)
7
7
  celluloid-pmap (~> 0.2, >= 0.2.2)
@@ -4,7 +4,6 @@ module CapistranoMulticonfigParallel
4
4
  class Application
5
5
  include Celluloid
6
6
  include Celluloid::Logger
7
- include CapistranoMulticonfigParallel::StagesHelper
8
7
  include CapistranoMulticonfigParallel::ApplicationHelper
9
8
 
10
9
  attr_reader :stages, :stage_apps, :top_level_tasks, :jobs, :branch_backup, :condition, :manager, :dependency_tracker, :application, :stage, :name, :args, :argv, :default_stage
@@ -106,13 +105,11 @@ module CapistranoMulticonfigParallel
106
105
  backup_the_branch if multi_apps?
107
106
  deploy_multiple_apps(apps, options)
108
107
  deploy_app(options) if !custom_command? || !multi_apps?
109
- rescue => e
110
- log_error(e)
111
108
  end
112
109
 
113
110
  def process_jobs
114
111
  return unless @jobs.present?
115
- FileUtils.rm Dir["#{CapistranoMulticonfigParallel.log_directory}/worker_*.log"]
112
+ FileUtils.rm Dir["#{log_directory}/worker_*.log"]
116
113
  if app_configuration.multi_secvential.to_s.downcase == 'true'
117
114
  @jobs.each { |job| CapistranoMulticonfigParallel::StandardDeploy.new(job) }
118
115
  else
@@ -11,38 +11,22 @@ module CapistranoMulticonfigParallel
11
11
 
12
12
  def enable_logging
13
13
  enable_file_logging
14
- Celluloid.logger = logger
15
- Celluloid.task_class = Celluloid::TaskThread
16
- end
17
-
18
- def detect_root
19
- if find_env_multi_cap_root
20
- Pathname.new(find_env_multi_cap_root)
21
- elsif defined?(::Rails)
22
- ::Rails.root
23
- else
24
- try_detect_capfile
25
- end
26
- end
27
-
28
- def config_file
29
- File.join(detect_root.to_s, 'config', 'multi_cap.yml')
30
- end
31
-
32
- def log_directory
33
- File.join(detect_root.to_s, 'log')
14
+ set_celluloid_exception_handling
34
15
  end
35
16
 
36
- def main_log_file
37
- File.join(log_directory, 'multi_cap.log')
38
- end
17
+ private
39
18
 
40
- def custom_commands
41
- ['deploy_multi_stages']
19
+ def set_celluloid_exception_handling
20
+ Celluloid.logger = logger
21
+ Celluloid.task_class = Celluloid::TaskThread
22
+ Celluloid.exception_handler do |ex|
23
+ unless ex.is_a?(Interrupt)
24
+ puts format_error(ex)
25
+ log_error(ex)
26
+ end
27
+ end
42
28
  end
43
29
 
44
- private
45
-
46
30
  def enable_file_logging
47
31
  if configuration.multi_debug.to_s.downcase == 'true'
48
32
  enable_main_log_file
@@ -51,12 +35,5 @@ module CapistranoMulticonfigParallel
51
35
  self.logger ||= ::Logger.new(DevNull.new)
52
36
  end
53
37
  end
54
-
55
- def enable_main_log_file
56
- FileUtils.mkdir_p(log_directory) unless File.directory?(log_directory)
57
- FileUtils.touch(main_log_file) unless File.file?(main_log_file)
58
- log_file = File.open(main_log_file, 'w')
59
- log_file.sync = true
60
- end
61
38
  end
62
39
  end
@@ -37,8 +37,6 @@ module CapistranoMulticonfigParallel
37
37
  @worker_supervisor.supervise_as(:web_server, CapistranoMulticonfigParallel::WebServer, websocket_config)
38
38
  end
39
39
 
40
-
41
-
42
40
  def generate_job_id(job)
43
41
  @jobs[job['id']] = job
44
42
  job['id']
@@ -168,12 +166,13 @@ module CapistranoMulticonfigParallel
168
166
  until apps_symlink_confirmation.present?
169
167
  sleep(0.1) # keep current thread alive
170
168
  end
169
+ apps_symlink_confirmation
171
170
  end
172
171
 
173
172
  def confirm_task_approval(result, task, worker = nil)
174
173
  return unless result.present?
175
- print_confirm_task_approvall(result, task, worker = nil)
176
- return if fetch(:apps_symlink_confirmation).blank? || fetch(:apps_symlink_confirmation).downcase != 'y'
174
+ result = print_confirm_task_approvall(result, task, worker = nil)
175
+ return if result.blank? || result.downcase != 'y'
177
176
  @jobs.pmap do |job_id, job|
178
177
  worker = get_worker_for_job(job_id)
179
178
  worker.publish_rake_event('approved' => 'yes',
@@ -194,8 +193,8 @@ module CapistranoMulticonfigParallel
194
193
  end
195
194
  else
196
195
  return nil
197
- end
198
196
  end
197
+ end
199
198
 
200
199
  def can_tag_staging?
201
200
  @job_manager.can_tag_staging? &&
@@ -78,7 +78,7 @@ module CapistranoMulticonfigParallel
78
78
  end
79
79
 
80
80
  def cd_working_directory
81
- "cd #{CapistranoMulticonfigParallel.detect_root}"
81
+ "cd #{detect_root}"
82
82
  end
83
83
 
84
84
  # def generate_command_new
@@ -169,7 +169,7 @@ module CapistranoMulticonfigParallel
169
169
  log_to_file("worker #{@job_id} triest to transition from #{@machine.state} to #{name}")
170
170
  @machine.transitions.on(name.to_s, @machine.state => name.to_s)
171
171
  @machine.go_to_transition(name.to_s)
172
- raise(CapistranoMulticonfigParallel::CelluloidWorker::TaskFailed, "task #{@action} failed ") if name == 'deploy:failed' # force worker to rollback
172
+ abort(CapistranoMulticonfigParallel::CelluloidWorker::TaskFailed, "task #{@action} failed ") if name == 'deploy:failed' # force worker to rollback
173
173
  end
174
174
 
175
175
  def setup_command_line(*options)
@@ -235,7 +235,7 @@ module CapistranoMulticonfigParallel
235
235
  def notify_finished(exit_status)
236
236
  if exit_status.exitstatus != 0
237
237
  log_to_file("worker #{job_id} tries to terminate")
238
- raise(CapistranoMulticonfigParallel::CelluloidWorker::TaskFailed, "task failed with exit status #{exit_status.inspect} ") # force worker to rollback
238
+ abort(CapistranoMulticonfigParallel::CelluloidWorker::TaskFailed, "task failed with exit status #{exit_status.inspect} ") # force worker to rollback
239
239
  else
240
240
  update_machine_state('FINISHED')
241
241
  log_to_file("worker #{job_id} notifies manager has finished")
@@ -2,35 +2,33 @@ module CapistranoMulticonfigParallel
2
2
  # class that handles the states of the celluloid worker executing the child process in a fork process
3
3
  class StateMachine
4
4
  include ComposableStateMachine::CallbackRunner
5
- attr_accessor :state, :model, :machine, :job, :initial_state, :transitions, :output
5
+ attr_accessor :job, :actor, :initial_state, :state, :output
6
6
 
7
7
  def initialize(job, actor)
8
8
  @job = job
9
9
  @actor = actor
10
10
  @initial_state = :unstarted
11
- @model = generate_model
12
- build_machine
11
+ machine
13
12
  end
14
13
 
15
14
  def go_to_transition(action)
16
- @machine.trigger(action.to_s)
15
+ machine.trigger(action.to_s)
17
16
  end
18
17
 
19
- private
20
-
21
- def build_machine
22
- @machine = ComposableStateMachine::MachineWithExternalState.new(
23
- @model, method(:state), method(:state=), state: initial_state.to_s, callback_runner: self)
18
+ def machine
19
+ @machine ||= ComposableStateMachine::MachineWithExternalState.new(
20
+ model, method(:state), method(:state=), state: @initial_state.to_s, callback_runner: self)
21
+ @machine
24
22
  end
25
23
 
26
- def generate_transitions
27
- @transitions = ComposableStateMachine::Transitions.new
24
+ def transitions
25
+ @transitions ||= ComposableStateMachine::Transitions.new
28
26
  @transitions
29
27
  end
30
28
 
31
- def generate_model
29
+ def model
32
30
  ComposableStateMachine.model(
33
- transitions: generate_transitions,
31
+ transitions: transitions,
34
32
  behaviors: {
35
33
  enter: {
36
34
  any: proc do |current_state, event, new_state|
@@ -42,6 +40,8 @@ module CapistranoMulticonfigParallel
42
40
  )
43
41
  end
44
42
 
43
+ private
44
+
45
45
  def actor_notify_state_change(current_state, event, new_state)
46
46
  @actor.send_msg(CapistranoMulticonfigParallel::TerminalTable.topic, type: 'event', message: "Going from #{current_state} to #{new_state} due to a #{event} event")
47
47
  end
@@ -24,10 +24,8 @@ module CapistranoMulticonfigParallel
24
24
  def notify_time_change(topic, message)
25
25
  return unless topic == CapistranoMulticonfigParallel::TerminalTable.topic
26
26
  default_headings = ['Job ID', 'Job UUID', 'App/Stage', 'Action', 'ENV Variables', 'Current Task']
27
- # if CapistranoMulticonfigParallel.show_task_progress
28
27
  # default_headings << 'Total'
29
28
  # default_headings << 'Progress'
30
- # end
31
29
  table = Terminal::Table.new(title: 'Deployment Status Table', headings: default_headings)
32
30
  if @manager.jobs.present? && message_valid?(message)
33
31
  count = 0
@@ -116,7 +114,7 @@ module CapistranoMulticonfigParallel
116
114
  { value: details['env_options'] },
117
115
  { value: "#{details['state']}" }
118
116
  ]
119
- # if CapistranoMulticonfigParallel.show_task_progress
117
+
120
118
  # if worker.alive?
121
119
  # row << { value: worker.rake_tasks.size }
122
120
  # row << { value: worker_progress(details, worker) }
@@ -124,7 +122,6 @@ module CapistranoMulticonfigParallel
124
122
  # row << { value: 0 }
125
123
  # row << { value: worker_state(worker) }
126
124
  # end
127
- # end
128
125
  table.add_row(row)
129
126
  table.add_separator if @manager.jobs.keys.last.to_i != job_id.to_i
130
127
  end
@@ -14,7 +14,6 @@ module CapistranoMulticonfigParallel
14
14
  if job_id.present?
15
15
  actor_start_working
16
16
  actor.wait_execution until actor.task_approved
17
- return unless actor.task_approved
18
17
  actor_execute_block(&block)
19
18
  else
20
19
  block.call
@@ -31,15 +30,23 @@ module CapistranoMulticonfigParallel
31
30
  CapistranoMulticonfigParallel::InputStream
32
31
  end
33
32
 
34
- def actor_execute_block(&block)
33
+ def before_hooks
35
34
  stringio = StringIO.new
36
35
  output_stream.hook(stringio)
37
36
  input_stream.hook(actor, stringio)
38
- block.call
37
+ end
38
+
39
+ def after_hooks
39
40
  input_stream.unhook
40
41
  output_stream.unhook
41
42
  end
42
43
 
44
+ def actor_execute_block(&block)
45
+ before_hooks
46
+ block.call
47
+ after_hooks
48
+ end
49
+
43
50
  def actor_start_working
44
51
  if actor.blank?
45
52
  supervise_actor
@@ -8,23 +8,15 @@ module CapistranoMulticonfigParallel
8
8
 
9
9
  # method used to start
10
10
  def start
11
- verify_validation
12
- start_work
13
- rescue Interrupt
14
- rescue_interrupt
15
- rescue => error
16
- rescue_error(error)
17
- end
18
-
19
- def rescue_interrupt
20
- `stty icanon echo`
21
- $stderr.puts 'Command cancelled.'
22
- end
23
-
24
- def rescue_error(error)
25
- $stderr.puts error
26
- $stderr.puts error.backtrace if error.respond_to?(:backtrace)
27
- exit(1)
11
+ execute_with_rescue('stderr') do
12
+ verify_validation
13
+ job_manager = CapistranoMulticonfigParallel::Application.new
14
+ if job_manager.argv[CapistranoMulticonfigParallel::ENV_KEY_JOB_ID].blank?
15
+ job_manager.start
16
+ else
17
+ Capistrano::Application.new.run
18
+ end
19
+ end
28
20
  end
29
21
 
30
22
  def verify_validation
@@ -32,15 +24,6 @@ module CapistranoMulticonfigParallel
32
24
  CapistranoMulticonfigParallel.original_args = ARGV.dup
33
25
  CapistranoMulticonfigParallel.configuration_valid?
34
26
  end
35
-
36
- def start_work
37
- job_manager = CapistranoMulticonfigParallel::Application.new
38
- if job_manager.argv[CapistranoMulticonfigParallel::ENV_KEY_JOB_ID].blank?
39
- job_manager.start
40
- else
41
- Capistrano::Application.new.run
42
- end
43
- end
44
27
  end
45
28
  end
46
29
  end
@@ -1,8 +1,12 @@
1
1
  require_relative './core_helper'
2
+ require_relative './internal_helper'
3
+ require_relative './stages_helper'
2
4
  module CapistranoMulticonfigParallel
3
5
  # class that holds the options that are configurable for this gem
4
6
  module ApplicationHelper
7
+ include CapistranoMulticonfigParallel::InternalHelper
5
8
  include CapistranoMulticonfigParallel::CoreHelper
9
+ include CapistranoMulticonfigParallel::StagesHelper
6
10
 
7
11
  module_function
8
12
 
@@ -3,39 +3,10 @@ module CapistranoMulticonfigParallel
3
3
  module CoreHelper
4
4
  module_function
5
5
 
6
- def internal_config_directory
7
- File.join(root.to_s, 'capistrano_multiconfig_parallel', 'configuration')
8
- end
9
-
10
- def internal_config_file
11
- File.join(internal_config_directory, 'default.yml')
12
- end
13
-
14
- def default_internal_config
15
- @default_config ||= YAML.load_file(internal_config_file)['default_config']
16
- @default_config
17
- end
18
-
19
- def find_env_multi_cap_root
20
- ENV['MULTI_CAP_ROOT']
21
- end
22
-
23
- def root
24
- File.expand_path(File.dirname(File.dirname(__dir__)))
25
- end
26
-
27
6
  def find_config_type(type)
28
7
  ['boolean'].include?(type.to_s) ? type.to_s.delete(':').to_sym : type.to_s.constantize
29
8
  end
30
9
 
31
- def try_detect_capfile
32
- root = Pathname.new(FileUtils.pwd)
33
- root = root.parent unless root.directory?
34
- root = root.parent until root.children.find { |f| f.file? && f.basename.to_s.downcase == 'capfile' }.present? || root.root?
35
- fail "Can't detect Capfile in the application root".red if root.root?
36
- root
37
- end
38
-
39
10
  def app_debug_enabled?
40
11
  app_configuration.multi_debug.to_s.downcase == 'true'
41
12
  end
@@ -48,10 +19,6 @@ module CapistranoMulticonfigParallel
48
19
  CapistranoMulticonfigParallel.configuration
49
20
  end
50
21
 
51
- def custom_commands
52
- CapistranoMulticonfigParallel.custom_commands
53
- end
54
-
55
22
  def app_logger
56
23
  CapistranoMulticonfigParallel.logger
57
24
  end
@@ -66,22 +33,30 @@ module CapistranoMulticonfigParallel
66
33
  end
67
34
 
68
35
  def ask_confirm(message, default)
36
+ force_confirmation do
37
+ Ask.input message, default: default
38
+ end
39
+ rescue
40
+ return nil
41
+ end
42
+
43
+ def force_confirmation(&block)
69
44
  `stty -raw echo`
70
45
  check_terminal_tty
71
- result = Ask.input message, default: default
46
+ result = block.call
72
47
  $stdout.flush
73
48
  `stty -raw echo`
74
- return result
75
- rescue
76
- return nil
49
+ result
50
+ end
51
+
52
+ def log_error(error)
53
+ log_to_file(format_error(error))
77
54
  end
78
55
 
79
- def log_error(message)
80
- log_to_file(
81
- class_name: message.class,
82
- message: message.respond_to?(:message) ? message.message : message.inspect,
83
- backtrace: message.respond_to?(:backtrace) ? message.backtrace.join("\n\n") : ''
84
- )
56
+ def format_error(error)
57
+ JSON.pretty_generate(class_name: error.class,
58
+ message: error.respond_to?(:message) ? error.message : error.inspect,
59
+ backtrace: error.respond_to?(:backtrace) ? error.backtrace.join("\n\n") : '')
85
60
  end
86
61
 
87
62
  def log_to_file(message, job_id = nil)
@@ -91,8 +66,8 @@ module CapistranoMulticonfigParallel
91
66
 
92
67
  def find_worker_log(job_id)
93
68
  return if job_id.blank?
94
- FileUtils.mkdir_p(CapistranoMulticonfigParallel.log_directory) unless File.directory?(CapistranoMulticonfigParallel.log_directory)
95
- filename = File.join(CapistranoMulticonfigParallel.log_directory, "worker_#{job_id}.log")
69
+ FileUtils.mkdir_p(log_directory) unless File.directory?(log_directory)
70
+ filename = File.join(log_directory, "worker_#{job_id}.log")
96
71
  worker_log = ::Logger.new(filename)
97
72
  worker_log.level = ::Logger::Severity::DEBUG
98
73
  worker_log.formatter = proc do |severity, datetime, progname, msg|
@@ -103,15 +78,33 @@ module CapistranoMulticonfigParallel
103
78
  end
104
79
 
105
80
  def debug_websocket?
106
- websocket_config['enable_debug'].to_s == 'true'
81
+ websocket_server_config['enable_debug'].to_s == 'true'
82
+ end
83
+
84
+ def websocket_server_config
85
+ app_configuration.fetch(:websocket_server, {}).stringify_keys
107
86
  end
108
87
 
109
88
  def websocket_config
110
- config = app_configuration[:websocket_server]
111
- config.present? && config.is_a?(Hash) ? config.stringify_keys : {}
112
- config['enable_debug'] = config.fetch('enable_debug', '').to_s == 'true'
113
- config
89
+ websocket_server_config.merge('enable_debug' => debug_websocket?)
90
+ end
91
+
92
+ def execute_with_rescue(output = nil)
93
+ yield if block_given?
94
+ rescue Interrupt
95
+ rescue_interrupt
96
+ rescue => error
97
+ rescue_error(error, output)
114
98
  end
115
99
 
100
+ def rescue_error(error, output = nil)
101
+ output.blank? ? log_error(error) : puts(format_error(error))
102
+ exit(1)
103
+ end
104
+
105
+ def rescue_interrupt
106
+ `stty icanon echo`
107
+ puts "\n Command was cancelled due to an Interrupt error."
108
+ end
116
109
  end
117
110
  end
@@ -0,0 +1,68 @@
1
+ module CapistranoMulticonfigParallel
2
+ # internal helpers for logging mostly
3
+ module InternalHelper
4
+ module_function
5
+
6
+ def internal_config_directory
7
+ File.join(root.to_s, 'capistrano_multiconfig_parallel', 'configuration')
8
+ end
9
+
10
+ def internal_config_file
11
+ File.join(internal_config_directory, 'default.yml')
12
+ end
13
+
14
+ def default_internal_config
15
+ @default_config ||= YAML.load_file(internal_config_file)['default_config']
16
+ @default_config
17
+ end
18
+
19
+ def find_env_multi_cap_root
20
+ ENV['MULTI_CAP_ROOT']
21
+ end
22
+
23
+ def root
24
+ File.expand_path(File.dirname(File.dirname(__dir__)))
25
+ end
26
+
27
+ def try_detect_capfile
28
+ root = Pathname.new(FileUtils.pwd)
29
+ root = root.parent unless root.directory?
30
+ root = root.parent until root.children.find { |f| f.file? && f.basename.to_s.downcase == 'capfile' }.present? || root.root?
31
+ fail "Can't detect Capfile in the application root".red if root.root?
32
+ root
33
+ end
34
+
35
+ def detect_root
36
+ if find_env_multi_cap_root
37
+ Pathname.new(find_env_multi_cap_root)
38
+ elsif defined?(::Rails)
39
+ ::Rails.root
40
+ else
41
+ try_detect_capfile
42
+ end
43
+ end
44
+
45
+ def config_file
46
+ File.join(detect_root.to_s, 'config', 'multi_cap.yml')
47
+ end
48
+
49
+ def log_directory
50
+ File.join(detect_root.to_s, 'log')
51
+ end
52
+
53
+ def main_log_file
54
+ File.join(log_directory, 'multi_cap.log')
55
+ end
56
+
57
+ def custom_commands
58
+ ['deploy_multi_stages']
59
+ end
60
+
61
+ def enable_main_log_file
62
+ FileUtils.mkdir_p(log_directory) unless File.directory?(log_directory)
63
+ FileUtils.touch(main_log_file) unless File.file?(main_log_file)
64
+ log_file = File.open(main_log_file, 'w')
65
+ log_file.sync = true
66
+ end
67
+ end
68
+ end
@@ -8,7 +8,7 @@ module CapistranoMulticonfigParallel
8
8
  module VERSION
9
9
  MAJOR = 0
10
10
  MINOR = 18
11
- TINY = 1
11
+ TINY = 2
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: 0.18.1
4
+ version: 0.18.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - bogdanRada
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-12-03 00:00:00.000000000 Z
11
+ date: 2015-12-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: celluloid-pmap
@@ -602,6 +602,7 @@ files:
602
602
  - ".codeclimate.yml"
603
603
  - ".coveralls.yml"
604
604
  - ".gitignore"
605
+ - ".reek"
605
606
  - ".rspec"
606
607
  - ".rubocop.yml"
607
608
  - ".travis.yml"
@@ -639,6 +640,7 @@ files:
639
640
  - lib/capistrano_multiconfig_parallel/helpers/application_helper.rb
640
641
  - lib/capistrano_multiconfig_parallel/helpers/configuration.rb
641
642
  - lib/capistrano_multiconfig_parallel/helpers/core_helper.rb
643
+ - lib/capistrano_multiconfig_parallel/helpers/internal_helper.rb
642
644
  - lib/capistrano_multiconfig_parallel/helpers/stages_helper.rb
643
645
  - lib/capistrano_multiconfig_parallel/initializers/rake.rb
644
646
  - lib/capistrano_multiconfig_parallel/version.rb