Custom GitHub Checks With Jenkins Pipeline

Lidor Ettinger
NI Tech Blog
Published in
4 min readMar 26, 2020

At Natural Intelligence, we are bringing massive complex pipelines into production and want to support multiple teams and their orchestration needs in a manner that is simple and easy to operate.

Using pipelines to run complex workflows is simple and easy to get started with. Our team builds pipelines which get triggered from Github and run on Jenkins. We have hundreds of repositories and sometimes we need to configure dependencies between them inside a single pipeline.

In this post, I will share the approach we have taken to bring complex pipelines in a trustable manner to production and the new groovy pipeline code I have written to make it possible.

Custom GitHub Checks With Jenkins Pipeline

The desire is to test the pull request in Github as good enough to merge into master. The default Jenkins behavior is to send the check only at the end of the pipeline. If the pipeline succeeds, the pull request in Github will be marked as mergeable, otherwise — merging will be blocked.

Our main purpose of the updated pipeline is to bring deep code visibility and transparency to the software development process. Each stage in the pipeline is Bulletproofed to determine the stage status and to reflect it on the pull request in Github.

To demonstrate how the whole setup works end to end, I think it is best to walk through the pipeline and dive into the functions.

This is a simple example of how to use the buildGithubCheck in your pipeline:

buildGithubCheckPipeline

As shown below, you can see in Github the stage name of each pipeline stage in Jenkins.

Introducing GitHub Webhook

Our deployment is triggered by a GitHub Webhook: Organization Folder which defines the Github hooks and also marks commit status on PR (pull request) using the GitHub check runs API.

The “check runs API” enables you to build GitHub Apps that run powerful checks against code changes in a repository. You can create apps that perform continuous integration, code linting, or code scanning services and provide detailed feedback on commits.

This is how you create a custom check run in your Jenkins Pipeline flow:

  • Step 1 — Configure the GitHub APP in order to integrate with Jenkins
  • Step 2 — Send the GitHub checks from Jenkins pipeline

Step 1: GitHub APP Configuration

  1. Create a GitHub App and select the permissions it needs to access such as: checks, contents, etc.
  2. Generate a private key from Github for the GitHub App and store it as a Jenkins credentials.
  3. Add a repository access for the Installed GitHub Apps

Once the application is registered, remember to write down your App ID and Installation ID, as they will be needed later.

  • App ID can be found here:
  • Installation ID can be found here:
https://github.com/organizations/<org_name>/settings/installations/<installation_id>

Step 2: Send a GitHub check from Jenkins pipeline

Each GitHub check run will be used in the following function:

buildGithubCheck

These are the function parameters:

Repository: The project name.

CommitID: The last commit id that occurred on the PR.

PrivateKey: The stored private key in Jenkins credentials.

Status: Tag the check run as: success, failure, neutral, and etc.

CheckName: The name of the check run.

Function Implementation details

  • Sending an HTTP request from Jenkins Pipeline
  • Generating a JsonWebToken
  • Validating the JsonWebToken
  • Getting an access token
  • Getting a previous check name run ID
  • Creating/Updating a check run

Sending a HTTP request from Jenkins Pipeline

There is a Jenkins plugin which allows sending an HTTP request but we did not want to be dependent on another plugin so that’s why we use pure Java class.

But there is a catch!

HttpsURLConnectionImpl.setRequestMethod() does not support PATCH requestMethod needed to update existing GitHub check. Therefore, we had to write our own function for setting the request method:

setRequestMethod

In order to authenticate API calls with GitHub App you need to use a jsonWebToken. The following steps describe how it is done.

JsonWebToken

Generate jsonWebToken signed with the private key:

getJsonWebToken

The function getRSAPrivateKey will use the private key that we created earlier in order to read the RSA private key through groovy code and will create a JSON Web Token (JWT) and encode it using the RS256 algorithm.

The function accessTime returns an object with two fields:

  • iat (issued at)— set to current time
  • expirationTime — current time + 50 seconds

ValidateAuth

Validate the jsonWebToken:

validateAuth

GitHub checks that the request is authenticated by verifying the jsonWebToken with the app’s stored public key.

GetToken

Send the jsonWebToken to the access_tokens API in order to get an access token:

getToken

Lists check runs for a commit ref

A previous pipeline execution could have already marked the PR, therefore we need to know if to update it or create a new one.

Let’s check if a check run already exists:

getPreviousCheckNameRunID

If it exists we will use its ID and set the requestMethod to PATCH, otherwise we will set the requestMethod to POST in order to create a new check run.

Create\Update a check run

Creates\Update a new check run for a specific commit in a repository. Use the requestMethod and the check run ID (if exists) from the previous function:

setCheckName

Summary

You can create your own GitHub check runs in Jenkins using pure groovy pipeline code and to confirm unit tests, typos, linting error and whatever your business might require.

The gist of the full code can be found here: buildGithubCheckScript

--

--