Jenkins — Your Butler for Continuous Integration — Solution to ‘Node not Found’ Problem

Jenkins Blue Ocean Docker Image

DevOps is a set of practices intended to reduce the time between committing a change to a system and the change being placed into normal production, while ensuring high quality.

Before we start, I want to draw a clear line between a ‘Software Developer’ and a ‘Software Programmer’. A developer is an all-round person who cares about all aspects of coding, like the use of continuous integration tools (CI) like Jenkins, CircelCI, TravisCI. A programmer just wants to ship his due part of the code…

A CI tool helps us to detect problems or bugs, as early as possible, in the development life cycle. Since the entire code base is integrated, built and tested constantly, the potential bugs and errors are caught earlier in the life cycle resulting in better quality software and reducing the overall cost.

The ultimate use of a CI looks like this:

  • Developer commits code to central repository.
  • Jenkins subscribes to this repository with a hook. Whenever a commit is detected, Jenkins builds the code base.
  • Unit tests are ran along with code quality and code coverage metrics to evaluate the code quality.
  • Automated deployment to production server.

Let’s take a look!


Jenkins: Blue Ocean Docker Image

Because Jenkins is a non-hosted CI solution, we decided to download the new Blue Ocean Docker image which is provided by Jenkins and contains all the necessary tools to get started.

docker pull jenkinsci/blueocean

Next, we want to launch a running container with this image. We attach the internal container port 8080 to port 8080 on your local machine.

docker run -p 8080:8080 jenkinsci/blueocean

If you open http://localhost:8080 you will have to walk through some basic authentication steps. After that, you should be able to see the dashboard.

Jenkins Dashboard

I always feel the need to have a terminal which gives me access to the container itself. It enables me to better understand what is happening behind the scenes. Docker provides the possibility to do this.

docker exec -it CONTAINER_ID /bin/bash

The CONTAINER_ID can be found with docker container list.

Scheduling First Job for NodeJS

We need some extra plugins to accomplish our CI for NodeJS deployment and testing. Navigate to the plugin manager at localhost:8080/pluginManager. Install following plugins based on your needs:

  • Github / Bitbucket plugin
  • NodeJS Plugin

Next, we need to define a NodeJS installation at Global Tool Configuration (localhost:8080/configureTools).

Choose for Install from nodejs.org and pick the required NodeJS version. You can optionally define global npm packages to be installed.

Configure Tools — NodeJS Installation

Let’s start with configuring our first job. Choose a source code management system, add your repository URL and specify a branch to be build.

This example won’t use a build trigger, we will trigger the build manually because this is a local installation. However, it is important to select the NodeJS version you have earlier defined.

At last, we need a build step to tell Jenkins what to do when a build is triggered. Because we are using a NodeJS example, I have defined a basic test script in the package.json file. First, we call npm install to install all required packages before running the tests withnpm run test.

Jenkins build step — Execute Shell

You will notice that this won’t work when you execute the build manually. The Docker container suffers from issues regarding the node/npm installation that can’t be found. After some investigation, we found out that Node was actually installed and could be found at /var/jenkins_home/jenkins.plugins.nodejs.tools.NodeJSInstallation/NodeJS_x.x.x/bin/.

After some time, we found a dirty solution for to this problem:

export PATH=/usr/local/bin:$PATH
Solution Node not found problem

We are a bit disappointed that we have to use this quick fix. Added to that, this solution is not applicable to a pipeline job. This is also the reason for using a ‘Freestyle Project’ instead of a ‘Pipeline’.

Conclusion

We liked the use of a Docker image for easy setup and management. However, this gave to much problems when building Docker images and running them whithin the Jenkins Docker container. In the end, we decided to install a local deployment on cloud services to avoid the problems with Docker inception and Node installations.