Using git & drush to win at workflow
by Adam Malone
As a sole developer or even as part of a small team (2-5 developers), setting up a development workflow seems on the face of it like a waste of time. Every minute that you're configuring version control, writing backup scripts, manicuring new environments, or simply tagging and pushing code around seems less fun than if those minutes were spent coding.
What happens though, when:
-A change is made on a production website that causes an irreversible database change
-You want to see which change made in the last two weeks caused a performance regression
-Management want to QA your work prior to release
-You want to dig deep into an issue that requires debug code out of your eyeballs
-Someone asks about your deployment strategy
As someone who has progressed from not knowing what HTML is to someone who pretends to know a little about Drupal, I most certainly fell victim to the trap of coding on production for a while. I had no version control, no backup strategy and if the worst had happened, I would have lost ALL of my content.
Since I've started working at Acquia, I've become intimately familiar with developmental workflow employed by enterprise level sites, where QA is mandatory and releases have to be signed off. These are sites with their own development teams and internal issue trackers to fill. The tools on the Acquia Cloud are, to put it simply, fantastic. Although as a solo developer myself, I'm aware that they're also beyond the needs of a lot of experimentalists and hackers.
This is where a personal developmental workflow strategy comes into play, and where good habits may be picked up.
Standing for DRUpal SHell, Drush is a command line tool for managing Drupal sites. Most of the useful commands may be found by visiting the online man pages so I'll only touch a little on the commands and more on the configuration of Drush such that it may become a tool for locally managing remote sites.
With Drush managing the Drupal site we'll also need something to manage the code that runs the site; this is where version control comes in. Version control provides the ability to ensure complete accountability at every step in the development cycle with the handy benefit of backing up your code! Whilst there is a light hearted rivalry between proponents of git and SVN, I feel that git comes more naturally to me. With this in mind I'll be focusing on git as a VCS over the course of this guide with SVN being, unfortunately, out of scope.
The simplest way to explain good workflow for a solo/small team is with the following:
1. Use a local environment to make changes pertinent to a single issue;
2. Once the issue is thought to be solved, thoroughly test in an interim environment;
3. With testing complete, move the changes into production.
This isolation of environments ensures that there is no pollution of bad code into a place that could affect visitors to the site, which in turn could affect business. It also allows for a production site to stay stable whilst a myriad of changes can occur locally which is conducive to an agile development environment.
Expanding on the above bullets we can see why this may have caused consternation in a traditional non drush/git system due to each step being a time sink. Since I'm such an automation advocate, it's my opinion that a workflow must be efficient if people are to be expected to use it.
The old (inefficient) way
1. Write some cool code that fixes a bug and updates a database schema
2. Use mysql-dump tool on a remote server to back-up the database
3. Copy that database to a store locally
4. Move the codebase to the test environment
5. Navigate to update.php
6. Click the button to accept database updates... etc
With git and drush this can happen fast and without requiring pages of instructions to remember steps.
Setting up your local and remove environments
Assuming the user has access to remote servers via SSH, the first thing that's required is to tell Drush about the remote servers and ensure it is able to get to the Drupal installs. By utilising a drush aliases file, this becomes trivial. I've included my alias file here for easy copying and reference. Save your file in the ~/.drush folder as aliases.drushrc.php and ensure you alter the file to include your own server details. It's also important that the user that logs into the server has access to the docroot where the Drupal installation is and that Drush is installed on the remote server.
A simple test to ensure you can connect to your remote installation would be to run drush @alias status and see whether it returned the expected details. The elements of your aliases array defined in the aliases.drushrc.php file correspond to the identifier placed after the @ symbol in the above command.
It's also useful to set up a file to track custom Drush commands you find useful in ~/.drush/drushrc.php. I've included a snippet of mine here so any commands I refer to further down the page won't seem so unfamiliar.
After adding all code from one environment to git and pushing them to Bitbucket, you'll want to ensure that this is echoed across however many environments you have. The simplest way to do this is to temporarily move your existing, unversioned codebase out of the way and to pull down your versioned repository.
-mv myawesomewebsite /tmp
-git clone firstname.lastname@example.org:myusername/myawesomewebsite.git
If you're working with production sites, I'd strongly recommend placing the production site in version control and then doing the above operation on all dev sites. This will ensure that you're not moving a live site and in turn ensuring the site does not experience downtime.
From here, with Drush able to connect to the remote sites and with everything under git, it becomes trivial to make changes on a site whilst also using best practices in workflow. Taking the example of a single update to a single file (let's use the .htaccess), the following would be recommended.
1. Backup your production database
drush @prod sql-dump > /path/to/local/backups.sql
2. Sync your production database to you are working with the latest database across your environments:
drush @dev sync-dbs
drush @test sync-dbs
3. Add your changes to the git repository
git add .htaccess
4. Pull the latest commits and ensure the database is updated on your test environment
drush @test pulldb
5. Utilise the test environment to check for errors and QA the update
6. Switch production into maintenance mode (optional) and run the same operation as on @test
drush @prod offline
drush @prod pulldb
drush @prod online
Whilst this method won't have your production code on tags, it does reduce the barrier for developers to start using drush and git with speed and ease.