Jenkins integration for NodeJS & NPM packages

Sourav Paul
4 min readOct 30, 2020
Credit- https://blog.harveydelaney.com

If you are new to CI/CD concept, or you might be familiar but don’t know how to integrate using NodeJS, this post is for you. I was working on an application where I had to connect to Jenkins, trigger a job and return the build log to front-end using NodeJS. I struggled to get a solution to my problem statement, so I thought to write this post. Let’s get started.

First of all, I will go ahead and create a test job in Jenkins, say ‘node_test_job’.

If you see the first job in list, it is created inside ‘File Transfers’ folder. The path of the job is http://localhost:8080/job/FileTransfers/job/node_test_job” . This is important to note, as I will use this path to trigger a build. The item is a freestyle project which I’ll integrate with NodeJS API. To do this, let’s install NPM package Jenkins by Silas.

Create a file say JenkinsJob.js and import the NPM package.

const Jenkins = require('jenkins')

Next, initialize a new Jenkins client with the following options:

  • crumbIssuer (Boolean, default: false): enable CSRF Protection support
  • baseUrl (String): Jenkins URL
  • formData (Function, optional): enable file upload support on parameterized builds (must pass in require('form-data') as value for this option)
  • headers (Object, optional): headers included in every request
  • promisify (Boolean|Function, optional): convert callback methods to promises
  • and more via papi
let jenkins = Jenkins({ baseUrl: 'http://user:pass@localhost:8080', crumbIssuer: true });

Note:- crumbIssuer is a plugin embedded in Jenkins core. It provides advanced options of configuration and recommended to protect instance from CSRF attacks. {crumbIssuer: true} enable CSRF Protection support.

How to check your crumb token?

In order to get your API working, check if crumb is enabled by hitting the URL http://user:pass@localhost:8080/crumbIssuer/api/json
This shall get you a response like this-
{"_class":"hudson.security.csrf.DefaultCrumbIssuer","crumb":"66ea7501ba4fe54adbbbdef6552a7","crumbRequestField":"Jenkins-Crumb"}

You can also enable this feature from Jenkins-
GOTO: Jenkins > Manage Jenkins > Configure Global Security and enable Prevent Cross Site Request Forgery exploits.
Select Default Crumb Issuer from Crumb Algorithm and save to apply changes and enable.
See the CSRF Protection Wiki page for more.

After successful connection, you can get your server information with the following code snippet-

jenkins.info(function(err, data) {if (err) throw err;
console.log('info', data);
});

Now that I am able to connect Jenkins and get server information, will try to build “node_test_job” that we created earlier. Let’s continue editing
JenkinsJob.js-

const Jenkins = require('jenkins');
let jenkins = Jenkins({ baseUrl: 'http://user:pass@localhost:8080', crumbIssuer: true });
jenkins.job.build(jenkins.job['jenkins']['_opts']['headers']['referer']+"job/FileTransfers/job/node_test_job",
function(err,data){
if (err) throw err;
console.log('queue item number', data)
});

jenkins.job[‘jenkins’[‘_opts’[‘headers’[‘referer’]+”job/FileTransfers/job/node_test_job is equivalent to http://localhost:8080/job/FileTransfers/job/node_test_job” path.

The above code will start building the job. To mention, the method also provides you to build with parameters.

Now that the job is moved to queue for build, lets get the build output on completion. To achieve this, the npm package comes with logStream method which gets you the log output of the build on multiple event cases.

const Jenkins = require('jenkins'); 
let buildNum;
let jenkins = Jenkins({ baseUrl: 'http://user:pass@localhost:8080', crumbIssuer: true });
jenkins.job.build("node_test_job", function(err, data){
if (err) throw err;
if(data){
jenkins.job.get("node_test_job", function(err, data){
if (err) throw err;
buildNum = data['nextBuildNumber'];
let log = jenkins.build.logStream("node_test_job",buildNum)
log.on('data',function(text){
console.log(text)
})
log.on('error',function(err){
console.error(err)
})
log.on('end',function(){
console.log('end')
})
})
}
});

In the above code I have declared a variable buildNum which is to get the latest build number that is triggered by jenkins.job.build(). So need not to worry about entering build number manually.

The above code will generate the following output on command line:-

Started by user Sourav Paul
Running as SYSTEM
Building in workspace /var/lib/jenkins/workspace/FileTransfers/node_test_job
Finished: SUCCESS

This is a simple yet took me time to troubleshoot connecting API with Jenkins as I was encountered with crumbIssuer & connection forbidden issues. If you face the same, you may refer to the GitHub link.

I hope this helped you to get your head wrapped around integrating Jenkins with NodeJS API (and handling errors).Would love to hear if you have a different approach to the problem or a way to improve this solution.

If this post helped you, go ahead and high +5 (✋) the clap button below to help share this with other folks who may also enjoy this post.

Thanks.

--

--

Sourav Paul

Software engineer,self learner & an adventurous traveller. I enjoy writing about tech, places & self improvement