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