ey-deploy 0.7.1 → 0.8.0
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/ey-deploy/cli.rb +44 -34
- data/lib/ey-deploy/configuration.rb +1 -1
- data/lib/ey-deploy/deploy.rb +39 -33
- data/lib/ey-deploy/logged_output.rb +18 -4
- data/lib/ey-deploy/strategies/git.rb +18 -4
- data/lib/ey-deploy/version.rb +1 -1
- metadata +4 -4
data/lib/ey-deploy/cli.rb
CHANGED
|
@@ -10,36 +10,41 @@ module EY
|
|
|
10
10
|
exit(1)
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
-
method_option :migrate,
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
method_option :migrate, :type => :string,
|
|
14
|
+
:desc => "Run migrations with this deploy",
|
|
15
|
+
:aliases => ["-m"]
|
|
16
16
|
|
|
17
|
-
method_option :branch,
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
method_option :branch, :type => :string,
|
|
18
|
+
:desc => "Branch to deploy from, defaults to master",
|
|
19
|
+
:aliases => ["-b"]
|
|
20
20
|
|
|
21
|
-
method_option :repo,
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
method_option :repo, :type => :string,
|
|
22
|
+
:desc => "Remote repo to deploy",
|
|
23
|
+
:aliases => ["-r"]
|
|
24
24
|
|
|
25
|
-
method_option :app,
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
method_option :app, :type => :string,
|
|
26
|
+
:required => true,
|
|
27
|
+
:desc => "Application to deploy",
|
|
28
|
+
:aliases => ["-a"]
|
|
29
29
|
|
|
30
|
-
method_option :
|
|
31
|
-
|
|
30
|
+
method_option :framework_env, :type => :string,
|
|
31
|
+
:required => true,
|
|
32
|
+
:desc => "Ruby web framework environment",
|
|
33
|
+
:aliases => ["-e"]
|
|
32
34
|
|
|
33
|
-
method_option :
|
|
34
|
-
|
|
35
|
+
method_option :config, :type => :string,
|
|
36
|
+
:desc => "Additional configuration"
|
|
35
37
|
|
|
36
|
-
method_option :
|
|
37
|
-
|
|
38
|
+
method_option :stack, :type => :string,
|
|
39
|
+
:desc => "Web stack (so we can restart it correctly)"
|
|
38
40
|
|
|
39
|
-
method_option :
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
method_option :instances, :type => :array,
|
|
42
|
+
:desc => "Instances in cluster"
|
|
43
|
+
|
|
44
|
+
method_option :verbose, :type => :boolean,
|
|
45
|
+
:default => false,
|
|
46
|
+
:desc => "Verbose output",
|
|
47
|
+
:aliases => ["-v"]
|
|
43
48
|
|
|
44
49
|
desc "deploy", "Deploy code from /data/<app>"
|
|
45
50
|
def deploy(default_task=:deploy)
|
|
@@ -51,20 +56,25 @@ module EY
|
|
|
51
56
|
EY::Deploy.run(options.merge("default_task" => default_task))
|
|
52
57
|
end
|
|
53
58
|
|
|
54
|
-
method_option :app,
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
59
|
+
method_option :app, :type => :string,
|
|
60
|
+
:required => true,
|
|
61
|
+
:desc => "Which application's hooks to run",
|
|
62
|
+
:aliases => ["-a"]
|
|
63
|
+
|
|
64
|
+
method_option :release_path, :type => :string,
|
|
65
|
+
:desc => "Value for #release_path in hooks (mostly for internal coordination)",
|
|
66
|
+
:aliases => ["-r"]
|
|
58
67
|
|
|
59
|
-
method_option :
|
|
60
|
-
|
|
61
|
-
:aliases => ["-r"]
|
|
68
|
+
method_option :current_role, :type => :string,
|
|
69
|
+
:desc => "Value for #current_role in hooks"
|
|
62
70
|
|
|
63
|
-
method_option :
|
|
64
|
-
|
|
71
|
+
method_option :framework_env, :type => :string,
|
|
72
|
+
:required => true,
|
|
73
|
+
:desc => "Ruby web framework environment",
|
|
74
|
+
:aliases => ["-e"]
|
|
65
75
|
|
|
66
|
-
method_option :current_name,
|
|
67
|
-
|
|
76
|
+
method_option :current_name, :type => :string,
|
|
77
|
+
:desc => "Value for #current_name in hooks"
|
|
68
78
|
|
|
69
79
|
desc "hook [NAME]", "Run a particular deploy hook"
|
|
70
80
|
def hook(hook_name)
|
data/lib/ey-deploy/deploy.rb
CHANGED
|
@@ -6,13 +6,15 @@ require 'yaml'
|
|
|
6
6
|
|
|
7
7
|
module EY
|
|
8
8
|
class DeployBase < Task
|
|
9
|
+
include LoggedOutput
|
|
10
|
+
|
|
9
11
|
# default task
|
|
10
12
|
def deploy
|
|
11
13
|
update_repository_cache
|
|
12
14
|
require_custom_tasks
|
|
13
15
|
push_code
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
info "~> Starting full deploy"
|
|
16
18
|
copy_repository_cache
|
|
17
19
|
|
|
18
20
|
with_failed_release_cleanup do
|
|
@@ -31,7 +33,7 @@ module EY
|
|
|
31
33
|
|
|
32
34
|
cleanup_old_releases
|
|
33
35
|
|
|
34
|
-
|
|
36
|
+
info "~> Finalizing deploy"
|
|
35
37
|
rescue Exception
|
|
36
38
|
puts_deploy_failure
|
|
37
39
|
raise
|
|
@@ -86,7 +88,7 @@ module EY
|
|
|
86
88
|
|
|
87
89
|
# task
|
|
88
90
|
def push_code
|
|
89
|
-
|
|
91
|
+
info "~> Pushing code to all servers"
|
|
90
92
|
barrier *(EY::Server.all.map do |server|
|
|
91
93
|
need_later { server.push_code }
|
|
92
94
|
end)
|
|
@@ -95,7 +97,7 @@ module EY
|
|
|
95
97
|
# task
|
|
96
98
|
def restart
|
|
97
99
|
@restart_failed = true
|
|
98
|
-
|
|
100
|
+
info "~> Restarting app servers"
|
|
99
101
|
roles :app_master, :app, :solo do
|
|
100
102
|
restart_command = case c.stack
|
|
101
103
|
when "nginx_unicorn"
|
|
@@ -117,7 +119,7 @@ module EY
|
|
|
117
119
|
# task
|
|
118
120
|
def bundle
|
|
119
121
|
if File.exist?("#{c.latest_release}/Gemfile")
|
|
120
|
-
|
|
122
|
+
info "~> Gemfile detected, bundling gems"
|
|
121
123
|
lockfile = File.join(c.latest_release, "Gemfile.lock")
|
|
122
124
|
|
|
123
125
|
bundler_version = if File.exist?(lockfile)
|
|
@@ -136,7 +138,7 @@ module EY
|
|
|
136
138
|
# task
|
|
137
139
|
def cleanup_old_releases
|
|
138
140
|
@cleanup_failed = true
|
|
139
|
-
|
|
141
|
+
info "~> Cleaning up old releases"
|
|
140
142
|
sudo "ls #{c.release_dir} | head -n -3 | xargs -I{} rm -rf #{c.release_dir}/{}"
|
|
141
143
|
@cleanup_failed = false
|
|
142
144
|
end
|
|
@@ -144,15 +146,18 @@ module EY
|
|
|
144
146
|
# task
|
|
145
147
|
def rollback
|
|
146
148
|
if c.all_releases.size > 1
|
|
147
|
-
puts "~> Rolling back to previous release"
|
|
148
149
|
c.release_path = c.previous_release
|
|
150
|
+
|
|
151
|
+
revision = File.read(File.join(c.release_path, 'REVISION')).strip
|
|
152
|
+
info "~> Rolling back to previous release: #{short_log_message(revision)}"
|
|
153
|
+
|
|
149
154
|
run_with_callbacks(:symlink, c.previous_release)
|
|
150
155
|
cleanup_latest_release
|
|
151
156
|
bundle
|
|
152
|
-
|
|
157
|
+
info "~> Restarting with previous release"
|
|
153
158
|
with_maintenance_page { run_with_callbacks(:restart) }
|
|
154
159
|
else
|
|
155
|
-
|
|
160
|
+
info "~> Already at oldest release, nothing to roll back to"
|
|
156
161
|
exit(1)
|
|
157
162
|
end
|
|
158
163
|
end
|
|
@@ -163,22 +168,22 @@ module EY
|
|
|
163
168
|
@migrations_reached = true
|
|
164
169
|
roles :app_master, :solo do
|
|
165
170
|
cmd = "cd #{c.latest_release} && #{c.framework_envs} #{c.migration_command}"
|
|
166
|
-
|
|
171
|
+
info "~> Migrating: #{cmd}"
|
|
167
172
|
run(cmd)
|
|
168
173
|
end
|
|
169
174
|
end
|
|
170
175
|
|
|
171
176
|
# task
|
|
172
177
|
def copy_repository_cache
|
|
173
|
-
|
|
178
|
+
info "~> Copying to #{c.release_path}"
|
|
174
179
|
sudo("mkdir -p #{c.release_path} && rsync -aq #{c.exclusions} #{c.repository_cache}/ #{c.release_path}")
|
|
175
180
|
|
|
176
|
-
|
|
181
|
+
info "~> Ensuring proper ownership"
|
|
177
182
|
sudo("chown -R #{c.user}:#{c.group} #{c.deploy_to}")
|
|
178
183
|
end
|
|
179
184
|
|
|
180
185
|
def symlink_configs(release_to_link=c.latest_release)
|
|
181
|
-
|
|
186
|
+
info "~> Symlinking configs"
|
|
182
187
|
[ "chmod -R g+w #{release_to_link}",
|
|
183
188
|
"rm -rf #{release_to_link}/log #{release_to_link}/public/system #{release_to_link}/tmp/pids",
|
|
184
189
|
"mkdir -p #{release_to_link}/tmp",
|
|
@@ -199,7 +204,7 @@ module EY
|
|
|
199
204
|
|
|
200
205
|
# task
|
|
201
206
|
def symlink(release_to_link=c.latest_release)
|
|
202
|
-
|
|
207
|
+
info "~> Symlinking code"
|
|
203
208
|
sudo "rm -f #{c.current_path} && ln -nfs #{release_to_link} #{c.current_path} && chown -R #{c.user}:#{c.group} #{c.current_path}"
|
|
204
209
|
@symlink_changed = true
|
|
205
210
|
rescue Exception
|
|
@@ -213,6 +218,7 @@ module EY
|
|
|
213
218
|
if File.exist?("#{c.latest_release}/deploy/#{what}.rb")
|
|
214
219
|
eysd_path = $0 # invoke others just like we were invoked
|
|
215
220
|
run "#{eysd_path} _#{VERSION}_ hook '#{what}' --app '#{config.app}' --release-path #{config.release_path}" do |server, cmd|
|
|
221
|
+
cmd << " --framework-env '#{c.environment}'"
|
|
216
222
|
cmd << " --current-role '#{server.role}'"
|
|
217
223
|
cmd << " --current-name '#{server.name}'" if server.name
|
|
218
224
|
cmd
|
|
@@ -224,19 +230,19 @@ module EY
|
|
|
224
230
|
|
|
225
231
|
def puts_deploy_failure
|
|
226
232
|
if @cleanup_failed
|
|
227
|
-
|
|
233
|
+
info "~> [Relax] Your site is running new code, but cleaning up old deploys failed"
|
|
228
234
|
elsif @maintenance_up
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
235
|
+
info "~> [Attention] Maintenance page still up, consider the following before removing:"
|
|
236
|
+
info " * any deploy hooks ran, be careful if they were destructive" if @callbacks_reached
|
|
237
|
+
info " * any migrations ran, be careful if they were destructive" if @migrations_reached
|
|
232
238
|
if @symlink_changed
|
|
233
|
-
|
|
239
|
+
info " * your new code is symlinked as current"
|
|
234
240
|
else
|
|
235
|
-
|
|
241
|
+
info " * your old code is still symlinked as current"
|
|
236
242
|
end
|
|
237
|
-
|
|
243
|
+
info " * application servers failed to restart" if @restart_failed
|
|
238
244
|
else
|
|
239
|
-
|
|
245
|
+
info "~> [Relax] Your site is still running old code and nothing destructive could have occurred"
|
|
240
246
|
end
|
|
241
247
|
end
|
|
242
248
|
|
|
@@ -267,17 +273,17 @@ module EY
|
|
|
267
273
|
DEFAULT_10_BUNDLER = '1.0.0.beta.1'
|
|
268
274
|
|
|
269
275
|
def warn_about_missing_lockfile
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
276
|
+
info "!>"
|
|
277
|
+
info "!> WARNING: Gemfile.lock is missing!"
|
|
278
|
+
info "!> You can get different gems in production than what you tested with."
|
|
279
|
+
info "!> You can get different gems on every deployment even if your Gemfile hasn't changed."
|
|
280
|
+
info "!> Deploying may take a long time."
|
|
281
|
+
info "!>"
|
|
282
|
+
info "!> Fix this by running \"git add Gemfile.lock; git commit\" and deploying again."
|
|
283
|
+
info "!> If you don't have a Gemfile.lock, run \"bundle lock\" to create one."
|
|
284
|
+
info "!>"
|
|
285
|
+
info "!> This deployment will use bundler #{DEFAULT_09_BUNDLER} to run 'bundle install'."
|
|
286
|
+
info "!>"
|
|
281
287
|
end
|
|
282
288
|
|
|
283
289
|
def get_bundler_version(lockfile)
|
|
@@ -9,7 +9,10 @@ module EY
|
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
def <<(output)
|
|
12
|
-
@streams.each
|
|
12
|
+
@streams.each do |s|
|
|
13
|
+
s << output
|
|
14
|
+
s.flush
|
|
15
|
+
end
|
|
13
16
|
self
|
|
14
17
|
end
|
|
15
18
|
end # Tee
|
|
@@ -37,12 +40,14 @@ module EY
|
|
|
37
40
|
EY::LoggedOutput.verbose?
|
|
38
41
|
end
|
|
39
42
|
|
|
40
|
-
def
|
|
41
|
-
|
|
43
|
+
def info(msg)
|
|
44
|
+
with_logfile do |log|
|
|
45
|
+
Tee.new($stdout, log) << (msg + "\n")
|
|
46
|
+
end
|
|
42
47
|
end
|
|
43
48
|
|
|
44
49
|
def logged_system(cmd)
|
|
45
|
-
|
|
50
|
+
with_logfile do |log|
|
|
46
51
|
out = verbose? ? Tee.new($stdout, log) : log
|
|
47
52
|
err = Tee.new($stderr, log) # we always want to see errors
|
|
48
53
|
|
|
@@ -54,5 +59,14 @@ module EY
|
|
|
54
59
|
end
|
|
55
60
|
end
|
|
56
61
|
|
|
62
|
+
private
|
|
63
|
+
def with_logfile
|
|
64
|
+
File.open(logfile, 'a') {|f| yield f }
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def logfile
|
|
68
|
+
EY::LoggedOutput.logfile
|
|
69
|
+
end
|
|
70
|
+
|
|
57
71
|
end
|
|
58
72
|
end
|
|
@@ -13,13 +13,22 @@ module EY
|
|
|
13
13
|
strategy.create_revision_file(c.release_path)
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
+
def short_log_message(revision)
|
|
17
|
+
strategy.short_log_message(revision)
|
|
18
|
+
end
|
|
19
|
+
|
|
16
20
|
def strategy
|
|
17
21
|
klass = Module.nesting[1]
|
|
22
|
+
# Use [] to access attributes instead of calling methods so
|
|
23
|
+
# that we get nils instead of NoMethodError.
|
|
24
|
+
#
|
|
25
|
+
# Rollback doesn't know about the repository location (nor
|
|
26
|
+
# should it need to), but it would like to use #short_log_message.
|
|
18
27
|
klass.new(
|
|
19
|
-
:repository_cache => c
|
|
20
|
-
:app => c
|
|
21
|
-
:repo => c
|
|
22
|
-
:ref => c
|
|
28
|
+
:repository_cache => c[:repository_cache],
|
|
29
|
+
:app => c[:app],
|
|
30
|
+
:repo => c[:repo],
|
|
31
|
+
:ref => c[:branch]
|
|
23
32
|
)
|
|
24
33
|
end
|
|
25
34
|
end
|
|
@@ -53,6 +62,7 @@ module EY
|
|
|
53
62
|
opts[:ref]
|
|
54
63
|
end
|
|
55
64
|
|
|
65
|
+
info "~> Deploying revision #{short_log_message(to_checkout)}"
|
|
56
66
|
logged_system("#{git} checkout -q '#{to_checkout}'") || logged_system("#{git} reset -q --hard '#{to_checkout}'")
|
|
57
67
|
end
|
|
58
68
|
|
|
@@ -60,6 +70,10 @@ module EY
|
|
|
60
70
|
`#{git} show --pretty=format:"%H" | head -1 > "#{dir}/REVISION"`
|
|
61
71
|
end
|
|
62
72
|
|
|
73
|
+
def short_log_message(rev)
|
|
74
|
+
`#{git} log --pretty=oneline --abbrev-commit '#{rev}^..#{rev}'`.strip
|
|
75
|
+
end
|
|
76
|
+
|
|
63
77
|
private
|
|
64
78
|
def git
|
|
65
79
|
"git --git-dir #{opts[:repository_cache]}/.git --work-tree #{opts[:repository_cache]}"
|
data/lib/ey-deploy/version.rb
CHANGED
metadata
CHANGED
|
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
|
4
4
|
prerelease: false
|
|
5
5
|
segments:
|
|
6
6
|
- 0
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
version: 0.
|
|
7
|
+
- 8
|
|
8
|
+
- 0
|
|
9
|
+
version: 0.8.0
|
|
10
10
|
platform: ruby
|
|
11
11
|
authors:
|
|
12
12
|
- EY Cloud Team
|
|
@@ -14,7 +14,7 @@ autorequire:
|
|
|
14
14
|
bindir: bin
|
|
15
15
|
cert_chain: []
|
|
16
16
|
|
|
17
|
-
date: 2010-06-
|
|
17
|
+
date: 2010-06-30 00:00:00 -07:00
|
|
18
18
|
default_executable: eysd
|
|
19
19
|
dependencies:
|
|
20
20
|
- !ruby/object:Gem::Dependency
|