Been thinking lately on continuous integration/delivery, and how we can have a project where everything required to build the site is in version control, but absolutely no more than necessary. In drupal-land, this is an install profile (with some extraneous data like snippets that will be appended to settings.php
, but that's out of scope here).
So to really do continuous delivery right, we need to be able to rebuild a the site in 3 weeks exactly as we built it tonight. But this is tough while using a workflow like described for Drupal.org packaging, which is a great way to operate otherwise. Why is this tough? Because the build-[distro].make
file, when written for an install profile that is a git repo, will only ever build the HEAD of a branch.
For example, something like this would normally be used to build the site:
core = 7.x
api = 2
projects[drupal][version] = 7.14
projects[projectname][type] = profile
projects[projectname][download][type] = git
projects[projectname][download][url] = [email protected]:myplanetdigital/projectname.git
projects[projectname][download][reference] = develop
See the problem here? The only way to have your CI system be able to re-deploy the site at any point is to manually include the commit hash of the current commit in that commit itself. Which is impossible. You can't know the current commit until after you've committed it... But we do want this file in version control so that everything we need to build the site is in the repo.
So here's the trick: You can script it so that your CI system rewrites the build-projectname.make
file on the fly, substituting in the commit hash in question after cloning the repo to get the proper build-projectname.make
that you want to run (potentially to build a site that's 2 weeks old.
Here's the example of the approach, although it does the substitute on core, so that you can test it on your local system:
$ mkdir /tmp/drush-make-test
$ cd drush-make-test
$ # Write simple makefile to disk
$ cat << EOH >> test.make
core = 7.x
api = 2
projects[drupal][version] = 7.14
EOH
$ cat test.make | sed 's/7\.14/7.13/g' | drush make php://stdin .
>>> Project information for drupal retrieved.
>>> drupal downloaded from http://ftp.drupal.org/files/projects/drupal-7.13.tar.gz.
$ head -2 CHANGELOG.txt
>>>
>>> Drupal 7.13 2012-05-02
>>> ======================
$
So as you can see, since jenkins knows the hash of the commit you just cloned, you can keep a build script in that install profile with something like this:
#!/bin/sh
set -e
cat ${WORKSPACE}/profile/build-projectname.make | sed 's/develop/${GIT_COMMIT}/g' | drush make php://stdin ${WORKSPACE}/build
And now, regardless of which git reference you use for your job to start, you'll be building that site. So someone can click a button to build a given past version of the site for your QA environment, and it will build that site and deploy it with a separate deploy script (also version-controlled, by the way).
Can also use
sed
to substitute out a TOKEN (like for a commit hash or branch name on git repos :) )EDIT: expanded to demostrate this