ms_deploy 0.2.3 → 0.2.4

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.
@@ -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: []