capistrano-kitchen 0.0.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +23 -0
  3. data/.rspec +2 -0
  4. data/.ruby-gemset.template +1 -0
  5. data/.ruby-version.template +1 -0
  6. data/.travis.yml +7 -0
  7. data/.yardopts +5 -0
  8. data/Gemfile +8 -0
  9. data/Guardfile +13 -0
  10. data/LICENSE.txt +46 -0
  11. data/Rakefile +14 -0
  12. data/capistrano-kitchen.gemspec +29 -0
  13. data/lib/capistrano-kitchen.rb +41 -0
  14. data/lib/capistrano_kitchen/dishes/aptitude/manage.rb +38 -0
  15. data/lib/capistrano_kitchen/dishes/bundler/hooks.rb +7 -0
  16. data/lib/capistrano_kitchen/dishes/bundler/install.rb +79 -0
  17. data/lib/capistrano_kitchen/dishes/git/hooks.rb +3 -0
  18. data/lib/capistrano_kitchen/dishes/git/install.rb +18 -0
  19. data/lib/capistrano_kitchen/dishes/java_7_oracle/hooks.rb +5 -0
  20. data/lib/capistrano_kitchen/dishes/java_7_oracle/install.rb +17 -0
  21. data/lib/capistrano_kitchen/dishes/nginx_unicorn/app.conf +66 -0
  22. data/lib/capistrano_kitchen/dishes/nginx_unicorn/hooks.rb +11 -0
  23. data/lib/capistrano_kitchen/dishes/nginx_unicorn/install.rb +176 -0
  24. data/lib/capistrano_kitchen/dishes/nginx_unicorn/manage.rb +1 -0
  25. data/lib/capistrano_kitchen/dishes/nginx_unicorn/mime.types.erb +79 -0
  26. data/lib/capistrano_kitchen/dishes/nginx_unicorn/nginx.conf +138 -0
  27. data/lib/capistrano_kitchen/dishes/nginx_unicorn/nginx_unicorn.god +47 -0
  28. data/lib/capistrano_kitchen/dishes/nginx_unicorn/nginx_unicorn.init +95 -0
  29. data/lib/capistrano_kitchen/dishes/nginx_unicorn/nginx_unicorn.logrotate +18 -0
  30. data/lib/capistrano_kitchen/dishes/nginx_unicorn/stub_status.conf +16 -0
  31. data/lib/capistrano_kitchen/dishes/nodejs/hooks.rb +4 -0
  32. data/lib/capistrano_kitchen/dishes/nodejs/install.rb +13 -0
  33. data/lib/capistrano_kitchen/dishes/provision/empty_roles.rb +60 -0
  34. data/lib/capistrano_kitchen/dishes/provision/manage.rb +49 -0
  35. data/lib/capistrano_kitchen/dishes/provision/task_once.rb +62 -0
  36. data/lib/capistrano_kitchen/dishes/ruby/hooks.rb +7 -0
  37. data/lib/capistrano_kitchen/dishes/ruby/install.rb +55 -0
  38. data/lib/capistrano_kitchen/dishes/teelogger/teelogger.rb +121 -0
  39. data/lib/capistrano_kitchen/dishes/unicorn/hooks.rb +9 -0
  40. data/lib/capistrano_kitchen/dishes/unicorn/install.rb +120 -0
  41. data/lib/capistrano_kitchen/dishes/unicorn/unicorn.god +71 -0
  42. data/lib/capistrano_kitchen/dishes/unicorn/unicorn.rb.erb +191 -0
  43. data/lib/capistrano_kitchen/recipes/aptitude.rb +1 -0
  44. data/lib/capistrano_kitchen/recipes/bundler.rb +1 -0
  45. data/lib/capistrano_kitchen/recipes/git.rb +1 -0
  46. data/lib/capistrano_kitchen/recipes/java_7_oracle.rb +1 -0
  47. data/lib/capistrano_kitchen/recipes/nginx_unicorn.rb +1 -0
  48. data/lib/capistrano_kitchen/recipes/nodejs.rb +1 -0
  49. data/lib/capistrano_kitchen/recipes/provision.rb +1 -0
  50. data/lib/capistrano_kitchen/recipes/ruby.rb +1 -0
  51. data/lib/capistrano_kitchen/recipes/teelogger.rb +1 -0
  52. data/lib/capistrano_kitchen/recipes/unicorn.rb +1 -0
  53. data/lib/capistrano_kitchen/recipes/utilities.rb +442 -0
  54. data/lib/capistrano_kitchen/version.rb +3 -0
  55. data/spec/capistrano_kitchen_spec.rb +5 -0
  56. data/spec/spec_helper.rb +21 -0
  57. metadata +200 -0
