Skip to content
tsantef edited this page Mar 17, 2012 · 3 revisions

--- Configuration ---

set :repo, "~/repos/reponame.git"

set :production, server( 
  :host     => "some.host.com", 
  :user     => "myuser", 
  :password => "xxxxxxxx",
  :type     => "ssh"
)

set :new_release, Time.new.utc.to_i
set :application, "www.superapp.com"

# Paths
set :releases_path,      "#{application}/releases"
set :shared_config_path, "#{application}/config"
set :shared_db_path,     "#{application}/db"
set :shared_log_path,    "#{application}/log"
set :current_path,       "#{application}/current"
set :shared_bundle_path, "#{application}/bundle"
set :new_release_path,   "#{releases_path}/#{new_release}"

set :target, production

# --- Default Deployment Steps --- #

step :pre_configure
step :clone_repo
step :create_resources
step :copy_configs
step :bundle_install
step :setup_symlinks
step :migrate_database
step :deploy_release
step :restart

# --- Deployment Steps --- #

def pre_configure
  target.run do

    # TODO: check for un committed changes

    if !exists? "#{shared_config_path}"
      puts "Creating application config folder"
      run "mkdir -p #{shared_config_path}"
    end

    if !exists? "#{releases_path}"
      puts "Creating releases folder"
      run "mkdir -p #{releases_path}"
    end

    if !exists? "#{shared_bundle_path}"
      puts "Creating vendor bundle folder"
      run "mkdir -p #{shared_bundle_path}"
    end

    if !exists? "#{shared_db_path}"
      puts "Creating application db folder"
      run "mkdir -p #{shared_db_path}"
    end

  end
end

def clone_repo
  target.run do
    run "rm -rf #{new_release_path}"
    run "git clone --depth 1 #{repo} #{new_release_path}"
    run "rm -rf #{new_release_path}/.git"
  end
end

def copy_configs
  target.run do
    if !exists? "#{shared_config_path}/database.yml"
      puts "Copying database.yml"
      copy "config/database.yml", "#{shared_config_path}"
    end

    if !exists? "#{shared_config_path}/application.yml"
      puts "Copying application.yml to shared config folder"
      copy "config/application.yml", "#{shared_config_path}"
    end
  end
end

def create_resources
  current_release = get_current_release
  target.run do
    run "echo '#{current_release}' > #{new_release_path}/previous.rev"
    run "echo '#{new_release}' > #{new_release_path}/current.rev"

    # Add restart.txt if missing
    if !exists? "#{new_release_path}/tmp/restart.txt"
      run "mkdir -p #{new_release_path}/tmp"
      run "touch #{new_release_path}/tmp/restart.txt"
    end

    # Create database is missing
    if !exists? "~/#{shared_db_path}/production.sqlite3"
      cd new_release_path do
        run "/usr/lib/ruby/gems/1.8/bin/bundle exec rake environment RAILS_ENV=production db:create"
        run "mv production.sqlite3 ~/#{shared_db_path}/"
      end
    end
  end
end

def bundle_install
  target.run do
    run "ln -s ~/#{shared_bundle_path} ~/#{new_release_path}/vendor/bundle"
    cd new_release_path do
      run "/usr/lib/ruby/gems/1.8/bin/bundle install --deployment"
    end
  end
end

def setup_symlinks
  target.run do
    cd new_release_path do
      # Link log
      run "[ ! -d ~/#{shared_log_path} ] && mv log ~/#{shared_log_path}" # move locdg if not exists
      run "[ -d log ] && rm -rf log"
      run "ln -s ~/#{shared_log_path} ~/#{new_release_path}/log"

      # Link application.yml
      delete "~/#{new_release_path}/config/application.yml"
      run "ln -s ~/#{shared_config_path}/application.yml ~/#{new_release_path}/config/application.yml" 

      # Link database.yml
      delete "~/#{new_release_path}/config/database.yml"
      run "ln -s ~/#{shared_config_path}/database.yml ~/#{new_release_path}/config/database.yml" 
    end
  end
end

def migrate_database
  target.run do
    # Link db
    run "ln -s ~/#{shared_db_path}/production.sqlite3 ~/#{new_release_path}/db/production.sqlite3" 

    cd new_release_path do
      run "/usr/lib/ruby/gems/1.8/bin/bundle exec rake db:migrate RAILS_ENV=production"
    end
  end
end

def deploy_release
  target.run do 
    run "[ -d #{current_path} ] && rm -rf #{current_path}" # if current is not a symbolic link
    run "[ -h #{current_path} ] && unlink #{current_path}"
    run "ln -s ~/#{new_release_path} #{current_path}"
  end
end

def restart
  target.run "touch ~/#{current_path}/tmp/restart.txt" 
end

# --- Utility Steps --- #

def send_configs
  target.run do
    copy "config/database.yml", "#{shared_config_path}"
    copy "config/application.yml", "#{shared_config_path}"
  end
end

def rollback
  target.run do
    previous_release = get_previous_release
    previous_release_path = "#{releases_path}/#{previous_release}"
    run "[ -d #{current_path} ] && rm -rf #{current_path}" # if current is not a symbolic link
    run "[ -h #{current_path} ] && unlink #{current_path}"
    run "ln -s ~/#{previous_release_path} #{current_path}"
  end
end

# --- Helper Methods --- #

def get_current_release
  result = target.exec "cat #{current_path}/current.rev", true
  return result[1].strip
end

def get_previous_release
  result = target.exec "cat #{current_path}/previous.rev", true
  return result[1].strip
end
Clone this wiki locally