Skip to content

Instantly share code, notes, and snippets.

@zev
Created May 26, 2009 11:19
Show Gist options
  • Save zev/118017 to your computer and use it in GitHub Desktop.
Save zev/118017 to your computer and use it in GitHub Desktop.
# in your deploy make sure you have git as scm and some load path hacks so that the capistrano and deploy override are seen from shared or
# whatever you want to call it.
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', '..', 'shared'))
require 'shared'
require 'git_deploy_override'
set :deploy_via, :git_sync
Capistrano::Configuration.instance(:must_exist).load do
_cset(:current_release) { current_path }
_cset(:previous_release) { nil } # No previous release will work on a dir format
def latest_release
current_path
end
def current_release
current_path
end
# =============================================================================
# OVERRIDE CAPISTRANO TASKS TO NEUTRALIZE THEM
# =============================================================================
namespace :deploy do
task :finalize_update, :except => { :no_release => true } do
run "chmod -R g+w #{current_path}" if fetch(:group_writable, true)
# mkdir -p is making sure that the directories are there for some SCM's that don't
# save empty folders
run <<-CMD
rm -rf #{current_path}/log #{current_path}/public/system #{current_path}/tmp/pids &&
mkdir -p #{current_path}/public &&
mkdir -p #{current_path}/tmp &&
ln -s #{shared_path}/log #{current_path}/log &&
ln -s #{shared_path}/system #{current_path}/public/system &&
ln -s #{shared_path}/pids #{current_path}/tmp/pids
CMD
if fetch(:normalize_asset_timestamps, true)
stamp = Time.now.utc.strftime("%Y%m%d%H%M.%S")
asset_paths = %w(images stylesheets javascripts).map { |p| "#{current_path}/public/#{p}" }.join(" ")
run "find #{asset_paths} -exec touch -t #{stamp} {} ';'; true", :env => { "TZ" => "UTC" }
end
end
# This simply sets the /app/current symlink from a release.
# Now app/current is always current, so this is meaningless now.
task :symlink do
# noop
end
# Rollback could cause some bad things, so just noop the delete tasks.
namespace :rollback do
task :revision, :except => { :no_release => true } do
strategy.rollback!
end
task :cleanup, :except => { :no_release => true } do
# noop
end
end
end
end
require 'capistrano/recipes/deploy/strategy/remote'
module Capistrano
module Deploy
module Strategy
# Implements the deployment strategy that keeps a checkout of
# the source code on each remote server. Each deploy simply updates the
# checkout
class GitSync < Remote
# Executes the SCM command for this strategy and writes the REVISION
# mark file to each host.
def deploy!
update_repository_cache
mark
end
# This may not be needed
def check!
super.check do |d|
d.remote.writable(shared_path)
end
end
def rollback!
filter_out = " sort -n -r | head -n 2 | tail -n 1 "
run "cd #{repository_path} && ROLLBACK_TAG=`#{scm} tag -l | grep RELEASE | #{filter_out}` && #{scm} checkout $ROLLBACK_TAG"
run "cd #{repository_path} && #{scm} submodule update"
end
private
def repository_path
configuration[:current_path]
end
def update_repository_cache
logger.trace "updating the repository checkout on all servers using #{repository_path} and revision #{revision}"
command = "if [ -d #{repository_path} ]; then " +
"#{source.sync(revision, repository_path)}; " +
"else #{source.checkout(revision, repository_path)}; fi"
scm_run(command)
end
# Returns the command which will write the identifier of the
# revision being deployed to the REVISION file on each host.
def mark
run "(echo #{revision} > #{repository_path}/REVISION)"
tag_release
end
def tag_release
tag_name = "RELEASE_#{Time.now.strftime('%Y%m%d%H%M%S')}"
run "cd #{repository_path} && #{scm} tag #{tag_name}"
end
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment