Tuesday, April 25, 2017

Jenkins, Bitbucket, and automated testing

Recently I've gotten to where I can't develop without building tests.  In fact, I've found building tests to be so efficient as opposed to doing all my step-by-step development in the browser, I have pretty much gone to only using my browser for styling.  Building my projects in Laravel - which has been my framework of choice over the last couple of years - has made these tests so easy.

So the next logical step was to introduce automated testing.  Initially I began using Bitbucket's pipelines, which worked ok, but there was one big problem I struggled with: Bitbucket does its pipelines in a Docker image, and I'm deploying to AWS.  I did find a Docker image that emulates an Amazon Linux AMI, but I would feel better knowing it was actually being run in AWS.  Plus, bitbucket is ending their free trial period, and I actually figured out that I could run a t2.micro server for less than 1,000 pipeline minutes - and I'd be building on the exact architecture that I'm deploying in!

I landed on Jenkins for my testing platform, mainly because of name recognition.  Installing it in AWS was trivial - a great blog post here got me up and running very quickly.

The hard part was getting it to talk to BitBucket using the newer Jenkinsfile method.  The Bitbucket Plugin works great with freestyle projects, but I wanted to get a multi branch project working.  This post is about getting those two talking, because for whatever reason I could not find anything online to help me in this quest.

So, here we go.  First, you'll need to install the Bitbucket Branch Source Plugin.  I also installed the Bitbucket Build Status Notifier Plugin, which does some nifty feedback to your repo.

Next you'll need a bitbucket project with a Jenkinsfile file in the root.  Here is the example Jenkinsfile in my project:


pipeline {
    agent any

    stages {
        stage("Test") {
            steps {
                script {
                    checkout scm
                    bitbucketStatusNotify(buildState: 'INPROGRESS')
                    try {
                        sh '''
                            # Run the scripts here
                            echo 'Running tests here'
                        '''
                    } catch (Exception e) {
                        echo "Exception"
                        bitbucketStatusNotify(buildState: 'FAILED')
                    }
                    bitbucketStatusNotify(buildState: 'SUCCESSFUL')
                }
            }
        }

        stage("Print Branch") {
            steps {
                script {
                    sh '''
                        echo ${BRANCH_NAME} has been tested
                    '''
                }
            }
        }
    }
}

Simply put, we have a single stage "Test" that basically updates the Bitbucket status and prints to the screen.  Of course, where the 'Running tests here' echo statement is would be where you'll put your tests.  Go ahead and push this to your Bitbucket repo.

Next, we need to set up our credentials in Jenkins.  This bit me for quite a while, because for whatever reason the Bitbucket Branch Source Plugin requires your Bitbucket username and password - it doesn't use OAuth - but the Bitbucket Build Status Notifier Plugin does.   So, in Bitbucket, go to your Bitbucket Settings and then to OAuth (under Access Management).  Add a consumer, make sure it's private, put the location of your Jenkins install in the Callback URL (which is actually not necessary but there must be something here), and give it read and write access to your repositories.  Then, in Jenkins, go to Credentials->System->Global Credentials->Add Credentials.  Make two new Username and Password credentials - one that is using your OAuth key as the username and secret as the password, and the other using your Bitbucket login username and password.  If you want to lock it down more you don't have to put them into the global scope, my goal here is to just get you in the door!

Now go back to the main Jenkins page and choose "New Item."  (Blue Ocean, while pretty, doesn't give you access to enough options to pull this off).  Name your project and choose Multibranch Pipeline.

In the configuration, under Branch Sources add a Bitbucket source.  For Scan Credentials, choose your username login info.  For Owner, choose the repo owner, and for Repository Name choose the repo name.  This comes from bitbucket.org/owner/repository.  Turn on "Auto-register webhook".  You should also set the "Periodically if not otherwise run" checkbox under "Scan Multibranch Pipeline Triggers" so that it harvests new branches - from what I can tell by researching, it won't grab any new branches from the webhook trigger.  Everything else can be left at the default.

When you hit OK, it should scan your package for branches and automatically run your first build!  And, when you push to your repo, the build will be automatically run!

One final note, if you are using a self-signed certificate on your Jenkins server (as I am), you will need to go into the Webhook in BitBucket that Jenkins created, and enable "Skip certificate verification" - otherwise, Bitbucket will see your self-signed certificate and bail on the webhook request.