But configuration of the project is just a half of the puzzle. Testing is must for me. And tests have to be executed. Execution must be automatic. So I needed to figure out Continuous Integration story for this project configuration.
Project parameters to consider
Let me quickly summarize base attributes of project configuration:
- Two Github repositories/sub-projects
- One main project called primediser
- builds sub-projects
- gathers deployment
- runs Protractor end-to-end tests against deployment
- gathers code coverage stats for client side code
Choosing CI server
Next I tried drone.io. Relatively new service. Initially seemed not very feature reach. But closer look actually showed that this is the right choice. It provides these features necessary for me:
- Temporary Docker Linux instance (is deleted after build) with pre-installed Node.JS
- Web hook for remote triggering builds
- Web interface for specifying Bash build commands
- Web interface for specifying private keys or credentials needed during build
This combination of features turned to be very powerful. There are few unpolished problems (e.g. visualization of build process makes Firefox unresponsive, missing option for following build progress – so need to scroll manually), but I can live with these.
I was also able to execute Protractor tests against Sauce Labs from drone.io and measure the code coverage. Measuring Protractor tests code coverage is described in separate blog. Any change against sub-project triggers also build of main project. Does this sound interesting? Let me describe this CI configuration in details.
I wouldn’t dive into drone.io, Sauce Labs or Protractor basic usage. They were new for me and I easily and quickly came through their docs. Here is list of docs I used to put together this CI configuration.
- drone.io is very intuitive. Here is their short Node.JS doc.
- Sauce Labs
Protractor – Souce Labs integration
Important part of this setup is Protractor integration with Sauce Labs. Sauce Labs provide Selenium server with WebDiver API for testing. Protractor uses Sauce Labs by default when you specify their credentials. So credentials are the only special configuration in test/protractor/protractorConf.js (bottom of the snippet). Other configuration was taken from grunt-protractor-coverage example. I am using this grunt plug-in for running Protractor tests and measuring code coverage.
You may ask now, how can I use localhost in the configuration, when remote selenium server is used for testing. Good question. Sauce Labs provide very useful feature called Sauce Connect. It is a tunnel that emulates access to your machine from Selenium server. This is super useful when you need to bypass company firewall. It will be used later in main project CI configuration.
Setting up CI for sub-projects
Main project kicked off by hitting the Web hook via wget Linux command from sub-project. As you can see in following picture, sub-project informs main project about a change and process its own build afterwards. Drone.io doesn’t provide concurrent builds (not sure if this is limitation of open source projects only), so main project will wait for sub-project’s build to finish. After that main project is build.
So build of main project is now triggered from sub-projects. Main project configuration is slightly more complicated. I uses various commands:
- First of all we need to specify Sauce Labs credentials in Environment Variables section
export SAUCE_USERNAME=******** export SAUCE_ACCESS_KEY=****************************
- Download, extract and execute Sauce Connect tunnel for Linux. This will make accessible some ports on build image for Selenium testing. Notice that execution of the tunnel is done with & (ampersand). This means that tunnel execution is done in forked process and current console can continue executing build.
wget https://d2nkw87yt5k0to.cloudfront.net/downloads/sc-latest-linux.tar.gz tar -xzvf sc-latest-linux.tar.gz cd sc-4.2-linux/bin ./sc & cd ../..
- Now standard Node.JS/Grunt build workflow is executed. Downloading and installing all NPM dependencies creates enough time for Sauce Connect tunnel to start.
npm install phantomjs time npm install -g protractor time npm install -g grunt-cli bower time npm install grunt
- Last command is closing the Sauce Labs tunnel after build, so that Docker build image wouldn’t hang.
Such configured job now takes 9 minutes. drone.io limit is 15 minutes. Hopefully there will be enough space for all end-to-end tests I am going to create. If you are curious about build output/progress, take a look at my drone.io jobs below.
- primediser – main project
- primediser-server – Node.JS/Express based back-end
- primediser-client– Angular based front-end