capistrano 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. data/bin/cap +11 -0
  2. data/examples/sample.rb +113 -0
  3. data/lib/capistrano.rb +1 -0
  4. data/lib/capistrano/actor.rb +438 -0
  5. data/lib/capistrano/cli.rb +295 -0
  6. data/lib/capistrano/command.rb +90 -0
  7. data/lib/capistrano/configuration.rb +243 -0
  8. data/lib/capistrano/extensions.rb +38 -0
  9. data/lib/capistrano/gateway.rb +118 -0
  10. data/lib/capistrano/generators/rails/deployment/deployment_generator.rb +25 -0
  11. data/lib/capistrano/generators/rails/deployment/templates/capistrano.rake +46 -0
  12. data/lib/capistrano/generators/rails/deployment/templates/deploy.rb +122 -0
  13. data/lib/capistrano/generators/rails/loader.rb +20 -0
  14. data/lib/capistrano/logger.rb +59 -0
  15. data/lib/capistrano/recipes/standard.rb +242 -0
  16. data/lib/capistrano/recipes/templates/maintenance.rhtml +53 -0
  17. data/lib/capistrano/scm/base.rb +62 -0
  18. data/lib/capistrano/scm/baz.rb +118 -0
  19. data/lib/capistrano/scm/bzr.rb +70 -0
  20. data/lib/capistrano/scm/cvs.rb +124 -0
  21. data/lib/capistrano/scm/darcs.rb +27 -0
  22. data/lib/capistrano/scm/perforce.rb +139 -0
  23. data/lib/capistrano/scm/subversion.rb +122 -0
  24. data/lib/capistrano/ssh.rb +39 -0
  25. data/lib/capistrano/transfer.rb +90 -0
  26. data/lib/capistrano/utils.rb +26 -0
  27. data/lib/capistrano/version.rb +30 -0
  28. data/test/actor_test.rb +294 -0
  29. data/test/command_test.rb +43 -0
  30. data/test/configuration_test.rb +233 -0
  31. data/test/fixtures/config.rb +5 -0
  32. data/test/fixtures/custom.rb +3 -0
  33. data/test/scm/cvs_test.rb +186 -0
  34. data/test/scm/subversion_test.rb +137 -0
  35. data/test/ssh_test.rb +104 -0
  36. data/test/utils.rb +50 -0
  37. metadata +107 -0
