[CI] Webhook to trigger Jenkins' job

Happy New Year 2021, goodbye 2020 - the Covid Year 1.

These days, I'm setting up CI tool for my team. The interesting thing I've just found is I cannot config our Git Server to trigger webhook for only changes of a specific branch. For example Bitbucket settings, there're only options for whole repository changes:

So how do we trigger job only for Push/Changes to only a branch?

The POST message

Git Server will call a HTTP POST request to our webhook server. It sends all infomation related to the change we allow. Let see details of POST body:

{
    "eventKey": "repo:refs_changed",
    "date": "2020-12-29T16:37:27+0900",
    "actor": {
        "name": "hapq",
        "emailAddress": "hapq@sample.com",
        "id": 11111,
        "displayName": "Ha PQ",
        "active": true,
        "slug": "hapq",
        "type": "NORMAL",
        "links": {
            "self": [
                {
                    "href": "https://bitbucket.com/users/hapq"
                }
            ]
        }
    },
    "repository": {
        "slug": "sample-repo",
        "id": 1111,
        "name": "sample-repo",
        "scmId": "git",
        "project": {
            "key": "SAMPE",
            "id": 123,
            "name": "Sample Proj",
            "type": "NORMAL",
            "links": {
                "self": [
                    {
                        "href": "https://bitbucket.com/projects/sample-proj"
                    }
                ]
            }
        }
    },
    "changes": [
        {
            "ref": {
                "id": "refs/heads/jenkins_build",
                "displayId": "jenkins_build",
                "type": "BRANCH"
            },
            "refId": "refs/heads/jenkins_build",
            "fromHash": "58d4fc0dfb83d8e445f906835ec9f6a3aa50ce2b",
            "toHash": "f78e648f3f5845f8ae5915348a6e1d88a5fbd55f",
            "type": "UPDATE"
        }
    ]
}

As we can see, the message is really details, we will parse it and handle our job easily.

Jenkins Generic Webhook

https://plugins.jenkins.io/generic-webhook-trigger/

This is a Jenkins Extension, just go to your Jenkins server and add it. After finish installing, just enable Generic Webhook Trigger in your Jenkins.

Token

The url http://JENKINS_URL/generic-webhook-trigger/invoke is same for all Jenkins job. To make it unique for your current job only, let add a token as url query:

Token can be a raw string or you can use Jenkins text credential.
If your url above does not send correct token, the job will not be triggered. http://JENKINS_URL/generic-webhook-trigger/invoke?token=YzlJ2vwAeQ

JSON Path

To let Jenkins understand the POST body message, we need to pick the correct value in the message, then assign it as an Jenkins Variable. Let see how to pick branch id in the POST body:

We must declare correctly JSON path. It's simple Java library, or you can use this tool to check your result.

$.actor.displayName : the user has made repo's changes.
$.changes[0].toHash : the commit id.
$.repository.project.links.self[0].href : the repo url.
$.repository.slug : the repo's name.

Message filter

We have just collect data properly. Next, we do filtering with those data.
Here I do a simple filter with branch param, now Jenkins just trigger current jobs when there're changes to jenkins_build branch only.

To accomplish this step, basic knowledge about Regular Expression is must.

Summary

For all steps above, we can easily auto-press-button to run expected Jenkins Job, developer just need to push to our Git Server. For bigger image, this is the whole process from Git to Deploy server:

Hope this can help you a bit in your CI/CD process.