<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xml:base="http://echodittolabs.org" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
 <title>EchoDitto Labs - Capistrano and Drupal - Comments</title>
 <link>http://echodittolabs.org/capistrano-and-drupal</link>
 <description>Comments for &quot;Capistrano and Drupal&quot;</description>
 <language>en</language>
<item>
 <title>Capistrano and Drupal</title>
 <link>http://echodittolabs.org/capistrano-and-drupal</link>
 <description>&lt;p&gt;I&#039;ve been messing around with Capistrano over the last few days. The system is best known for deploying Rails applications, but at its heart it&#039;s really just a Ruby-based way of making it easier to manage repetitive server tasks over SSH.&lt;/p&gt;
&lt;p&gt;There&#039;s one task in particular that I&#039;ve used it to automate, and which you might find useful, too.  Here at EchoDitto we&#039;re spread out over a number of offices &amp;mdash; DC, Boston, New York, and often who-knows-where-else.  This presents some development challenges when collaborating on sites built on a system that, like Drupal, puts alot of site configuration in the database, where version control systems can&#039;t be used to manage it.&lt;/p&gt;
&lt;p&gt;Of course we do development locally when possible, but we also run a remote dev server to let us collaborate off a single database (and to allow clients to see our work).  The obvious solution is to tunnel our local server&#039;s database traffic to the central server, allowing different developers&#039; filesystems to connect to the same datastore.  But this is slooow.&lt;/p&gt;
&lt;p&gt;So other options: setting up MySQL replication?  Well, that seems like overkill, and precludes offline development.  The solution I&#039;ve come up with is automating a simple database dump from the dev server.  When I need to make config changes I do it on the dev site; when I&#039;m working in the filesystem and need fresh data, I simply invoke a command to pull down the dev DB.  For most sites this only takes a few seconds to run, and invoking it is as simple as running `cap get_db` from anywhere within the dev site directory structure.&lt;/p&gt;
&lt;p&gt;I used to do this with a somewhat horrible bash script.  But it made various assumptions about filesystem and had to be modified for each new local project.  Capistrano has let me make this a bit more abstract and reusable.  The following script still makes a few assumptions about our servers and configuration, but you might find it useful, too.&lt;/p&gt;
&lt;p&gt;Among those assumptions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;There&#039;s no password on the local database. This could be easily changed, but I just don&#039;t bother -- if they&#039;ve got access to my laptop, security has failed badly enough that I&#039;m already in trouble.&lt;/li&gt;
&lt;li&gt;Your dev site directories follow a common naming standard -- for us it&#039;s xxx.dev.echoditto.com&lt;/li&gt;
&lt;li&gt;The master database credentials are stores in sites/default/settings.php.  Presumably you&#039;ll override these with other entries in the sites/ directory for local development.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Without further ado, here&#039;s my .caprc.  Like pretty much all Capistrano stuff, it assumes you have public key access set up for your dev server.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;/p&gt;
&lt;pre&gt;
SSH_CREDENTIALS = &quot;yourusername@your.dev.server.com&quot;

role :dev, SSH_CREDENTIALS

require &#039;Time&#039;

desc &quot;Dump the database and load it locally&quot;
task :get_db, :roles =&gt; :dev do
  
  # edit this line to match your dev server directory scheme
  # this code assumes that your dev site configs are in 
  # directories like:
  # /Users/yourusername/Sites/someclient.your.dev.server.com/sites/default/settings.php
  site_root = `pwd`.strip.sub(/^(.*?)\.your\.dev\.server\.com\/.*$/i,&#039;\1.your.dev.server.com&#039;)
  
  # assumes that dev DB settings will be specified in sites/default/settings.php and overridden for local development
  mysql_hits = `grep -hi &quot;mysql://&quot; #{site_root}/sites/default/settings.php`
  
  db_info = mysql_hits.split(&quot;\n&quot;)[-1].scan(/mysql:\/\/([\w_\-\.]*):([\w_\-\.]*)@([\w_\-\.]*)\/([\w_\-\.]*)/)

  if(db_info.length&amp;gt;0)
    DB_USER = db_info[0][0]
    DB_PASSWORD = db_info[0][1]
    DB_HOST = db_info[0][2]
    DB_NAME = db_info[0][3]
    MYSQL = &#039;/usr/bin/mysql&#039;
    
    # create a one-time filename
    now = Time.now.to_i
    outfile = &quot;#{DB_NAME}-#{now}.sql&quot;

    # dump the database, zip it up, transfer it, uncompress it
    run &quot;mysqldump -p#{DB_PASSWORD} -h#{DB_HOST} -u#{DB_USER} #{DB_NAME} &amp;gt; /tmp/#{outfile}&quot;
    run &quot;nice gzip -9 /tmp/#{outfile}&quot; # we zip it this way rather than during scp for better compression and to control the CPU hit
    `scp #{SSH_CREDENTIALS}:/tmp/#{outfile}.gz /tmp/#{outfile}.gz`
    `gunzip /tmp/#{outfile}.gz`

    # assumes that the local database runs as root with no password
    `echo &quot;DROP DATABASE IF EXISTS #{DB_NAME};&quot; | #{MYSQL} -u root`
    `echo &quot;CREATE DATABASE #{DB_NAME};&quot; | #{MYSQL} -u root`
    `#{MYSQL} -u root -D#{DB_NAME} &amp;lt; /tmp/#{outfile}`

    # clean up the temporary files
    `rm /tmp/#{outfile}`
    run &quot;rm /tmp/#{outfile}.gz&quot;
  else
    STDOUT.puts(&#039;Could not find dev database information! Is it in sites/default/settings.php?&#039;)
  end
   
end

&lt;/pre&gt;&lt;p&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Some might note that Capistrano is ordinarily used for deploying &lt;em&gt;to&lt;/em&gt; a server rather than pulling from it.  This is true.  It&#039;s just that we don&#039;t have a use for cap in that role, as we&#039;ve got a separate, custom deployment system built around SVN triggers and a Ruby daemon.  Capistrano&#039;s still awfully useful for other tasks, though.&lt;/p&gt;
</description>
 <comments>http://echodittolabs.org/capistrano-and-drupal#comments</comments>
 <category domain="http://echodittolabs.org/taxonomy/term/210">capistrano</category>
 <category domain="http://echodittolabs.org/taxonomy/term/212">database</category>
 <category domain="http://echodittolabs.org/taxonomy/term/211">deployment</category>
 <category domain="http://echodittolabs.org/taxonomy/term/46">drupal</category>
 <category domain="http://echodittolabs.org/taxonomy/term/213">script</category>
 <pubDate>Tue, 16 Sep 2008 09:45:59 -0700</pubDate>
 <dc:creator>Tom</dc:creator>
 <guid isPermaLink="false">84 at http://echodittolabs.org</guid>
</item>
</channel>
</rss>
