deploy.rb |
|
---|---|
These tasks provide the basic mechanism getting new code onto servers using git. |
require 'recap/tasks'
require 'recap/support/capistrano_extensions' |
These deployment tasks are designed to work alongside the tasks for altering environment variables, as well as the preflight checks and bootstrap tasks. |
require 'recap/tasks/env'
require 'recap/tasks/preflight'
require 'recap/tasks/bootstrap'
module Recap::Tasks::Deploy
extend Recap::Support::Namespace
namespace :deploy do |
To use this recipe, both the application’s name and its git repository are required. |
set(:application) { abort "You must set the name of your application in your Capfile, e.g.: set :application, 'tomafro.net'" }
set(:repository) { abort "You must set the git respository location in your Capfile, e.g.: set :respository, 'git@github.com/tomafro/tomafro.net'" } |
The recipe assumes that the application code will be run as a dedicated user. Any user who can deploy the application should be added as a member of the application’s group. By default, both the application user and group take the same name as the application. |
set(:application_user) { application }
set(:application_group) { application_user } |
Deployments can be made from any branch. |
set(:branch, 'master') |
Unlike a standard capistrano deployment, all releases are stored directly in the |
set(:deploy_to) { "/home/#{application_user}/app" } |
Each release is marked by a unique tag, generated with the current timestamp. This should not be changed, as the format is matched in the list of tags to find deploy tags. |
set(:release_tag) { Time.now.utc.strftime("%Y%m%d%H%M%S") } |
If |
set(:release_matcher) { /\A[0-9]{14}\Z/ } |
On tagging a release, a message is also recorded alongside the tag. This message can contain anything useful – its contents are not important for the recipe. |
set(:release_message, "Deployed at #{Time.now}") |
Some tasks need to know the |
set(:latest_tag) { latest_tag_from_repository } |
Force a complete deploy, even if no trigger files have changed |
set(:force_full_deploy, false) |
To authenticate with github or other git servers, it is easier (and cleaner) to forward the deploying user’s ssh key than manage keys on deployment servers. |
ssh_options[:forward_agent] = true |
If key forwarding isn’t possible, git may show a password prompt which stalls capistrano unless
|
default_run_options[:pty] = true |
The |
desc "Prepare servers for deployment"
task :setup, :except => {:no_release => true} do
transaction do
top.env.set
clone_code
end
end |
The |
task :clone_code, :except => {:no_release => true} do
on_rollback { as_app "rm -fr #{deploy_to}" } |
Before cloning, the directory needs to exist and be both readable and writeable by the application group |
as_app "mkdir -p #{deploy_to}", "~"
as_app "chmod g+rw #{deploy_to}" |
Then clone the code and change to the given branch |
git "clone #{repository} ."
git "reset --hard origin/#{branch}"
end |
The |
desc "Deploy the latest application code"
task :default do
transaction do
top.env.set
update_code
tag
end
restart
end |
|
task :full do
set(:force_full_deploy, true)
default
end |
Fetch the latest changes, then update |
task :update_code, :except => {:no_release => true} do
on_rollback { git "reset --hard #{latest_tag}" if latest_tag }
git "fetch"
git "reset --hard origin/#{branch}"
end |
Tag |
task :tag, :except => {:no_release => true} do
unless release_tag =~ release_matcher
abort "The release_tag must be matched by the release_matcher regex, #{release_tag} doesn't match #{release_matcher}"
end
on_rollback { git "tag -d #{release_tag}" }
git "tag #{release_tag} -m '#{release_message}'"
end |
After a successful deployment, the app is restarted. In the most basic deployments this does nothing, but other recipes may override it, or attach tasks to its before or after hooks. |
desc "Restart the application following a deploy"
task :restart do
end |
To rollback a release, the latest tag is deleted, and |
desc "Rollback to the previous release"
namespace :rollback do
task :default do
if latest_tag
git "tag -d #{latest_tag}"
if previous_tag = latest_tag_from_repository
git "reset --hard #{previous_tag}"
end
restart
else
abort "This app is not currently deployed"
end
end
end |
The |
desc "Remove all deployed files"
task :destroy do
sudo "rm -rf #{deploy_to}"
end
end
end |