Created
April 5, 2012 12:29
-
-
Save real34/2310646 to your computer and use it in GitHub Desktop.
Capistrano : CakePHP2.x deployment recipe
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## | |
# CakePHP2.x deployment recipe | |
# TODO Implement a way to revert migrations given the map.php files of a previous release | |
# TODO Make a difference between tmp files and others | |
# TODO Give a way to the application to define its own custom directories | |
## | |
_cset (:app_symlinks) { [ | |
"/webroot/cache_css", "/webroot/cache_js", | |
"/tmp" | |
] } | |
_cset(:app_shared_dirs) { ["/Config", "/tmp/cache/models", "/tmp/cache/persistent", "/tmp/sessions", "/tmp/logs", "/tmp/tests"] } | |
_cset(:app_shared_files) { ["/Config/database.php"] } | |
_cset(:cake_repo) { "git://github.com/cakephp/cakephp.git" } | |
_cset(:cake_branch) { "master" } | |
_cset(:cake_migrations) { ['app'] } | |
_cset(:app_path) { "" } # path of your "app" directory from the base of the repository without trailing slash | |
# Used by the interactive database creation prompt | |
def defaults(val, default) | |
val = default if (val.empty?) | |
val | |
end | |
######### | |
# Based on the following resources | |
# - https://github.com/cakephp/cakepackages/blob/master/Config/deploy.rb | |
# - http://mark-story.com/posts/view/deploying-a-cakephp-site-with-capistrano | |
# - https://github.com/jadb/capcake/blob/master/lib/capcake.rb | |
# - http://www.assembla.com/code/cakephp_svn/subversion/nodes/trunk/deploy/deploy.rb?affiliate=d1rk | |
namespace :cake do | |
desc <<-DESC | |
Prepares one or more servers for deployment of CakePHP. | |
By default, it will create a shallow clone of the CakePHP repository | |
inside shared_path/cake and run cake:update. | |
It will also create needed directories | |
It is safe to run this task on servers that have already been set up; it | |
will not destroy any deployed revisions or data. | |
DESC | |
task :setup, :roles => :web, :except => { :no_release => true } do | |
run "cd #{shared_path} && rm -rf cake && git clone --depth 1 #{cake_repo} cake" | |
if app_shared_dirs | |
app_shared_dirs.each { |link| run "#{try_sudo} mkdir -p #{shared_path}#{link} && chmod 777 #{shared_path}#{link}"} | |
end | |
if app_symlinks | |
app_symlinks.each { |link| run "#{try_sudo} mkdir -p #{shared_path}#{link} && chmod 777 #{shared_path}#{link}"} | |
end | |
if app_shared_files | |
app_shared_files.each { |link| run "#{try_sudo} touch #{shared_path}#{link} && chmod 777 #{shared_path}#{link}" } | |
end | |
create_db_config | |
clear_cache | |
chmod | |
end | |
desc 'Generate / Replace the database.php file' | |
task :create_db_config do | |
require 'erb' | |
on_rollback { run "rm #{shared_path}/Config/database.php" } | |
puts "Database configuration" | |
_cset :db_driver, defaults(Capistrano::CLI.ui.ask("driver [Database/Mysql]:"), 'Database/Mysql') | |
_cset :db_host, defaults(Capistrano::CLI.ui.ask("hostname [localhost]:"), 'localhost') | |
_cset :db_name, defaults(Capistrano::CLI.ui.ask("db name [#{application}]:"), application) | |
_cset :db_login, defaults(Capistrano::CLI.ui.ask("username [#{user}]:"), user) | |
_cset :db_password, Capistrano::CLI.password_prompt("password:") | |
_cset :db_prefix, Capistrano::CLI.ui.ask("prefix:") | |
_cset :db_persistent, defaults(Capistrano::CLI.ui.ask("persistent [false]:"), 'false') | |
_cset :db_encoding, defaults(Capistrano::CLI.ui.ask("encoding [utf8]:"), 'utf8') | |
DATABASE_CONFIG_TPL = <<-TEXT | |
<?php | |
class DATABASE_CONFIG { | |
public $default = array( | |
'datasource' => '<%= db_driver %>', | |
'persistent' => '<%= db_persistent %>', | |
'host' => '<%= db_host %>', | |
'login' => '<%= db_login %>', | |
'password' => '<%= db_password %>', | |
'database' => '<%= db_name %>', | |
'prefix' => '<%= db_prefix %>', | |
'encoding' => '<%= db_encoding %>', | |
); | |
} | |
?> | |
TEXT | |
DATABASE_CONFIG = ERB.new(DATABASE_CONFIG_TPL).result(binding) | |
put DATABASE_CONFIG, "#{shared_path}/Config/database.php", :mode => 0644 | |
end | |
desc <<-DESC | |
Force CakePHP installation to checkout a new branch/tag | |
By default, it will checkout the :cake_branch you set in | |
deploy.rb, but you can change that on runtime by specifying | |
the BRANCH environment variable: | |
$ cap cake:update BRANCH="1.3" | |
DESC | |
task :update do | |
set :cake_branch, ENV['BRANCH'] if ENV.has_key?('BRANCH') | |
stream "cd #{shared_path}/cake && git fetch && git checkout #{cake_branch} && git pull" | |
run "#{try_sudo} rm -rf #{releases_path}/lib" | |
end | |
desc <<-DESC | |
Touches up the released code. This is called by update_code after the basic deploy finishes. | |
Any directories deployed from the SCM are first removed and then replaced with | |
symlinks to the same directories within the shared location. | |
DESC | |
task :finalize_update, :roles => :web, :except => { :no_release => true } do | |
run "chmod -R g+w #{latest_release}#{app_path}" if fetch(:group_writable, true) | |
if app_symlinks | |
app_symlinks.each { |link| run "#{try_sudo} rm -rf #{latest_release}#{app_path}#{link}" } | |
app_symlinks.each { |link| run "ln -nfs #{shared_path}#{link} #{latest_release}#{app_path}#{link}" } | |
end | |
if app_shared_files | |
app_shared_files.each { |link| run "#{try_sudo} rm -rf #{latest_release}#{app_path}/#{link}" } | |
app_shared_files.each { |link| run "ln -s #{shared_path}#{link} #{latest_release}#{app_path}#{link}" } | |
end | |
sed_command = "sed -i '2idefine(\"CAKE_CORE_INCLUDE_PATH\", \"#{shared_path}/cake/lib\");' #{latest_release}#{app_path}/webroot/index.php" | |
run sed_command | |
end | |
desc 'Blow up all the cache files CakePHP uses, ensuring a clean restart.' | |
task :clear_cache do | |
# Create TMP folders | |
run [ | |
"find #{shared_path}/tmp/* -type d ! -name 'logs' -print0 | xargs -0 rm -rf", | |
"mkdir -p #{shared_path}/tmp/cache/models", | |
"mkdir -p #{shared_path}/tmp/cache/persistent", | |
"mkdir -p #{shared_path}/tmp/cache/views", | |
"mkdir -p #{shared_path}/tmp/sessions", | |
"mkdir -p #{shared_path}/tmp/tests", | |
].join(' && ') | |
chmod | |
end | |
desc 'Chmod Cake directories' | |
task :chmod do | |
run [ | |
"chmod -R 777 #{shared_path}/tmp", | |
# Add here upload directories and other app-specif files | |
].join(' && ') | |
end | |
## Miscellaneous tasks | |
namespace :misc do | |
desc 'Initialize the submodules and update them' | |
task :submodule do | |
run "cd #{current_release} && git submodule sync && git submodule init && git submodule update --recursive" | |
end | |
desc 'Remove the test file' | |
task :rm_test do | |
run "cd #{current_release}#{app_path} && rm -rf webroot/test.php" if deploy_env == :production | |
end | |
desc 'Tail the log files' | |
task :tail do | |
run "tail -f #{shared_path}/tmp/logs/*.log" | |
end | |
end | |
desc <<-DESC | |
Executes a cake shell on the remote server. | |
Usage: | |
cap cake:shell (lists all the available shells) | |
cap cake:shell -s command="i18n extract" (run the "extract" method of the shell "i18n") | |
DESC | |
task :shell do | |
command = variables[:command] || "" | |
run "#{shared_path}/cake/lib/Cake/Console/cake -app #{latest_release}#{app_path} #{command}" | |
end | |
## Tasks involving migrations | |
namespace :migrate do | |
desc 'Run CakeDC Migrations' | |
task :all, :roles => :db, :only => { :primary => true } do | |
run "cd #{deploy_to}/#{current_dir}" | |
cake_migrations.each do |plugin| | |
if plugin == "app" | |
run "#{shared_path}/cake/lib/Cake/Console/cake -app #{deploy_to}/#{current_dir}#{app_path} Migrations.migration all" | |
else | |
run "#{shared_path}/cake/lib/Cake/Console/cake -app #{deploy_to}/#{current_dir}#{app_path} Migrations.migration all --plugin #{plugin}" | |
end | |
end | |
end | |
desc 'Gets the status of CakeDC Migrations' | |
task :status, :roles => :db, :only => { :primary => true } do | |
run "cd #{deploy_to}/#{current_dir} && #{shared_path}/cake/lib/Cake/Console/cake -app #{deploy_to}/#{current_dir}#{app_path} Migrations.migration status" | |
end | |
# TODO Implement a revert method | |
end | |
end | |
after 'deploy:setup', 'cake:setup' | |
before 'deploy:finalize_update', 'cake:update' | |
after 'deploy:finalize_update', 'cake:finalize_update' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment