engineyard-serverside 1.5.35.pre.2 → 1.6.0.pre

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. data/lib/engineyard-serverside.rb +3 -1
  2. data/lib/engineyard-serverside/cli.rb +73 -38
  3. data/lib/engineyard-serverside/configuration.rb +38 -12
  4. data/lib/engineyard-serverside/deploy.rb +63 -51
  5. data/lib/engineyard-serverside/deploy_hook.rb +21 -18
  6. data/lib/engineyard-serverside/deprecation.rb +9 -17
  7. data/lib/engineyard-serverside/lockfile_parser.rb +1 -1
  8. data/lib/engineyard-serverside/rails_asset_support.rb +5 -5
  9. data/lib/engineyard-serverside/server.rb +8 -11
  10. data/lib/engineyard-serverside/shell.rb +101 -0
  11. data/lib/engineyard-serverside/shell/formatter.rb +70 -0
  12. data/lib/engineyard-serverside/shell/helpers.rb +29 -0
  13. data/lib/engineyard-serverside/strategies/git.rb +12 -15
  14. data/lib/engineyard-serverside/task.rb +28 -5
  15. data/lib/engineyard-serverside/version.rb +1 -1
  16. data/lib/vendor/open4/lib/open4.rb +432 -0
  17. data/spec/basic_deploy_spec.rb +9 -9
  18. data/spec/bundler_deploy_spec.rb +1 -1
  19. data/spec/custom_deploy_spec.rb +45 -4
  20. data/spec/deploy_hook_spec.rb +77 -78
  21. data/spec/deprecation_spec.rb +4 -26
  22. data/spec/git_strategy_spec.rb +6 -2
  23. data/spec/nodejs_deploy_spec.rb +2 -2
  24. data/spec/services_deploy_spec.rb +11 -10
  25. data/spec/shell_spec.rb +48 -0
  26. data/spec/spec_helper.rb +48 -25
  27. data/spec/sqlite3_deploy_spec.rb +1 -2
  28. data/spec/support/integration.rb +1 -13
  29. metadata +57 -97
  30. data/lib/engineyard-serverside/logged_output.rb +0 -91
  31. data/lib/vendor/systemu/LICENSE +0 -3
  32. data/lib/vendor/systemu/lib/systemu.rb +0 -363
  33. data/lib/vendor/systemu/systemu.gemspec +0 -45
  34. data/spec/fixtures/gitrepo/bar +0 -0
  35. data/spec/logged_output_spec.rb +0 -55
@@ -8,7 +8,7 @@ else
8
8
  end
9
9
 
10
10
  $LOAD_PATH.unshift File.expand_path('vendor/thor/lib', File.dirname(__FILE__))
11
- $LOAD_PATH.unshift File.expand_path('vendor/systemu/lib', File.dirname(__FILE__))
11
+ $LOAD_PATH.unshift File.expand_path('vendor/open4/lib', File.dirname(__FILE__))
12
12
  $LOAD_PATH.unshift File.expand_path('vendor/escape/lib', File.dirname(__FILE__))
13
13
  $LOAD_PATH.unshift File.expand_path('vendor/json_pure/lib', File.dirname(__FILE__))
14
14
 
@@ -26,6 +26,8 @@ require 'engineyard-serverside/cli'
26
26
  require 'engineyard-serverside/configuration'
27
27
  require 'engineyard-serverside/deprecation'
28
28
  require 'engineyard-serverside/future'
29
+ require 'engineyard-serverside/shell'
30
+
29
31
 
30
32
  module EY
31
33
  module Serverside
@@ -1,5 +1,8 @@
1
1
  require 'thor'
2
2
  require 'pathname'
3
+ require 'engineyard-serverside/deploy'
4
+ require 'engineyard-serverside/shell'
5
+ require 'engineyard-serverside/server'
3
6
 
4
7
  module EY
5
8
  module Serverside
@@ -22,6 +25,14 @@ module EY
22
25
  :desc => "Application to deploy",
23
26
  :aliases => ["-a"]
24
27
 
