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.
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