by Jerad Bitner on July 17, 2013 // Short URL

GitHub Pull Request Builder for Drupal

Simplify testing with a dedicated QA site for every new feature — automatically!

It's no secret that at Lullabot, we love GitHub. We use it for as many projects as possible, and have found some great success with the tools it provides. They've helped us simplify development, code review, documentation, and even communication and transparency with our clients.

Our typical process for Drupal project begins with of a checkout of our Drupal Boilerplate (thanks Eric Duran!). It gives us a base directory structure to start from, some basic drush commands, and drush aliases to simplify deployment tasks. From there, we commit Drupal into docroot and start to build out the site as normal.

Next, we input the projects requirements into the GitHub issue tracker. These take various forms for different clients, depending on whether we're starting from user stories, visual design assets, or actual written technical requirements. After we have a decent backlog of tickets, we prioritize them with the client and group them into milestones. Those milestones are typically set up as two week sprints, and each ticket will typically get its own branch of code.

When a ticket is ready for review, the issue can be turned into a pull request with a nice command line tool called hub. Pull requests are an effective means of performing peer review on code before merging into your stable branch. If one developer sends a pull request, another reviews the code before it's merged with the project's master branch.

While the peer review process is something we do for our own sanity, quality control, and knowledge sharing, it's rarely a process that clients can participate with. When the client is technically savvy and has time to work with us on that level it's great, but it's not something we can count on with every project.

A solution we've found to address this is to leverage the power of GitHub and to add some Jenkins magic into the mix. By tying GitHub's webhooks into a Jenkins instance, we can turn the changes for each pull request into a fully testable Drupal environment. This allows the client or a reviewer to click around a fresh QA site, test the features that would be affected, and easily approve or deny those changes. They don't have to manually push code to a QA environment, or worry about stepping on other in-progress features in the process. The site they're testing is completely dedicated to the changes within that feature's branch, and it's extremely productive as a result.

If you'd like to skip ahead to the geeky details, dive right into the GitHub repository. Otherwise, you can stick around for an overview of how we did it.

The process goes something like this:

  1. A new Pull Request is created.
  2. Jenkins detects the Pull Request, creates a new Drupal instance, and applies the Pull Request to the new instance.
  3. Jenkins posts back to the Pull Request on GitHub with a comment about where the new environment can be found.
  4. Once the Pull Request is merged, you can tell Jenkins to delete the environment, and it can then post a comment to that effect.

There are other commands you can access by posting to the pull request's comment, such as asking the bot to please rebuild (such as after a new commit), and it will also post to the thread if a build fails.

This process has really helped in our projects to streamline peer reviews. Here's what a client had to say about the process:

"The pull request environments have been a huge help in testing and validating the features or bugs for our sites. We are able to isolate an issue and validate it on a functioning site before final testing and deployment. It has also made our development practices clear, since you know what you're committing code to and testing against." — Mike Shaver, Intel

Overall this tool really saves Lullabot a lot of time, which saves our clients money. We've open-sourced the project on GitHub and would love to hear what you think of this. If you find it useful, but don't have the expertise to set it up, give us a shout and let's talk about how we can help you.

Jerad Bitner

Sr. Technical Project Manager

Want Jerad Bitner to speak at your event? Contact us with the details and we’ll be in touch soon.


Ashok Modi

Very interesting

While I've not had a chance to build out a CI system with github as the code repository as much as I would like (my workflow involving Jenkins and Drupal/Wordpress/whatever is somewhat similar to the ideas presented in, the idea of being able to have sandboxed environments on a per-issue (or branch? that is one part I'm not wholly clear on) basis is that can get created/destroyed at any time is, while more complex, certainly very appealing (especially if you have various kinds of tests that can get deployed to run with an issue build as well).

My first question in all this would be about the environments - do you require a wildcard domain to be pointed at the server where the builds will be created or do you create the environments in subdirectories on the server (ie something like or It was not something I was completely clear on after reading through the scripts.

Also, how do the builds get affected as a pull request is updated with new changesets (do you remove a current build of an issue with an updated version of the build or is there something else going on)?



wildcard vs subdirectory

wildcard vs subdirectory

This is up to you. We've done it both ways and you can make the adjustments to the scripts for either method.

pull request updates

You can set this up to automatically build when a pull request is updated, or you can comment in the thread with something like "Please test this" and the job will trigger a rebuild.



We don't/haven't use/d

We don't/haven't use/d vagrant in this process. Andrew is the only one that has done much work on the rome project so I'll ping him to see if he can comment further on that.



We aren't directly using

We aren't directly using vagrant or Rome for this, as it's intentionally one VM for many pull request environments.

However, for our own servers and for Rome we are using the same basic puppet configs. There's no dependency on them, but they might be useful for setting up the LAMP stack before you set up the PR builder. Our internal server for this is using these puppet configs as a base.


Ali Davoodifar


This project doesn't seem to have a license attached and as such could not be ragarded as open-source/free-software. It would be great if you'd add a proper free-software license so it could actually be used.



Hey, so i haven't played with

Hey, so i haven't played with jenkins that much. I'm kinda wondering what happens if there are multiple pull requests made?



Jenkins executors

It really depends on how you have Jenkins configured and how much beef your server has. You can set up the number of executors (simultaneous jobs that can run) per server and per job. If you set it to one, then once the first build is finished, the second one will start.



That rare case where making things *more* technical helps the PM

As a project manager, and not a coder, this has totally changed my job. I'm able to see or spin up test environments for every pull request, compare a live environment with the same configuration to the requirements, and I don't have to deal with maintaining my own local, which was always a task right at the limit of my technical ability and didn't always justify the amount of time it took to maintain. In addition the PR environment is linked to the pull request which is often created from the original ticket, so you have an environment to match the long thread of conversation and requirements.

I suppose you could do the same type of QA with a dev environment, but if something is wrong or broken, as a PM, you're powerless to know what broke the build or how to fix it. In my experience, dev was usually built off of master or head and often broken. These "PR" environments as we refer to them have completely replaced the need for dev. We still need a staging environment to test a whole group of pull requests as a release to make sure they play nice, but even that is debatable unless you're having to pull together a release from a bunch of PRs all at once.

Thanks for the write up Jerad!