From 9cc5374ff17895ef756791a8a7646abdce5671f2 Mon Sep 17 00:00:00 2001 From: Chulki Lee Date: Tue, 6 Jan 2015 23:31:43 -0800 Subject: [PATCH] capistrano 3 --- .gitignore | 1 + Capfile | 10 +++++++--- Gemfile | 5 ++++- Gemfile.lock | 40 ++++++++++++++++++++++++++-------------- config/config.example.yml | 13 ------------- config/deploy.example.rb | 135 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------------------------------- config/deploy/production.example.rb | 45 +++++++++++++++++++++++++++++++++++++++++++++ docs/deployment/capistrano.md | 24 +++++++++++++++++++++--- 8 files changed, 166 insertions(+), 107 deletions(-) create mode 100644 config/deploy/production.example.rb diff --git a/.gitignore b/.gitignore index 05cc086..b0a2ec1 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,4 @@ bundle coverage *# .ruby-version +.capistrano/metrics diff --git a/Capfile b/Capfile index e04728e..c963c3a 100644 --- a/Capfile +++ b/Capfile @@ -1,4 +1,8 @@ -load 'deploy' if respond_to?(:namespace) # cap2 differentiator -Dir['vendor/plugins/*/recipes/*.rb'].each { |plugin| load(plugin) } +require 'capistrano/setup' +require 'capistrano/deploy' -load 'config/deploy' # remove this line to skip loading any of the default tasks \ No newline at end of file +require 'capistrano/rbenv' if ENV['rbenv'] +require 'capistrano/bundler' +require 'capistrano/rails/assets' + +Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r } diff --git a/Gemfile b/Gemfile index 15620ba..62f7696 100644 --- a/Gemfile +++ b/Gemfile @@ -62,7 +62,10 @@ group :development, :test do end group :development do - gem 'capistrano', '~> 2.0', :require => false + gem 'capistrano', require: false + gem 'capistrano-bundler', require: false + gem 'capistrano-rails', require: false + gem 'capistrano-rbenv', require: false # better errors gem 'better_errors' diff --git a/Gemfile.lock b/Gemfile.lock index 221baee..8ea3100 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -60,12 +60,21 @@ GEM builder (3.2.2) callsite (0.0.11) campy (1.0.0) - capistrano (2.15.5) - highline - net-scp (>= 1.0.0) - net-sftp (>= 2.0.0) - net-ssh (>= 2.0.14) - net-ssh-gateway (>= 1.1.0) + capistrano (3.3.5) + capistrano-stats (~> 1.1.0) + i18n + rake (>= 10.0.0) + sshkit (~> 1.3) + capistrano-bundler (1.1.3) + capistrano (~> 3.1) + sshkit (~> 1.2) + capistrano-rails (1.1.2) + capistrano (~> 3.1) + capistrano-bundler (~> 1.1) + capistrano-rbenv (2.0.2) + capistrano (~> 3.1) + sshkit (~> 1.3) + capistrano-stats (1.1.1) capybara (2.1.0) mime-types (>= 1.16) nokogiri (>= 1.3.3) @@ -81,6 +90,7 @@ GEM coffee-script-source execjs coffee-script-source (1.8.0) + colorize (0.7.5) connection_pool (2.1.0) coveralls (0.7.0) multi_json (~> 1.3) @@ -124,7 +134,6 @@ GEM haml (4.0.3) tilt hashie (2.0.5) - highline (1.6.20) hike (1.2.3) hipchat (0.12.0) httparty @@ -183,13 +192,9 @@ GEM multi_json (1.10.1) multi_xml (0.5.5) multipart-post (1.2.0) - net-scp (1.1.2) - net-ssh (>= 2.6.5) - net-sftp (2.1.2) - net-ssh (>= 2.6.5) - net-ssh (2.7.0) - net-ssh-gateway (1.2.0) + net-scp (1.2.1) net-ssh (>= 2.6.5) + net-ssh (2.9.1) nokogiri (1.6.4.1) mini_portile (~> 0.6.0) oauth2 (0.8.1) @@ -309,6 +314,10 @@ GEM actionpack (>= 3.0) activesupport (>= 3.0) sprockets (>= 2.8, < 4.0) + sshkit (1.6.1) + colorize (>= 0.7.0) + net-scp (>= 1.1.2) + net-ssh (>= 2.8.0) term-ansicolor (1.2.2) tins (~> 0.8) test-unit (3.0.8) @@ -348,7 +357,10 @@ DEPENDENCIES better_errors binding_of_caller campy - capistrano (~> 2.0) + capistrano + capistrano-bundler + capistrano-rails + capistrano-rbenv capybara coffee-rails coveralls diff --git a/config/config.example.yml b/config/config.example.yml index 7232ab9..c504899 100644 --- a/config/config.example.yml +++ b/config/config.example.yml @@ -62,19 +62,6 @@ use_gravatar: true # Default Gravatar image, can be: mm, identicon, monsterid, wavatar, retro. gravatar_default: identicon -# Setup your deploy options for capistrano. -deployment: - hosts: - web: errbit.example.com - app: errbit.example.com - db: errbit.example.com - repository: https://github.com/errbit/errbit.git - branch: master - user: deploy - deploy_to: /var/www/apps/errbit - # setup path to unicorn pids folder (or deploy_to/shared/pids will be used) - # pids: /var/www/apps/errbit/shared/pids - # GitHub OAuth configuration # If you want to allow authentication via GitHub, you will need to register # your app at: https://github.com/settings/applications diff --git a/config/deploy.example.rb b/config/deploy.example.rb index 306d0ce..b51348c 100644 --- a/config/deploy.example.rb +++ b/config/deploy.example.rb @@ -6,98 +6,87 @@ # `cap deploy` whenever you would like to deploy Errbit. Refer # to the Readme for more information. -config = YAML.load_file('config/config.yml')['deployment'] || {} - -require 'bundler/capistrano' -load 'deploy/assets' - -set :application, "errbit" -set :repository, config['repository'] - -role :web, config['hosts']['web'] -role :app, config['hosts']['app'] -role :db, config['hosts']['db'], :primary => true - -set :user, config['user'] -set :use_sudo, false -if config.has_key?('ssh_key') - set :ssh_options, { :forward_agent => true, :keys => [ config['ssh_key'] ] } -else - set :ssh_options, { :forward_agent => true } -end -default_run_options[:pty] = true - -set :deploy_to, config['deploy_to'] -set :deploy_via, :remote_cache -set :copy_cache, true -set :copy_exclude, [".git"] -set :copy_compression, :bz2 - -set :scm, :git -set :scm_verbose, true -set :branch, config['branch'] || 'master' - -before 'deploy:assets:symlink', 'errbit:symlink_configs' -# if unicorn is started through something like runit (the tool which restarts the process when it's stopped) -# after 'deploy:restart', 'unicorn:stop' - -namespace :deploy do - task :start do ; end - task :stop do ; end - task :restart, :roles => :app, :except => { :no_release => true } do - run "#{try_sudo} touch #{File.join(current_path,'tmp','restart.txt')}" - end -end +# config valid only for current version of Capistrano +lock '3.3.5' + +set :application, 'errbit' +set :repo_url, 'https://github.com/errbit/errbit.git' +set :branch, ENV['branch'] || 'master' +set :deploy_to, '/var/www/apps/errbit' +set :keep_releases, 5 + +set :pty, true +set :ssh_options, forward_agent: true + +set :linked_files, fetch(:linked_files, []) + %w( + .env + config/config.yml + config/mongoid.yml + config/newrelic.yml + config/initializers/secret_token.rb +) + +set :linked_dirs, fetch(:linked_dirs, []) + %w( + log + tmp/cache tmp/pids tmp/sockets + vendor/bundle +) + +# check out capistrano-rbenv documentation +# set :rbenv_type, :system +# set :rbenv_path, '/usr/local/rbenv' +# set :rbenv_ruby, File.read(File.expand_path('../../.ruby-version', __FILE__)).strip +# set :rbenv_roles, :all namespace :errbit do task :setup_configs do - shared_configs = File.join(shared_path,'config') - run "mkdir -p #{shared_configs}" - run "if [ ! -f #{shared_configs}/config.yml ]; then cp #{latest_release}/config/config.example.yml #{shared_configs}/config.yml; fi" - run "if [ ! -f #{shared_configs}/mongoid.yml ]; then cp #{latest_release}/config/mongoid.example.yml #{shared_configs}/mongoid.yml; fi" - - # Generate unique secret token - run %Q{if [ ! -f #{shared_configs}/secret_token.rb ]; then - cd #{current_release}; - echo "Errbit::Application.config.secret_token = '$(bundle exec rake secret)'" > #{shared_configs}/secret_token.rb; - fi}.compact - end - - task :symlink_configs do - errbit.setup_configs - shared_configs = File.join(shared_path,'config') - release_configs = File.join(release_path,'config') - run("ln -nfs #{shared_configs}/config.yml #{release_configs}/config.yml") - run("ln -nfs #{shared_configs}/mongoid.yml #{release_configs}/mongoid.yml") - run("ln -nfs #{shared_configs}/secret_token.rb #{release_configs}/initializers/__secret_token.rb") + on roles(:app) do + execute "mkdir -p #{shared_path}/config" + { + 'config/config.example.yml' => 'config/config.yml', + 'config/mongoid.example.yml' => 'config/mongoid.yml', + 'config/newrelic.example.yml' => 'config/newrelic.yml' + }.each do |src, target| + execute "if [ ! -f #{shared_path}/#{target} ]; then cp #{current_path}/#{src} #{shared_path}/#{target}; fi" + end + end end end namespace :db do desc "Create the indexes defined on your mongoid models" task :create_mongoid_indexes do - run "cd #{current_path} && bundle exec rake db:mongoid:create_indexes" + on roles(:db) do + within current_path do + with rails_env: fetch(:rails_env) do + execute :rake, 'db:mongoid:create_indexes' + end + end + end end end -namespace :unicorn do - set(:unicorn_pid) do - path = config['pids'] || "#{deploy_to}/shared/pids" - "`cat #{path}/unicorn.pid`" - end +set :unicorn_pid, "`cat #{"#{fetch(:deploy_to)}/shared/pids"}/unicorn.pid`" +namespace :unicorn do desc 'Reload unicorn' - task :reload, :roles => :app, :except => { :no_release => true } do - run "kill -HUP #{unicorn_pid}" + task :reload do + on roles(:app) do + execute :kill, "-HUP #{fetch(:unicorn_pid)}" + end end desc 'Stop unicorn' - task :stop, :roles => :app, :except => { :no_release => true } do - run "kill -QUIT #{unicorn_pid}" + task :stop do + on roles(:app) do + execute :kill, "-QUIT #{fetch(:unicorn_pid)}" + end end desc 'Reexecute unicorn' - task :reexec, :roles => :app, :except => { :no_release => true } do - run "kill -USR2 #{unicorn_pid}" + task :reexec do + on roles(:app) do + execute :kill, "-USR2 #{fetch(:unicorn_pid)}" + end end end diff --git a/config/deploy/production.example.rb b/config/deploy/production.example.rb new file mode 100644 index 0000000..ff72d7a --- /dev/null +++ b/config/deploy/production.example.rb @@ -0,0 +1,45 @@ +# Simple Role Syntax +# ================== +# Supports bulk-adding hosts to roles, the primary server in each group +# is considered to be the first unless any hosts have the primary +# property set. Don't declare `role :all`, it's a meta role. + +role :app, %w(deploy@example.com) +role :web, %w(deploy@example.com) +role :db, %w(deploy@example.com) + + +# Extended Server Syntax +# ====================== +# This can be used to drop a more detailed server definition into the +# server list. The second argument is a, or duck-types, Hash and is +# used to set extended properties on the server. + +server 'example.com', user: 'deploy', roles: %w(web app), my_property: :my_value + + +# Custom SSH Options +# ================== +# You may pass any option but keep in mind that net/ssh understands a +# limited set of options, consult[net/ssh documentation](http://net-ssh.github.io/net-ssh/classes/Net/SSH.html#method-c-start). +# +# Global options +# -------------- +# set :ssh_options, { +# keys: %w(/home/rlisowski/.ssh/id_rsa), +# forward_agent: false, +# auth_methods: %w(password) +# } +# +# And/or per server (overrides global) +# ------------------------------------ +# server 'example.com', +# user: 'user_name', +# roles: %w{web app}, +# ssh_options: { +# user: 'user_name', # overrides user setting above +# keys: %w(/home/user_name/.ssh/id_rsa), +# forward_agent: false, +# auth_methods: %w(publickey password) +# # password: 'please use keys' +# } diff --git a/docs/deployment/capistrano.md b/docs/deployment/capistrano.md index e97ab0e..322501f 100644 --- a/docs/deployment/capistrano.md +++ b/docs/deployment/capistrano.md @@ -5,14 +5,32 @@ suit your needs, so you should understand how to use capistrano before you continue. ## Clone and prepare the source code repository + ```bash git clone git@github.com:errbit/errbit.git cd errbit + +# Create and edit deploy.rb +cp config/deploy.example.rb config/deploy.rb +$EDITOR config/deploy.rb + +# Create and edit production.rb +cp config/deploy/production.example.rb config/deploy/production.rb +$EDITOR config/deploy/production.rb + +# Create required directories. +# It will print out what files are missing. +# Create them manually or use errbit:setup_configs task after first deploy +bundle exec cap production deploy:check ``` -- Copy `config/deploy.example.rb` to `config/deploy.rb` -- Update the `deploy.rb` or `config.yml` file with information about your server -- Setup server and deploy +### rbenv support + +Pass `rbenv` environment when running `cap` to use rbenv. + +```bash +rbenv=1 bundle exec cap production deploy +``` ## Schedule recurring tasks You may want to periodically clear resolved errors to free up space. Schedule -- libgit2 0.21.2