28
+ method_option :environment_name,:type => :string,
29
+ :required => true,
30
+ :desc => "Environment name"
31
+
32
+ method_option :account_name, :type => :string,
33
+ :required => true,
34
+ :desc => "Account name"
35
+
25
36
  method_option :framework_env, :type => :string,
26
37
  :desc => "Ruby web framework environment",
27
38
  :aliases => ["-e"]
@@ -44,21 +55,13 @@ module EY
44
55
  :desc => "Instance names, keyed on hostname. e.g. instance1:name1 instance2:name2"
45
56
 
46
57
  method_option :verbose, :type => :boolean,
47
- :default => false,
48
58
  :desc => "Verbose output",
49
59
  :aliases => ["-v"]
50
60
 
51
61
  desc "deploy", "Deploy code from /data/<app>"
52
62
  def deploy(default_task=:deploy)
53
- config = EY::Serverside::Deploy::Configuration.new(options)
54
- load_servers(config)
55
-
56
- EY::Serverside::LoggedOutput.verbose = options[:verbose]
57
- EY::Serverside::LoggedOutput.logfile = File.join(ENV['HOME'], "#{options[:app]}-deploy.log")
58
-
59
- invoke :propagate
60
-
61
- EY::Serverside::Deploy.new(config).send(default_task)
63
+ config, shell = init_and_propagate(options, 'deploy')
64
+ EY::Serverside::Deploy.new(config, shell).send(default_task)
62
65
  end
63
66
 
64
67
  method_option :app, :type => :string,
@@ -66,6 +69,14 @@ module EY
66
69
  :desc => "Which application's hooks to run",
67
70
  :aliases => ["-a"]
68
71
 
72
+ method_option :environment_name, :type => :string,
73
+ :required => true,
74
+ :desc => "Environment name"
75
+
76
+ method_option :account_name, :type => :string,
77
+ :required => true,
78
+ :desc => "Account name"
79
+
69
80
  method_option :release_path, :type => :string,
70
81
  :desc => "Value for #release_path in hooks (mostly for internal coordination)",
71
82
  :aliases => ["-r"]
@@ -84,9 +95,14 @@ module EY
84
95
  method_option :current_name, :type => :string,
85
96
  :desc => "Value for #current_name in hooks"
86
97
 
98
+ method_option :verbose, :type => :boolean,
99
+ :desc => "Verbose output",
100
+ :aliases => ["-v"]
101
+
87
102
  desc "hook [NAME]", "Run a particular deploy hook"
88
103
  def hook(hook_name)
89
- EY::Serverside::DeployHook.new(options).run(hook_name)
104
+ config, shell = init(options, "hook-#{hook_name}")
105
+ EY::Serverside::DeployHook.new(config, shell).run(hook_name)
90
106
  end
91
107
 
92
108
 
@@ -95,6 +111,14 @@ module EY
95
111
  :desc => "Application to deploy",
96
112
  :aliases => ["-a"]
97
113
 
114
+ method_option :environment_name,:type => :string,
115
+ :required => true,
116
+ :desc => "Environment name"
117
+
118
+ method_option :account_name, :type => :string,
119
+ :required => true,
120
+ :desc => "Account name"
121
+
98
122
  method_option :framework_env, :type => :string,
99
123
  :required => true,
100
124
  :desc => "Ruby web framework environment",
@@ -115,13 +139,10 @@ module EY
115
139
  :desc => "Instance names, keyed on hostname. e.g. instance1:name1 instance2:name2"
116
140
 
117
141
  method_option :verbose, :type => :boolean,
118
- :default => false,
119
142
  :desc => "Verbose output",
120
143
  :aliases => ["-v"]
121
144
  desc "integrate", "Integrate other instances into this cluster"
122
145
  def integrate
123
- EY::Serverside::LoggedOutput.verbose = options[:verbose]
124
- EY::Serverside::LoggedOutput.logfile = File.join(ENV['HOME'], "#{options[:app]}-integrate.log")
125
146
 
