2015-04-11

Circleci is another straight-forward continuous integration and deployment service that integrates easily with github.

Here is what my circle.yml for running my tests against Drupal 7 looks like:

machine:
  environment:
    SERVER: your-project.local
  php:
    version: 5.5.21
  hosts:
    SERVER: 127.0.0.1

dependencies:
  pre:
    - cp cnf/circle.conf /etc/apache2/sites-available/default
    - sudo sed -e "s?%HOME%?$(pwd)?g" --in-place /etc/apache2/sites-available/default
    - sudo sed -e "s?%PROJECT_DIR%?www?g" --in-place /etc/apache2/sites-available/default
    - sudo sed -e "s?%SERVER%?SERVER?g" --in-place /etc/apache2/sites-available/default
    - sudo a2enmod rewrite
    - sudo service apache2 restart
    - cp cnf/settings.php www/sites/default
  override:
    - composer install --prefer-dist
  post:
    - sudo chown -R $(whoami):www-data www
    - build/install.sh

   test:
      override:
          - bin/behat -f pretty
          - cd www && ../bin/drush fl | grep -qi 'overridden' && (echo 'Feature override test: fail' && exit 0) || (echo 'Feature override: pass' && exit 1)

As always, actually reading the circleci documentation will decrypt most of this for you, including variable names ("machine", "pre", "override", etc.). So with an RTFM error premtively thrown, here nonetheless is roughly what is being accomplished:

At the very top, I am setting some project-specific tunables since I want to reuse essentially same circle.yml for every project. This is a personal preference but has the virtue of allowing me to share my circle.yml with others.

~~~php machine: environment: SERVER: your-project.local php: version: 5.5.21 hosts: SERVER: 127.0.0.1 ~~~

I am creating a custom variable called SERVER that corresponds to the localhost alias of my project. After specifying the php requirement for my project, I am establishing this SERVER variable as my host. I refer again to my host when setting up the virtualhost.

Next we have the project setup, the bulk of which is apache2 configuration:

~~~php dependencies: pre: - cp cnf/circle.conf /etc/apache2/sites-available/default - sudo sed -e "s?%HOME%?$(pwd)?g" --in-place /etc/apache2/sites-available/default - sudo sed -e "s?%PROJECT_DIR%?www?g" --in-place /etc/apache2/sites-available/default - sudo sed -e "s?%SERVER%?SERVER?g" --in-place /etc/apache2/sites-available/default - sudo a2enmod rewrite - sudo service apache2 restart ~~~

The two most important actions here are setting a virtualhost for your project so that apache2 knows where the Drupal in order to serve it up and the enabling of rewrite, which Drupal needs.

My virtualhost config is stored inside circle.conf within a directory called cnf where it is then copied into apache2's sites-available. Here is what my generic circle.conf looks like, complete with Rewrite configurations:

<VirtualHost *:80>
    UseCanonicalName Off
    DocumentRoot %HOME%/%PROJECT_DIR%
    ServerName %SERVER%

  <Directory %HOME%/*>
    Options FollowSymLinks
    AllowOverride None
    RewriteEngine On
    RewriteBase /
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule %HOME%/%PROJECT_DIR%/(.*)$ index.php/?q=$1 [L,QSA]
    Order allow,deny
    Allow from all
  </Directory>

  <Directory />
    Options FollowSymLinks
    AllowOverride None
  </Directory>
</VirtualHost>

Notice that I am replacing out the placeholders inside circle.yml with tubables that I am setting at the top of the circle.yml. (I am assuming that your drupal root lives inside www of your project root). Of course, all that sudo sed -e replacement is completely unnecessary if you just hard-code in the circleci and your project's directory paths. Again, I have found it easier to use the same virtualhost file for each project and replace the globals.

Next we copy in a settings.php with circleci variables that Drupal can bootstrap:

~~~php - cp cnf/settings.php www/sites/default ~~~

Here is what my settings.php looks like:

<?php

$databases['default']['default'] = array(
      'driver' => 'mysql',
       'database' => 'circle_test',
       'username' => 'ubuntu',
       'password' => '',
       'host' => '127.0.0.1',
       'prefix' => '',
       );

Next we are installing the project's dependencies with composer:

    - composer install --prefer-dist

You will at least need drush to build your project. If your tests are in behat, as mine are, you will need that as well.

Finally, I build my project with a bash script (a series of drush commands inside install.sh), run my behat test suite, and check that there are no features overridden.

Now go forth and make your Drupal build explicit, repeatable, and testable.