In the first article, we focused on setting up Jenkins and configuring it to support Node projects. Please complete those steps if you haven’t already.
In this part, we will add an actual Node project to Jenkins with the following hotness:
- Code coverage analysis
- Test suite results
- Code style analysis
- Support for build badges
- Build hooks with GitHub
Finally we will round up by looking at open source tooling and best practices for building and deploying node.js applications in production.
Let’s look at setting up a new project in Jenkins.
Setting up a Node project
First, create a new Jenkins project by selecting “New Item” from the navigation sidebar (1). Then, enter a name (2) for the project and choose “Build a free-style software project” (3). Lastly, click “OK” (4) to configure it:
After submitting, the main project configuration page appears. We will frequent this page in the remainder of the tutorial.
Configuring the repository
The first thing we will configure is our GitHub repository. We have a fictional setup for this tutorial called jenkins-example. However, GitHub hooks won’t work unless you have administrative rights so you will need to fork the repo to play along. Just replace any references to the StrongLoop repository with yours.
On the current Project Configuration Page head to the “Source Code Management” section and select “Git” (1). Then, enter your project repository URL (2) and select the credentials for GitHub (3) from the dropdown. The remaining defaults are good:
Under “Build Triggers” (1), check “Build when a change is pushed to GitHub”. Then, click “Save” (2):
npm as well so we can execute all our tests from the shell. To do this, scroll down to “Build Environment” and check “Provide Node & npm bin/ folder to PATH” (1). Then, select the desired Node installation (2) and save (3).
Now our project is configured to: pull from our GitHub repo, build whenever we push a new commit to
master, and use Node.
Let’s try it out by clicking “Build Now” (1) on the Main Project Page (you are staring at it). You will see a progress bar start rolling in the “Build History” section. This progress bar will eventually be based on the time your last build took. If everything is peachy, you’ll see a blue orb (2) indicating a successful build:
Of course, the project isn’t too interesting at this point. We basically installed Node (if it hadn’t been already), checked out the lastest
master and exited. Let’s start adding some useful reports.
Adding test and code coverage reporting
We can make our build fail if the test runner reports a non-zero exit code, but we’d rather report the results of all the individual tests in order to pinpoint a problem. And while we are at it, let’s see where we are missing tests by adding code coverage as well!
We will use
istanbul to generate coverage reports and have our test runner write out a TAP report. TAP output has great support among popular testing frameworks (i.e.
tape). In our example, we will use
npm install tape istanbul --save-dev
We won’t be writing any tests here but you can see the jenkins-example for a sample.
Then, let’s add an npm script that will generate test and coverage output. The script will formatted as such:
istanbul cover [test command] > test.tap && istanbul report clover
In our case, since
tape outputs TAP by default, the [test command] will be:
If you are using
mocha, it would look something like
_mocha -- -R tap \"test/*-test.js\"
Pulling it all together, we use the following
ci-test script in the jenkins-example repo:
"ci-test": "istanbul cover tape \"test/*-test.js\" > test.tap && istanbul report clover"
With this code on GitHub, switch over to Jenkins and visit the Project Configuration Page again. This time we are going to add a build step by visiting the “Build” section, clicking the “Add Build Step” dropdown and selecting “Execute shell”:
This will allow you to run arbitrary commands on the shell. Add the following commands in the text area that appears.
npm run ci-test || :
Head down to the “Post-build actions” and add a “Publish TAP Results” (1) from the dropdown. Then, add the
test.tap output we create from our
ci-testscript to the “Test results” input (2):
Next, add the action “Publish Clover Coverage Report” (1) to the “Post-build actions” dropdown. Then, add “coverage” as the “Clover report directory” (2) as
istanbul uses that folder for default:
Notice there are a lot of options to determine the health of the build. You may want to adjust those depending on the makeup of your project to be more “Stormy” when coverage isn’t met.
Now that coverage and test reports are integrated, let’s save our configuration and click “Run Build” again on the Main Project Page. After that builds, we can refresh the Project page to start seeing results:
As you run more builds, the Main Project Page graphs will also change. Let’s add code style reporting.
Adding code style reporting
In addition to coverage and test reporting, we can also set up checkstyle reporting. This format has good support among popular linting frameworks (i.e.
eslint). In our example, we will use
npm install eslint --save-dev
We won’t be defining any style rules with
eslinthere, but you can see the jenkins-example for a sample ruleset.
In our case, the command to configure
eslint for checkstyle output is:
eslint -f checkstyle index.js
If you are using
jshint, it would be
jshint --reporter=checkstyle index.js
Let’s add a
ci-lint script next to our
ci-test to run the linting and output it to checkstyle-result.xml:
"ci-test": "istanbul cover tape \"test/*-test.js\" > test.tap && istanbul report clover",
"ci-lint": "eslint -f checkstyle index.js > checkstyle-result.xml"
Now, let’s switch over to Jenkins and visit the Project Configuration Page again for our Test Project. We’ll add
npm run ci-lint || : to our shell execution:
Next, add another post-build action called “Publish Checkstyle analysis results” (1). Since we are using the default output filename in
ci-lint, we can click “Save” (2):
Just like the Coverage plugin discussed above, there are many ways to configure the health of builds based on which warning or error thresholds are exceeded in the “Advanced” settings for this plugin. Adjust this as it makes sense for your project.
Now click “Run Build” again on the Main Project Page. After that builds, we can refresh the Project page and we’ll see more results:
Pretty sweet, huh? Let’s bring it back to our GitHub project by adding a status badge.
Embedding status badges on GitHub
Click the “Embeddable Build Status” icon in the project sidebar to reveal embeddable markup. Copy and paste the relevant format for your readme file. Make sure to copy the unprotected markup so it can be accessed anonymously:
Add that snippet to your readme for this result:
Where we do go from here?
Now you should have a running example of a repository fully integrated with Jenkins. Hoorah! Poke around to see the kinds of reports and data that can be drawn out of the tools. I hope this tutorial saved you valuable time.
I’ll leave you with more tips for Jenkins functionality that we didn’t cover in this tutorial:
- Want successful builds pushed right away to test environments? Or make manual production deployments with a click of a button? Check out the Promoted Builds Plugin
- Send an email to those who break the build by setting up a post build action on the Project Configuration Page.
- Run isolated build environments using Docker containers with the Docker Plugin.
- Handle pull requests with the GitHub pull request builder plugin.
- Mark the build status on GitHub commits by adding a “Set build status on GitHub commit” post-build action on the Project Configuration Page.
- And so much more.
Continual feedback is incredibly helpful for the health of any serious project. Let Jenkins take care of all the busy work of running tools and generating reports to give you time to focus on the fun stuff: the code itself. If you use Jenkins already, please share your helpful plugins/workflows in the comments!
Additional open source innovations and deployment best practices
One of the struggles developers face when moving to Node.js is the lack of best practices for automated deployment of Node applications. The challenges are many-fold – packaging and dependency management, single step deploy, and start/re-start without bringing down the house!
There are tools out there, but they are often not composable, are incomplete, or we just don’t agree with how they do things. StrongLoop’s Node.js core team members have created modular tooling to solve these problems like
strong-build, to package your application for deployment, and
strong-deploy to push your application packages to
strong-pm, the process manager that will manage your deployed applications.
Check out the production best practices blog by Sam Roberts.
Continual enhancements have been requested by the community and are being planned for more distributed and scaled deployments in Arc.