engineyard-serverside 1.6.0.pre5 → 1.6.3
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 +1 -3
- data/lib/engineyard-serverside/cli.rb +38 -73
- data/lib/engineyard-serverside/configuration.rb +12 -38
- data/lib/engineyard-serverside/deploy.rb +54 -63
- data/lib/engineyard-serverside/deploy_hook.rb +18 -21
- data/lib/engineyard-serverside/deprecation.rb +17 -9
- data/lib/engineyard-serverside/lockfile_parser.rb +1 -1
- data/lib/engineyard-serverside/logged_output.rb +91 -0
- data/lib/engineyard-serverside/rails_asset_support.rb +5 -5
- data/lib/engineyard-serverside/server.rb +11 -8
- data/lib/engineyard-serverside/strategies/git.rb +15 -12
- data/lib/engineyard-serverside/task.rb +8 -29
- data/lib/engineyard-serverside/version.rb +1 -1
- data/lib/vendor/systemu/LICENSE +3 -0
- data/lib/vendor/systemu/lib/systemu.rb +363 -0
- data/lib/vendor/systemu/systemu.gemspec +45 -0
- data/spec/basic_deploy_spec.rb +9 -9
- data/spec/bundler_deploy_spec.rb +1 -1
- data/spec/custom_deploy_spec.rb +4 -63
- data/spec/deploy_hook_spec.rb +78 -77
- data/spec/deprecation_spec.rb +26 -4
- data/spec/git_strategy_spec.rb +2 -6
- data/spec/logged_output_spec.rb +55 -0
- data/spec/nodejs_deploy_spec.rb +2 -2
- data/spec/services_deploy_spec.rb +10 -11
- data/spec/spec_helper.rb +25 -48
- data/spec/sqlite3_deploy_spec.rb +2 -1
- data/spec/support/integration.rb +14 -2
- metadata +79 -94
- data/lib/engineyard-serverside/shell.rb +0 -102
- data/lib/engineyard-serverside/shell/formatter.rb +0 -73
- data/lib/engineyard-serverside/shell/helpers.rb +0 -29
- data/lib/vendor/open4/lib/open4.rb +0 -432
- data/spec/shell_spec.rb +0 -50
@@ -1,73 +0,0 @@
|
|
1
|
-
module EY
|
2
|
-
module Serverside
|
3
|
-
class Shell
|
4
|
-
class Formatter
|
5
|
-
def initialize(stdout, stderr, start_time, verbose)
|
6
|
-
@stdout, @stderr = stdout, stderr
|
7
|
-
@start = start_time.to_i
|
8
|
-
@verbose = verbose
|
9
|
-
end
|
10
|
-
|
11
|
-
def call(severity, time, _, message)
|
12
|
-
msg = build_message(severity, timestamp(time), message)
|
13
|
-
put_to_io(severity, msg)
|
14
|
-
msg
|
15
|
-
end
|
16
|
-
|
17
|
-
def build_message(severity, stamp, message)
|
18
|
-
if %w[WARN ERROR FATAL].include?(severity)
|
19
|
-
prepend("#{stamp}!> ", "#{message}")
|
20
|
-
elsif severity == "WARN"
|
21
|
-
prepend("#{stamp}!> ", "#{message}")
|
22
|
-
elsif severity == "INFO"
|
23
|
-
prepend(stamp, message)
|
24
|
-
else
|
25
|
-
prepend(' ' * stamp.size, message)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def prepend(pre, str)
|
30
|
-
str.gsub(/^/, pre).sub(/\n?\z/m,"\n")
|
31
|
-
end
|
32
|
-
|
33
|
-
def put_to_io(severity, msg)
|
34
|
-
case severity
|
35
|
-
when "DEBUG"
|
36
|
-
if @verbose
|
37
|
-
@stdout << msg
|
38
|
-
end
|
39
|
-
when "INFO"
|
40
|
-
# Need to differentiate info messages more when we're running in verbose mode
|
41
|
-
@stdout << (@verbose && msg.index('~>') ? "\n#{thor_shell.set_color(msg, :white, true)}" : msg)
|
42
|
-
@stdout.flush
|
43
|
-
when "WARN"
|
44
|
-
@stderr << "\n" << thor_shell.set_color(msg, :yellow, true)
|
45
|
-
@stderr.flush
|
46
|
-
when "ERROR"
|
47
|
-
@stderr << "\n" << thor_shell.set_color(msg, :red, true)
|
48
|
-
@stderr.flush
|
49
|
-
else
|
50
|
-
@stderr << msg
|
51
|
-
@stderr.flush
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
def timestamp(datetime)
|
56
|
-
diff = datetime.to_i - @start
|
57
|
-
diff = 0 if diff < 0
|
58
|
-
div, mod = diff.divmod(60)
|
59
|
-
if div.zero?
|
60
|
-
"+ %02ds " % mod
|
61
|
-
else
|
62
|
-
"+%2dm %02ds " % [div,mod]
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
def thor_shell
|
67
|
-
thor_shell ||= Thor::Shell::Color.new
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
@@ -1,29 +0,0 @@
|
|
1
|
-
module EY
|
2
|
-
module Serverside
|
3
|
-
class Shell
|
4
|
-
# Compatibility with old LoggedOutput where the module was included into the class.
|
5
|
-
module Helpers
|
6
|
-
def verbose?
|
7
|
-
shell.verbose?
|
8
|
-
end
|
9
|
-
|
10
|
-
def warning(*a)
|
11
|
-
shell.warning(*a)
|
12
|
-
end
|
13
|
-
|
14
|
-
def info(*a)
|
15
|
-
shell.info(*a)
|
16
|
-
end
|
17
|
-
|
18
|
-
def debug(*a)
|
19
|
-
shell.debug(*a)
|
20
|
-
end
|
21
|
-
|
22
|
-
def logged_system(*a)
|
23
|
-
shell.logged_system(*a)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
@@ -1,432 +0,0 @@
|
|
1
|
-
# vim: ts=2:sw=2:sts=2:et:fdm=marker
|
2
|
-
require 'fcntl'
|
3
|
-
require 'timeout'
|
4
|
-
require 'thread'
|
5
|
-
|
6
|
-
module Open4
|
7
|
-
VERSION = '1.3.0'
|
8
|
-
def self.version() VERSION end
|
9
|
-
|
10
|
-
class Error < ::StandardError; end
|
11
|
-
|
12
|
-
def pfork4(fun, &b)
|
13
|
-
Open4.do_popen(b, :block) do |ps_read, _|
|
14
|
-
ps_read.close
|
15
|
-
begin
|
16
|
-
fun.call
|
17
|
-
rescue SystemExit => e
|
18
|
-
# Make it seem to the caller that calling Kernel#exit in +fun+ kills
|
19
|
-
# the child process normally. Kernel#exit! bypasses this rescue
|
20
|
-
# block.
|
21
|
-
exit! e.status
|
22
|
-
else
|
23
|
-
exit! 0
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
module_function :pfork4
|
28
|
-
|
29
|
-
def popen4(*cmd, &b)
|
30
|
-
Open4.do_popen(b, :init) do |ps_read, ps_write|
|
31
|
-
ps_read.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
|
32
|
-
ps_write.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
|
33
|
-
exec(*cmd)
|
34
|
-
raise 'forty-two' # Is this really needed?
|
35
|
-
end
|
36
|
-
end
|
37
|
-
alias open4 popen4
|
38
|
-
module_function :popen4
|
39
|
-
module_function :open4
|
40
|
-
|
41
|
-
def popen4ext(closefds=false, *cmd, &b)
|
42
|
-
Open4.do_popen(b, :init, closefds) do |ps_read, ps_write|
|
43
|
-
ps_read.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
|
44
|
-
ps_write.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
|
45
|
-
exec(*cmd)
|
46
|
-
raise 'forty-two' # Is this really needed?
|
47
|
-
end
|
48
|
-
end
|
49
|
-
module_function :popen4ext
|
50
|
-
|
51
|
-
def self.do_popen(b = nil, exception_propagation_at = nil, closefds=false, &cmd)
|
52
|
-
pw, pr, pe, ps = IO.pipe, IO.pipe, IO.pipe, IO.pipe
|
53
|
-
|
54
|
-
verbose = $VERBOSE
|
55
|
-
begin
|
56
|
-
$VERBOSE = nil
|
57
|
-
|
58
|
-
cid = fork {
|
59
|
-
if closefds
|
60
|
-
exlist = [0, 1, 2] | [pw,pr,pe,ps].map{|p| [p.first.fileno, p.last.fileno] }.flatten
|
61
|
-
ObjectSpace.each_object(IO){|io|
|
62
|
-
io.close if (not io.closed?) and (not exlist.include? io.fileno)
|
63
|
-
}
|
64
|
-
end
|
65
|
-
|
66
|
-
pw.last.close
|
67
|
-
STDIN.reopen pw.first
|
68
|
-
pw.first.close
|
69
|
-
|
70
|
-
pr.first.close
|
71
|
-
STDOUT.reopen pr.last
|
72
|
-
pr.last.close
|
73
|
-
|
74
|
-
pe.first.close
|
75
|
-
STDERR.reopen pe.last
|
76
|
-
pe.last.close
|
77
|
-
|
78
|
-
STDOUT.sync = STDERR.sync = true
|
79
|
-
|
80
|
-
begin
|
81
|
-
cmd.call(ps)
|
82
|
-
rescue Exception => e
|
83
|
-
Marshal.dump(e, ps.last)
|
84
|
-
ps.last.flush
|
85
|
-
ensure
|
86
|
-
ps.last.close unless ps.last.closed?
|
87
|
-
end
|
88
|
-
|
89
|
-
exit!
|
90
|
-
}
|
91
|
-
ensure
|
92
|
-
$VERBOSE = verbose
|
93
|
-
end
|
94
|
-
|
95
|
-
[ pw.first, pr.last, pe.last, ps.last ].each { |fd| fd.close }
|
96
|
-
|
97
|
-
Open4.propagate_exception cid, ps.first if exception_propagation_at == :init
|
98
|
-
|
99
|
-
pw.last.sync = true
|
100
|
-
|
101
|
-
pi = [ pw.last, pr.first, pe.first ]
|
102
|
-
|
103
|
-
begin
|
104
|
-
return [cid, *pi] unless b
|
105
|
-
|
106
|
-
begin
|
107
|
-
b.call(cid, *pi)
|
108
|
-
ensure
|
109
|
-
pi.each { |fd| fd.close unless fd.closed? }
|
110
|
-
end
|
111
|
-
|
112
|
-
Open4.propagate_exception cid, ps.first if exception_propagation_at == :block
|
113
|
-
|
114
|
-
Process.waitpid2(cid).last
|
115
|
-
ensure
|
116
|
-
ps.first.close unless ps.first.closed?
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
def self.propagate_exception(cid, ps_read)
|
121
|
-
e = Marshal.load ps_read
|
122
|
-
raise Exception === e ? e : "unknown failure!"
|
123
|
-
rescue EOFError
|
124
|
-
# Child process did not raise exception.
|
125
|
-
rescue
|
126
|
-
# Child process raised exception; wait it in order to avoid a zombie.
|
127
|
-
Process.waitpid2 cid
|
128
|
-
raise
|
129
|
-
ensure
|
130
|
-
ps_read.close
|
131
|
-
end
|
132
|
-
|
133
|
-
class SpawnError < Error
|
134
|
-
attr 'cmd'
|
135
|
-
attr 'status'
|
136
|
-
attr 'signals'
|
137
|
-
def exitstatus
|
138
|
-
@status.exitstatus
|
139
|
-
end
|
140
|
-
def initialize cmd, status
|
141
|
-
@cmd, @status = cmd, status
|
142
|
-
@signals = {}
|
143
|
-
if status.signaled?
|
144
|
-
@signals['termsig'] = status.termsig
|
145
|
-
@signals['stopsig'] = status.stopsig
|
146
|
-
end
|
147
|
-
sigs = @signals.map{|k,v| "#{ k }:#{ v.inspect }"}.join(' ')
|
148
|
-
super "cmd <#{ cmd }> failed with status <#{ exitstatus.inspect }> signals <#{ sigs }>"
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
class ThreadEnsemble
|
153
|
-
attr 'threads'
|
154
|
-
|
155
|
-
def initialize cid
|
156
|
-
@cid, @threads, @argv, @done, @running = cid, [], [], Queue.new, false
|
157
|
-
@killed = false
|
158
|
-
end
|
159
|
-
|
160
|
-
def add_thread *a, &b
|
161
|
-
@running ? raise : (@argv << [a, b])
|
162
|
-
end
|
163
|
-
|
164
|
-
#
|
165
|
-
# take down process more nicely
|
166
|
-
#
|
167
|
-
def killall
|
168
|
-
c = Thread.critical
|
169
|
-
return nil if @killed
|
170
|
-
Thread.critical = true
|
171
|
-
(@threads - [Thread.current]).each{|t| t.kill rescue nil}
|
172
|
-
@killed = true
|
173
|
-
ensure
|
174
|
-
Thread.critical = c
|
175
|
-
end
|
176
|
-
|
177
|
-
def run
|
178
|
-
@running = true
|
179
|
-
|
180
|
-
begin
|
181
|
-
@argv.each do |a, b|
|
182
|
-
@threads << Thread.new(*a) do |*a|
|
183
|
-
begin
|
184
|
-
b[*a]
|
185
|
-
ensure
|
186
|
-
killall rescue nil if $!
|
187
|
-
@done.push Thread.current
|
188
|
-
end
|
189
|
-
end
|
190
|
-
end
|
191
|
-
rescue
|
192
|
-
killall
|
193
|
-
raise
|
194
|
-
ensure
|
195
|
-
all_done
|
196
|
-
end
|
197
|
-
|
198
|
-
@threads.map{|t| t.value}
|
199
|
-
end
|
200
|
-
|
201
|
-
def all_done
|
202
|
-
@threads.size.times{ @done.pop }
|
203
|
-
end
|
204
|
-
end
|
205
|
-
|
206
|
-
def to timeout = nil
|
207
|
-
Timeout.timeout(timeout){ yield }
|
208
|
-
end
|
209
|
-
module_function :to
|
210
|
-
|
211
|
-
def new_thread *a, &b
|
212
|
-
cur = Thread.current
|
213
|
-
Thread.new(*a) do |*a|
|
214
|
-
begin
|
215
|
-
b[*a]
|
216
|
-
rescue Exception => e
|
217
|
-
cur.raise e
|
218
|
-
end
|
219
|
-
end
|
220
|
-
end
|
221
|
-
module_function :new_thread
|
222
|
-
|
223
|
-
def getopts opts = {}
|
224
|
-
lambda do |*args|
|
225
|
-
keys, default, ignored = args
|
226
|
-
catch(:opt) do
|
227
|
-
[keys].flatten.each do |key|
|
228
|
-
[key, key.to_s, key.to_s.intern].each do |key|
|
229
|
-
throw :opt, opts[key] if opts.has_key?(key)
|
230
|
-
end
|
231
|
-
end
|
232
|
-
default
|
233
|
-
end
|
234
|
-
end
|
235
|
-
end
|
236
|
-
module_function :getopts
|
237
|
-
|
238
|
-
def relay src, dst = nil, t = nil
|
239
|
-
send_dst =
|
240
|
-
if dst.respond_to?(:call)
|
241
|
-
lambda{|buf| dst.call(buf)}
|
242
|
-
elsif dst.respond_to?(:<<)
|
243
|
-
lambda{|buf| dst << buf }
|
244
|
-
else
|
245
|
-
lambda{|buf| buf }
|
246
|
-
end
|
247
|
-
|
248
|
-
unless src.nil?
|
249
|
-
if src.respond_to? :gets
|
250
|
-
while buf = to(t){ src.gets }
|
251
|
-
send_dst[buf]
|
252
|
-
end
|
253
|
-
|
254
|
-
elsif src.respond_to? :each
|
255
|
-
q = Queue.new
|
256
|
-
th = nil
|
257
|
-
|
258
|
-
timer_set = lambda do |t|
|
259
|
-
th = new_thread{ to(t){ q.pop } }
|
260
|
-
end
|
261
|
-
|
262
|
-
timer_cancel = lambda do |t|
|
263
|
-
th.kill if th rescue nil
|
264
|
-
end
|
265
|
-
|
266
|
-
timer_set[t]
|
267
|
-
begin
|
268
|
-
src.each do |buf|
|
269
|
-
timer_cancel[t]
|
270
|
-
send_dst[buf]
|
271
|
-
timer_set[t]
|
272
|
-
end
|
273
|
-
ensure
|
274
|
-
timer_cancel[t]
|
275
|
-
end
|
276
|
-
|
277
|
-
elsif src.respond_to? :read
|
278
|
-
buf = to(t){ src.read }
|
279
|
-
send_dst[buf]
|
280
|
-
|
281
|
-
else
|
282
|
-
buf = to(t){ src.to_s }
|
283
|
-
send_dst[buf]
|
284
|
-
end
|
285
|
-
end
|
286
|
-
end
|
287
|
-
module_function :relay
|
288
|
-
|
289
|
-
def spawn arg, *argv
|
290
|
-
argv.unshift(arg)
|
291
|
-
opts = ((argv.size > 1 and Hash === argv.last) ? argv.pop : {})
|
292
|
-
argv.flatten!
|
293
|
-
cmd = argv.join(' ')
|
294
|
-
|
295
|
-
|
296
|
-
getopt = getopts opts
|
297
|
-
|
298
|
-
ignore_exit_failure = getopt[ 'ignore_exit_failure', getopt['quiet', false] ]
|
299
|
-
ignore_exec_failure = getopt[ 'ignore_exec_failure', !getopt['raise', true] ]
|
300
|
-
exitstatus = getopt[ %w( exitstatus exit_status status ) ]
|
301
|
-
stdin = getopt[ %w( stdin in i 0 ) << 0 ]
|
302
|
-
stdout = getopt[ %w( stdout out o 1 ) << 1 ]
|
303
|
-
stderr = getopt[ %w( stderr err e 2 ) << 2 ]
|
304
|
-
pid = getopt[ 'pid' ]
|
305
|
-
timeout = getopt[ %w( timeout spawn_timeout ) ]
|
306
|
-
stdin_timeout = getopt[ %w( stdin_timeout ) ]
|
307
|
-
stdout_timeout = getopt[ %w( stdout_timeout io_timeout ) ]
|
308
|
-
stderr_timeout = getopt[ %w( stderr_timeout ) ]
|
309
|
-
status = getopt[ %w( status ) ]
|
310
|
-
cwd = getopt[ %w( cwd dir ) ]
|
311
|
-
|
312
|
-
exitstatus =
|
313
|
-
case exitstatus
|
314
|
-
when TrueClass, FalseClass
|
315
|
-
ignore_exit_failure = true if exitstatus
|
316
|
-
[0]
|
317
|
-
else
|
318
|
-
[*(exitstatus || 0)].map{|i| Integer i}
|
319
|
-
end
|
320
|
-
|
321
|
-
stdin ||= '' if stdin_timeout
|
322
|
-
stdout ||= '' if stdout_timeout
|
323
|
-
stderr ||= '' if stderr_timeout
|
324
|
-
|
325
|
-
started = false
|
326
|
-
|
327
|
-
status =
|
328
|
-
begin
|
329
|
-
chdir(cwd) do
|
330
|
-
Timeout::timeout(timeout) do
|
331
|
-
popen4(*argv) do |c, i, o, e|
|
332
|
-
started = true
|
333
|
-
|
334
|
-
%w( replace pid= << push update ).each do |msg|
|
335
|
-
break(pid.send(msg, c)) if pid.respond_to? msg
|
336
|
-
end
|
337
|
-
|
338
|
-
te = ThreadEnsemble.new c
|
339
|
-
|
340
|
-
te.add_thread(i, stdin) do |i, stdin|
|
341
|
-
relay stdin, i, stdin_timeout
|
342
|
-
i.close rescue nil
|
343
|
-
end
|
344
|
-
|
345
|
-
te.add_thread(o, stdout) do |o, stdout|
|
346
|
-
relay o, stdout, stdout_timeout
|
347
|
-
end
|
348
|
-
|
349
|
-
te.add_thread(e, stderr) do |o, stderr|
|
350
|
-
relay e, stderr, stderr_timeout
|
351
|
-
end
|
352
|
-
|
353
|
-
te.run
|
354
|
-
end
|
355
|
-
end
|
356
|
-
end
|
357
|
-
rescue
|
358
|
-
raise unless(not started and ignore_exec_failure)
|
359
|
-
end
|
360
|
-
|
361
|
-
raise SpawnError.new(cmd, status) unless
|
362
|
-
(ignore_exit_failure or (status.nil? and ignore_exec_failure) or exitstatus.include?(status.exitstatus))
|
363
|
-
|
364
|
-
status
|
365
|
-
end
|
366
|
-
module_function :spawn
|
367
|
-
|
368
|
-
def chdir cwd, &block
|
369
|
-
return(block.call Dir.pwd) unless cwd
|
370
|
-
Dir.chdir cwd, &block
|
371
|
-
end
|
372
|
-
module_function :chdir
|
373
|
-
|
374
|
-
def background arg, *argv
|
375
|
-
require 'thread'
|
376
|
-
q = Queue.new
|
377
|
-
opts = { 'pid' => q, :pid => q }
|
378
|
-
case argv.last
|
379
|
-
when Hash
|
380
|
-
argv.last.update opts
|
381
|
-
else
|
382
|
-
argv.push opts
|
383
|
-
end
|
384
|
-
thread = Thread.new(arg, argv){|arg, argv| spawn arg, *argv}
|
385
|
-
sc = class << thread; self; end
|
386
|
-
sc.module_eval {
|
387
|
-
define_method(:pid){ @pid ||= q.pop }
|
388
|
-
define_method(:spawn_status){ @spawn_status ||= value }
|
389
|
-
define_method(:exitstatus){ @exitstatus ||= spawn_status.exitstatus }
|
390
|
-
}
|
391
|
-
thread
|
392
|
-
end
|
393
|
-
alias bg background
|
394
|
-
module_function :background
|
395
|
-
module_function :bg
|
396
|
-
|
397
|
-
def maim pid, opts = {}
|
398
|
-
getopt = getopts opts
|
399
|
-
sigs = getopt[ 'signals', %w(SIGTERM SIGQUIT SIGKILL) ]
|
400
|
-
suspend = getopt[ 'suspend', 4 ]
|
401
|
-
pid = Integer pid
|
402
|
-
existed = false
|
403
|
-
sigs.each do |sig|
|
404
|
-
begin
|
405
|
-
Process.kill sig, pid
|
406
|
-
existed = true
|
407
|
-
rescue Errno::ESRCH
|
408
|
-
return(existed ? nil : true)
|
409
|
-
end
|
410
|
-
return true unless alive? pid
|
411
|
-
sleep suspend
|
412
|
-
return true unless alive? pid
|
413
|
-
end
|
414
|
-
return(not alive?(pid))
|
415
|
-
end
|
416
|
-
module_function :maim
|
417
|
-
|
418
|
-
def alive pid
|
419
|
-
pid = Integer pid
|
420
|
-
begin
|
421
|
-
Process.kill 0, pid
|
422
|
-
true
|
423
|
-
rescue Errno::ESRCH
|
424
|
-
false
|
425
|
-
end
|
426
|
-
end
|
427
|
-
alias alive? alive
|
428
|
-
module_function :alive
|
429
|
-
module_function :'alive?'
|
430
|
-
end
|
431
|
-
|
432
|
-
def open4(*cmd, &b) cmd.size == 0 ? Open4 : Open4::popen4(*cmd, &b) end
|