k3_capistrano 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/Rakefile +1 -0
- data/Readme.md +86 -0
- data/k3_capistrano.gemspec +30 -0
- data/lib/capistrano_database_yml.rb +142 -0
- data/lib/k3/capistrano.rb +2 -0
- data/lib/k3_capistrano.rb +5 -0
- data/lib/k3_capistrano/asset_pipeline.rb +316 -0
- data/lib/k3_capistrano/capistrano.rb +132 -0
- data/lib/k3_capistrano/chef.rb +41 -0
- data/lib/k3_capistrano/db.rb +72 -0
- data/lib/k3_capistrano/db_backups.rb +207 -0
- data/lib/k3_capistrano/ensure_db_is_set_up.rb +34 -0
- data/lib/k3_capistrano/git.rb +37 -0
- data/lib/k3_capistrano/logs.rb +20 -0
- data/lib/k3_capistrano/ssh.rb +14 -0
- data/lib/k3_capistrano/test_request.rb +16 -0
- data/lib/k3_capistrano/test_results.rb +85 -0
- data/lib/k3_capistrano/unicorn.rb +30 -0
- data/lib/k3_capistrano/version.rb +5 -0
- data/lib/templates/database.yml.erb +8 -0
- data/lib/test_result_logging.rb +79 -0
- metadata +164 -0
@@ -0,0 +1,34 @@
|
|
1
|
+
Capistrano::Configuration.instance(:must_exist).load do
|
2
|
+
|
3
|
+
require 'parseconfig'
|
4
|
+
require 'facets/string/cleanlines'
|
5
|
+
|
6
|
+
namespace :deploy do
|
7
|
+
task :is_db_set_up do
|
8
|
+
#puts %(list_tables=#{(list_tables).to_a.inspect})
|
9
|
+
db.list_tables.include? 'schema_migrations'
|
10
|
+
end
|
11
|
+
|
12
|
+
task :ensure_db_is_set_up do
|
13
|
+
if !is_db_set_up
|
14
|
+
puts "Database #{application} has not been set up/migrated yet. Setting up via '#{db_setup_method}' now..."
|
15
|
+
|
16
|
+
case db_setup_method
|
17
|
+
when 'db:setup'
|
18
|
+
db.setup
|
19
|
+
when 'db:migrate'
|
20
|
+
deploy.migrate
|
21
|
+
when 'restore_backup'
|
22
|
+
raise "backup_to_restore_for_initial_setup must be set if db_setup_method is 'restore_backup'" unless exists?(:backup_to_restore_for_initial_setup)
|
23
|
+
set :which_backup, "#{db_backups_dir}/#{backup_to_restore_for_initial_setup}"
|
24
|
+
backup.restore
|
25
|
+
else
|
26
|
+
raise ArgumentError, "unknown db_setup_method #{db_setup_method.inspect}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
require 'capistrano_database_yml'
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# Git
|
2
|
+
|
3
|
+
Capistrano::Configuration.instance(:must_exist).load do
|
4
|
+
|
5
|
+
require 'timeout'
|
6
|
+
require 'facets/string/cleanlines'
|
7
|
+
|
8
|
+
namespace :git do
|
9
|
+
desc "Checks to see if your branch is ahead of its remote and needs to be pushed. Because it's easy to forget to git push..."
|
10
|
+
task :check_if_needs_push do
|
11
|
+
lines = `git status`.cleanlines.grep(/Your branch is ahead of|Your branch and.*have diverged/)
|
12
|
+
if lines.any?
|
13
|
+
beep
|
14
|
+
puts lines
|
15
|
+
response = nil
|
16
|
+
begin
|
17
|
+
timeout(wait_for = 15) do
|
18
|
+
response = Capistrano::CLI.ui.ask("Do you want to git push now? y/n")
|
19
|
+
end
|
20
|
+
rescue Timeout::Error
|
21
|
+
puts "No response after #{wait_for} seconds. Continuing without push..."
|
22
|
+
end
|
23
|
+
|
24
|
+
if response == 'y'
|
25
|
+
git.push
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
desc "Pushes your local commits to the git server so that they will actually get deployed"
|
31
|
+
task :push do
|
32
|
+
system "git push origin"
|
33
|
+
abort "git push failed" unless $?.success?
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
Capistrano::Configuration.instance(:must_exist).load do
|
2
|
+
|
3
|
+
namespace :logs do
|
4
|
+
desc "tail all 4 app log files to help you debug problems with your app (n={number of lines to show from each})"
|
5
|
+
task :tail, :roles => :app do
|
6
|
+
set :user, ENV['USER']
|
7
|
+
n = ENV['n'] || 25
|
8
|
+
puts %(user=#{(user).inspect})
|
9
|
+
sudo "tail -v -n#{n} /var/log/nginx/error.log"; puts
|
10
|
+
sudo "tail -v -n#{n} /etc/service/#{application}/log/main/current"; puts
|
11
|
+
sudo "tail -v -n#{n} #{current_path}/log/unicorn.log"; puts
|
12
|
+
sudo "tail -v -n#{n} #{current_path}/log/production.log"; puts
|
13
|
+
end
|
14
|
+
desc "tail -f the production.log file"
|
15
|
+
task :watch, :roles => :app do
|
16
|
+
stream("tail -f #{current_path}/log/production.log")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
Capistrano::Configuration.instance(:must_exist).load do
|
2
|
+
|
3
|
+
desc <<-End
|
4
|
+
ssh to the server specified by the 'domain' variable.
|
5
|
+
|
6
|
+
This allows you to quickly ssh to the staging or production server for your app without having to remember the hostname to connect to.
|
7
|
+
$ cap staging ssh
|
8
|
+
$ cap production ssh
|
9
|
+
End
|
10
|
+
task :ssh do
|
11
|
+
exec_verbose "ssh #{user}@#{domain}"
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# Note: This is not automatically included from k3/capistrano in case you want
|
2
|
+
# to add another after 'deploy:restart' trigger before this one.
|
3
|
+
|
4
|
+
Capistrano::Configuration.instance(:must_exist).load do
|
5
|
+
|
6
|
+
namespace :deploy do
|
7
|
+
desc 'Does a test request to the web site so we know everything is working'
|
8
|
+
task :test_request do
|
9
|
+
sleep 5
|
10
|
+
system_verbose "curl #{defined?(test_url) || "http://#{domain}/"} | head -n5"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
after 'deploy:restart', 'deploy:test_request'
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'test_result_logging'
|
2
|
+
|
3
|
+
Capistrano::Configuration.instance(:must_exist).load do
|
4
|
+
|
5
|
+
#===================================================================================================
|
6
|
+
# Additional subdirectories under shared (deploy:setup creates the shared directories, deploy:finalize_update task creates the symlinks)
|
7
|
+
|
8
|
+
# In addition to these defaults:
|
9
|
+
#_cset :shared_children, %w(public/system log tmp/pids)
|
10
|
+
|
11
|
+
#set :shared_children, shared_children + %w(
|
12
|
+
# public/features
|
13
|
+
# public/spec
|
14
|
+
#)
|
15
|
+
|
16
|
+
#===================================================================================================
|
17
|
+
|
18
|
+
# Work around the fact that there is an 'upload' namespace defined somewhere (where?) that is hiding the upload method provided by FileTransfer. (The 'put' method, on the other hand, still works.)
|
19
|
+
# So we have to do:
|
20
|
+
# upload.call local_file, remote_file
|
21
|
+
# instead of:
|
22
|
+
# upload local_file, remote_file
|
23
|
+
#upload = Capistrano::Configuration::Actions::FileTransfer.instance_method(:upload).bind(parent)
|
24
|
+
|
25
|
+
namespace :test_results do
|
26
|
+
desc 'Create the */results directories in shared/ and create symlinks to them in public/'
|
27
|
+
task 'ensure_directories_exist' do
|
28
|
+
['spec', 'features'].each do |type|
|
29
|
+
run <<-End
|
30
|
+
mkdir -p #{shared_path}/#{type}/results &&
|
31
|
+
ln -nfsT #{shared_path}/#{type} #{latest_release}/public/#{type}
|
32
|
+
End
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
desc 'upload_latest'
|
37
|
+
task 'upload_latest' do
|
38
|
+
ensure_directories_exist
|
39
|
+
rspec.upload_latest
|
40
|
+
cucumber.upload_latest
|
41
|
+
end
|
42
|
+
|
43
|
+
def _upload_latest_for_logging(logging)
|
44
|
+
logging.each_format_to_current_files do |format, latest|
|
45
|
+
_upload latest # upload the symlink
|
46
|
+
latest = (latest.dirname + latest.readlink) rescue (puts $!)
|
47
|
+
_upload latest # upload the target of the symlink
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
namespace :rspec do
|
52
|
+
desc 'upload_latest'
|
53
|
+
task :upload_latest do
|
54
|
+
_upload_latest_for_logging(RspecTestResultLogging.new)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
namespace :cucumber do
|
59
|
+
desc 'upload_latest'
|
60
|
+
task :upload_latest do
|
61
|
+
_upload_latest_for_logging(CucumberTestResultLogging.new)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def _upload(files)
|
66
|
+
files = Array(files)
|
67
|
+
upload_method = Capistrano::Configuration::Actions::FileTransfer.instance_method(:upload).bind(parent)
|
68
|
+
files.each do |local_file|
|
69
|
+
next unless local_file.exist?
|
70
|
+
remote_file = Pathname(shared_path) + local_file
|
71
|
+
upload_method.call local_file.to_s, remote_file.to_s
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
desc 'upload a single result file (file=features/results/{file_name}.html)'
|
76
|
+
task 'upload', on_error: :continue do
|
77
|
+
file = Pathname(ENV['file'])
|
78
|
+
_upload file
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
#before 'deploy:create_symlink', 'test_results:upload_latest'
|
83
|
+
before 'deploy:create_symlink', 'test_results:ensure_directories_exist'
|
84
|
+
|
85
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
Capistrano::Configuration.instance(:must_exist).load do
|
2
|
+
|
3
|
+
_cset 'sv_cmd', 'sv'
|
4
|
+
|
5
|
+
namespace :deploy do
|
6
|
+
if http_server == 'unicorn'
|
7
|
+
task :start, :roles => :app, :except => { :no_release => true } do
|
8
|
+
run "#{sv_cmd} start #{application}"
|
9
|
+
end
|
10
|
+
task :stop, :roles => :app, :except => { :no_release => true } do
|
11
|
+
run "#{sv_cmd} stop #{application}"
|
12
|
+
end
|
13
|
+
task :graceful_stop, :roles => :app, :except => { :no_release => true } do
|
14
|
+
run "kill -s QUIT `cat #{unicorn_pid}`"
|
15
|
+
end
|
16
|
+
task :reload, :roles => :app, :except => { :no_release => true } do
|
17
|
+
run "kill -s USR2 `cat #{unicorn_pid}`"
|
18
|
+
end
|
19
|
+
task :restart, :roles => :app, :except => { :no_release => true } do
|
20
|
+
run "#{sv_cmd} restart #{application}"
|
21
|
+
end
|
22
|
+
elsif http_server == 'passenger'
|
23
|
+
desc "Restarting mod_rails with restart.txt"
|
24
|
+
task :restart, :roles => :app, :except => { :no_release => true } do
|
25
|
+
run "touch #{current_path}/tmp/restart.txt"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
production:
|
2
|
+
adapter: <%= database['adapter'] %>
|
3
|
+
encoding: <%= database['encoding'] %>
|
4
|
+
database: <%= database['database'] %>
|
5
|
+
username: <%= database['username'] %>
|
6
|
+
password: <%= my_cnf['client']['password'] %>
|
7
|
+
reconnect: <%= database['reconnect'] %>
|
8
|
+
pool: 5
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'active_support/core_ext/class/attribute'
|
2
|
+
|
3
|
+
class TestResultLogging
|
4
|
+
class_attribute :formats_to_extensions
|
5
|
+
class_attribute :_results_dir
|
6
|
+
|
7
|
+
# Used for generating filenames for where we should store the results of the current test run (new_file)
|
8
|
+
attr_accessor :current_run_name
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
self.current_run_name = Time.now.strftime("%Y-%m-%dT%H:%M:%S")
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.user
|
15
|
+
ENV['USER']
|
16
|
+
end
|
17
|
+
def user; self.class.user; end
|
18
|
+
|
19
|
+
def self.results_dir
|
20
|
+
Pathname(_results_dir).tap {|_| _.mkpath unless _.exist? }
|
21
|
+
end
|
22
|
+
def results_dir; self.class.results_dir; end
|
23
|
+
|
24
|
+
def self.latest_default_file_for_format(format)
|
25
|
+
ext = formats_to_extensions[format]
|
26
|
+
results_dir + ("default.#{ext}")
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.latest_symlink_for_format(format)
|
30
|
+
ext = formats_to_extensions[format]
|
31
|
+
results_dir + ("latest.#{user}.#{ext}")
|
32
|
+
end
|
33
|
+
|
34
|
+
def new_file_for_format(format)
|
35
|
+
ext = formats_to_extensions[format]
|
36
|
+
results_dir + ("#{current_run_name}.#{user}.#{ext}")
|
37
|
+
end
|
38
|
+
|
39
|
+
def each_format_to_current_files
|
40
|
+
formats_to_extensions.each do |format, ext|
|
41
|
+
yield [
|
42
|
+
format,
|
43
|
+
self.class.latest_symlink_for_format(format),
|
44
|
+
new_file_for_format(format)
|
45
|
+
]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def update_latest_symlinks
|
50
|
+
each_format_to_current_files do |format, latest_symlink, new_file|
|
51
|
+
puts "Updating #{latest_symlink} to point to #{new_file.basename}..."
|
52
|
+
latest_symlink.tap {|_| _.unlink rescue nil }.make_symlink new_file.basename
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
class RspecTestResultLogging < TestResultLogging
|
58
|
+
self.formats_to_extensions = { 'html'=>'html', 'doc'=>'doc.txt', 'failures'=>'failures.txt' }
|
59
|
+
self._results_dir = 'spec/results'
|
60
|
+
|
61
|
+
def set_env_to_log_results
|
62
|
+
each_format_to_current_files do |format, latest_symlink, new_file|
|
63
|
+
ENV["rspec_#{format}_file"] = new_file.basename.to_s
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
class CucumberTestResultLogging < TestResultLogging
|
70
|
+
self.formats_to_extensions = { 'html'=>'html', 'pretty'=>'txt', 'rerun'=>'rerun.txt' }
|
71
|
+
self._results_dir = 'features/results'
|
72
|
+
|
73
|
+
def set_env_to_log_results
|
74
|
+
each_format_to_current_files do |format, latest_symlink, new_file|
|
75
|
+
ENV["cucumber_#{format}_file"] = new_file.basename.to_s
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
metadata
ADDED
@@ -0,0 +1,164 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: k3_capistrano
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Tyler Rick
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-03-11 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: parseconfig
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: capistrano-ext
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: capistrano_colors
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: facets
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :runtime
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: rvm-capistrano
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :runtime
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: colored
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :runtime
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
description: Common Capistrano tasks and defaults used by K3 Integrations
|
111
|
+
email:
|
112
|
+
- tyler@k3integrations.com
|
113
|
+
executables: []
|
114
|
+
extensions: []
|
115
|
+
extra_rdoc_files: []
|
116
|
+
files:
|
117
|
+
- .gitignore
|
118
|
+
- Gemfile
|
119
|
+
- Rakefile
|
120
|
+
- Readme.md
|
121
|
+
- k3_capistrano.gemspec
|
122
|
+
- lib/capistrano_database_yml.rb
|
123
|
+
- lib/k3/capistrano.rb
|
124
|
+
- lib/k3_capistrano.rb
|
125
|
+
- lib/k3_capistrano/asset_pipeline.rb
|
126
|
+
- lib/k3_capistrano/capistrano.rb
|
127
|
+
- lib/k3_capistrano/chef.rb
|
128
|
+
- lib/k3_capistrano/db.rb
|
129
|
+
- lib/k3_capistrano/db_backups.rb
|
130
|
+
- lib/k3_capistrano/ensure_db_is_set_up.rb
|
131
|
+
- lib/k3_capistrano/git.rb
|
132
|
+
- lib/k3_capistrano/logs.rb
|
133
|
+
- lib/k3_capistrano/ssh.rb
|
134
|
+
- lib/k3_capistrano/test_request.rb
|
135
|
+
- lib/k3_capistrano/test_results.rb
|
136
|
+
- lib/k3_capistrano/unicorn.rb
|
137
|
+
- lib/k3_capistrano/version.rb
|
138
|
+
- lib/templates/database.yml.erb
|
139
|
+
- lib/test_result_logging.rb
|
140
|
+
homepage: ''
|
141
|
+
licenses: []
|
142
|
+
post_install_message:
|
143
|
+
rdoc_options: []
|
144
|
+
require_paths:
|
145
|
+
- lib
|
146
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
147
|
+
none: false
|
148
|
+
requirements:
|
149
|
+
- - ! '>='
|
150
|
+
- !ruby/object:Gem::Version
|
151
|
+
version: '0'
|
152
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
153
|
+
none: false
|
154
|
+
requirements:
|
155
|
+
- - ! '>='
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: '0'
|
158
|
+
requirements: []
|
159
|
+
rubyforge_project: k3_capistrano
|
160
|
+
rubygems_version: 1.8.24
|
161
|
+
signing_key:
|
162
|
+
specification_version: 3
|
163
|
+
summary: Common Capistrano tasks and defaults used by K3 Integrations
|
164
|
+
test_files: []
|