ktheory-vlad 2.0.0
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/.autotest +24 -0
- data/History.txt +173 -0
- data/Manifest.txt +25 -0
- data/PATCHES.txt +27 -0
- data/README.txt +78 -0
- data/Rakefile +58 -0
- data/VERSION +1 -0
- data/considerations.txt +91 -0
- data/doco/deploying-merb-with-vlad.txt +155 -0
- data/doco/deploying-sinatra-with-vlad.txt +119 -0
- data/doco/faq.txt +131 -0
- data/doco/getting_started.txt +61 -0
- data/doco/migration.txt +43 -0
- data/doco/perforce.txt +5 -0
- data/doco/variables.txt +79 -0
- data/ktheory-vlad.gemspec +98 -0
- data/lib/rake_remote_task.rb +600 -0
- data/lib/vlad.rb +91 -0
- data/lib/vlad/apache.rb +37 -0
- data/lib/vlad/core.rb +191 -0
- data/lib/vlad/darcs.rb +24 -0
- data/lib/vlad/git.rb +86 -0
- data/lib/vlad/god.rb +23 -0
- data/lib/vlad/lighttpd.rb +85 -0
- data/lib/vlad/maintenance.rb +20 -0
- data/lib/vlad/merb.rb +51 -0
- data/lib/vlad/mercurial.rb +37 -0
- data/lib/vlad/mongrel.rb +62 -0
- data/lib/vlad/nginx.rb +48 -0
- data/lib/vlad/passenger.rb +8 -0
- data/lib/vlad/perforce.rb +117 -0
- data/lib/vlad/subversion.rb +35 -0
- data/lib/vlad/thin.rb +63 -0
- data/lib/vlad_test_case.rb +73 -0
- data/test/test_rake_remote_task.rb +279 -0
- data/test/test_vlad.rb +210 -0
- data/test/test_vlad_git.rb +65 -0
- data/test/test_vlad_mercurial.rb +31 -0
- data/test/test_vlad_perforce.rb +37 -0
- data/test/test_vlad_subversion.rb +27 -0
- data/vladdemo.sh +97 -0
- metadata +134 -0
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'vlad'
|
2
|
+
|
3
|
+
namespace :vlad do
|
4
|
+
|
5
|
+
set :lighttpd_port, 65536
|
6
|
+
set :web_command, "lighttpd"
|
7
|
+
set :lighttpd_user, "nobody"
|
8
|
+
set :lighttpd_group, "nobody"
|
9
|
+
set(:lighttpd_init) { "#{shared_path}/lighttpd.sh" }
|
10
|
+
set(:lighttpd_conf) { "#{shared_path}/lighttpd.conf" }
|
11
|
+
|
12
|
+
desc "Prepares application servers for deployment. Lighttpd
|
13
|
+
configuration is set via the lighttpd_* variables.".cleanup
|
14
|
+
|
15
|
+
remote_task :setup_lighttpd, :roles => :app do
|
16
|
+
require 'tempfile'
|
17
|
+
|
18
|
+
put lighttpd_conf, 'vlad.lighttpd_config' do
|
19
|
+
conf = <<-"EOF"
|
20
|
+
server.modules = ( "mod_rewrite",
|
21
|
+
"mod_access",
|
22
|
+
"mod_fastcgi",
|
23
|
+
"mod_compress",
|
24
|
+
"mod_accesslog" )
|
25
|
+
|
26
|
+
server.document-root = "#{current_path}/public"
|
27
|
+
server.errorlog = "#{shared_path}/log/lighttpd.error.log"
|
28
|
+
accesslog.filename = "#{shared_path}/log/lighttpd.access.log"
|
29
|
+
server.pid-file = "#{shared_path}/pids/lighttpd.pid"
|
30
|
+
server.port = #{lighttpd_port}
|
31
|
+
server.username = "#{lighttpd_user}"
|
32
|
+
server.groupname = "#{lighttpd_group}"
|
33
|
+
server.error-handler-404 = "/dispatch.fcgi"
|
34
|
+
server.indexfiles = ( "index.html", "index.rb" )
|
35
|
+
url.access-deny = ( "~", ".inc" )
|
36
|
+
compress.cache-dir = "#{shared_path}/tmp/cache/compress"
|
37
|
+
compress.filetype = ("text/html","text/plain","text/javascript","text/css")
|
38
|
+
server.tag = "lighttpd | TextDriven"
|
39
|
+
|
40
|
+
fastcgi.server = (
|
41
|
+
".fcgi" => (
|
42
|
+
"localhost" => (
|
43
|
+
"min-procs" => 1,
|
44
|
+
"max-procs" => 1,
|
45
|
+
"socket" => "#{shared_path}/pids/rubyholic.socket",
|
46
|
+
"bin-path" => "#{current_path}/public/dispatch.fcgi",
|
47
|
+
"bin-environment" => ( "RAILS_ENV" => "production" ) ) ) )
|
48
|
+
EOF
|
49
|
+
end
|
50
|
+
|
51
|
+
run "mkdir -p \"#{shared_path}/tmp/cache/compress\""
|
52
|
+
end
|
53
|
+
|
54
|
+
desc "(Re)Start the web servers"
|
55
|
+
|
56
|
+
remote_task :start_web, :roles => :web do
|
57
|
+
cmd = %w(lighttpd ruby).map {|app| "(killall #{app} || true)"}.join(" && ")
|
58
|
+
cmd += " && #{web_command} -f #{lighttpd_conf} </dev/null >/dev/null 2>&1"
|
59
|
+
run cmd
|
60
|
+
end
|
61
|
+
|
62
|
+
desc "Stop the web servers"
|
63
|
+
remote_task :stop_web, :roles => :web do
|
64
|
+
cmd = %w(lighttpd ruby).map {|app| "(killall #{app} || true)"}.join(" && ")
|
65
|
+
|
66
|
+
run cmd
|
67
|
+
end
|
68
|
+
|
69
|
+
##
|
70
|
+
# Everything HTTP.
|
71
|
+
|
72
|
+
desc "(Re)Start the web and app servers"
|
73
|
+
|
74
|
+
remote_task :start do
|
75
|
+
Rake::Task['vlad:start_app'].invoke
|
76
|
+
Rake::Task['vlad:start_web'].invoke
|
77
|
+
end
|
78
|
+
|
79
|
+
desc "Stop the web and app servers"
|
80
|
+
|
81
|
+
remote_task :stop do
|
82
|
+
Rake::Task['vlad:stop_app'].invoke
|
83
|
+
Rake::Task['vlad:stop_web'].invoke
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'vlad'
|
2
|
+
|
3
|
+
##
|
4
|
+
# See the following documents for recipes:
|
5
|
+
#
|
6
|
+
# * http://clarkware.com/cgi/blosxom/2007/01/05/CustomMaintenancePages
|
7
|
+
# * http://blog.nodeta.fi/2009/03/11/stopping-your-rails-application-with-phusion-passenger/
|
8
|
+
#
|
9
|
+
|
10
|
+
namespace :vlad do
|
11
|
+
namespace :maintenance do
|
12
|
+
remote_task :on, :roles => [:web] do
|
13
|
+
run "cp -f #{shared_path}/config/maintenance.html #{shared_path}/system/"
|
14
|
+
end
|
15
|
+
|
16
|
+
remote_task :off, :roles => [:web] do
|
17
|
+
run "rm -f #{shared_path}/system/maintenance.html"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/vlad/merb.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'vlad'
|
2
|
+
|
3
|
+
namespace :vlad do
|
4
|
+
##
|
5
|
+
# Merb app server
|
6
|
+
|
7
|
+
set :merb_address, "127.0.0.1"
|
8
|
+
set :merb_command, 'merb'
|
9
|
+
set :merb_environment, "production"
|
10
|
+
set :merb_port, 8000
|
11
|
+
set :merb_servers, 2
|
12
|
+
|
13
|
+
# maybe needed later
|
14
|
+
#set :merb_clean, false
|
15
|
+
#set(:merb_conf) { "#{current_path}/config/merb.yml" }
|
16
|
+
#set :merb_config_script, nil
|
17
|
+
#set :merb_group, nil
|
18
|
+
#set :merb_log_file, nil
|
19
|
+
#set :merb_pid_file, nil
|
20
|
+
#set :merb_prefix, nil
|
21
|
+
#set :merb_user, nil
|
22
|
+
|
23
|
+
desc "Start the app servers"
|
24
|
+
remote_task :start_app, :roles => :app do
|
25
|
+
cmd = [
|
26
|
+
"cd #{current_path} &&", # work around merb bug,
|
27
|
+
# http://merb.devjavu.com/ticket/469
|
28
|
+
"#{merb_command}",
|
29
|
+
#"-m #{current_path}", # the buggy behaviour
|
30
|
+
"-e #{merb_environment}",
|
31
|
+
"-p #{merb_port}",
|
32
|
+
"-c #{merb_servers}"
|
33
|
+
].compact.join ' '
|
34
|
+
run cmd
|
35
|
+
end
|
36
|
+
|
37
|
+
desc "Stop the app servers"
|
38
|
+
remote_task :stop_app, :roles => :app do
|
39
|
+
merb_servers.times do |i|
|
40
|
+
cmd = "#{current_path}/script/stop_merb #{merb_port + i}"
|
41
|
+
puts "$ #{cmd}"
|
42
|
+
run cmd
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
desc "Stop, then restart the app servers"
|
47
|
+
remote_task :restart_app, :roles => :app do
|
48
|
+
Rake::Task['vlad:stop_app'].invoke
|
49
|
+
Rake::Task['vlad:start_app'].invoke
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
class Vlad::Mercurial
|
2
|
+
|
3
|
+
set :source, Vlad::Mercurial.new
|
4
|
+
|
5
|
+
##
|
6
|
+
# Returns the command that will check out +revision+ from the repository
|
7
|
+
# into directory +destination+
|
8
|
+
|
9
|
+
def checkout(revision, destination)
|
10
|
+
revision = 'tip' if revision =~ /^head$/i
|
11
|
+
|
12
|
+
[ "if [ ! -d #{destination}/.hg ]; then hg init -R #{destination}; fi",
|
13
|
+
"hg pull -r #{revision} -R #{destination} #{repository}"
|
14
|
+
].join(' && ')
|
15
|
+
end
|
16
|
+
|
17
|
+
##
|
18
|
+
# Returns the command that will export +revision+ from the repository into
|
19
|
+
# the directory +destination+.
|
20
|
+
|
21
|
+
def export(revision_or_source, destination)
|
22
|
+
revision_or_source = 'tip' if revision_or_source =~ /^head$/i
|
23
|
+
if revision_or_source =~ /^(\d+|tip)$/i then
|
24
|
+
"hg archive -r #{revision_or_source} -R #{repository} #{destination}"
|
25
|
+
else
|
26
|
+
"hg archive -R #{revision_or_source} #{destination}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
##
|
31
|
+
# Returns a command that maps human-friendly revision identifier +revision+
|
32
|
+
# into a subversion revision specification.
|
33
|
+
|
34
|
+
def revision(revision)
|
35
|
+
"`hg identify -R #{repository} | cut -f1 -d\\ `"
|
36
|
+
end
|
37
|
+
end
|
data/lib/vlad/mongrel.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'vlad'
|
2
|
+
|
3
|
+
namespace :vlad do
|
4
|
+
##
|
5
|
+
# Mongrel app server
|
6
|
+
|
7
|
+
set :mongrel_address, "127.0.0.1"
|
8
|
+
set :mongrel_clean, false
|
9
|
+
set :mongrel_command, 'mongrel_rails'
|
10
|
+
set(:mongrel_conf) { "#{shared_path}/mongrel_cluster.conf" }
|
11
|
+
set :mongrel_config_script, nil
|
12
|
+
set :mongrel_environment, "production"
|
13
|
+
set :mongrel_group, nil
|
14
|
+
set :mongrel_log_file, nil
|
15
|
+
set :mongrel_pid_file, nil
|
16
|
+
set :mongrel_port, 8000
|
17
|
+
set :mongrel_prefix, nil
|
18
|
+
set :mongrel_servers, 2
|
19
|
+
set :mongrel_user, nil
|
20
|
+
|
21
|
+
desc "Prepares application servers for deployment. Mongrel
|
22
|
+
configuration is set via the mongrel_* variables.".cleanup
|
23
|
+
|
24
|
+
remote_task :setup_app, :roles => :app do
|
25
|
+
cmd = [
|
26
|
+
'cluster::configure',
|
27
|
+
"-N #{mongrel_servers}",
|
28
|
+
"-p #{mongrel_port}",
|
29
|
+
"-e #{mongrel_environment}",
|
30
|
+
"-a #{mongrel_address}",
|
31
|
+
"-c #{current_path}",
|
32
|
+
("-P #{mongrel_pid_file}" if mongrel_pid_file),
|
33
|
+
("-l #{mongrel_log_file}" if mongrel_log_file),
|
34
|
+
("--user #{mongrel_user}" if mongrel_user),
|
35
|
+
("--group #{mongrel_group}" if mongrel_group),
|
36
|
+
("--prefix #{mongrel_prefix}" if mongrel_prefix),
|
37
|
+
("-S #{mongrel_config_script}" if mongrel_config_script),
|
38
|
+
]
|
39
|
+
|
40
|
+
run mongrel(*cmd)
|
41
|
+
end
|
42
|
+
|
43
|
+
def mongrel(cmd, *opts) # :nodoc:
|
44
|
+
cmd = ["#{mongrel_command} #{cmd} -C #{mongrel_conf}"]
|
45
|
+
cmd << ' --clean' if mongrel_clean unless cmd == 'cluster::configure'
|
46
|
+
cmd.push(*opts)
|
47
|
+
|
48
|
+
cmd.compact.join ' '
|
49
|
+
end
|
50
|
+
|
51
|
+
desc "Restart the app servers"
|
52
|
+
|
53
|
+
remote_task :start_app, :roles => :app do
|
54
|
+
run mongrel("cluster::restart")
|
55
|
+
end
|
56
|
+
|
57
|
+
desc "Stop the app servers"
|
58
|
+
|
59
|
+
remote_task :stop_app, :roles => :app do
|
60
|
+
run mongrel("cluster::stop")
|
61
|
+
end
|
62
|
+
end
|
data/lib/vlad/nginx.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'vlad'
|
2
|
+
|
3
|
+
namespace :vlad do
|
4
|
+
##
|
5
|
+
# Nginx web server on Gentoo/Debian init.d systems FIX
|
6
|
+
|
7
|
+
set :web_command, "/etc/init.d/nginx"
|
8
|
+
|
9
|
+
remote_task :setup_app, :roles => :web do
|
10
|
+
config_file = "/etc/nginx/vhosts/#{application}_#{environment}.conf"
|
11
|
+
raise "not yet... must review this code"
|
12
|
+
run [ "sudo test -e #{config_file} || ",
|
13
|
+
"sudo sh -c \"ruby ",
|
14
|
+
" /etc/sliceconfig/install/interactive/nginx_config.rb ",
|
15
|
+
"'#{app_domain}' '#{application}' '#{environment}' ",
|
16
|
+
"'#{app_port}' '#{app_servers}' #{only_www ? 1 : 0} ",
|
17
|
+
"> #{config_file}\""
|
18
|
+
].join(" ")
|
19
|
+
end
|
20
|
+
|
21
|
+
desc "(Re)Start the web servers"
|
22
|
+
|
23
|
+
remote_task :start_web, :roles => :web do
|
24
|
+
run "#{web_command} restart"
|
25
|
+
# TODO: run %Q(sudo #{web_command} configtest && sudo #{web_command} reload)
|
26
|
+
end
|
27
|
+
|
28
|
+
desc "Stop the web servers"
|
29
|
+
|
30
|
+
remote_task :stop_web, :roles => :web do
|
31
|
+
run "#{web_command} stop"
|
32
|
+
end
|
33
|
+
|
34
|
+
##
|
35
|
+
# Everything HTTP.
|
36
|
+
|
37
|
+
desc "(Re)Start the web and app servers"
|
38
|
+
|
39
|
+
remote_task :start do
|
40
|
+
Rake::Task['vlad:start_app'].invoke
|
41
|
+
Rake::Task['vlad:start_web'].invoke
|
42
|
+
end
|
43
|
+
|
44
|
+
remote_task :stop do
|
45
|
+
Rake::Task['vlad:stop_app'].invoke
|
46
|
+
Rake::Task['vlad:stop_web'].invoke
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
class Vlad::Perforce
|
2
|
+
|
3
|
+
set :p4_cmd, "p4"
|
4
|
+
set :source, Vlad::Perforce.new
|
5
|
+
|
6
|
+
##
|
7
|
+
# Returns the p4 command that will checkout +revision+ into the directory
|
8
|
+
# +destination+.
|
9
|
+
|
10
|
+
def checkout(revision, destination)
|
11
|
+
"#{p4_cmd} sync ...#{rev_no(revision)}"
|
12
|
+
end
|
13
|
+
|
14
|
+
##
|
15
|
+
# Returns the p4 command that will export +revision+ into the directory
|
16
|
+
# +directory+.
|
17
|
+
|
18
|
+
def export(revision_or_source, destination)
|
19
|
+
if revision_or_source =~ /^(\d+|head)$/i then
|
20
|
+
"(cd #{destination} && #{p4_cmd} sync ...#{rev_no(revision_or_source)})"
|
21
|
+
else
|
22
|
+
"cp -r #{revision_or_source} #{destination}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
##
|
27
|
+
# Returns a command that maps human-friendly revision identifier +revision+
|
28
|
+
# into a Perforce revision specification.
|
29
|
+
|
30
|
+
def revision(revision)
|
31
|
+
"`#{p4_cmd} changes -s submitted -m 1 ...#{rev_no(revision)} | cut -f 2 -d\\ `"
|
32
|
+
end
|
33
|
+
|
34
|
+
##
|
35
|
+
# Maps revision +revision+ into a Perforce revision.
|
36
|
+
|
37
|
+
def rev_no(revision)
|
38
|
+
case revision.to_s
|
39
|
+
when /head/i then
|
40
|
+
"#head"
|
41
|
+
when /^\d+$/ then
|
42
|
+
"@#{revision}"
|
43
|
+
else
|
44
|
+
revision
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
namespace :vlad do
|
50
|
+
remote_task :setup_app, :roles => :app do
|
51
|
+
p4data = p4port = p4user = p4passwd = nil
|
52
|
+
|
53
|
+
if ENV['P4CONFIG'] then
|
54
|
+
p4config_name = ENV['P4CONFIG']
|
55
|
+
p4config = nil
|
56
|
+
orig_dir = Dir.pwd.split File::SEPARATOR
|
57
|
+
|
58
|
+
until orig_dir.length == 1 do
|
59
|
+
p4config = orig_dir + [p4config_name]
|
60
|
+
p4config = File.join p4config
|
61
|
+
break if File.exist? p4config
|
62
|
+
orig_dir.pop
|
63
|
+
end
|
64
|
+
|
65
|
+
raise "couldn't find .p4config" unless File.exist? p4config
|
66
|
+
|
67
|
+
p4data = File.readlines(p4config).map { |line| line.strip.split '=', 2 }
|
68
|
+
p4data = Hash[*p4data.flatten]
|
69
|
+
else
|
70
|
+
p4data = ENV
|
71
|
+
end
|
72
|
+
|
73
|
+
p4port = p4data['P4PORT']
|
74
|
+
p4user = p4data['P4USER']
|
75
|
+
p4passwd = p4data['P4PASSWD']
|
76
|
+
|
77
|
+
raise "couldn't get P4PORT" if p4port.nil?
|
78
|
+
raise "couldn't get P4USER" if p4user.nil?
|
79
|
+
raise "couldn't get P4PASSWD" if p4passwd.nil?
|
80
|
+
|
81
|
+
p4client = [p4user, target_host, application].join '-'
|
82
|
+
|
83
|
+
require 'tmpdir'
|
84
|
+
require 'tempfile'
|
85
|
+
|
86
|
+
put File.join(scm_path, '.p4config'), 'vlad.p4config' do
|
87
|
+
[ "P4PORT=#{p4port}",
|
88
|
+
"P4USER=#{p4user}",
|
89
|
+
"P4PASSWD=#{p4passwd}",
|
90
|
+
"P4CLIENT=#{p4client}" ].join("\n")
|
91
|
+
end
|
92
|
+
|
93
|
+
p4client_path = File.join deploy_to, 'p4client.tmp'
|
94
|
+
|
95
|
+
put p4client_path, 'vlad.p4client' do
|
96
|
+
conf = <<-"CLIENT"
|
97
|
+
Client: #{p4client}
|
98
|
+
|
99
|
+
Owner: #{p4user}
|
100
|
+
|
101
|
+
Root: #{scm_path}
|
102
|
+
|
103
|
+
View:
|
104
|
+
#{repository}/... //#{p4client}/...
|
105
|
+
CLIENT
|
106
|
+
end
|
107
|
+
|
108
|
+
cmds = [
|
109
|
+
"cd #{scm_path}",
|
110
|
+
"p4 client -i < #{p4client_path}",
|
111
|
+
"rm #{p4client_path}",
|
112
|
+
]
|
113
|
+
|
114
|
+
run cmds.join(' && ')
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
@@ -0,0 +1,35 @@
|
|
1
|
+
class Vlad::Subversion
|
2
|
+
|
3
|
+
set :source, Vlad::Subversion.new
|
4
|
+
set :svn_cmd, "svn"
|
5
|
+
|
6
|
+
##
|
7
|
+
# Returns the command that will check out +revision+ from the repository
|
8
|
+
# into directory +destination+
|
9
|
+
|
10
|
+
def checkout(revision, destination)
|
11
|
+
"#{svn_cmd} co -r #{revision} #{repository} #{destination}"
|
12
|
+
end
|
13
|
+
|
14
|
+
##
|
15
|
+
# Returns the command that will export +revision+ from the repository into
|
16
|
+
# the directory +destination+.
|
17
|
+
|
18
|
+
def export(revision_or_source, destination)
|
19
|
+
"#{svn_cmd} #{deploy_via} " +
|
20
|
+
if revision_or_source =~ /^(\d+|head)$/i then
|
21
|
+
"-r #{revision_or_source} #{repository} #{destination}"
|
22
|
+
else
|
23
|
+
"#{revision_or_source} #{destination}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
##
|
28
|
+
# Returns a command that maps human-friendly revision identifier +revision+
|
29
|
+
# into a subversion revision specification.
|
30
|
+
|
31
|
+
def revision(revision)
|
32
|
+
"`#{svn_cmd} info #{repository} | grep 'Revision:' | cut -f2 -d\\ `"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|