Thursday, January 5, 2017

Re-Introducing Jenkins: Automated Testing with Pipelines

As our applications become more complex - with Composer dependencies, Webpack build scripts, and per-environment variables - we inevitably reach a point where testing all of these different intricacies becomes slow and laborious, especially when you're tearing down and rebuilding the entire environment for each test. Likewise, code style might deviate over time and creating a production ready deployment archive requires a specific set of steps to be followed.

Suppose that, to test your application, you need to perform the following steps:

  1. Run composer install to ensure the dependencies are installed
  2. Run php -l against each PHP file in the codebase to check for syntax errors
  3. Run PHPUnit for unit testing
  4. Run Codeception for functional testing

Jenkins Logo

If any of these steps fail then the software should be considered unsuitable for deployment until the errors have been addressed. As your software becomes more complex and the number of tests increases over time it can take many minutes to run the full suite which slows down your developers which in turn slows down the release process.

To help overcome this you can introduce a build server into your development workflow. A build server runs a piece of software that enables you to run a series of steps over and over again in the background, and if one of the steps fails the build server can inform you of the issue. If you've contributed to an open source project you may have seen a build server such as TravisCI or CircleCI in action. For example, every pull request on the Laravel project is tested by TravisCI to ensure the change doesn't break any tests, then StyleCI ensures the code change matches the project code style.

laravel-checks.png

Jenkins is a popular open-source build server that this year had its 2.0 release. One of the principal features of this new release is the inclusion of the (previously optional) pipelines plugin as a core feature.

A pipeline is a set of completely customizable steps that can be run in order to test and build your code. Pipelines are written in the Groovy scripting language which has a very simple syntax that is easy to get comfortable with. For example, if you wanted to describe the test steps described before as a pipeline, it might look similar to this:

node {
    stage("composer_install") {
        sh 'composer install'
    }

    stage("php_lint") {
        sh 'find . -name "*.php" -print0 | xargs -0 -n1 php -l'
    }

    stage("phpunit") {
        sh 'vendor/bin/phpunit'
    }

    stage("codeception") {
        sh 'vendor/bin/codecept run'
    }
}

The node statement tells Jenkins to assign a single build node (Jenkins can run either in a single-server mode, or a multi-node setup). Inside the node block are multiple stages which each perform a specific action.
Jenkins will run each of the stages in turn and if any of them should fail then the entire build will fail and Jenkins will stop executing.

From this simple example you could easily add additional stages with other tests, tell Jenkins to send a Slack notification for successful or failed builds, push successfully tested code into a release branch or mark a pull request as good to merge.

Installing Jenkins

Jenkins is very easy to install and for this tutorial we're going to use Laravel Homestead to give a consistent virtual environment so you can play with Jenkins locally.

The first step is to install Laravel Homestead - there is a useful guide here. You only need to get the virtual machine up and running, we don’t need to configure any sites in the homestead.yaml file.

With your Homestead virtual machine up and running, SSH into it with vagrant ssh.

Homestead ships with all the dependencies we need, namely Git, PHP and Composer so we just need to install Jenkins itself. Following the Jenkins Debian package guide we need to perform the following steps.

Run wget -q -O - http://ift.tt/2gq3rAf | sudo apt-key add -. This command adds the code-signing key to Aptitude so the Jenkins packages from this repository will be trusted.

Next, the package sources list needs updating so Aptitude knows about the Jenkins package repository. Execute echo "deb http://ift.tt/2gq0mjB binary/" | sudo tee -a /etc/apt/sources.list.

Finally, we need Aptitude to update its cache of available packages, and then install Jenkins:

sudo apt-get update && sudo apt-get install jenkins

Installing Jenkins will take approximately five minutes as it has quite a number of dependencies that also need installing.

Once Jenkins is installed, open http://ift.tt/2iIlPTz in your browser (or your virtual host configured URL like homestead.app) and you should see a page titled “Unlock Jenkins”.

unlock-jenkins.png

Inside the VM, run the following command - sudo cat /var/lib/jenkins/secrets/initialAdminPassword and a random string of number and letters will be printed to the console. Copy and paste that string into the text field in the browser and press "Continue".

customise-jenkins.png

You’ll be presented with two options - choose “Install suggested plugins” and wait a few minutes while the plugins are downloaded and installed.

create-admin-user.png

On the next screen, enter the details of an admin user and press “Save and Finish”.

jenkins-dashboard.png

Jenkins is now installed and configured!

Creating your first job

With Jenkins set up, we’re going to create a new build job that will do the following:

  1. Check out the latest build of laravel/framework
  2. Install Composer dependencies
  3. Run PHPUnit

Click the “create new jobs” link on the dashboard (or the “new item” link - they both do the same thing).

Continue reading %Re-Introducing Jenkins: Automated Testing with Pipelines%


by Alex Bilbie via SitePoint

No comments:

Post a Comment