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.
- data/lib/engineyard-serverside.rb +3 -1
- data/lib/engineyard-serverside/cli.rb +73 -38
- data/lib/engineyard-serverside/configuration.rb +38 -12
- data/lib/engineyard-serverside/deploy.rb +63 -51
- data/lib/engineyard-serverside/deploy_hook.rb +21 -18
- data/lib/engineyard-serverside/deprecation.rb +9 -17
- data/lib/engineyard-serverside/lockfile_parser.rb +1 -1
- data/lib/engineyard-serverside/rails_asset_support.rb +5 -5
- data/lib/engineyard-serverside/server.rb +8 -11
- data/lib/engineyard-serverside/shell.rb +101 -0
- data/lib/engineyard-serverside/shell/formatter.rb +70 -0
- data/lib/engineyard-serverside/shell/helpers.rb +29 -0
- data/lib/engineyard-serverside/strategies/git.rb +12 -15
- data/lib/engineyard-serverside/task.rb +28 -5
- data/lib/engineyard-serverside/version.rb +1 -1
- data/lib/vendor/open4/lib/open4.rb +432 -0
- data/spec/basic_deploy_spec.rb +9 -9
- data/spec/bundler_deploy_spec.rb +1 -1
- data/spec/custom_deploy_spec.rb +45 -4
- data/spec/deploy_hook_spec.rb +77 -78
- data/spec/deprecation_spec.rb +4 -26
- data/spec/git_strategy_spec.rb +6 -2
- data/spec/nodejs_deploy_spec.rb +2 -2
- data/spec/services_deploy_spec.rb +11 -10
- data/spec/shell_spec.rb +48 -0
- data/spec/spec_helper.rb +48 -25
- data/spec/sqlite3_deploy_spec.rb +1 -2
- data/spec/support/integration.rb +1 -13
- metadata +57 -97
- data/lib/engineyard-serverside/logged_output.rb +0 -91
- data/lib/vendor/systemu/LICENSE +0 -3
- data/lib/vendor/systemu/lib/systemu.rb +0 -363
- data/lib/vendor/systemu/systemu.gemspec +0 -45
- data/spec/fixtures/gitrepo/bar +0 -0
- 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/
|
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 =
|
54
|
-
|
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
|
-
|
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 =
|
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
|
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
|
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
|
-
|
181
|
-
EY::Serverside::LoggedOutput.logfile = File.join(ENV['HOME'], "#{options[:app]}-restart.log")
|
204
|
+
config, shell = init_and_propagate(options, 'restart')
|
182
205
|
|
183
|
-
|
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
|
-
|
207
|
-
|
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
|
223
|
-
|
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
|
-
|
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
|
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
|
-
|
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
|
-
@
|
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
|
-
|
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
|
-
|
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
|
-
|
51
|
+
configuration[key]
|
39
52
|
end
|
40
53
|
end
|
41
54
|
|
42
55
|
def has_key?(key)
|
43
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
50
|
+
shell.status "Finished deploy at #{Time.now.asctime}"
|
51
51
|
rescue Exception
|
52
|
-
|
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
|
-
|
76
|
+
shell.status "Gemfile found."
|
77
77
|
if lockfile
|
78
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
259
|
+
shell.status "Restarting with previous release."
|
259
260
|
with_maintenance_page { run_with_callbacks(:restart) }
|
260
261
|
else
|
261
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
340
|
+
shell.status "#{what}"
|
336
341
|
run(cmd)
|
337
342
|
end
|
338
343
|
|
339
344
|
owner = [c.user, c.group].join(':')
|
340
|
-
|
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
|
-
|
351
|
+
shell.status "Preparing shared resources for release."
|
347
352
|
symlink_tasks(release_to_link).each do |what, cmd|
|
348
|
-
|
353
|
+
shell.substatus what
|
349
354
|
run(cmd)
|
350
355
|
end
|
351
356
|
owner = [c.user, c.group].join(':')
|
352
|
-
|
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
|
-
|
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
|
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
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
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
|
-
|
431
|
+
shell.status "[Relax] Your site is running new code, but clean up of old deploys failed."
|
424
432
|
elsif @maintenance_up
|
425
|
-
|
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
|
-
|
443
|
+
shell.status "Need help? File a ticket for support."
|
436
444
|
else
|
437
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
515
|
-
|
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
|