I, too, am new to Capistrano, and trying to use it for the first time to deploy a Rails app to production servers I configured with Puppet.
I finally had to dig into the Capistrano source (and capistrano/bundler, and capistrano/rails, and even sshkit and net-ssh to debug auth problems) to determine exactly how everything works before I felt confidant deciding for myself what changes I wanted to make. I just finished making those changes, and I'm pleased with the results:
# lib/capistrano/tasks/cold.rake
namespace :deploy do
desc "deploy app for the first time (expects pre-created but empty DB)"
task :cold do
before 'deploy:migrate', 'deploy:initdb'
invoke 'deploy'
end
desc "initialize a brand-new database (db:schema:load, db:seed)"
task :initdb do
on primary :web do |host|
within release_path do
if test(:psql, 'portal_production -c "SELECT table_name FROM information_schema.tables WHERE table_schema=\'public\' AND table_type=\'BASE TABLE\';"|grep schema_migrations')
puts '*** THE PRODUCTION DATABASE IS ALREADY INITIALIZED, YOU IDIOT! ***'
else
execute :rake, 'db:schema:load'
execute :rake, 'db:seed'
end
end
end
end
end
The deploy:cold task merely hooks my custom deploy:inidb task to run before deploy:migrate. That way the schema and seeds get loaded, and the deploy:migrate step that follows does nothing (safely) because there are no new migrations to run. As a safety, I test to see if the schema_migrations table already exists before loading the schema in case you run deploy:cold again.
Note: I choose to create the DB using Puppet so I can avoid having to grant the CREATEDB privilege to my production postgresql user, but if you want Capistrano to do it, just add "execute :rake, 'db:create'" before the db:schema:load, or replace all three lines with 'db:setup'.