@@ -0,0 +1,53 @@
1
+
2
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
3
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
4
+
5
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
6
+
7
+ <head>
8
+ <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
9
+ <title>System down for maintenance</title>
10
+
11
+ <style type="text/css">
12
+ div.outer {
13
+ position: absolute;
14
+ left: 50%;
15
+ top: 50%;
16
+ width: 500px;
17
+ height: 300px;
18
+ margin-left: -260px;
19
+ margin-top: -150px;
20
+ }
21
+
22
+ .DialogBody {
23
+ margin: 0;
24
+ padding: 10px;
25
+ text-align: left;
26
+ border: 1px solid #ccc;
27
+ border-right: 1px solid #999;
28
+ border-bottom: 1px solid #999;
29
+ background-color: #fff;
30
+ }
31
+
32
+ body { background-color: #fff; }
33
+ </style>
34
+ </head>
35
+
36
+ <body>
37
+
38
+ <div class="outer">
39
+ <div class="DialogBody" style="text-align: center;">
40
+ <div style="text-align: center; width: 200px; margin: 0 auto;">
41
+ <p style="color: red; font-size: 16px; line-height: 20px;">
42
+ The system is down for <%= reason ? reason : "maintenance" %>
43
+ as of <%= Time.now.strftime("%H:%M %Z") %>.
44
+ </p>
45
+ <p style="color: #666;">
46
+ It'll be back <%= deadline ? "by #{deadline}" : "shortly" %>.
47
+ </p>
48
+ </div>
49
+ </div>
50
+ </div>
51
+
52
+ </body>
53
+ </html>
@@ -0,0 +1,62 @@
1
+ module Capistrano
2
+ module SCM
3
+
4
+ # The ancestor class of the various SCM module implementations.
5
+ class Base
6
+ attr_reader :configuration
7
+
8
+ def initialize(configuration) #:nodoc:
9
+ @configuration = configuration
10
+ end
11
+
12
+ def latest_revision
13
+ nil
14
+ end
15
+
16
+ def current_revision(actor)
17
+ raise "#{self.class} doesn't support querying the deployed revision"
18
+ end
19
+
20
+ def diff(actor, from=nil, to=nil)
21
+ raise "#{self.class} doesn't support diff(from, to)"
22
+ end
23
+
24
+ def update(actor)
25
+ raise "#{self.class} doesn't support update(actor)"
26
+ end
27
+
28
+ private
29
+
30
+ def run_checkout(actor, guts, &block)
31
+ log = "#{configuration.deploy_to}/revisions.log"
32
+ directory = File.basename(configuration.release_path)
33
+
34
+ command = <<-STR
35
+ if [[ ! -d #{configuration.release_path} ]]; then
36
+ #{guts}
37
+ #{logging_commands(directory)}
38
+ fi
39
+ STR
40
+
41
+ actor.run(command, &block)
42
+ end
43
+
44
+ def run_update(actor, guts, &block)
45
+ command = <<-STR
46
+ #{guts}
47
+ #{logging_commands}
48
+ STR
49
+
50
+ actor.run(command, &block)
51
+ end
52
+
53
+ def logging_commands(directory = nil)
54
+ log = "#{configuration.deploy_to}/revisions.log"
55
+
56
+ "(test -e #{log} || touch #{log} && chmod 666 #{log}) && " +
57
+ "echo `date +\"%Y-%m-%d %H:%M:%S\"` $USER #{configuration.revision} #{directory} >> #{log};"
58
+ end
59
+ end
60
+
61
+ end
62
+ end
@@ -0,0 +1,118 @@
1
+ require 'capistrano/scm/base'
2
+
3
+ module Capistrano
4
+ module SCM
5
+
6
+ # An SCM module for using Bazaar as your source control tool. This
7
+ # module is used by default, but you can explicitly specify it by
8
+ # placing the following line in your configuration:
9
+ #
10
+ # set :scm, :baz
11
+ #
12
+ # Also, this module accepts a <tt>:baz</tt> configuration variable,
13
+ # which (if specified) will be used as the full path to the svn
14
+ # executable on the remote machine:
15
+ #
16
+ # set :baz, "/opt/local/bin/baz"
17
+ #
18
+ # Set the version you wish to deploy as the repository variable,
19
+ # for example:
20
+ #
21
+ # set :repository, "you@example.com--dev/yourstuff--trunk--1.0"
22
+ #
23
+ # Ensure that you have already registered the archive on the target
24
+ # machines.
25
+ #
26
+ # As bazaar keeps a great deal of extra information on a checkout,
27
+ # you will probably want to use export instead:
28
+ #
29
+ # set :checkout, "export"
30
+ #
31
+ # TODO: provide setup recipe to register archive
32
+ class Baz < Base
33
+ # Return an integer identifying the last known revision in the baz
34
+ # repository. (This integer is currently the revision number.)
35
+ def latest_revision
36
+ `#{baz} revisions #{configuration.repository}`.split.last =~ /\-(\d+)$/
37
+ $1
38
+ end
39
+
40
+ # Return the number of the revision currently deployed.
41
+ def current_revision(actor)
42
+ latest = actor.releases.last
43
+ grep = %(grep " #{latest}$" #{configuration.deploy_to}/revisions.log)
44
+ result = ""
45
+ actor.run(grep, :once => true) do |ch, str, out|
46
+ result << out if str == :out
47
+ raise "could not determine current revision" if str == :err
48
+ end
49
+
50
+ date, time, user, rev, dir = result.split
51
+ raise "current revision not found in revisions.log" unless dir == latest
52
+ rev.to_i
53
+ end
54
+
55
+ # Return a string containing the diff between the two revisions. +from+
56
+ # and +to+ may be in any format that bzr recognizes as a valid revision
57
+ # identifier. If +from+ is +nil+, it defaults to the last deployed
58
+ # revision. If +to+ is +nil+, it defaults to the last developed revision.
59
+ def diff(actor, from=nil, to=nil)
60
+ from ||= current_revision(actor)
61
+ to ||= latest_revision
62
+ from = baz_revision_name(from)
63
+ to = baz_revision_name(to)
64
+ `#{baz} delta --diffs -A #{baz_archive} #{baz_version}--#{from} #{baz_version}--#{to}`
65
+ end
66
+
67
+ # Check out (on all servers associated with the current task) the latest
68
+ # revision. Uses the given actor instance to execute the command.
69
+ def checkout(actor)
70
+ op = configuration[:checkout] || "get"
71
+ from = baz_revision_name(configuration.revision)
72
+ command = "#{baz} #{op} #{configuration.repository}--#{from} #{actor.release_path} &&"
73
+ run_checkout(actor, command, &baz_stream_handler(actor))
74
+ end
75
+
76
+ def update(actor)
77
+ command = "cd #{actor.current_path} && #{baz} update &&"
78
+ run_update(actor, command, &baz_stream_handler(actor))
79
+ end
80
+
81
+ private
82
+ def baz
83
+ configuration[:baz] || "baz"
84
+ end
85
+
86
+ def baz_revision_name(number)
87
+ if number.to_i == 0 then
88
+ "base-0"
89
+ else
90
+ "patch-#{number}"
91
+ end
92
+ end
93
+
94
+ def baz_archive
95
+ configuration[:repository][/(.*)\//, 1]
96
+ end
97
+
98
+ def baz_version
99
+ configuration[:repository][/\/(.*)$/, 1]
100
+ end
101
+
102
+ def baz_stream_handler(actor)
103
+ Proc.new do |ch, stream, out|
104
+ prefix = "#{stream} :: #{ch[:host]}"
105
+ actor.logger.info out, prefix
106
+ if out =~ /\bpassword.*:/i
107
+ actor.logger.info "baz is asking for a password", prefix
108
+ ch.send_data "#{actor.password}\n"
109
+ elsif out =~ %r{passphrase}
110
+ message = "baz needs your key's passphrase, sending empty string"
111
+ actor.logger.info message, prefix
112
+ ch.send_data "\n"
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,70 @@
1
+ require 'capistrano/scm/base'
2
+
3
+ module Capistrano
4
+ module SCM
5
+
6
+ # An SCM module for using Bazaar-NG (bzr) as your source control tool.
7
+ # You can use it by placing the following line in your configuration:
8
+ #
9
+ # set :scm, :bzr
10
+ #
11
+ # Also, this module accepts a <tt>:bzr</tt> configuration variable,
12
+ # which (if specified) will be used as the full path to the bzr
13
+ # executable on the remote machine:
14
+ #
15
+ # set :bzr, "/opt/local/bin/bzr"
16
+ class Bzr < Base
17
+ # Return an integer identifying the last known revision in the bzr
18
+ # repository. (This integer is currently the revision number.)
19
+ def latest_revision
20
+ `#{bzr} revno #{configuration.repository}`.to_i
21
+ end
22
+
23
+ # Return the number of the revision currently deployed.
24
+ def current_revision(actor)
25
+ command = "#{bzr} revno #{actor.release_path} &&"
26
+ run_update(actor, command, &bzr_stream_handler(actor))
27
+ end
28
+
29
+ # Return a string containing the diff between the two revisions. +from+
30
+ # and +to+ may be in any format that bzr recognizes as a valid revision
31
+ # identifier. If +from+ is +nil+, it defaults to the last deployed
32
+ # revision. If +to+ is +nil+, it defaults to the last developed revision.
33
+ # Pay attention to the fact that as of now bzr does NOT support
34
+ # diff on remote locations.
35
+ def diff(actor, from=nil, to=nil)
36
+ from ||= current_revision(actor)
37
+ to ||= ""
38
+ `#{bzr} diff -r #{from}..#{to} #{configuration.repository}`
39
+ end
40
+
41
+ # Check out (on all servers associated with the current task) the latest
42
+ # revision. Uses the given actor instance to execute the command. If
43
+ # bzr asks for a password this will automatically provide it (assuming
44
+ # the requested password is the same as the password for logging into the
45
+ # remote server.)
46
+ def checkout(actor)
47
+ op = configuration[:checkout] || "branch"
48
+ command = "#{bzr} #{op} -r#{configuration.revision} #{configuration.repository} #{actor.release_path} &&"
49
+ run_checkout(actor, command, &bzr_stream_handler(actor))
50
+ end
51
+
52
+ def update(actor)
53
+ command = "cd #{actor.current_path} && #{bzr} pull -q &&"
54
+ run_update(actor, command, &bzr_stream_handler(actor))
55
+ end
56
+
57
+ private
58
+ def bzr
59
+ configuration[:bzr] || "bzr"
60
+ end
61
+
62
+ def bzr_stream_handler(actor)
63
+ Proc.new do |ch, stream, out|
64
+ prefix = "#{stream} :: #{ch[:host]}"
65
+ actor.logger.info out, prefix
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,124 @@
1
+ require 'time'
2
+ require 'capistrano/scm/base'
3
+
4
+ module Capistrano
5
+ module SCM
6
+
7
+ # An SCM module for using CVS as your source control tool. You can
8
+ # specify it by placing the following line in your configuration:
9
+ #
10
+ # set :scm, :cvs
11
+ #
12
+ # Also, this module accepts a <tt>:cvs</tt> configuration variable,
13
+ # which (if specified) will be used as the full path to the cvs
14
+ # executable on the remote machine:
15
+ #
16
+ # set :cvs, "/opt/local/bin/cvs"
17
+ #
18
+ # You can specify the location of your local copy (used to query
19
+ # the revisions, etc.) via the <tt>:local</tt> variable, which defaults to
20
+ # ".".
21
+ #
22
+ # You may also specify a <tt>:branch</tt> configuration variable,
23
+ # which (if specified) will be used in the '-r' option to the cvs
24
+ # check out command. If it is not set, the module will determine if a
25
+ # branch is being used in the CVS sandbox relative to
26
+ # <tt>:local</tt> and act accordingly.
27
+ #
28
+ # set :branch, "prod-20060124"
29
+ #
30
+ # Also, you can specify the CVS_RSH variable to use on the remote machine(s)
31
+ # via the <tt>:cvs_rsh</tt> variable. This defaults to the value of the
32
+ # CVS_RSH environment variable locally, or if it is not set, to "ssh".
33
+ class Cvs < Base
34
+ def initialize(configuration)
35
+ super(configuration)
36
+ if not configuration.respond_to?(:branch) then
37
+ configuration.set(:branch) { self.current_branch }
38
+ else
39
+ @current_branch = configuration[:branch]
40
+ end
41
+ end
42
+
43
+ # Return a string representing the date of the last revision (CVS is
44
+ # seriously retarded, in that it does not give you a way to query when
45
+ # the last revision was made to the repository, so this is a fairly
46
+ # expensive operation...)
47
+ def latest_revision
48
+ return @latest_revision if @latest_revision
49
+ configuration.logger.debug "querying latest revision..."
50
+ @latest_revision = cvs_log(cvs_local, configuration.branch).
51
+ split(/\r?\n/).
52
+ grep(/^date: (.*?);/) { Time.parse($1).strftime("%Y-%m-%d %H:%M:%S") }.
53
+ sort.
54
+ last
55
+ end
56
+
57
+ # Return a string representing the branch that the sandbox
58
+ # relative to <tt>:local</tt> contains.
59
+ def current_branch
60
+ return @current_branch if @current_branch
61
+ configuration.logger.debug "determining current_branch..."
62
+ @current_branch = cvs_branch(cvs_local)
63
+ end
64
+
65
+ # Check out (on all servers associated with the current task) the latest
66
+ # revision, using a branch if necessary. Uses the given actor instance
67
+ # to execute the command.
68
+ def checkout(actor)
69
+ cvs = configuration[:cvs] || "cvs"
70
+ cvs_rsh = configuration[:cvs_rsh] || ENV['CVS_RSH'] || "ssh"
71
+
72
+ if "HEAD" == configuration.branch then
73
+ branch_option = ""
74
+ else
75
+ branch_option = "-r #{configuration.branch}"
76
+ end
77
+
78
+ command = <<-CMD
79
+ cd #{configuration.releases_path};
80
+ CVS_RSH="#{cvs_rsh}" #{cvs} -d #{configuration.repository} -Q co -D "#{configuration.revision}" #{branch_option} -d #{File.basename(actor.release_path)} #{actor.application};
81
+ CMD
82
+
83
+ run_checkout(actor, command) do |ch, stream, out|
84
+ prefix = "#{stream} :: #{ch[:host]}"
85
+ actor.logger.info out, prefix
86
+ if out =~ %r{password:}
87
+ actor.logger.info "CVS is asking for a password", prefix
88
+ ch.send_data "#{actor.password}\n"
89
+ elsif out =~ %r{^Enter passphrase}
90
+ message = "CVS needs your key's passphrase and cannot proceed"
91
+ actor.logger.info message, prefix
92
+ raise message
93
+ end
94
+ end
95
+ end
96
+
97
+ private
98
+
99
+ # Look for a 'CVS/Tag' file in the path. If this file exists
100
+ # and contains a Line starting with 'T' then this CVS sandbox is
101
+ # 'tagged' with a branch. In the default case return 'HEAD'
102
+ def cvs_branch(path)
103
+ branch = "HEAD"
104
+ branch_file = File.join(path || ".", "CVS", "Tag")
105
+ if File.exists?(branch_file) then
106
+ File.open(branch_file) do |f|
107
+ possible_branch = f.find { |l| l =~ %r{^T} }
108
+ branch = possible_branch.strip[1..-1] if possible_branch
109
+ end
110
+ end
111
+ branch
112
+ end
113
+
114
+ def cvs_log(path,branch)
115
+ `cd #{path || "."} && cvs -q log -N -r#{branch}`
116
+ end
117
+
118
+ def cvs_local
119
+ configuration.local || "."
120
+ end
121
+ end
122
+
123
+ end
124
+ end
@@ -0,0 +1,27 @@
1
+ require 'capistrano/scm/base'
2
+
3
+ module Capistrano
4
+ module SCM
5
+
6
+ # An SCM module for using darcs as your source control tool. Use it by
7
+ # specifying the following line in your configuration:
8
+ #
9
+ # set :scm, :darcs
10
+ #
11
+ # Also, this module accepts a <tt>:darcs</tt> configuration variable,
12
+ # which (if specified) will be used as the full path to the darcs
13
+ # executable on the remote machine:
14
+ #
15
+ # set :darcs, "/opt/local/bin/darcs"
16
+ class Darcs < Base
17
+ # Check out (on all servers associated with the current task) the latest
18
+ # revision. Uses the given actor instance to execute the command.
19
+ def checkout(actor)
20
+ darcs = configuration[:darcs] ? configuration[:darcs] : "darcs"
21
+ revision = configuration[:revision] ? %(--to-match "#{configuration.revision}") : ""
22
+ run_checkout(actor, "#{darcs} get -q --set-scripts-executable #{revision} #{configuration.repository} #{actor.release_path};")
23
+ end
24
+ end
25
+
26
+ end
27
+ end