ms_deploy 0.2.3 → 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -48,10 +48,6 @@ set(:files_to_link) {
48
48
  }
49
49
  }
50
50
 
51
- set(:config_file_to_setup) {
52
- %W(config.#{stage}.yml unicorn.#{stage}.rb)
53
- }
54
-
55
51
  set(:files_to_delete) {
56
52
  %W()
57
53
  }
@@ -1,18 +1,26 @@
1
1
  Capistrano::Configuration.instance.load do
2
2
 
3
- load 'deploy/assets' # http://guides.rubyonrails.org/asset_pipeline.html#in-production
3
+ load 'deploy/assets' unless ENV['NOASSETS'] # http://guides.rubyonrails.org/asset_pipeline.html#in-production
4
4
 
5
- # http://www.bencurtis.com/2011/12/skipping-asset-compilation-with-capistrano/
6
- namespace :deploy do
7
- namespace :assets do
8
- #task :precompile, :roles => :web, :except => { :no_release => true } do
9
- # from = source.next_revision(current_revision)
10
- # if capture("cd #{latest_release} && #{source.local.log(from)} lib/assets/ vendor/assets/ app/assets/ | wc -l").to_i > 0
11
- # run %Q{cd #{latest_release} && #{rake} RAILS_ENV=#{rails_env} #{asset_env} assets:precompile}
12
- # else
13
- # logger.info "Skipping asset pre-compilation because there were no asset changes"
14
- # end
15
- #end
5
+ set :assets_dir, 'system' unless exists?(:assets_dir)
6
+ set :local_assets_dir, 'public' unless exists?(:local_assets_dir)
7
+
8
+ namespace :assets do
9
+ namespace :local do
10
+ desc 'Synchronize your local assets using remote assets'
11
+ task :sync do
12
+ if Util.prompt "Are you sure you want to erase your local assets with server assets"
13
+ servers = find_servers :roles => :app
14
+ [assets_dir].flatten.each do |dir|
15
+ system("rsync -a --del --progress --rsh='ssh -p #{fetch(:ssh_port, 22)}' #{user}@#{servers.first}:#{shared_path}/#{dir}/ #{local_assets_dir}")
16
+ end
17
+ end
18
+ end
19
+ end
20
+
21
+ desc 'Synchronize your local assets using remote assets'
22
+ task :pull do
23
+ assets.local.sync
16
24
  end
17
25
  end
18
26
  end
@@ -0,0 +1,44 @@
1
+ Capistrano::Configuration.instance.load do |instance|
2
+
3
+ require File.expand_path("#{File.dirname(__FILE__)}/../../util")
4
+ require File.expand_path("#{File.dirname(__FILE__)}/../../mysql")
5
+
6
+ instance.set :local_rails_env, ENV['RAILS_ENV'] || 'development' unless exists?(:local_rails_env)
7
+ instance.set :db_local_clean, false unless exists?(:db_local_clean)
8
+
9
+ namespace :db do
10
+ namespace :remote do
11
+ desc 'Synchronize the local database to the remote database'
12
+ task :sync, :roles => :db do
13
+ if if Util.prompt 'Are you sure you want to REPLACE THE REMOTE DATABASE with local database'
14
+ Database.local_to_remote(instance)
15
+ end
16
+ end
17
+ end
18
+
19
+ namespace :local do
20
+ desc 'Synchronize your local database using remote database data'
21
+ task :sync, :roles => :db do
22
+ puts "Local database: #{Database::Local.new(instance).database}"
23
+ if rails_env == 'production'
24
+ puts 'Never sync remote production database!'
25
+ else
26
+ if Util.prompt 'Are you sure you want to erase your local database with server database'
27
+ Database.remote_to_local(instance)
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ desc 'Synchronize your local database using remote database data'
34
+ task :pull do
35
+ db.local.sync
36
+ end
37
+
38
+ desc 'Synchronize the local database to the remote database'
39
+ task :push do
40
+ db.remote.sync
41
+ end
42
+ end
43
+ end
44
+ end
@@ -1,5 +1,7 @@
1
1
  Capistrano::Configuration.instance.load do
2
2
 
3
+ require File.expand_path("#{File.dirname(__FILE__)}/../../util")
4
+
3
5
  set :keep_releases, 10
4
6
  set :use_sudo, false
5
7
 
@@ -20,8 +22,10 @@ Capistrano::Configuration.instance.load do
20
22
 
21
23
  default_run_options[:pty] = true
22
24
 
25
+ # if you want to remove the dump file after loading
26
+ set :db_local_clean, true
27
+
23
28
  task :test_and_prepare_cap_env do
24
- abort "You must run this using 'bundle exec ...'" unless ENV['BUNDLE_BIN_PATH'] || ENV['BUNDLE_GEMFILE']
25
29
  abort "You must set :user before using defaults" unless fetch(:user, nil)
26
30
  abort "You must set :repository before using defaults" unless fetch(:repository, nil)
27
31
  abort "You must set :branch before using defaults" unless fetch(:branch, nil)
@@ -2,81 +2,79 @@ require "ms_deploy/render"
2
2
 
3
3
  Capistrano::Configuration.instance.load do
4
4
 
5
- namespace :service do
6
- namespace :nginx do
7
- desc <<-DESC
5
+ namespace :nginx do
6
+ desc <<-DESC
8
7
  Starts the nginx web-server.
9
- DESC
10
- task :start do
11
- #run "sudo god start nginx"
12
- run "sudo /etc/init.d/nginx start"
13
- end
8
+ DESC
9
+ task :start do
10
+ #run "sudo god start nginx"
11
+ run "sudo /etc/init.d/nginx start"
12
+ end
14
13
 
15
- desc <<-DESC
14
+ desc <<-DESC
16
15
  #Stops the nginx web-server.
17
- DESC
18
- task :stop do
19
- #run "sudo god stop nginx"
20
- run "sudo /etc/init.d/nginx stop"
21
- end
16
+ DESC
17
+ task :stop do
18
+ #run "sudo god stop nginx"
19
+ run "sudo /etc/init.d/nginx stop"
20
+ end
22
21
 
23
- desc <<-DESC
22
+ desc <<-DESC
24
23
  Restarts the nginx web-server.
25
- DESC
26
- task :restart do
27
- #run "sudo god restart nginx"
28
- run "sudo /etc/init.d/nginx restart"
29
- end
24
+ DESC
25
+ task :restart do
26
+ #run "sudo god restart nginx"
27
+ run "sudo /etc/init.d/nginx restart"
28
+ end
30
29
 
31
- task :install do
32
- protocol = fetch(:protocol, nil).to_s
33
- template_path = File.expand_path('../../templates/vhost.erb', __FILE__)
34
- vars = {
35
- 'application'=> application,
36
- 'project_root' => deploy_to + '/current',
37
- 'domain' => vhost_domain, 'stage' => stage,
38
- 'auth_basic_title' => fetch(:auth_basic_title, nil),
39
- 'auth_basic_password_file' => fetch(:auth_basic_password_file, nil),
40
- 'protocol' => 'http',
41
- 'nginx_cert_dir' => fetch(:nginx_cert_dir, '/etc/nginx/cert'),
42
- 'with_upstream_server' => true,
43
- 'with_file_expire_max' => fetch(:with_file_expire_max, true),
44
- 'optional_http_content' => fetch(:optional_nginx_server_http_content, ''),
45
- 'optional_https_content' => fetch(:optional_nginx_server_https_content, ''),
46
- 'cert_type' => fetch(:cert_type, 'pem'),
47
- 'key_type' => fetch(:cert_type, 'key')
48
- }
30
+ task :setup do
31
+ protocol = fetch(:protocol, nil).to_s
32
+ template_path = File.expand_path('../../templates/vhost.erb', __FILE__)
33
+ vars = {
34
+ 'application' => application,
35
+ 'project_root' => deploy_to + '/current',
36
+ 'domain' => vhost_domain, 'stage' => stage,
37
+ 'auth_basic_title' => fetch(:auth_basic_title, nil),
38
+ 'auth_basic_password_file' => fetch(:auth_basic_password_file, nil),
39
+ 'protocol' => 'http',
40
+ 'nginx_cert_dir' => fetch(:nginx_cert_dir, '/etc/nginx/cert'),
41
+ 'with_upstream_server' => true,
42
+ 'with_file_expire_max' => fetch(:with_file_expire_max, true),
43
+ 'optional_http_content' => fetch(:optional_nginx_server_http_content, ''),
44
+ 'optional_https_content' => fetch(:optional_nginx_server_https_content, ''),
45
+ 'cert_type' => fetch(:cert_type, 'pem'),
46
+ 'key_type' => fetch(:cert_type, 'key')
47
+ }
49
48
 
50
- if protocol.nil? or protocol == 'http' or protocol == 'both'
51
- config_path = "#{shared_path}/config/#{application}_vhost.conf"
49
+ if protocol.nil? or protocol == 'http' or protocol == 'both'
50
+ config_path = "#{shared_path}/config/#{application}_vhost.conf"
52
51
 
53
- put(render_erb_template(template_path, vars), config_path)
54
- sudo "rm -f /etc/nginx/sites-enabled/#{application}_#{stage}.conf"
55
- sudo "ln -s #{config_path} /etc/nginx/sites-enabled/#{application}_#{stage}.conf"
56
- end
57
- if protocol == 'https' or protocol == 'both'
58
- vars.merge!({'protocol' => 'https'})
52
+ put(render_erb_template(template_path, vars), config_path)
53
+ sudo "rm -f /etc/nginx/sites-enabled/#{application}_#{stage}.conf"
54
+ sudo "ln -s #{config_path} /etc/nginx/sites-enabled/#{application}_#{stage}.conf"
55
+ end
56
+ if protocol == 'https' or protocol == 'both'
57
+ vars.merge!({'protocol' => 'https'})
59
58
 
60
- config_path = "#{shared_path}/config/#{application}_ssl_vhost.conf"
59
+ config_path = "#{shared_path}/config/#{application}_ssl_vhost.conf"
61
60
 
62
- put(render_erb_template(template_path, vars), config_path)
63
- sudo "rm -f /etc/nginx/sites-enabled/#{application}_#{stage}_ssl.conf"
64
- sudo "ln -s #{config_path} /etc/nginx/sites-enabled/#{application}_#{stage}_ssl.conf"
65
- end
61
+ put(render_erb_template(template_path, vars), config_path)
62
+ sudo "rm -f /etc/nginx/sites-enabled/#{application}_#{stage}_ssl.conf"
63
+ sudo "ln -s #{config_path} /etc/nginx/sites-enabled/#{application}_#{stage}_ssl.conf"
66
64
  end
65
+ end
67
66
 
68
- task :uninstall do
69
- protocol = fetch(:protocol, nil)
67
+ task :uninstall do
68
+ protocol = fetch(:protocol, nil)
70
69
 
71
- if protocol.blank? or protocol == 'http' or protocol == 'both'
72
- sudo "rm -f /etc/nginx/sites-enabled/#{application}_#{stage}.conf"
73
- elsif protocol == 'https' or protocol == 'both'
74
- sudo "rm -f /etc/nginx/sites-enabled/#{application}_#{stage}_ssl.conf"
75
- end
70
+ if protocol.blank? or protocol == 'http' or protocol == 'both'
71
+ sudo "rm -f /etc/nginx/sites-enabled/#{application}_#{stage}.conf"
72
+ elsif protocol == 'https' or protocol == 'both'
73
+ sudo "rm -f /etc/nginx/sites-enabled/#{application}_#{stage}_ssl.conf"
76
74
  end
77
75
  end
78
76
  end
79
77
 
80
- after :"deploy:setup", :"service:nginx:install";
78
+ after :"deploy:setup", :"nginx:setup";
81
79
 
82
80
  end
@@ -1,25 +1,33 @@
1
1
  Capistrano::Configuration.instance.load do
2
2
 
3
- set :unicorn_bin, "bundle exec unicorn"
4
- set :unicorn_pid, "tmp/pids/unicorn.pid"
5
- #require "capistrano-unicorn"
3
+ _cset :unicorn_bin, "bundle exec unicorn"
4
+ _cset :unicorn_pid, "#{deploy_to}/current/tmp/pids/unicorn.pid"
5
+ _cset :unicorn_std_log, "log/unicorn.stderr.log"
6
+ _cset :unicorn_err_log, "log/unicorn.stderr.log"
7
+ _cset :unicorn_worker_processes, 2
8
+ _cset :unicorn_listen_backlog, 2048
6
9
 
7
- namespace :deploy do
8
- desc "Zero-downtime restart of Unicorn"
9
- task :restart, :except => { :no_release => true } do
10
- stop
11
- start
12
- end
13
-
14
- desc "Start unicorn"
15
- task :start, :except => { :no_release => true } do
16
- set :unicorn_config, "config/unicorn.#{fetch(:stage, 'production')}.rb"
17
- run "cd #{current_path} && #{try_sudo} #{unicorn_bin} -c #{current_path}/#{unicorn_config} -E #{rails_env} -D"
18
- end
10
+ require "capistrano-unicorn"
19
11
 
20
- desc "Stop unicorn"
21
- task :stop, :except => { :no_release => true } do
22
- run "kill -s QUIT `cat #{shared_path}/pids/unicorn.pid`;exit 0"
12
+ namespace :unicorn do
13
+ desc "Setup unicorn"
14
+ task :setup, :except => { :no_release => true } do
15
+ run "mkdir -p \"#{shared_path}/config/unicorn\""
16
+ config_path = "#{shared_path}/config/unicorn/#{stage}.rb"
17
+ template_path = File.expand_path('../../templates/unicorn/unicorn.rb.erb', __FILE__)
18
+ vars = {
19
+ 'application'=> application,
20
+ 'current_path' => current_path,
21
+ 'unicorn_pid' => unicorn_pid,
22
+ 'unicorn_std_log' => unicorn_std_log,
23
+ 'unicorn_err_log' => unicorn_err_log,
24
+ 'stage' => stage,
25
+ 'unicorn_listen_backlog' => unicorn_listen_backlog,
26
+ 'unicorn_worker_processes' => unicorn_worker_processes
27
+ }
28
+ put(render_erb_template(template_path, vars), config_path)
23
29
  end
24
30
  end
31
+
32
+ after :"deploy:setup", :"unicorn:setup";
25
33
  end
@@ -0,0 +1,34 @@
1
+ working_directory "<%= current_path %>"
2
+ pid "<%= unicorn_pid %>"
3
+ stderr_path "<%= unicorn_std_log %>"
4
+ stdout_path "<%= unicorn_err_log %>"
5
+
6
+ listen "/tmp/socket.<%= application %>_<%= stage %>.sock", :backlog => <%= unicorn_listen_backlog %>
7
+ worker_processes <%= unicorn_worker_processes %>
8
+ timeout 30
9
+
10
+ preload_app true
11
+
12
+ before_fork do |server, worker|
13
+ # Disconnect since the database connection will not carry over
14
+ if defined? ActiveRecord::Base
15
+ ActiveRecord::Base.connection.disconnect!
16
+ end
17
+
18
+ # Quit the old unicorn process
19
+ old_pid = "#{server.config[:pid]}.oldbin"
20
+ if File.exists?(old_pid) && server.pid != old_pid
21
+ begin
22
+ Process.kill("QUIT", File.read(old_pid).to_i)
23
+ rescue Errno::ENOENT, Errno::ESRCH
24
+ # someone else did our job for us
25
+ end
26
+ end
27
+ end
28
+
29
+ after_fork do |server, worker|
30
+ # Start up the database connection again in the worker
31
+ if defined?(ActiveRecord::Base)
32
+ ActiveRecord::Base.establish_connection
33
+ end
34
+ end
@@ -7,7 +7,7 @@ upstream <%= application %>_<%= stage %>_<%= protocol %>_server {
7
7
  # single worker for timing out).
8
8
 
9
9
  # This is the socket we configured in unicorn.rb
10
- server unix:/tmp/sockets/<%= application %>_<%= stage %>.sock fail_timeout=0;
10
+ server unix:/tmp/socket.<%= application %>_<%= stage %>.sock fail_timeout=0;
11
11
 
12
12
  # for TCP setups, point these to your backend servers
13
13
  # server 127.0.0.1:8080 fail_timeout=0;
@@ -1,3 +1,3 @@
1
1
  module MsDeploy
2
- VERSION = "0.2.3"
2
+ VERSION = "0.2.4"
3
3
  end
data/lib/mysql.rb ADDED
@@ -0,0 +1,109 @@
1
+ module Database
2
+ class Base
3
+ attr_accessor :config, :output_file
4
+ def initialize(cap_instance)
5
+ @cap = cap_instance
6
+ end
7
+
8
+ def mysql?
9
+ @config['adapter'] == 'mysql' || @config['adapter'] == 'mysql2'
10
+ end
11
+
12
+ def credentials
13
+ " -u #{@config['username']} " + (@config['password'] ? " -p\"#{@config['password']}\" " : '') + (@config['host'] ? " -h #{@config['host']}" : '')
14
+ end
15
+
16
+ def database
17
+ @config['database']
18
+ end
19
+
20
+ def output_file
21
+ @output_file ||= "db/dump_#{database}.sql.bz2"
22
+ end
23
+
24
+ private
25
+ def dump_cmd
26
+ "mysqldump #{credentials} #{database}"
27
+ end
28
+
29
+ def import_cmd(file)
30
+ "mysql #{credentials} -D #{database} < #{file}"
31
+ end
32
+ end
33
+
34
+ class Remote < Base
35
+ def initialize(cap_instance)
36
+ super(cap_instance)
37
+ @cap.run("cat #{@cap.current_path}/config/database.yml") { |c, s, d| @config = YAML.load(d)[(@cap.rails_env || 'production').to_s] }
38
+ end
39
+
40
+ def dump
41
+ @cap.run "cd #{@cap.current_path}; #{dump_cmd} | bzip2 - - > #{output_file}"
42
+ self
43
+ end
44
+
45
+ def download(local_file = "#{output_file}")
46
+ remote_file = "#{@cap.current_path}/#{output_file}"
47
+ @cap.get remote_file, local_file
48
+ end
49
+
50
+ # cleanup = true removes the mysqldump file after loading, false leaves it in db/
51
+ def load(file, cleanup)
52
+ unzip_file = File.join(File.dirname(file), File.basename(file, '.bz2'))
53
+ @cap.run "cd #{@cap.current_path}; bunzip2 -f #{file} && RAILS_ENV=#{@cap.rails_env} rake db:drop db:create && #{import_cmd(unzip_file)}"
54
+ File.unlink(unzip_file) if cleanup
55
+ end
56
+ end
57
+
58
+ class Local < Base
59
+ def initialize(cap_instance)
60
+ super(cap_instance)
61
+ @config = YAML.load_file(File.join('config', 'database.yml'))[@cap.local_rails_env]
62
+ end
63
+
64
+ # cleanup = true removes the mysqldump file after loading, false leaves it in db/
65
+ def load(file, cleanup)
66
+ unzip_file = File.join(File.dirname(file), File.basename(file, '.bz2'))
67
+ system("bunzip2 -f #{file} && rake db:drop db:create && #{import_cmd(unzip_file)} && rake db:migrate")
68
+ File.unlink(unzip_file) if cleanup
69
+ end
70
+
71
+ def dump
72
+ system "#{dump_cmd} | bzip2 - - > #{output_file}"
73
+ self
74
+ end
75
+
76
+ def upload
77
+ remote_file = "#{@cap.current_path}/#{output_file}"
78
+ @cap.upload output_file, remote_file
79
+ end
80
+ end
81
+
82
+ class << self
83
+ def check(local_db, remote_db)
84
+ unless local_db.mysql? && remote_db.mysql?
85
+ raise 'Only mysql on remote and local server is supported'
86
+ end
87
+ end
88
+
89
+ def remote_to_local(instance)
90
+ local_db = Database::Local.new(instance)
91
+ remote_db = Database::Remote.new(instance)
92
+
93
+ check(local_db, remote_db)
94
+
95
+ remote_db.dump.download
96
+ local_db.load(remote_db.output_file, instance.fetch(:db_local_clean))
97
+ end
98
+
99
+ def local_to_remote(instance)
100
+ local_db = Database::Local.new(instance)
101
+ remote_db = Database::Remote.new(instance)
102
+
103
+ check(local_db, remote_db)
104
+
105
+ local_db.dump.upload
106
+ remote_db.load(local_db.output_file, instance.fetch(:db_local_clean))
107
+ end
108
+ end
109
+ end
data/lib/util.rb ADDED
@@ -0,0 +1,10 @@
1
+ module Util
2
+ def self.prompt(msg, prompt = "(y)es, (n)o ")
3
+ answer = Capistrano::CLI.ui.ask("#{msg} #{prompt} ? ") do |q|
4
+ q.overwrite = false
5
+ q.validate = /^y$|^yes$|^n$|^no$/i
6
+ q.responses[:not_valid] = prompt
7
+ end
8
+ (answer =~ /^y$|^yes$/i) == 0
9
+ end
10
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ms_deploy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.2.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-07-23 00:00:00.000000000 Z
12
+ date: 2012-08-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: gemcutter
@@ -171,6 +171,7 @@ files:
171
171
  - lib/ms_deploy/recipes/airbrake.rb
172
172
  - lib/ms_deploy/recipes/assets.rb
173
173
  - lib/ms_deploy/recipes/bundler.rb
174
+ - lib/ms_deploy/recipes/database.rb
174
175
  - lib/ms_deploy/recipes/defaults.rb
175
176
  - lib/ms_deploy/recipes/info.rb
176
177
  - lib/ms_deploy/recipes/monitoring.rb
@@ -187,8 +188,11 @@ files:
187
188
  - lib/ms_deploy/recipes/unicorn.rb
188
189
  - lib/ms_deploy/recipes/whenever.rb
189
190
  - lib/ms_deploy/render.rb
191
+ - lib/ms_deploy/templates/unicorn/unicorn.rb.erb
190
192
  - lib/ms_deploy/templates/vhost.erb
191
193
  - lib/ms_deploy/version.rb
194
+ - lib/mysql.rb
195
+ - lib/util.rb
192
196
  - ms_deploy.gemspec
193
197
  homepage: https://github.com/mschiller/ms_deploy
194
198
  licenses: []