Wednesday, March 18, 2015

Triggering Jenkins jobs remotely via git post-commit hooks

Assume you want a Jenkins job (for example a job that deploys code or a job that runs integration tests) to run automatically every time you commit code via git. One way to do this would be to configure Github to access a webhook exposed by Jenkins, but this is tricky to do when your Jenkins instance is not exposed to the world.

One way I found to achieve this is to trigger Jenkins job remotely via a local git post-commit hook. There were several steps I had to take:

1) Create a Jenkins user to be used by remote curl commands -- let's call it user1 with password password1.

2) Configure a given Jenkins job -- let's call it JOB-NUMBER1 -- to allow remote builds to be triggered. If you go to the Jenkins configuration page for that job, you'll see a checkbox under the Build Triggers section called "Trigger builds remotely (e.g. from scripts)". Check that checkbox and also specify a random string as the Authentication Token -- let's say it is mytoken1.

3) Try to trigger a remote build for JOB-NUMBER1 by using a curl command similar to this one:

curl --user 'user1:password1' -X POST "http://jenkins.mycompany.com:8080/job/JOB-NUMBER1/build" --data token=mytoken1 --data delay=0sec

If the Jenkins build is parameterized, you need to specify each parameter in the curl command, even if those parameters have default values specified in the Jenkins job definition. Let's say you have 2 parameters, TARGET_HOST and TARGET_USER. Then the curl command looks something like this:

curl --user 'user1:password1' -X POST "http://jenkins.mycompany.com:8080/job/JOB-NUMBER1/build" --data token=mytoken1 --data delay=0sec --data-urlencode json='{"parameter": [{"name":"TARGET_HOST", "value":"myhost1.mycompany.com"}, {"name":"TARGET_USER", "value":"mytargetuser1"}]}'

When you run these curl commands, you should see JOB-NUMBER1 being triggered instanly in the Jenkins dashboard.

Note: if you get an error similar to "HTTP ERROR 403 No valid crumb was included in the request" it means that you have "Prevent Cross Site Request Forgery exploits" checked on the Jenkins "Configure Global Security" page. You need to uncheck that option. Since you're most probably not exposing your Jenkins instance to the world, that should be fine.

 4) Create git post-commit hook. To do this, you need to create a file called post-commit in your local .git/hooks directory under the repository from which you want to trigger the Jenkins job. The post-commit file is a regular bash script:

#!/bin/bash

curl --user 'user1:password1' -X POST "http://jenkins.mycompany.com:8080/job/JOB-NUMBER1/build" --data token=mytoken1 --data delay=0sec

Don't forget to make the post-commit file executabe: chmod 755 post-commit

At this point, whenever you commit code in this repository, you should see the Jenkins job being triggered instantly.

2 comments:

Anonymous said...

Awesome, worked as a breeze. Thanks a ton.

Anonymous said...

Much appreciated! I had to change a couple of things but it worked like a charm!