engineyard-serverside 1.6.0.pre5 → 1.6.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. data/lib/engineyard-serverside.rb +1 -3
  2. data/lib/engineyard-serverside/cli.rb +38 -73
  3. data/lib/engineyard-serverside/configuration.rb +12 -38
  4. data/lib/engineyard-serverside/deploy.rb +54 -63
  5. data/lib/engineyard-serverside/deploy_hook.rb +18 -21
  6. data/lib/engineyard-serverside/deprecation.rb +17 -9
  7. data/lib/engineyard-serverside/lockfile_parser.rb +1 -1
  8. data/lib/engineyard-serverside/logged_output.rb +91 -0
  9. data/lib/engineyard-serverside/rails_asset_support.rb +5 -5
  10. data/lib/engineyard-serverside/server.rb +11 -8
  11. data/lib/engineyard-serverside/strategies/git.rb +15 -12
  12. data/lib/engineyard-serverside/task.rb +8 -29
  13. data/lib/engineyard-serverside/version.rb +1 -1
  14. data/lib/vendor/systemu/LICENSE +3 -0
  15. data/lib/vendor/systemu/lib/systemu.rb +363 -0
  16. data/lib/vendor/systemu/systemu.gemspec +45 -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 +4 -63
  20. data/spec/deploy_hook_spec.rb +78 -77
  21. data/spec/deprecation_spec.rb +26 -4
  22. data/spec/git_strategy_spec.rb +2 -6
  23. data/spec/logged_output_spec.rb +55 -0
  24. data/spec/nodejs_deploy_spec.rb +2 -2
  25. data/spec/services_deploy_spec.rb +10 -11
  26. data/spec/spec_helper.rb +25 -48
  27. data/spec/sqlite3_deploy_spec.rb +2 -1
  28. data/spec/support/integration.rb +14 -2
  29. metadata +79 -94
  30. data/lib/engineyard-serverside/shell.rb +0 -102
  31. data/lib/engineyard-serverside/shell/formatter.rb +0 -73
  32. data/lib/engineyard-serverside/shell/helpers.rb +0 -29
  33. data/lib/vendor/open4/lib/open4.rb +0 -432
  34. 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