126
147
  app_dir = Pathname.new "/data/#{options[:app]}"
127
148
  current_app_dir = app_dir + "current"
@@ -133,23 +154,19 @@ module EY
133
154
  # we have to deploy the same SHA there as here
134
155
  integrate_options[:branch] = (current_app_dir + 'REVISION').read.strip
135
156
 
136
- config = EY::Serverside::Deploy::Configuration.new(integrate_options)
137
-
138
- load_servers(config)
139
-
140
- invoke :propagate
157
+ config, shell = init_and_propagate(integrate_options, 'integrate')
141
158
 
142
159
  EY::Serverside::Server.all.each do |server|
143
- server.sync_directory app_dir
160
+ server.sync_directory(app_dir) { |cmd| shell.logged_system(cmd) }
144
161
  # we're just about to recreate this, so it has to be gone
145
162
  # first. otherwise, non-idempotent deploy hooks could screw
146
163
  # things up, and since we don't control deploy hooks, we must
147
164
  # assume the worst.
148
- server.run("rm -rf #{current_app_dir}")
165
+ run_on_server(server,"rm -rf #{current_app_dir}")
149
166
  end
150
167
 
151
168
  # deploy local-ref to other instances into /data/$app/local-current
152
- EY::Serverside::Deploy.new(config).cached_deploy
169
+ EY::Serverside::Deploy.new(config, shell).cached_deploy
153
170
  end
154
171
 
155
172
  method_option :app, :type => :string,
@@ -157,6 +174,14 @@ module EY
157
174
  :desc => "Application to deploy",
158
175
  :aliases => ["-a"]
159
176
 
177
+ method_option :environment_name,:type => :string,
178
+ :required => true,
179
+ :desc => "Environment name"
180
+
181
+ method_option :account_name, :type => :string,
182
+ :required => true,
183
+ :desc => "Account name"
184
+
160
185
  method_option :stack, :type => :string,
161
186
  :desc => "Web stack (so we can restart it correctly)"
162
187
 
@@ -172,20 +197,13 @@ module EY
172
197
  :desc => "Instance names, keyed on hostname. e.g. instance1:name1 instance2:name2"
173
198
 
174
199
  method_option :verbose, :type => :boolean,
175
- :default => false,
176
200
  :desc => "Verbose output",
177
201
  :aliases => ["-v"]
178
202
  desc "restart", "Restart app servers, conditionally enabling maintenance page"
179
203
  def restart
180
- EY::Serverside::LoggedOutput.verbose = options[:verbose]
181
- EY::Serverside::LoggedOutput.logfile = File.join(ENV['HOME'], "#{options[:app]}-restart.log")
204
+ config, shell = init_and_propagate(options, 'restart')
182
205
 
183
- config = EY::Serverside::Deploy::Configuration.new(options)
184
- load_servers(config)
185
-
186
- invoke :propagate
187
-
188
- EY::Serverside::Deploy.new(config).restart_with_maintenance_page
206
+ EY::Serverside::Deploy.new(config, shell).restart_with_maintenance_page
189
207
  end
190
208
 
191
209
  desc "install_bundler [VERSION]", "Make sure VERSION of bundler is installed (in system ruby)"
@@ -203,8 +221,10 @@ module EY
203
221
  end
204
222
  end
205
223
 
206
- desc "propagate", "Propagate the engineyard-serverside gem to the other instances in the cluster. This will install exactly version #{EY::Serverside::VERSION}."
207
- def propagate
224
+ private
225
+
226
+ # Put the same engineyard-serverside on all the servers (Used to be public but is unused as an actual CLI command now)
227
+ def propagate(shell)
208
228
  config = EY::Serverside::Deploy::Configuration.new
209
229
  gem_filename = "engineyard-serverside-#{EY::Serverside::VERSION}.gem"
210
230
  local_gem_file = File.join(Gem.dir, 'cache', gem_filename)
@@ -219,23 +239,38 @@ module EY
219
239
  # 0.5.11, and mistakenly thinking 0.5.1 is there
