Trigger Jenkins Jobs ONLY when Pull Requests are made to SPECIFIC GitHub branches
Capture the Webhook sent by GitHub, manipulate it and send a POST request to Jenkins.
If you want to skip the tutorial and head straight to the solution simply clone the GitHub repository and set the .env variables.
Our company required the following CD/CD architecture:
- Developers will make pull requests to the dev branch, which will trigger distinct unit tests and do some code checks.
- Then a senior engineer or the team lead will make a bigger pull request from the dev branch to the main branch which will run more unit, regression & automated UAT tests.
- At the end of each sprint, releases will be made from the main branch.
The plugins that were available for Jenkins did not necessarily allow me to manipulate the payload sent by the GitHub Webhook (or maybe they did, and I missed it) and only notify a Jenkins pipeline when a pull request is made to a specific branch.
I created a small dockerized Node.js service that acts as a conduit between GitHub and Jenkins, intercepting the webhook.
Create a simple Node.js project with Express.
If you are a beginner watch this tutorial by Mosh to set up your environment.
Watch this to configure your environment to work with REST API.
Set up your app to listen at the specified port.
node index.js and go to the port you have configured in your browser to ensure it works fine.
You should see the
res(response) sent by the
app.post(“/hook”) end-point which will be the route that is configured in the GitHub repository to receive the webhook.
app.post — Lines 2 & 3: Get the header & body data from the payload and set them to variables.
app.post — Lines 6–9: The following methods would get the required data for 1) the pull request branch, 2) the base branch the pull request was targetted to be merged, 3) URL of the commit, which will be linked to the unique pull request page you will see on the browser (image 1.0) and 4) which action triggered the pull request —in this case, it will be ‘pull request’ but if you look at the webhook page, you will see that you can configure it to become triggered on various actions.
Note that I have used dlv to traverse through the objects dot-notated path to get the required values.
app.post —Lines 10 & 11: The header of the webhook would have
x-github-delivery, which is used by the post request to Jenkins to keep track of the webhook and
x-github-event, which describes what event triggered the webhook. This value is necessary to ensure that the Jenkins job is only triggered when a pull request is made. The following methods get those values.
app.post — Lines 12-17: Refer to the README.md file to understand why you must set these ENV variables.
app.post — Lines 19-24: Given that the payload action is open, the
x-github-event is a pull request and the subject branch set by the .env is the same as the base branch, the two methods
postToJenkins will be called (Step 5). The POST request will only be made if the pull request is made to the subject branch which has a specific purpose in the CI/CD process.
The easiest way to do Step 5 and Step 6 is to use Postman and create the POST request from the platform and simply generate the code snippet.
The commit page (Image 1.1) will be updated when the pull request is made which will inform users the status of the branch protection rules.
updateCommitStatus — Line 2: The
data variable is sent in the body of the request. It’ll contain information needed to inform the user of the
updateCommitStatus — Line 6: The target endpoint, along with the access token from a GitHub account.
postToJenkins — Line 4: The payload sent by GitHub will be sent to Jenkins in the body of the request.
postToJenkins — Line 8: The endpoint (Image 2.0) along with the access token you set in the Jenkins job.
postToJenkins — Line 9–13: Metadata about the webhook.
Dockerize your application by adding a
Dockerfile, set all the .env variables and use Docker Compose as it makes deployment easier. You will also need a domain name to configure the webhook in GitHub.
This is only a template for you to work with and I hope you can use it to meet the requirements of your CI/CD practices.