Working with Drush alias files in teams

Within our company we use Drush and Drush alias files a lot. Recently I wrote a company blog post (in Dutch) about the workflow we’ve set-up and this post is its English translation. For those of you not familiar with Drush, I’ll start with a short introduction. If you are already familiar with Drush and Drush alias files, you can skip to the interesting part.

What is Drush?

A lot of Drupal developers use Drush (Drupal Shell) to speed-up their daily processes. After you’ve install Drush locally, you can run tasks on the command-line which you would normally run via the interface. Here are some often used commands:

  • drush cc all: clear all Drupal caches
  • drush fra: revert all features
  • drush upwd Baris –password=”test”: change the password of user Baris to ‘test’
  • drush sql-dump > dump.sql: export the current database to a file
  • drush sqlc < dump.sql: import an exported database-dump

It is quite easy to create custom drush commands for task that you need often in your daily work. Many contrib modules come with their own drush implementation (for example drush search-api-index to index your site content).

What are Drush alias files?

In so-called alias files you describe the server information per website. They contain paths and usernames of all environments of a site (dev, test, staging, live). Here’s an example:

Filename: customer.aliases.drushrc.php. I’ve placed this file in my ‘aliases’ folder within my .drush folder. On Linux you can find it here: ~/.drush/aliases

limoengroen.aliases.drushrc.php

$aliases['dev'] = array(
  'root' => '/Users/BarisW/Sites/company.com',
  'uri' => 'dev.company.com',
  'path-aliases' => array(
    '%dump' => '/tmp/dump-company.sql',
    '%files' => 'files',
   ),
);

$aliases['test'] = array(
  'root' => '/var/www/company-test/htdocs',
  'remote-host' => 'webserver1.company.com',
  'remote-user' => 'username-test',
  'uri' => 'test.company.com',
  'path-aliases' => array(
    '%dump' => '/tmp/dump-company.sql',
    '%files' => 'files',
   ),
);

$aliases['prod'] = array(
  'root' => '/var/www/company-prod/htdocs',
  'remote-host' => 'webserver2.company.com',
  'remote-user' => 'username-prod',
  'uri' => 'www.company.com',
  'path-aliases' => array(
    '%dump' => '/tmp/dump-company.sql',
    '%files' => 'files',
   ),
);

The main advantage of using alias files is that you can use them to run all the drush commands on external servers. To be able to do this you need SSH access to the external server and that Drush is installed on the external server as well. If you don’t want to enter your password each time you run an external Drush command, you can also add your SSH key to the external server.

Using these alias files I can now simple run a command like this to clear the caches on the production environment:

drush @company.prod cc all

Or, to copy the production database to my local machine:

drush sql-sync @company.prod @company.dev

Ideal! Optionally, Drush sql-sync can also sanitize the data (to obscure all e-mails and passwords). This prevents developers to store sensitive customer data on their laptops.

drush sql-sync @company.prod @company.dev --sanitize

How to use Drush alias files in teams?

Extremely handy, but each developer had to enter all the settings from the various local environments in their alias files. The solution we found for this is simple and very effective: Dropbox / SparkleShare or similar.

We created a folder in Dropbox that contains all alias files. We symlinked the alias directory in ~/.drush/aliases to that folder. In this way, each team member always uses the correct data for all the project environments. You can also use these same alias files for your Continuous Integration environment (we re-use them also for our automated deployments using Jenkins).

To be able to do so we had to change one setting: instead of the ‘dev’ alias we use the names of our employees (because each employee runs his local environment somewhere else). So in my case it is now:

drush sql-sync @company.prod @company.baris

Bonus tip: alias files inheritance

The real fun starts when you start using inheritance within your alias files. For example; we use a ‘localdev’ alias for all local environments:

defaults.aliases.drushrc.php

$aliases['localdev'] = array(
  'target-command-specific' => array(
    'sql-sync' => array(
      'sanitize' => TRUE,
      'confirm-sanitizations' => TRUE,
      'no-ordered-dump' => TRUE,
      'no-cache' => TRUE,
      'enable' => array(
        'devel',
        'stage_file_proxy',
        'ds_ui',
        'fields_ui',
        'views_ui',
      ),
    ),
  ),
);

customer.aliases.drushrc.php

$aliases['localdev'] = array(
  'parent' => '@defaults.localdev',
  'uri' => 'dev.company.com',
  'path-aliases' => array(
    '%dump' => '/tmp/company-dump.sql',
    '%files' => 'files',
  ),
);

$aliases['baris'] = array(
  'parent' => '@company.localdev',
  'root' => '/Users/BarisW/Sites/company.com',
);

$aliases['eric'] = array(
  'parent' => '@company.localdev',
  'root' => '/Users/EricM/Sites/dev.company.com',
);

This setup ensures that every sql-sync is automatically sanitized, and that a number of dev modules are enabled that are turned off on the live environment (like the devel module).

PS: to use the 'enable' command, you need to copy the sync_enable.drush.inc file from your drush installation folder to your ~/.drush folder.

How do you use Drush alias files in your team? Please share your tips in the comments!

Next post

Easily import Tweets into Drupal using JSON and Feeds

Read More »

Comments

Thanks!

Great tip!  At the company I work for, we generate the aliases for our CI environments automatically, pulling from a Redmine database (our blog post). Interesting to see that you're approaching the problem from the opposite direction - maintaining a static alias file, but sharing it between developers.  

Why not combine it?

I see possibilities in combining it: generate the alias files like you do it, and store the output in a Dropbox folder so others can use it as well :)

Nice writeup!

Thanks for the nice writeup on using Drush alias files in teams.  It's great to see sync_enable in use.

One other thing that you might want to consider is that Drush configuration files are written in executable php; this makes it easy to improve your workflow by adding code to customize shared alias files.  This will remove the need to put user-specific settings in your shared files.

Drush will read and execute the user's ~/.drush/drushrc.php file before it reads any alias files, so you can put your customizations there.  One thing you might do is have everyone define their preferred path to their local Drupal root in a pre-defined Drush context; we'll call it DRUPAL_ROOTS.

drushrc.php:

$drupal_roots['customer_dev'] = '/my/custom/location';
drush_set_context('DRUPAL_ROOTS', $drupal_roots);

customer.aliases.drushrc.php:

$aliases['company1.dev'] = array(
 'parent' => '@company1.localdev',
 'root' => '/Users/BarisW/Sites/company1.com',
);
$aliases['company2.dev'] = array(
 'parent' => '@company2.localdev',
 'root' => '/Users/BarisW/Sites/company2.com',
);

Note that in this example, @company1.localdev is defined as $aliases['localdev'] in the file company1.aliases.drushrc.php, and @company1.dev is defined as $aliases['company1.dev'] in the file aliases.drushrc.php.  Drush is happy to let you do this; however, if you do, company1.dev will not show up in the list of all 'company1' aliases when you run drush sa @company1.  It can still be a useful convention in team environments, though.

Greg Anderson (via e-mail)