capistrano_recipes 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.gitignore +18 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/Gemfile +9 -0
- data/LICENSE.txt +22 -0
- data/README.md +89 -0
- data/Rakefile +7 -0
- data/capistrano_recipes.gemspec +24 -0
- data/lib/capistrano/recipes/bundle.rb +9 -0
- data/lib/capistrano/recipes/bundler.rb +2 -0
- data/lib/capistrano/recipes/git.rb +119 -0
- data/lib/capistrano/recipes/multistage.rb +73 -0
- data/lib/capistrano/recipes/mysql.rb +134 -0
- data/lib/capistrano/recipes/nginx.rb +75 -0
- data/lib/capistrano/recipes/rails_assets.rb +7 -0
- data/lib/capistrano/recipes/templates/mysql.yml.erb +7 -0
- data/lib/capistrano/recipes/templates/nginx.vhost.erb +139 -0
- data/lib/capistrano/recipes/templates/unicorn.rb.erb +47 -0
- data/lib/capistrano/recipes/templates/unicorn_init.erb +84 -0
- data/lib/capistrano/recipes/unicorn.rb +71 -0
- data/lib/capistrano/recipes.rb +1 -0
- data/lib/capistrano_recipes.rb +129 -0
- data/spec/bundle_spec.rb +15 -0
- data/spec/bundler_spec.rb +14 -0
- data/spec/git_spec.rb +57 -0
- data/spec/multistage_spec.rb +66 -0
- data/spec/mysql_spec.rb +14 -0
- data/spec/nginx_spec.rb +16 -0
- data/spec/rails_assets.rb +37 -0
- data/spec/spec_helper.rb +108 -0
- data/spec/unicorn_spec.rb +16 -0
- metadata +126 -0
@@ -0,0 +1,139 @@
|
|
1
|
+
<% if using_recipe?(:unicorn) %>
|
2
|
+
upstream unicorn_<%= application %> {
|
3
|
+
server unix:<%= unicorn_socket %> fail_timeout=0;
|
4
|
+
}
|
5
|
+
|
6
|
+
<% end %>
|
7
|
+
<% if exists?(:domain_alias) %>
|
8
|
+
server {
|
9
|
+
server_name <%= domain_alias %>;
|
10
|
+
rewrite ^(.*) http://<%= domain %>$1 permanent;
|
11
|
+
}
|
12
|
+
|
13
|
+
<% end %>
|
14
|
+
server {
|
15
|
+
listen <%= nginx_port %>;
|
16
|
+
server_name <%= domain %>;
|
17
|
+
|
18
|
+
root <%= current_path %>/public;
|
19
|
+
access_log <%= shared_path %>/log/access.log main;
|
20
|
+
error_log <%= shared_path %>/log/error.log info;
|
21
|
+
|
22
|
+
# Rewrite all the requests to the maintenance.html
|
23
|
+
# page if it exists in the doc root. This is for
|
24
|
+
# capistrano's disable web task
|
25
|
+
if (-f $document_root/system/maintenance.html) {
|
26
|
+
rewrite ^(.*)$ /system/maintenance.html last;
|
27
|
+
break;
|
28
|
+
}
|
29
|
+
|
30
|
+
location / {
|
31
|
+
# If the file exists as a static file, serve it directly
|
32
|
+
# without running all the other rewrite tests on it
|
33
|
+
if (-f $request_filename) {
|
34
|
+
break;
|
35
|
+
}
|
36
|
+
|
37
|
+
# Check for index.html
|
38
|
+
if (-f $request_filename/index.html) {
|
39
|
+
rewrite (.*) $1/index.html break;
|
40
|
+
}
|
41
|
+
|
42
|
+
# Check if .html file exists for page caching
|
43
|
+
if (-f $request_filename.html) {
|
44
|
+
rewrite (.*) $1.html break;
|
45
|
+
}
|
46
|
+
}
|
47
|
+
|
48
|
+
<% if using_recipe?(:rails_assets) %>
|
49
|
+
# Asset pipeline
|
50
|
+
location ^~ /assets/ {
|
51
|
+
gzip_static on;
|
52
|
+
expires max;
|
53
|
+
add_header Cache-Control public;
|
54
|
+
}
|
55
|
+
|
56
|
+
<% end %>
|
57
|
+
<% if using_recipe?(:unicorn) %>
|
58
|
+
try_files $uri/index.html $uri @unicorn;
|
59
|
+
location @unicorn {
|
60
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
61
|
+
proxy_set_header Host $http_host;
|
62
|
+
proxy_redirect off;
|
63
|
+
proxy_pass http://unicorn_<%= application %>;
|
64
|
+
}
|
65
|
+
|
66
|
+
<% end %>
|
67
|
+
error_page 500 502 503 504 /500.html;
|
68
|
+
location = /500.html {
|
69
|
+
root <%= current_path %>/public;
|
70
|
+
}
|
71
|
+
}
|
72
|
+
<% if using_ssl? %>
|
73
|
+
|
74
|
+
server {
|
75
|
+
listen <%= nginx_ssl_port %>;
|
76
|
+
server_name <%= domain %>;
|
77
|
+
|
78
|
+
root <%= current_path %>/public;
|
79
|
+
access_log <%= shared_path %>/log/ssl-access.log main;
|
80
|
+
error_log <%= shared_path %>/log/ssl-error.log info;
|
81
|
+
|
82
|
+
ssl on;
|
83
|
+
ssl_certificate <%= File.join nginx_ssl_certs_path, nginx_ssl_cert %>;
|
84
|
+
ssl_certificate_key <%= File.join nginx_ssl_private_path, nginx_ssl_key %>;
|
85
|
+
ssl_session_timeout 5m;
|
86
|
+
|
87
|
+
|
88
|
+
# Rewrite all the requests to the maintenance.html
|
89
|
+
# page if it exists in the doc root. This is for
|
90
|
+
# capistrano's disable web task
|
91
|
+
if (-f $document_root/system/maintenance.html) {
|
92
|
+
rewrite ^(.*)$ /system/maintenance.html last;
|
93
|
+
break;
|
94
|
+
}
|
95
|
+
|
96
|
+
location / {
|
97
|
+
# If the file exists as a static file, serve it directly
|
98
|
+
# without running all the other rewrite tests on it
|
99
|
+
if (-f $request_filename) {
|
100
|
+
break;
|
101
|
+
}
|
102
|
+
|
103
|
+
# Check for index.html
|
104
|
+
if (-f $request_filename/index.html) {
|
105
|
+
rewrite (.*) $1/index.html break;
|
106
|
+
}
|
107
|
+
|
108
|
+
# Check if .html file exists for page caching
|
109
|
+
if (-f $request_filename.html) {
|
110
|
+
rewrite (.*) $1.html break;
|
111
|
+
}
|
112
|
+
}
|
113
|
+
|
114
|
+
<% if using_recipe?(:rails_assets) %>
|
115
|
+
# Asset pipeline
|
116
|
+
location ^~ /assets/ {
|
117
|
+
gzip_static on;
|
118
|
+
expires max;
|
119
|
+
add_header Cache-Control public;
|
120
|
+
}
|
121
|
+
|
122
|
+
<% end %>
|
123
|
+
<% if using_recipe?(:unicorn) %>
|
124
|
+
try_files $uri/index.html $uri @unicorn;
|
125
|
+
location @unicorn {
|
126
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
127
|
+
proxy_set_header X-Forwarded-Proto https;
|
128
|
+
proxy_set_header Host $http_host;
|
129
|
+
proxy_redirect off;
|
130
|
+
proxy_pass http://unicorn_<%= application %>;
|
131
|
+
}
|
132
|
+
|
133
|
+
<% end %>
|
134
|
+
error_page 500 502 503 504 /500.html;
|
135
|
+
location = /500.html {
|
136
|
+
root <%= current_path %>/public;
|
137
|
+
}
|
138
|
+
}
|
139
|
+
<% end %>
|
@@ -0,0 +1,47 @@
|
|
1
|
+
working_directory "<%= current_path %>"
|
2
|
+
pid "<%= unicorn_pid_file %>"
|
3
|
+
stderr_path "<%= unicorn_log_file %>"
|
4
|
+
stdout_path "<%= unicorn_log_file %>"
|
5
|
+
|
6
|
+
# Listen on a Unix domain socket
|
7
|
+
# Use shorter backlog for quicker failover when busy
|
8
|
+
listen "<%= unicorn_socket_file %>", backlog: 64
|
9
|
+
|
10
|
+
# Preload our app for more speed
|
11
|
+
preload_app true
|
12
|
+
|
13
|
+
# See unicorn docs for more configuration details
|
14
|
+
worker_processes <%= unicorn_workers %>
|
15
|
+
|
16
|
+
# Kill workers after <%= unicorn_workers_timeout %> seconds, instead of the default 60
|
17
|
+
timeout <%= unicorn_workers_timeout %>
|
18
|
+
|
19
|
+
before_fork do |server, worker|
|
20
|
+
# the following is recommended for Rails + "preload_app true"
|
21
|
+
# as there is no need for the master process to hold a connection
|
22
|
+
if defined?(ActiveRecord::Base)
|
23
|
+
ActiveRecord::Base.connection.disconnect!
|
24
|
+
end
|
25
|
+
|
26
|
+
# Before forking, kill the master process that belongs to the .oldbin PID.
|
27
|
+
# This enables 0 downtime deploys.
|
28
|
+
old_pid = "<%= unicorn_pid_file %>.oldbin"
|
29
|
+
|
30
|
+
if File.exists?(old_pid) && server.pid != old_pid
|
31
|
+
begin
|
32
|
+
Process.kill("QUIT", File.read(old_pid).to_i)
|
33
|
+
rescue Errno::ENOENT, Errno::ESRCH
|
34
|
+
# someone else killed it
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
after_fork do |server, worker|
|
40
|
+
# the following is required for Rails + "preload_app true"
|
41
|
+
if defined?(ActiveRecord::Base)
|
42
|
+
ActiveRecord::Base.establish_connection
|
43
|
+
end
|
44
|
+
|
45
|
+
# if preload_app is true, you may also want to check and
|
46
|
+
# restart any other shared sockets such as Memcached
|
47
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
### BEGIN INIT INFO
|
3
|
+
# Provides: unicorn
|
4
|
+
# Required-Start: $remote_fs $syslog
|
5
|
+
# Required-Stop: $remote_fs $syslog
|
6
|
+
# Default-Start: 2 3 4 5
|
7
|
+
# Default-Stop: 0 1 6
|
8
|
+
# Short-Description: Manage unicorn server
|
9
|
+
# Description: Start, stop, restart unicorn server for a specific application.
|
10
|
+
### END INIT INFO
|
11
|
+
set -e
|
12
|
+
|
13
|
+
# Feel free to change any of the following variables for your app:
|
14
|
+
TIMEOUT=${TIMEOUT-60}
|
15
|
+
APP_ROOT=<%= current_path %>
|
16
|
+
PID=<%= unicorn_pid_file %>
|
17
|
+
CMD="cd <%= current_path %>; <%= unicorn_command %> -D -c <%= unicorn_config_file %> -E <%= rails_env %>"
|
18
|
+
AS_USER=<%= unicorn_user %>
|
19
|
+
set -u
|
20
|
+
|
21
|
+
OLD_PID="$PID.oldbin"
|
22
|
+
|
23
|
+
sig () {
|
24
|
+
test -s "$PID" && kill -$1 `cat $PID`
|
25
|
+
}
|
26
|
+
|
27
|
+
oldsig () {
|
28
|
+
test -s $OLD_PIN && kill -$1 `cat $OLD_PIN`
|
29
|
+
}
|
30
|
+
|
31
|
+
run () {
|
32
|
+
if [ "$(id -un)" = "$AS_USER" ]; then
|
33
|
+
eval $1
|
34
|
+
else
|
35
|
+
su -c "$1" - $AS_USER
|
36
|
+
fi
|
37
|
+
}
|
38
|
+
|
39
|
+
case "$1" in
|
40
|
+
start)
|
41
|
+
sig 0 && echo >&2 "Already running" && exit 0
|
42
|
+
run "$CMD"
|
43
|
+
;;
|
44
|
+
stop)
|
45
|
+
kill -s QUIT `cat $PID` && exit 0
|
46
|
+
echo >&2 "Not running"
|
47
|
+
;;
|
48
|
+
force-stop)
|
49
|
+
sig TERM && exit 0
|
50
|
+
echo >&2 "Not running"
|
51
|
+
;;
|
52
|
+
restart|reload)
|
53
|
+
kill -s USR2 `cat $PID` && echo reloaded OK && exit 0
|
54
|
+
echo >&2 "Couldn't reload, starting '$CMD' instead"
|
55
|
+
run "$CMD"
|
56
|
+
;;
|
57
|
+
upgrade)
|
58
|
+
if sig USR2 && sleep 2 && sig 0 && oldsig QUIT
|
59
|
+
then
|
60
|
+
n=$TIMEOUT
|
61
|
+
while test -s $OLD_PIN && test $n -ge 0
|
62
|
+
do
|
63
|
+
printf '.' && sleep 1 && n=$(( $n - 1 ))
|
64
|
+
done
|
65
|
+
echo
|
66
|
+
|
67
|
+
if test $n -lt 0 && test -s $OLD_PIN
|
68
|
+
then
|
69
|
+
echo >&2 "$OLD_PID still exists after $TIMEOUT seconds"
|
70
|
+
exit 1
|
71
|
+
fi
|
72
|
+
exit 0
|
73
|
+
fi
|
74
|
+
echo >&2 "Couldn't upgrade, starting '$CMD' instead"
|
75
|
+
run "$CMD"
|
76
|
+
;;
|
77
|
+
reopen-logs)
|
78
|
+
sig USR1
|
79
|
+
;;
|
80
|
+
*)
|
81
|
+
echo >&2 "Usage: $0 <start|stop|restart|upgrade|force-stop|reopen-logs>"
|
82
|
+
exit 1
|
83
|
+
;;
|
84
|
+
esac
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module CapistranoRecipes
|
2
|
+
module Unicorn
|
3
|
+
def self.load_into(configuration)
|
4
|
+
configuration.load do
|
5
|
+
# Start workers with this user
|
6
|
+
_cset :unicorn_user, lambda { user }
|
7
|
+
|
8
|
+
# Number of unicorn workers
|
9
|
+
_cset :unicorn_workers, lambda { 2 }
|
10
|
+
|
11
|
+
# Unicorn workers timeout in seconds
|
12
|
+
_cset :unicorn_workers_timeout, lambda { 15 }
|
13
|
+
|
14
|
+
# Unicorn config template
|
15
|
+
_cset :unicorn_config_template, lambda { File.join templates_path, 'unicorn.rb.erb' }
|
16
|
+
|
17
|
+
# Unicorn config file
|
18
|
+
_cset :unicorn_config_file, lambda { File.join config_path, 'unicorn.rb' }
|
19
|
+
|
20
|
+
# Whether or not to use unicorn init to start on reboot
|
21
|
+
_cset :use_unicorn_init, lambda { true }
|
22
|
+
|
23
|
+
# Unicorn init template
|
24
|
+
_cset :unicorn_init_template, lambda { File.join templates_path, 'unicorn_init.erb' }
|
25
|
+
|
26
|
+
# Unicorn init file
|
27
|
+
_cset :unicorn_init_file, lambda { "/etc/init.d/unicorn-#{application}" }
|
28
|
+
|
29
|
+
# Unicorn pid file
|
30
|
+
_cset :unicorn_pid_file, lambda { File.join pids_path, 'unicorn.pid' }
|
31
|
+
|
32
|
+
# Unicorn log file
|
33
|
+
_cset :unicorn_log_file, lambda { File.join log_path, 'unicorn.log' }
|
34
|
+
|
35
|
+
# Unicorn socket file
|
36
|
+
_cset :unicorn_socket_file, lambda { File.join sockets_path, 'unicorn.sock' }
|
37
|
+
|
38
|
+
# Unicofn command
|
39
|
+
_cset :unicorn_command, lambda { using_recipe?(:bundle) ? 'bundle exec unicorn' : 'unicorn' }
|
40
|
+
|
41
|
+
def using_unicorn_init?
|
42
|
+
fetch(:use_unicorn_init)
|
43
|
+
end
|
44
|
+
|
45
|
+
namespace :unicorn do
|
46
|
+
desc 'Setup unicorn'
|
47
|
+
task :setup, :roles => :app, :except => { :no_release => true } do
|
48
|
+
run "rm -f #{unicorn_socket_file}"
|
49
|
+
upload_template unicorn_config_template, unicorn_config_file
|
50
|
+
|
51
|
+
if using_unicorn_init?
|
52
|
+
upload_template unicorn_init_template, unicorn_init_file, '+x'
|
53
|
+
run "#{sudo} chkconfig --levels 235 unicorn-#{application} on"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
after 'deploy:setup' do
|
57
|
+
unicorn.setup if agree? "Create and upload unicorn config for #{application}?"
|
58
|
+
end
|
59
|
+
|
60
|
+
%w[start stop restart].each do |command|
|
61
|
+
desc "#{command.capitalize} unicorn"
|
62
|
+
task command, :roles => :app, :except => { :no_release => true } do
|
63
|
+
run "#{unicorn_init_file} #{command}"
|
64
|
+
end
|
65
|
+
after "deploy:#{command}", "unicorn:#{command}"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'capistrano_recipes'
|
@@ -0,0 +1,129 @@
|
|
1
|
+
require 'capistrano'
|
2
|
+
|
3
|
+
module CapistranoRecipes
|
4
|
+
def self.load_into(configuration)
|
5
|
+
configuration.load('deploy')
|
6
|
+
|
7
|
+
configuration.load do
|
8
|
+
_cset :shared_children, %w(public/system log tmp/pids tmp/sockets)
|
9
|
+
_cset(:domain) { abort "Please specify domain, set :domain, 'domain.com'"}
|
10
|
+
_cset :config_dir, 'config'
|
11
|
+
_cset :config_path, lambda { File.join shared_path, config_dir }
|
12
|
+
_cset :backup_dir, 'backup'
|
13
|
+
_cset :backup_path, lambda { File.join shared_path, backup_dir }
|
14
|
+
_cset :log_path, lambda { File.join shared_path, 'log' }
|
15
|
+
_cset :pids_path, lambda { File.join shared_path, 'pids' }
|
16
|
+
_cset :sockets_path, lambda { File.join shared_path, 'sockets' }
|
17
|
+
|
18
|
+
set :user, 'deployer'
|
19
|
+
|
20
|
+
@used_recipes = []
|
21
|
+
|
22
|
+
class << self
|
23
|
+
attr_reader :used_recipes
|
24
|
+
end
|
25
|
+
|
26
|
+
def use_recipe(recipe_name)
|
27
|
+
return if @used_recipes.include?(recipe_name.to_sym)
|
28
|
+
|
29
|
+
begin
|
30
|
+
require "capistrano/recipes/#{recipe_name}"
|
31
|
+
|
32
|
+
recipe = CapistranoRecipes.const_get(recipe_name.to_s.capitalize.gsub(/_(\w)/) { $1.upcase })
|
33
|
+
recipe.load_into(self)
|
34
|
+
@used_recipes << recipe.to_s.split('::').last.downcase.to_sym
|
35
|
+
rescue LoadError
|
36
|
+
abort "Did you misspell `#{recipe_name}` recipe name?"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def use_recipes(*recipes)
|
41
|
+
recipes.each do |recipe|
|
42
|
+
use_recipe(recipe)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def using_recipe?(recipe)
|
47
|
+
used_recipes.include?(recipe.to_sym)
|
48
|
+
end
|
49
|
+
|
50
|
+
def upload_template(local_file, remote_file, permissions = nil)
|
51
|
+
temp_file = "/tmp/#{File.basename(remote_file)}"
|
52
|
+
template = parse_template(local_file)
|
53
|
+
put template, temp_file
|
54
|
+
run "chmod #{permissions} #{temp_file}" unless permissions.nil?
|
55
|
+
run "#{sudo} mv #{temp_file} #{remote_file}"
|
56
|
+
end
|
57
|
+
|
58
|
+
def templates_path
|
59
|
+
expanded_path_for('capistrano/recipes/templates')
|
60
|
+
end
|
61
|
+
|
62
|
+
def expanded_path_for(path)
|
63
|
+
e = File.join(File.dirname(__FILE__), path)
|
64
|
+
File.expand_path(e)
|
65
|
+
end
|
66
|
+
|
67
|
+
def parse_template(file)
|
68
|
+
require 'erb'
|
69
|
+
template = File.read(file)
|
70
|
+
return ERB.new(template, nil, '<>').result(binding)
|
71
|
+
end
|
72
|
+
|
73
|
+
def ask(question)
|
74
|
+
q = "\n#{question} : "
|
75
|
+
Capistrano::CLI.ui.ask(q)
|
76
|
+
end
|
77
|
+
|
78
|
+
def agree?(question)
|
79
|
+
q = "\n#{question} : "
|
80
|
+
Capistrano::CLI.ui.agree(q)
|
81
|
+
end
|
82
|
+
|
83
|
+
def password_prompt(prompt)
|
84
|
+
p = "\n#{prompt} : "
|
85
|
+
Capistrano::CLI.password_prompt(p)
|
86
|
+
end
|
87
|
+
|
88
|
+
def say(message)
|
89
|
+
m = "\n#{message}"
|
90
|
+
Capistrano::CLI.ui.say(m)
|
91
|
+
end
|
92
|
+
|
93
|
+
namespace :deploy do
|
94
|
+
desc 'Deploy application'
|
95
|
+
task :default do
|
96
|
+
update
|
97
|
+
restart
|
98
|
+
end
|
99
|
+
|
100
|
+
desc 'Setup servers for deployment'
|
101
|
+
task :setup, :except => { :no_release => true } do
|
102
|
+
dirs = [deploy_to, releases_path, shared_path, config_path, backup_path]
|
103
|
+
dirs += shared_children.map { |d| File.join(shared_path, d.split('/').last) }
|
104
|
+
run "#{try_sudo} mkdir -p #{dirs.join(' ')}"
|
105
|
+
run "#{try_sudo} chmod g+w #{dirs.join(' ')}" if fetch(:group_writable, true)
|
106
|
+
end
|
107
|
+
|
108
|
+
task :restart do
|
109
|
+
# nothing
|
110
|
+
# if task is not being used, it will not appear in `cap -T`
|
111
|
+
end
|
112
|
+
|
113
|
+
task :start do
|
114
|
+
# nothing
|
115
|
+
# if task is not being used, it will not appear in `cap -T`
|
116
|
+
end
|
117
|
+
|
118
|
+
task :stop do
|
119
|
+
# nothing
|
120
|
+
# if task is not being used, it will not appear in `cap -T`
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
if Capistrano::Configuration.instance
|
128
|
+
CapistranoRecipes.load_into(Capistrano::Configuration.instance)
|
129
|
+
end
|
data/spec/bundle_spec.rb
ADDED
data/spec/git_spec.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'git' do
|
4
|
+
before do
|
5
|
+
mock_config do
|
6
|
+
use_recipe :git
|
7
|
+
set :deploy_to, '/foo/bar'
|
8
|
+
def finalize_update; return; end;
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'has branch' do
|
13
|
+
config.branch.should == 'master'
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'with repository' do
|
17
|
+
before do
|
18
|
+
mock_config { set :repository, 'git@example.com/test-app.git' }
|
19
|
+
end
|
20
|
+
|
21
|
+
describe 'deploy:setup' do
|
22
|
+
before do
|
23
|
+
mock_config do
|
24
|
+
set :shared_path, "#{deploy_to}/shared"
|
25
|
+
set :shared_children, %w(public/system log tmp/pids)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'clones repository' do
|
30
|
+
cli_execute 'deploy:setup'
|
31
|
+
config.should have_run('git clone --no-checkout git@example.com/test-app.git /foo/bar/current')
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe 'deploy:update' do
|
36
|
+
it 'updates' do
|
37
|
+
cli_execute 'deploy:update'
|
38
|
+
config.should have_run('cd /foo/bar && git fetch origin && git reset --hard origin/master')
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'has current revision' do
|
44
|
+
config.should_receive(:capture).with('cd /foo/bar && git rev-parse --short HEAD') { "baz\n" }
|
45
|
+
config.current_revision.should == 'baz'
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'shows pending' do
|
49
|
+
config.should_receive(:current_revision) { 'baz' }
|
50
|
+
config.namespaces[:deploy].namespaces[:pending].should_receive(:system).with('git log --pretty=medium --stat baz..origin/master')
|
51
|
+
cli_execute 'deploy:pending'
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'sets forward agent' do
|
55
|
+
config.ssh_options[:forward_agent].should == true
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'multistage' do
|
4
|
+
before do
|
5
|
+
mock_config do
|
6
|
+
use_recipes :multistage
|
7
|
+
|
8
|
+
set :default_stage, :development
|
9
|
+
stage(:development, :branch => 'develop') { set :foo, 'bar' }
|
10
|
+
stage(:production, :branch => 'master') { set :foo, 'baz' }
|
11
|
+
stage :another_stage, :foo => 'bar'
|
12
|
+
|
13
|
+
task(:example) {}
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'uses default stage' do
|
18
|
+
cli_execute 'example'
|
19
|
+
config.current_stage.should == 'development'
|
20
|
+
config.foo.should == 'bar'
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'aborts when no stage selected' do
|
24
|
+
with_stderr do |output|
|
25
|
+
config.unset :default_stage
|
26
|
+
expect { cli_execute 'example' }.to raise_error(SystemExit)
|
27
|
+
output.should include('No stage specified. Please specify one of: development, production')
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'uses specified stage' do
|
32
|
+
cli_execute %w[production example]
|
33
|
+
config.current_stage.should == 'production'
|
34
|
+
config.foo.should == 'baz'
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'sets variables from options' do
|
38
|
+
cli_execute 'another_stage'
|
39
|
+
config.foo.should == 'bar'
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'accepts default option' do
|
43
|
+
mock_config { stage :to_be_default, :default => true }
|
44
|
+
config.default_stage.should == :to_be_default
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'with git' do
|
48
|
+
before do
|
49
|
+
mock_config { use_recipe :git }
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'infers stage using local branch' do
|
53
|
+
config.stub(:local_branch) { 'master' }
|
54
|
+
cli_execute 'example'
|
55
|
+
config.current_stage.should == 'production'
|
56
|
+
config.branch.should == 'master'
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'uses default state when local branch not matches' do
|
60
|
+
config.stub(:local_branch) { 'foo' }
|
61
|
+
cli_execute 'example'
|
62
|
+
config.current_stage.should == 'development'
|
63
|
+
config.branch.should == 'develop'
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/spec/mysql_spec.rb
ADDED
data/spec/nginx_spec.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'nginx' do
|
4
|
+
|
5
|
+
before do
|
6
|
+
mock_config do
|
7
|
+
use_recipe :nginx
|
8
|
+
set :application, 'foo'
|
9
|
+
set :deploy_to, '/foo/bar'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'returns used recipe' do
|
14
|
+
config.used_recipes.should == [:nginx]
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'rails assets' do
|
4
|
+
before do
|
5
|
+
mock_config do
|
6
|
+
use_recipe :rails_assets
|
7
|
+
set :application, 'foo'
|
8
|
+
set :deploy_to, '/foo/bar'
|
9
|
+
set :latest_release, deploy_to
|
10
|
+
set :use_sudo, false
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe 'deploy:assets:precompile' do
|
15
|
+
it 'runs precompile' do
|
16
|
+
cli_execute 'deploy:assets:precompile'
|
17
|
+
config.should have_run('[ -e /foo/bar/shared/assets/manifest* ] && cat /foo/bar/shared/assets/manifest* || echo')
|
18
|
+
config.should have_run(' cd -- /foo/bar && rake RAILS_ENV=production RAILS_GROUPS=assets assets:precompile ')
|
19
|
+
config.should have_run('ls -1 /foo/bar/shared/assets/manifest* | wc -l')
|
20
|
+
config.should have_run('ls /foo/bar/shared/assets/manifest*')
|
21
|
+
config.should have_run(" cp -- '' ''/assets_manifest ")
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'uses bundle command' do
|
25
|
+
mock_config { use_recipe :bundle }
|
26
|
+
cli_execute 'deploy:assets:precompile'
|
27
|
+
config.should have_run(' cd -- /foo/bar && bundle exec rake RAILS_ENV=production RAILS_GROUPS=assets assets:precompile ')
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe 'deploy:assets:clean' do
|
32
|
+
it 'runs clean' do
|
33
|
+
cli_execute 'deploy:assets:clean'
|
34
|
+
config.should have_run('cd /foo/bar && rake RAILS_ENV=production RAILS_GROUPS=assets assets:clean')
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|