Continuous Integration for Javascript - No Fluff Just Stuff

Continuous Integration for Javascript

Posted by: Eric Wendelin on

I have posted more thoughts and tools on how to improve this here.

Jenkins is a CI tool that is often used for Running tests and code analysis for Java and .NET projects. There are a lot of benefits that we as a community are not taking advantage of for our web (CSS, JS, etc) code. In this article I’m going to walk you through setting up automated building and testing for a JavaScript project.

NOTE: The steps outlined are generally Linux/Mac centric, I don’t go into depth on Windows setup, but it shouldn’t be much different using Cygwin.

Why use CI?

Aside from the traditional benefits you see from your compiled code, there are some very compelling reasons:

  1. Automate versioning, combining, minifying, and gzipping files
  2. Run automated tests and get reports, keeping the codebase maintainable
  3. Run static analysis tools like the closure compiler or jshint
  4. Auto-deploy files (to S3, say) if our build passes
  5. Tag and other special stuff for release builds
  6. And that’s not all!TM We can also hook in Selenium tests, CSS Lint, and more

Not convinced? Tell me why in the comments.

Jenkins setup

Downloading and running Jenkins is incredibly easy. Just download Jenkins and run:

1
2
wget http://mirrors.jenkins-ci.org/war/latest/jenkins.war
java -jar jenkins.war

There are also native installers for most environments.

Now point your browser to http://localhost:8080 to see it running.

Nailed it! Now we have a CI server!

Prerequisites

If we’re going to be using git and gradle, we’ll need to install them (Windows Git installer).

Install git
1
2
3
4
sudo yum install git-core  # CentOS/RedHat/etc
sudo apt-get install git   # Debian/Ubuntu/etc
sudo port install git-core # MacPorts
sudo brew install git      # Homebrew
Install Gradle
1
2
3
4
5
# Replace "XX" with the latest version of Gradle [http://gradle.org]
wget http://services.gradle.org/distributions/gradle-XX-bin.zip
sudo mv gradle-1.0* /usr/local
sudo unzip /usr/local/gradle-XX-bin.zip
sudo ln -s /usr/local/gradle-XX-bin /usr/local/gradle

To tell Jenkins where to find Gradle, we go to Manage Jenkins > Configure System from the top page. Add a name and enter your GRADLE_HOME (/usr/local/gradle if you followed the instructions above). It should look like this:

Jenkins Gradle Setup

Setup a CI job

As an example, I’m going to use my stacktrace.js project on GitHub. Even though it’s a small JS library, almost all of the setup can be used for any type of project.

First, we want to install a few plugins that will help us out. We’ll need Git to pull down the code and Gradle to build it. You’ll want the Git, Gradle, and Violations plugins installed. It’s pretty easy to figure out, but hit up the Jenkins wiki if you get stuck.

We want to create a new job that runs analysis on our JS and runs our tests. Click New Job on the Jenkins sidebar and you’ll see the setup form.

Checking out and building a repo

Under Source Code Management choose Git and enter git://github.com/eriwen/javascript-stacktrace.git for the repo location and master for the branch. It’ll look something like this: Jenkins Git Setup

For the Build section of the setup, we want to run the minify build target from Gradle. You’ll also want to enter the location of the build file as build.gradle. Don’t worry about the contents of our build script right now, I have a slew of blog posts in-progress that explain it. Stay tuned. Jenkins Gradle Minify

Now would be a good time to click Save at the bottom and then click Build Now on the sidebar for the job. You should see Jenkins checkout, pull down the latest Closure Compiler, and use it to minify stacktrace.js.

Running JS unit tests with PhantomJS

The days are past when you have to open a browser to see if your JS is generally working. PhantomJS is a headless WebKit browser that lets us interact with web pages (click links, pull from localStorage, etc.) without the browser window! This will let Jenkins run a browser with our tests and report the result. To follow along with the example, download and install PhantomJS in /usr/local/bin (on Mac OS I just sudo ln -s /Applications/phantomjs.app/Contents/MacOS/phantomjs /usr/local/bin/phantomjs). Note that if you’re running Jenkins on a headless server, you’ll want to have xvfb.

We also need to update the Build part of the configuration by telling gradle to run the test target. Jenkins Gradle Setup

Gradle is now setup to run the QUnit tests in the project, but we need to tell Jenkins where to find the test reports. Easy! I encourage you to check out the source of build.gradle if you want to know how this is setup. It’s really quite interesting. Jenkins JUnit Setup

Save and try that build again to bask in automated JavaScript testing awesomeness.

Finding potential bugs with JSHint

I’m a big fan of JSHint and I think it’s worthwhile to have it run on every git push. Here’s how to add that. To follow the example, you’ll have to install NodeJS and the jshint module from npm:

1
2
3
4
5
6
sudo brew install node      # Homebrew
sudo port install node      # MacPorts
sudo apt-get install nodejs # Debian-based

curl http://npmjs.org/install.sh | sudo sh # Install NPM
sudo npm install -g jshint

Now we just need to tell Jenkins to run jshint as well as our tests and where to find the JSHint report. The gradle build puts it in target/jshint.xml. It should look like this: Jenkins Violations Setup Jenkins JSHint Setup

One more Build Now and we have a fully functioning JavaScript build. You’ll also see graphs with test and jshint results on the job page and can drill down into details.

I have really loved my CI setup for my web projects as well as my JVM-based ones. Now you have the power to go build a cool CI system for your projects. You can read more of my thoughts on this from my notes from my pursuit of the perfect front-end build. Enjoy!

Eric Wendelin

About Eric Wendelin

I want to make building software easier.

Leads the Build Tool Core Team @ Gradle. Areas on significant contribution: console, completion, and daemon.

Creator of stacktrace.js.

Why Attend the NFJS Tour?

  • » Cutting-Edge Technologies
  • » Agile Practices
  • » Peer Exchange

Current Topics:

  • Languages on the JVM: Scala, Groovy, Clojure
  • Enterprise Java
  • Core Java, Java 8
  • Agility
  • Testing: Geb, Spock, Easyb
  • REST
  • NoSQL: MongoDB, Cassandra
  • Hadoop
  • Spring 4
  • Cloud
  • Automation Tools: Gradle, Git, Jenkins, Sonar
  • HTML5, CSS3, AngularJS, jQuery, Usability
  • Mobile Apps - iPhone and Android
  • More...
Learn More »