Continuous Integration with Jenkins and Drupal 7

As part of the Knowledge Lab at Cocomore on 2 September, 2011, I outlined how to use Jenkins to implement Continuous Integration for a Drupal-based project. The basic building blocks for the demonstration included Jenkins, a demo Drupal project, and its automatic update from the SVN version control system, which triggers each run of SimpleTest. I will describe the primary steps to this process here.

Basic Installation

There are fully prepared Jenkins packages available for download for the most popular Linux distributions, including the Debian server version I used. The Jenkins project even maintains a repository which blends seamlessly into the software management. All the necessary commands are described on the Jenkins download page; with them, installing the base system is simply an “apt-get install jenkins” away.

Of course, since we want to test a Drupal system, our machine also needs a Web server (Apache), PHP, and a database (MySQL). Installing Ant is also useful, since it provides a good way to automate tasks and is very well supported by Jenkins.

Configuration

The next step is to create a new Job in Jenkins for testing our project. The “Build a free-style software project” option is the recommended setting for an Ant-based project like this.

Create a new job in Jenkins

On the configuration page, there are numerous settings to customize the job, according to your needs. For example, you can configure which version control system to use. CVS and SVN support are included in the Jenkins default installation, but there are easily-installed Jenkins plugins available for numerous other systems such as Git, Mercurial, or Bazaar. In this example, we are using SVN.

We need to add the repository URL (including path) to allow Jenkins to find our source code. We also need to configure what should trigger a build. For easy setup, it makes sense to either start the build at fixed intervals, or have Jenkins make periodic checks for changes in the repository and begin build execution after changes. We’ll choose the latter option and, for this example, the code in the “Schedule” field is set to check the repository every two minutes. It’s also useful that Jenkins examines not only the version of the “direct” project code, but also any linked dependencies via svn:externals.

Configure SVN in Jenkins

Now that Jenkins can find the source code, we need to configure what should happen during a build. We have chosen to create an Ant-based target, so we create a series of steps for our build, as Ant targets, which are executed in sequence.

Build processes in Selenium configured with Ant targets

We have yet to define what to do with the results of the build. We want to configure SimpleTest to write its output in JUnit XML format, so we select the JUnit plugin and enter the location our SimpleTest output will be found.

Post-build actions in Jenkins.

Here’s the relevant excerpt of the Ant target which runs the SimpleTests. In this example, it runs all tests in the group, “Demo”:

   target name="run_simpletests">
  [...]
   <exec dir="${basedir}/htdocs"
    executable="php"
    failonerror="true">
    arg line="scripts/run-tests.sh --php /usr/bin/php --url http://demo.debiserv/
      $--xml {basedir}/build/logs/simpletest Demo"/>
   </exec>
  </target>

The example below shows a very simple “Dummy” SimpleTest, which can be switched back and forth between returning “test successful” and “test failed”.

<?php
    
class DemoModuleTestCase extends DrupalWebTestCase {

      public static function
getInfo() {
       return array(
      
'name' => 'Demo Module tests',
      
'description' => 'Test the demo module.',
      
'group' => 'Demo',
        );
      }
   
      public function
testDummyTest() {
      
$value = true;
      
//$value = false;
      
$this->assertTrue($value, 'The value is true.');
      }
     }
?>

Jenkins build historyHere, if we look at the “Build History” block, we can see the results summary for recent test commits. The first was set to trigger a SimpleTest failure. Jenkins recognized a change in SVN, which triggered running build #34. The yellow ball indicates a build which completed, but a test failed. A subsequent commit to SVN triggered build #35; the blue ball indicates that the build and test were successful.

You can easily configure Jenkins to send notifications, via RSS or email, whenever the status of a project changes, so your development team is immediately made aware whenever any code changes cause a test to fail.

Conclusion: Continuous integration with Jenkins is useful

In conclusion, continuous integration can be implemented with Jenkins for a Drupal project. It is useful to formulate the steps as Ant targets; these targets can also be used for setting up development environments, so the time taken to write the automation is spent once, with continuous dividends throughout the life of your project. Drupal’s built-in SimpleTest framework can be a step in the project build process and further integrate its output with JUnit-compatible post-processing plug-ins. Jenkins notification features help keep developers up-to-date on the status of the project. With a little configuration, this can produce a complete solution.

PS: This basic demonstration of Jenkins did not cover the issues of security and authentication. As you’d expect, Jenkins supports users and access rights. On real installations such configuration should be considered mandatory, even if the system is in your internal network.

Comments

Jenkins error

Hi,

Thanks for these pointers, it helped me a lot!
Just got this error while building with Jenkins:
simpletest:
[exec]
[exec] Drupal test run
[exec] ---------------
[exec]
[exec] Tests to be run:
[exec] - Views Analyze (ViewsAnalyzeTest)
[exec] - Basic query test (ViewsBasicTest)
[exec] - G/usr/bin/daemon: unrecognized option '--url'
[exec] usage: daemon [options] [--] [cmd arg...]
[exec] options:
[exec]
[exec] -h, --help -lossary Test (ViewsGlossaryTestCase)
[exec] - Handlers test (ViewsHandlersTest)
[exec] - Tests views.module (ViewsModuleTest)
[exec] - Groupby (Vi Print a help message then exit

and later on each test to be run again.
First i removed the --url parameter from the php run-tests.sh command and put the $basedir = ''; in my settings.php so it isn't needed anymore, and stil this error keeps comming back.

Any suggestions?

Thanks a million!

nevermind... I removed the

nevermind...

I removed the --php /usr/bin/php argument because i didn't need it when i execute the commands from the terminal, when i put it back in the build.xml it stated to work.

That was quick...

Glad you got it sorted out, Martin. :-)