220
240
  has_gem_cmd = "#{gem_binary} list engineyard-serverside | grep \"engineyard-serverside\" | egrep -q '#{egrep_escaped_version}[,)]'"
221
241
 
222
- if !server.run(has_gem_cmd) # doesn't have this exact version
223
- puts "~> Installing engineyard-serverside on #{server.hostname}"
242
+ if !run_on_server(server,has_gem_cmd) # doesn't have this exact version
243
+ shell.status "Installing engineyard-serverside on #{server.hostname}"
224
244
 
225
- system(Escape.shell_command([
245
+ shell.logged_system(Escape.shell_command([
226
246
  'scp', '-i', "#{ENV['HOME']}/.ssh/internal",
227
247
  "-o", "StrictHostKeyChecking=no",
228
248
  local_gem_file,
229
249
  "#{config.user}@#{server.hostname}:#{remote_gem_file}",
230
250
  ]))
231
- server.run("sudo #{gem_binary} install --no-rdoc --no-ri '#{remote_gem_file}'")
251
+ run_on_server(server,"sudo #{gem_binary} install --no-rdoc --no-ri '#{remote_gem_file}'")
232
252
  end
233
253
  end
234
254
 
235
255
  EY::Serverside::Future.success?(futures)
236
256
  end
237
257
 
238
- private
258
+ def init_and_propagate(*args)
259
+ config, shell = init(*args)
260
+ load_servers(config)
261
+ propagate(shell)
262
+ [config, shell]
263
+ end
264
+
265
+ def init(options, action)
266
+ config = EY::Serverside::Deploy::Configuration.new(options)
267
+ shell = EY::Serverside::Shell.new(:verbose => config.verbose, :log_path => File.join(ENV['HOME'], "#{config.app}-#{action}.log"))
268
+ [config, shell]
269
+ end
270
+
271
+ def run_on_server(server, command)
272
+ server.run(command) { |cmd| shell.logged_system(cmd) }
273
+ end
239
274
 
240
275
  def load_servers(config)
241
276
  EY::Serverside::Server.load_all_from_array(assemble_instance_hashes(config))
@@ -10,41 +10,50 @@ module EY
10
10
  "bundle_without" => "test development",
11
11
  })
12
12
 
13
- attr_reader :configuration
14
- alias :c :configuration
15
-
16
13
  attr_writer :release_path
17
14
 
18
15
  def initialize(options={})
19
16
  opts = options.dup
20
17
  @release_path = opts[:release_path]
21
18
  config = JSON.parse(opts.delete("config") || "{}")
22
- @configuration = DEFAULT_CONFIG.merge(config).merge(opts)
19
+ @configs = [config, opts] # low to high priority
20
+ end
21
+
22
+ def configuration
23
+ @configuration ||= @configs.inject(DEFAULT_CONFIG) {|low,high| low.merge(high)}
23
24
  end
25
+ alias :c :configuration # FIXME: awful, but someone is probably using it :(
24
26
 
25
27
  # Delegate to the configuration objects
26
28
  def method_missing(meth, *args, &blk)
27
- c.key?(meth.to_s) ? c[meth.to_s] : super
29
+ configuration.key?(meth.to_s) ? c[meth.to_s] : super
28
30
  end
29
31
 
30
32
  def respond_to?(meth, include_private=false)
31
- c.key?(meth.to_s) ? true : super
33
+ configuration.key?(meth.to_s) ? true : super
34
+ end
35
+
36
+ def ey_yml_data=(data)
37
+ environments = data['environments']
38
+ if environments && (env_data = environments[environment_name])
39
+ @configuration = nil # reset cached configuration hash
40
+ @configs.unshift(env_data) # insert just above default configuration
41
+ true
42
+ else
43
+ false
44
+ end
32
45
  end
33
46
 
34
47
  def [](key)
35
48
  if respond_to?(key.to_sym)
36
49
  send(key.to_sym)
37
50
  else
38
- c[key]
51
+ configuration[key]
39
52
  end
40
53
  end
41
54
 
42
55
  def has_key?(key)
43
- if respond_to?(key.to_sym)
44
- true
45
- else
46
- c.has_key?(key)
47
- end
56
+ respond_to?(key.to_sym) || configuration.has_key?(key)
48
57
  end
49
58
 
50
59
  def to_json
@@ -55,9 +64,22 @@ module EY
55
64
  EY::Serverside.node
56
65
  end
57
66
 
67
+ def verbose
68
+ configuration['verbose']
69
+ end
70
+
58
71
  def app
59
72
  configuration['app'].to_s
60
73
  end
74
+ alias app_name app
75
+
76
+ def environment_name
77
+ configuration['environment_name'].to_s
78
+ end
79
+
80
+ def account_name
81
+ configuration['account_name'].to_s
82
+ end
61
83
 
62
84
  def revision
63
85
  IO.read(File.join(latest_release, 'REVISION'))
@@ -95,6 +117,10 @@ module EY
95
117
  node['instance_role']
96
118
  end
97
119
 
120
+ def current_roles
121
+ configuration['current_roles'] || []
122
+ end
123
+
98
124
  def current_role
99
125
  current_roles.first
100
126
  end
@@ -7,22 +7,22 @@ require 'engineyard-serverside/rails_asset_support'
7
7
  module EY
8
8
  module Serverside
9
9
  class DeployBase < Task
10
- include LoggedOutput
11
10
  include ::EY::Serverside::RailsAssetSupport
12
11
 
13
12
  # default task
14
13
  def deploy
15
- debug "Starting deploy at #{Time.now.asctime}"
14
+ shell.status "Starting deploy at #{shell.start_time.asctime}"
16
15
  update_repository_cache
17
16
  cached_deploy
18
17
  end
19
18
 
20
19
  def cached_deploy
21
- debug "Deploying app from cached copy at #{Time.now.asctime}"
20
+ shell.status "Deploying app from cached copy at #{Time.now.asctime}"
22
21
  require_custom_tasks
22
+ load_ey_yml
23
23
  push_code
24
24
 
25
- info "~> Starting full deploy"
25
+ shell.status "Starting full deploy"
26
26
  copy_repository_cache
27
27
  check_repository
28
28
 
@@ -47,9 +47,9 @@ module EY
47
47
  disable_maintenance_page
48
48
 
49
49
  cleanup_old_releases
50
- debug "Finished deploy at #{Time.now.asctime}"
50
+ shell.status "Finished deploy at #{Time.now.asctime}"
51
51
  rescue Exception
52
- debug "Finished failing to deploy at #{Time.now.asctime}"
52
+ shell.status "Finished failing to deploy at #{Time.now.asctime}"
53
53
  puts_deploy_failure
54
54
  raise
55
55
  end
@@ -73,9 +73,9 @@ module EY
73
73
 
74
74
  def check_repository
75
75
  if gemfile?
76
- info "~> Gemfile found."
76
+ shell.status "Gemfile found."
77
77
  if lockfile
78
- info "~> Gemfile.lock found."
78
+ shell.status "Gemfile.lock found."
79
79
  unless lockfile.any_database_adapter?
80
80
  warning <<-WARN
81
81
  Gemfile.lock does not contain a recognized database adapter.
@@ -97,7 +97,7 @@ To fix this problem, commit your Gemfile.lock to your repository and redeploy.
97
97
  WARN
98
98
  end
99
99
  else
100
- info "~> No Gemfile. Deploying without bundler support."
100
+ shell.status "No Gemfile. Deploying without bundler support."
101
101
  end
102
102
  end
103
103
 
@@ -163,9 +163,9 @@ To fix this problem, commit your Gemfile.lock to your repository and redeploy.
163
163
 
164
164
  # task
165
165
  def push_code
166
- info "~> Pushing code to all servers"
166
+ shell.status "Pushing code to all servers"
167
167
  futures = EY::Serverside::Future.call(EY::Serverside::Server.all) do |server|
168
- server.sync_directory(config.repository_cache)
168
+ server.sync_directory(config.repository_cache) { |cmd| shell.logged_system(cmd) }
169
169
  end
170
170
  EY::Serverside::Future.success?(futures)
171
171
  end
@@ -173,7 +173,7 @@ To fix this problem, commit your Gemfile.lock to your repository and redeploy.
173
173
  # task
174
174
  def restart
175
175
  @restart_failed = true
176
- info "~> Restarting app servers"
176
+ shell.status "Restarting app servers"
177
177
  roles :app_master, :app, :solo do
178
178
  run(restart_command)
179
179
  end
@@ -191,12 +191,8 @@ To fix this problem, commit your Gemfile.lock to your repository and redeploy.
191
191
 
192
192
  # If we don't have a local version of the ssh wrapper script yet,
193
193
  # create it on all the servers that will need it.
194
- # TODO - This logic likely fails when people change deploy keys.
195
194
  def ssh_executable
196
- roles :app_master, :app, :solo, :util do
197
- run(generate_ssh_wrapper)
198
- end
199
- ssh_wrapper_path
195
+ @path ||= generate_ssh_wrapper
200
196
  end
201
197
 
202
198
  # We specify 'IdentitiesOnly' to avoid failures on systems with > 5 private keys available.
@@ -205,12 +201,17 @@ To fix this problem, commit your Gemfile.lock to your repository and redeploy.
205
201
  # Learned this at http://lists.mindrot.org/pipermail/openssh-unix-dev/2009-February/027271.html
206
202
  # (Thanks Jim L.)
207
203
  def generate_ssh_wrapper
204
+ path = ssh_wrapper_path
208
205
  identity_file = "~/.ssh/#{c.app}-deploy-key"
209
- %{ echo "#{wrapper_for(identity_file)}" > #{ssh_wrapper_path} && chmod 0700 #{ssh_wrapper_path} }
210
- end
211
-
212
- def wrapper_for(identity)
213
- "#!/bin/sh\nunset SSH_AUTH_SOCK; ssh -o CheckHostIP=no -o StrictHostKeyChecking=no -o PasswordAuthentication=no -o LogLevel=DEBUG -o IdentityFile=#{identity} -o IdentitiesOnly=yes -o UserKnownHostsFile=/dev/null $*"
206
+ run <<-SCRIPT
207
+ [[ -x #{path} ]] || cat > #{path} <<'SSH'
208
+ #!/bin/sh
209
+ unset SSH_AUTH_SOCK
210
+ ssh -o 'CheckHostIP no' -o 'StrictHostKeyChecking no' -o 'PasswordAuthentication no' -o 'LogLevel DEBUG' -o 'IdentityFile #{identity_file}' -o 'IdentitiesOnly yes' -o 'UserKnownHostsFile /dev/null' $*
211
+ SSH
212
+ chmod 0700 #{path}
213
+ SCRIPT
214
+ path
214
215
  end
215
216
 
216
217
  def ssh_wrapper_path
@@ -238,7 +239,7 @@ To fix this problem, commit your Gemfile.lock to your repository and redeploy.
238
239
  def clean_release_directory(dir, count = 3)
239
240
  @cleanup_failed = true
240
241
  ordinal = count.succ.to_s
241
- info "~> Cleaning release directory: #{dir}"
242
+ shell.status "Cleaning release directory: #{dir}"
242
243
  sudo "ls -r #{dir} | tail -n +#{ordinal} | xargs -I@ rm -rf #{dir}/@"
243
244
  @cleanup_failed = false
244
245
  end
@@ -250,15 +251,15 @@ To fix this problem, commit your Gemfile.lock to your repository and redeploy.
250
251
  c.release_path = c.previous_release(rolled_back_release)
251
252
 
252
253
  revision = File.read(File.join(c.release_path, 'REVISION')).strip
253
- info "~> Rolling back to previous release: #{short_log_message(revision)}"
254
+ shell.status "Rolling back to previous release: #{short_log_message(revision)}"
254
255
 
255
256
  run_with_callbacks(:symlink)
256
257
  sudo "rm -rf #{rolled_back_release}"
257
258
  bundle
258
- info "~> Restarting with previous release."
259
+ shell.status "Restarting with previous release."
259
260
  with_maintenance_page { run_with_callbacks(:restart) }
260
261
  else
261
- info "~> Already at oldest release, nothing to roll back to."
262
+ shell.status "Already at oldest release, nothing to roll back to."
262
263
  exit(1)
263
264
  end
264
265
  end
@@ -269,17 +270,17 @@ To fix this problem, commit your Gemfile.lock to your repository and redeploy.
269
270
  @migrations_reached = true
270
271
  roles :app_master, :solo do
271
272
  cmd = "cd #{c.release_path} && PATH=#{c.binstubs_path}:$PATH #{c.framework_envs} #{c.migration_command}"
272
- info "~> Migrating: #{cmd}"
273
+ shell.status "Migrating: #{cmd}"
273
274
  run(cmd)
274
275
  end
275
276
  end
276
277
 
277
278
  # task
278
279
  def copy_repository_cache
279
- info "~> Copying to #{c.release_path}"
280
+ shell.status "Copying to #{c.release_path}"
280
281
  run("mkdir -p #{c.release_path} #{c.failed_release_dir} && rsync -aq #{c.exclusions} #{c.repository_cache}/ #{c.release_path}")
281
282
 
282
- info "~> Ensuring proper ownership."
283
+ shell.status "Ensuring proper ownership."
283
284
  sudo("chown -R #{c.user}:#{c.group} #{c.deploy_to}")
284
285
  end
285
286
 
@@ -295,8 +296,12 @@ To fix this problem, commit your Gemfile.lock to your repository and redeploy.
295
296
  "/usr/local/ey_resin/ruby/bin/ey-services-setup #{config.app}"
296
297
  end
297
298
 
299
+ def node_package_manager_command_check
300
+ "which npm"
301
+ end
302
+
298
303
  def setup_services
299
- info "~> Setting up external services."
304
+ shell.status "Setting up external services."
300
305
  previously_configured_services = parse_configured_services
301
306
  begin
302
307
  sudo(services_command_check)
@@ -332,24 +337,24 @@ YML
332
337
  WRAP
333
338
  ["Symlink database.yml", "ln -nfs #{c.shared_path}/config/database.sqlite3.yml #{c.release_path}/config/database.yml"],
334
339
  ].each do |what, cmd|
335
- info "~> #{what}"
340
+ shell.status "#{what}"
336
341
  run(cmd)
337
342
  end
338
343
 
339
344
  owner = [c.user, c.group].join(':')
340
- info "~> Setting ownership to #{owner}"
345
+ shell.status "Setting ownership to #{owner}"
341
346
  sudo "chown -R #{owner} #{c.release_path}"
342
347
  end
343
348
  end
344
349
 
345
350
  def symlink_configs(release_to_link=c.release_path)
346
- info "~> Preparing shared resources for release."
351
+ shell.status "Preparing shared resources for release."
347
352
  symlink_tasks(release_to_link).each do |what, cmd|
348
- info "~> #{what}"
353
+ shell.substatus what
349
354
  run(cmd)
350
355
  end
351
356
  owner = [c.user, c.group].join(':')
352
- info "~> Setting ownership to #{owner}"
357
+ shell.status "Setting ownership to #{owner}"
353
358
  sudo "chown -R #{owner} #{release_to_link}"
354
359
  end
355
360
 
@@ -372,7 +377,7 @@ WRAP
372
377
 
373
378
  # task
374
379
  def symlink(release_to_link=c.release_path)
375
- info "~> Symlinking code."
380
+ shell.status "Symlinking code."
376
381
  run "rm -f #{c.current_path} && ln -nfs #{release_to_link} #{c.current_path} && chown -R #{c.user}:#{c.group} #{c.current_path}"
377
382
  @symlink_changed = true
378
383
  rescue Exception
@@ -382,7 +387,7 @@ WRAP
382
387
  end
383
388
 
384
389
  def callback(what)
385
- @callbacks_reached = true
390
+ @callbacks_reached ||= true
386
391
  if File.exist?("#{c.release_path}/deploy/#{what}.rb")
387
392
  run Escape.shell_command(base_callback_command_for(what)) do |server, cmd|
388
393
  per_instance_args = [
@@ -406,11 +411,14 @@ WRAP
406
411
  end
407
412
 
408
413
  def base_callback_command_for(what)
409
- [serverside_bin, 'hook', what.to_s,
410
- '--app', config.app,
411
- '--release-path', config.release_path.to_s,
412
- '--framework-env', c.environment.to_s,
413
- ].compact
414
+ cmd = [serverside_bin, 'hook', what.to_s]
415
+ cmd << '--app' << config.app
416
+ cmd << '--environment-name' << config.environment_name
417
+ cmd << '--account-name' << config.account_name
418
+ cmd << '--release-path' << config.release_path.to_s
419
+ cmd << '--framework-env' << config.environment.to_s
420
+ cmd << '--verbose' if config.verbose
421
+ cmd
414
422
  end
415
423
 
416
424
  def serverside_bin
@@ -420,9 +428,9 @@ WRAP
420
428
 
421
429
  def puts_deploy_failure
422
430
  if @cleanup_failed
423
- info "~> [Relax] Your site is running new code, but clean up of old deploys failed."
431
+ shell.status "[Relax] Your site is running new code, but clean up of old deploys failed."
424
432
  elsif @maintenance_up
425
- info "~> [Attention] Maintenance page still up, consider the following before removing:"
433
+ shell.status "[Attention] Maintenance page still up, consider the following before removing:"
426
434
  info " * Deploy hooks ran. This might cause problems for reverting to old code." if @callbacks_reached
427
435
  info " * Migrations ran. This might cause problems for reverting to old code." if @migrations_reached
428
436
  if @symlink_changed
@@ -432,9 +440,9 @@ WRAP
432
440
  end
433
441
  info " * Application servers failed to restart." if @restart_failed
434
442
  info ""
435
- info "~> Need help? File a ticket for support."
443
+ shell.status "Need help? File a ticket for support."
436
444
  else
437
- info "~> [Relax] Your site is still running old code and nothing destructive has occurred."
445
+ shell.status "[Relax] Your site is still running old code and nothing destructive has occurred."
438
446
  end
439
447
  end
440
448
 
@@ -447,7 +455,7 @@ WRAP
447
455
  def with_failed_release_cleanup
448
456
  yield
449
457
  rescue Exception
450
- info "~> Release #{c.release_path} failed, saving release to #{c.failed_release_dir}."
458
+ shell.status "Release #{c.release_path} failed, saving release to #{c.failed_release_dir}."
451
459
  sudo "mv #{c.release_path} #{c.failed_release_dir}"
452
460
  raise
453
461
  end
@@ -480,7 +488,7 @@ WRAP
480
488
 
481
489
  def check_ruby_bundler
482
490
  if gemfile?
483
- info "~> Bundling gems..."
491
+ shell.status "Bundling gems..."
484
492
 
485
493
  clean_bundle_on_system_version_change
486
494
 
@@ -511,14 +519,18 @@ WRAP
511
519
 
512
520
  def check_node_npm
513
521
  if File.exist?("#{c.release_path}/package.json")
514
- info "~> package.json detected, installing npm packages"
515
- run "cd #{c.release_path} && npm install"
522
+ unless run(node_package_manager_command_check)
523
+ abort "*** [Error] package.json detected, but npm was not installed"
524
+ else
525
+ shell.status "package.json detected, installing npm packages"
526
+ run "cd #{c.release_path} && npm install"
527
+ end
516
528
  end
517
529
  end
518
530
  end # DeployBase
519
531
 
520
532
  class Deploy < DeployBase
521
- def self.new(config)
533
+ def self.new(config, shell=nil)
522
534
  # include the correct fetch strategy
523
535
  include EY::Serverside::Strategies.const_get(config.strategy)::Helpers
524
536
  super