@@ -0,0 +1,95 @@
1
+ #! /bin/sh
2
+
3
+ ### BEGIN INIT INFO
4
+ # Provides: nginx
5
+ # Required-Start: $local_fs $remote_fs $network $syslog
6
+ # Required-Stop: $local_fs $remote_fs $network $syslog
7
+ # Default-Start: 2 3 4 5
8
+ # Default-Stop: 0 1 6
9
+ # Short-Description: starts the nginx web server
10
+ # Description: starts nginx using start-stop-daemon
11
+ ### END INIT INFO
12
+
13
+ PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
14
+ DAEMON=<%=nginx_unicorn_sbin_file%>
15
+ DAEMON_OPTS="-c <%="#{nginx_unicorn_conf_dir}/nginx.conf"%>"
16
+ NAME=<%=nginx_unicorn_init_d%>
17
+ DESC=<%=nginx_unicorn_init_d%>
18
+ PID=<%=nginx_unicorn_pid_file%>
19
+
20
+ test -x $DAEMON || exit 0
21
+
22
+ # Include nginx defaults if available
23
+ if [ -f /etc/default/nginx ] ; then
24
+ . /etc/default/nginx
25
+ fi
26
+
27
+ set -e
28
+
29
+ . /lib/lsb/init-functions
30
+
31
+ test_nginx_config() {
32
+ if $DAEMON -t $DAEMON_OPTS >/dev/null 2>&1
33
+ then
34
+ return 0
35
+ else
36
+ $DAEMON -t $DAEMON_OPTS
37
+ return $?
38
+ fi
39
+ }
40
+
41
+ case "$1" in
42
+ start)
43
+ echo -n "Starting $DESC: "
44
+ test_nginx_config
45
+ start-stop-daemon --start --quiet --pidfile $PID \
46
+ --exec $DAEMON -- $DAEMON_OPTS || true
47
+ echo "$NAME."
48
+ ;;
49
+ stop)
50
+ echo -n "Stopping $DESC: "
51
+ start-stop-daemon --stop --quiet --pidfile $PID \
52
+ --exec $DAEMON || true
53
+ echo "$NAME."
54
+ ;;
55
+ restart|force-reload)
56
+ echo -n "Restarting $DESC: "
57
+ start-stop-daemon --stop --quiet --pidfile \
58
+ $PID --exec $DAEMON || true
59
+ sleep 1
60
+ test_nginx_config
61
+ start-stop-daemon --start --quiet --pidfile \
62
+ $PID --exec $DAEMON -- $DAEMON_OPTS || true
63
+ echo "$NAME."
64
+ ;;
65
+ reload)
66
+ echo -n "Reloading $DESC configuration: "
67
+ test_nginx_config
68
+ start-stop-daemon --stop --signal HUP --quiet --pidfile $PID \
69
+ --exec $DAEMON || true
70
+ echo "$NAME."
71
+ ;;
72
+ reopen)
73
+ echo -n "Reopening $DESC log files: "
74
+ $DAEMON -s reopen || true
75
+ echo "$NAME."
76
+ ;;
77
+ configtest)
78
+ echo -n "Testing $DESC configuration: "
79
+ if test_nginx_config
80
+ then
81
+ echo "$NAME."
82
+ else
83
+ exit $?
84
+ fi
85
+ ;;
86
+ status)
87
+ status_of_proc -p $PID "$DAEMON" nginx && exit 0 || exit $?
88
+ ;;
89
+ *)
90
+ echo "Usage: $NAME {start|stop|restart|reload|force-reload|reopen|status|configtest}" >&2
91
+ exit 1
92
+ ;;
93
+ esac
94
+
95
+ exit 0
@@ -0,0 +1,18 @@
1
+ <%=nginx_unicorn_log_dir%>/*.log {
2
+ daily
3
+ missingok
4
+ rotate 52
5
+ compress
6
+ delaycompress
7
+ notifempty
8
+ create 0640 www-data adm
9
+ sharedscripts
10
+ prerotate
11
+ if [ -d /etc/logrotate.d/httpd-prerotate ]; then \
12
+ run-parts /etc/logrotate.d/httpd-prerotate; \
13
+ fi; \
14
+ endscript
15
+ postrotate
16
+ [ ! -f /var/run/<%=nginx_unicorn_init_d%>.pid ] || kill -USR1 `cat /var/run/<%=nginx_unicorn_init_d%>.pid`
17
+ endscript
18
+ }
@@ -0,0 +1,16 @@
1
+ server {
2
+ listen 127.0.0.1:80;
3
+ server_name localhost;
4
+
5
+ location /nginx_status {
6
+ # copied from http://blog.kovyrin.net/2006/04/29/monitoring-nginx-with-rrdtool/
7
+ # Generate stupid load to see the counters increase
8
+ # ab -n 1000 http://127.0.0.1/nginx_status
9
+ stub_status on;
10
+ access_log off;
11
+ allow 127.0.0.1;
12
+ deny all;
13
+ }
14
+
15
+ }
16
+
@@ -0,0 +1,4 @@
1
+ # @author Donovan Bray <donnoman@donovanbray.com>
2
+ Capistrano::Configuration.instance(true).load do
3
+ after "deploy:provision", "nodejs:install"
4
+ end
@@ -0,0 +1,13 @@
1
+ # @author Donovan Bray <donnoman@donovanbray.com>
2
+ Capistrano::Configuration.instance(true).load do
3
+
4
+ namespace :nodejs do
5
+
6
+ desc "Install nodejs"
7
+ task :install, :except => {:no_release => true} do
8
+ utilities.apt_install "nodejs"
9
+ end
10
+
11
+ end
12
+
13
+ end
@@ -0,0 +1,60 @@
1
+ # Allows Tasks that have no servers to be skipped instead of raising a NoMatchingServersError
2
+
3
+ module Capistrano
4
+ class Configuration
5
+ module Connections
6
+ def execute_on_servers(options={})
7
+ raise ArgumentError, "expected a block" unless block_given?
8
+
9
+ if task = current_task
10
+ servers = find_servers_for_task(task, options)
11
+
12
+ if servers.empty?
13
+ #raise Capistrano::NoMatchingServersError, "`#{task.fully_qualified_name}' is only run for servers matching #{task.options.inspect}, but no servers matched"
14
+ logger.info "skipping `#{task.fully_qualified_name}' because no servers matched"
15
+ return
16
+ end
17
+
18
+ if task.continue_on_error?
19
+ servers.delete_if { |s| has_failed?(s) }
20
+ return if servers.empty?
21
+ end
22
+ else
23
+ servers = find_servers(options)
24
+ raise Capistrano::NoMatchingServersError, "no servers found to match #{options.inspect}" if servers.empty?
25
+ end
26
+
27
+ servers = [servers.first] if options[:once]
28
+ logger.trace "servers: #{servers.map { |s| s.host }.inspect}"
29
+
30
+ max_hosts = (options[:max_hosts] || (task && task.max_hosts) || servers.size).to_i
31
+ is_subset = max_hosts < servers.size
32
+
33
+ # establish connections to those servers in groups of max_hosts, as necessary
34
+ servers.each_slice(max_hosts) do |servers_slice|
35
+ begin
36
+ establish_connections_to(servers_slice)
37
+ rescue ConnectionError => error
38
+ raise error unless task && task.continue_on_error?
39
+ error.hosts.each do |h|
40
+ servers_slice.delete(h)
41
+ failed!(h)
42
+ end
43
+ end
44
+
45
+ begin
46
+ yield servers_slice
47
+ rescue RemoteError => error
48
+ raise error unless task && task.continue_on_error?
49
+ error.hosts.each { |h| failed!(h) }
50
+ end
51
+
52
+ # if dealing with a subset (e.g., :max_hosts is less than the
53
+ # number of servers available) teardown the subset of connections
54
+ # that were just made, so that we can make room for the next subset.
55
+ teardown_connections_to(servers_slice) if is_subset
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,49 @@
1
+ # @author Donovan Bray <donnoman@donovanbray.com>
2
+ require File.expand_path(File.dirname(__FILE__) + '/../utilities')
3
+
4
+ # Provisioning hooks into many of the scripts to give a single hook to install
5
+ # the requisite software.
6
+ #
7
+ # The provisioning process assumes capistrano has been overriden to support empty roles
8
+ #
9
+ # Supported tasks add a ' after "deploy:provision", "app:install" ' in their hooks.rb
10
+ # if you don't include ' require 'cap_recipes/tasks/provision' ' in your deploy.rb then the provision task
11
+ # is never fire, and all of the extra hooks are ignored.
12
+ #
13
+ # It's convenient to override the provision task in your deploy.rb to do something more meaningful as well.
14
+ #
15
+ # desc "Provision the servers"
16
+ # task :provision do
17
+ # utilities.apt_install "git-core telnet elinks netcat socat curl arping rsync nload wget locate strace"
18
+ # mysql.install_client_libs #needed to build mysql2 gem
19
+ # deploy.provision_bundler_dependencies
20
+ # end
21
+
22
+ Capistrano::Configuration.instance(true).load do
23
+
24
+ namespace :deploy do
25
+
26
+ # Init all base roles so they can be empty
27
+ roles[:web]
28
+ roles[:app]
29
+ roles[:db]
30
+
31
+ # This block allows us to add items to the very beginning of provisioning
32
+ # while allowing the consumer to freely override the deploy:provision task to add
33
+ # thier own non-framework items.
34
+ on :start, :only => "deploy:provision" do
35
+ deploy.provision_prerequisites
36
+ end
37
+
38
+ task :provision_prerequisites do
39
+ utilities.apt_update
40
+ utilities.apt_install_by_command('add-apt-repository')
41
+ end
42
+
43
+ task :provision do
44
+ logger.info "Provisioning Services"
45
+ end
46
+
47
+ end
48
+
49
+ end
@@ -0,0 +1,62 @@
1
+ module Capistrano
2
+ class Configuration
3
+ module Servers
4
+ # Identifies all servers that the given task should be executed on.
5
+ # The options hash accepts the same arguments as #find_servers, and any
6
+ # preexisting options there will take precedence over the options in
7
+ # the task.
8
+ def find_servers_for_task(task, options={})
9
+ find_servers(task.options.merge(options))
10
+ end
11
+
12
+ # Attempts to find all defined servers that match the given criteria.
13
+ # The options hash may include a :hosts option (which should specify
14
+ # an array of host names or ServerDefinition instances), a :roles
15
+ # option (specifying an array of roles), an :only option (specifying
16
+ # a hash of key/value pairs that any matching server must match), and
17
+ # an :exception option (like :only, but the inverse).
18
+ #
19
+ # Additionally, if the HOSTS environment variable is set, it will take
20
+ # precedence over any other options. Similarly, the ROLES environment
21
+ # variable will take precedence over other options. If both HOSTS and
22
+ # ROLES are given, HOSTS wins.
23
+ #
24
+ # Yet additionally, if the HOSTFILTER environment variable is set, it
25
+ # will limit the result to hosts found in that (comma-separated) list.
26
+ #
27
+ # Usage:
28
+ #
29
+ # # return all known servers
30
+ # servers = find_servers
31
+ #
32
+ # # find all servers in the app role that are not exempted from
33
+ # # deployment
34
+ # servers = find_servers :roles => :app,
35
+ # :except => { :no_release => true }
36
+ #
37
+ # # returns the given hosts, translated to ServerDefinition objects
38
+ # servers = find_servers :hosts => "jamis@example.host.com"
39
+ def find_servers(options={})
40
+ hosts = server_list_from(ENV['HOSTS'] || options[:hosts])
41
+
42
+ if hosts.any?
43
+ filter_server_list(hosts.uniq)
44
+ else
45
+ roles = role_list_from(ENV['ROLES'] || options[:roles] || self.roles.keys)
46
+ only = options[:only] || {}
47
+ except = options[:except] || {}
48
+
49
+ servers = roles.inject([]) { |list, role| list.concat(self.roles[role]) }
50
+ servers = servers.select { |server| only.all? { |key,value| server.options[key] == value } }
51
+ servers = servers.reject { |server| except.any? { |key,value| server.options[key] == value } }
52
+
53
+ #allows you to add the option :once to a task ie: task :my_task, :roles => :app, :once => true do ...
54
+ servers = [servers.first] if options[:once] and servers.size > 1
55
+ logger.trace "servers: #{servers.map { |s| s.host }.inspect}"
56
+
57
+ filter_server_list(servers.uniq)
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,7 @@
1
+ # @author Donovan Bray <donnoman@donovanbray.com>
2
+ Capistrano::Configuration.instance(true).load do
3
+ after "deploy:provision", "ruby:install"
4
+ after "ruby:install", "ruby:rubygems_source_fix"
5
+ after "ruby:install", "ruby:ruby_debugger"
6
+ after "deploy:setup", "ruby:ensure_trust_github"
7
+ end
@@ -0,0 +1,55 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../utilities')
2
+
3
+ Capistrano::Configuration.instance(true).load do
4
+
5
+ namespace :ruby do
6
+
7
+ set :ruby_ver_latest_type, "stable" # can be major.minor numbers ie: 1.8, 2.1 etc. or 'stable'
8
+ set(:ruby_ver_latest) { open("http://ftp.ruby-lang.org/pub/ruby/#{ruby_ver_latest_type}").read.scan(/href="(ruby-\d.\d.\d(-p\d+)?).tar.bz2/).map{|r| r[0]}.sort.reverse.first }
9
+ set(:ruby_ver) { utilities.suggest_version(:ruby_ver,ruby_ver_latest) }
10
+
11
+ # Ruby Versioning: ruby-MAJOR.MINOR.TEENY-pPATCHLEVEL
12
+ set(:ruby_major_minor) { ruby_ver.match(/ruby-(\d\.\d)/)[1]}
13
+ set(:ruby_src) { "http://cache.ruby-lang.org/pub/ruby/#{ruby_major_minor}/#{ruby_ver}.tar.bz2"}
14
+
15
+ set :base_ruby_path, '/usr'
16
+ set :ruby_debugger_support, false
17
+ set :ruby_rubygems_source_fix_support, false
18
+ set :ruby_ensure_trust_github, true
19
+
20
+ # New Concept ':except => {:no_ruby => true}' to allow all systems by default
21
+ # to have ruby installed to allow use of ruby gems like god on all systems
22
+ # regardless of whether they have releases deployed to them, they may have other things
23
+ # that we want god to watch on them.
24
+
25
+ desc "install ruby"
26
+ task :install, :except => {:no_ruby => true} do
27
+ utilities.apt_install %w[build-essential openssl libreadline6 libreadline6-dev curl git-core zlib1g zlib1g-dev libssl-dev libyaml-dev libsqlite3-0 libsqlite3-dev sqlite3 libxml2-dev libxslt-dev autoconf libc6-dev ncurses-dev automake libtool]
28
+ sudo "mkdir -p /usr/local/src/"
29
+ run "#{sudo} rm -rf /usr/local/src/#{ruby_ver}" #make clean is not allowing a re-install #http://www.ruby-forum.com/topic/4409005
30
+ run "cd /usr/local/src && #{sudo} wget --tries=2 -c --progress=bar:force #{ruby_src} && #{sudo} bunzip2 --keep --force #{ruby_ver}.tar.bz2 && #{sudo} tar xvf #{ruby_ver}.tar"
31
+ run "cd /usr/local/src/#{ruby_ver} && #{sudo} ./configure --prefix=#{base_ruby_path} --enable-shared && #{sudo} make install"
32
+ end
33
+
34
+ desc "add ruby debugger support"
35
+ task :ruby_debugger, :except => { :no_ruby => true } do
36
+ if ruby_debugger_support
37
+ utilities.gem_install("debugger-ruby_core_source -- --with-ruby-include=/usr/local/src/#{ruby_ver}")
38
+ utilities.gem_install("debugger-linecache -- --with-ruby-include=/usr/local/src/#{ruby_ver}")
39
+ end
40
+ end
41
+
42
+ desc "Remove legacy rubygems.org as gem source"
43
+ task :rubygems_source_fix, :except => { :no_ruby => true } do
44
+ if ruby_rubygems_source_fix_support
45
+ run "#{sudo} gem source -a http://production.s3.rubygems.org"
46
+ run "#{sudo} gem source -r http://rubygems.org/"
47
+ end
48
+ end
49
+
50
+ task :ensure_trust_github, :except => { :no_ruby => true } do
51
+ utilities.run_with_input("ssh -i ~/.ssh/id_rsa git@github.com;true", /\?/, "yes\n") if ruby_ensure_trust_github
52
+ end
53
+
54
+ end
55
+ end
@@ -0,0 +1,121 @@
1
+ class TeeLogWriter
2
+ #use this to exit cap but still have a zero exit code
3
+ class NormalExit < Capistrano::Error; end
4
+ ##
5
+ # This passes through the value and adds it to the redaction list
6
+ #
7
+ # set(:mysql_client_user) { TeeLogWriter.redact(database_user) }
8
+ #
9
+ # So your capistrano variable has the correct value, but it will be redacted from TeeLogWriters output.
10
+ def self.redact(secure_message)
11
+ self.redactions = (self.redactions + [secure_message].flatten).uniq
12
+ secure_message
13
+ end
14
+
15
+ def self.redaction_replacement
16
+ @redaction_replacement ||= '######'
17
+ end
18
+
19
+ def self.redaction_replacement=(replacement)
20
+ @redaction_replacement = replacement
21
+ end
22
+
23
+ def self.redacted(message)
24
+ with_ensured_encoding(message) do |message|
25
+ redactions.inject(message) do |message,redaction|
26
+ message.gsub(redaction,redaction_replacement)
27
+ end
28
+ end
29
+ end
30
+
31
+ def with_redactions(message)
32
+ yield self.class.redacted(message)
33
+ end
34
+
35
+ def puts(message)
36
+ with_redactions(message) do |message|
37
+ STDOUT.puts message
38
+ file.puts "[#{log_timestamp}] #{message}"
39
+ end
40
+ end
41
+
42
+ def tty?
43
+ true
44
+ end
45
+
46
+ private
47
+
48
+
49
+ def self.redactions
50
+ @redactions ||= []
51
+ end
52
+
53
+ def self.redactions=(value)
54
+ @redactions = value
55
+ end
56
+
57
+ def self.with_ensured_encoding(message)
58
+ yield message.respond_to?(:force_encoding) ? message.force_encoding("UTF-8") : message
59
+ end
60
+
61
+ def file
62
+ @file ||= File.open(File.join(logdir,"deploy.#{file_timestamp}.log"), "w")
63
+ end
64
+
65
+ def log_timestamp
66
+ Time.now.strftime("%Y-%m-%d %H:%M:%S%z")
67
+ end
68
+
69
+ def file_timestamp
70
+ Time.now.strftime("%Y%m%d-%H%M%S%z")
71
+ end
72
+
73
+ def caproot
74
+ @caproot ||= File.dirname(capfile)
75
+ end
76
+
77
+ def logdir
78
+ FileUtils.mkdir_p(File.join(caproot,'log')).first
79
+ end
80
+
81
+ def capfile
82
+ previous = nil
83
+ current = File.expand_path(Dir.pwd)
84
+
85
+ until !File.directory?(current) || current == previous
86
+ filename = File.join(current, 'Capfile')
87
+ return filename if File.file?(filename)
88
+ current, previous = File.expand_path("..", current), current
89
+ end
90
+ end
91
+
92
+ end
93
+
94
+ require 'capistrano/configuration'
95
+
96
+ module Capistrano
97
+ class CLI
98
+ module Execute
99
+ def handle_error(error) #:nodoc:
100
+ case error
101
+ when TeeLogWriter::NormalExit #used to force capistrano to end but without an error code.
102
+ exit 0
103
+ when Net::SSH::AuthenticationFailed
104
+ abort "authentication failed for `#{TeeLogWriter.redacted(error.message)}'"
105
+ when Capistrano::Error
106
+ abort(TeeLogWriter.redacted(error.message))
107
+ else
108
+ puts TeeLogWriter.redacted(error.message)
109
+ puts error.backtrace
110
+ exit 1
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end
116
+
117
+
118
+ Capistrano::Configuration.instance(true).load do
119
+ #replace the running logger device with our own.
120
+ self.logger.instance_variable_set(:@device,TeeLogWriter.new)
121
+ end