Baeldung Pro – Ops – NPI EA (cat = Baeldung on Ops)
announcement - icon

Learn through the super-clean Baeldung Pro experience:

>> Membership and Baeldung Pro.

No ads, dark-mode and 6 months free of IntelliJ Idea Ultimate to start with.

1. Overview

Keeping track of Jenkins build status directly in GitHub helps us stay on top of code quality without switching between platforms. Instead of checking Jenkins manually, we can make the build status visible in GitHub, allowing us to catch failures early and keep our workflow smooth.

In this tutorial, we’ll set up Jenkins to automatically update build statuses in GitHub.

2. Prerequisites

Before we begin, we need:

  • A GitHub repository
  • A running Jenkins instance (self-hosted or cloud)
  • Git installed and configured on our local machine
  • Basic knowledge of Jenkins and GitHub workflows

3. Setting up the Demo Project

Before integrating GitHub Actions with Jenkins, let’s set up a simple Node.js project and configure Jenkins and GitHub Secrets.

3.1. Clone the Demo Project

Firstly, let’s run the following command to clone the project:

$ git clone https://github.com/Baeldung/ops-tutorials.git

Next, we navigate to the starter project directory with the following command:

$ cd ops-tutorials/jenkins-modules/monitor-jenkins-build-status/starter

3.2. Configure Jenkins

Now, let’s configure the Jenkins job that GitHub Actions will trigger.

Firstly, we head over to our Jenkins dashboard. Then, click on New Item, enter the job name, select Freestyle Project item type, and click the OK button:

Jenkins New Job

After this, we select the GitHub project option and enter our GitHub repository URL:
GitHub Project URL

Next, in the Source Code Management section, we select Git, then enter the Repository URL:

Source Code Management

After this, in the Triggers section, we select the Trigger builds remotely (e.g., from scripts) option. Here, we can enter a unique phrase for our Authentication Token, such as secret-token. This token will allow GitHub Actions to trigger Jenkins builds remotely.

Next, in the Environment section, we select the Delete workspace before build starts option. This ensures Jenkins starts each build in a clean workspace, preventing leftover files from interfering with our tests:

Triggers Build Remotely

Now, let’s configure our build steps. Scroll to the Build Steps section, click the Add build step dropdown, and then select the Execute shell option. In the provided field, we enter these commands to install dependencies and run tests:

npm install
npm test
Build steps

We can now click the Save button to apply the changes we made. These commands install our project’s dependencies and execute tests. With this, Jenkins is now configured to run builds for our Node.js project.

3.3. Generate a Jenkins API Token

To allow GitHub Actions to communicate with Jenkins, we need to generate an API token.

First, we click on our username at the top right, then click on the Security option in the sidebar and enter a name for our token. Next, click the Generate button to generate an API token and click Save.

New API token

After this, let’s copy and store the token securely as we will use it for authentication later on.

3.4. Configure Github Secrets for Authentication

Since our integration requires secure authentication, we will store the Jenkins credentials inside GitHub Secrets.

So, next, let’s head to the Settings tab in our repository. Under Secrets and variables, select Actions, then click on the New repository secret button to add the following secrets:

  • JENKINS_URL – the link to your Jenkins server
  • JENKINS_USER – our Jenkins username
  • JENKINS_API_TOKEN – our Jenkins API token
  • JENKINS_JOB_NAME – our Jenkins job name
  • JENKINS_SECRET_TOKEN – our Jenkins secret token

With this, GitHub Actions can securely trigger Jenkins builds.

4. GitHub Actions + Jenkins Integration

With Jenkins configured, let’s automate builds using GitHub Actions. This section demonstrates how to integrate GitHub Actions with Jenkins to create a lightweight CI/CD setup. Whenever we push code to the GitHub repository, it will automatically trigger a Jenkins build and report the result back to GitHub.

4.1. How It Works

To trigger Jenkins builds from GitHub Actions, we will create a workflow file that:

  1. Listens for code pushes to the repository
  2. Sends an API request to Jenkins to start a build
  3. Waits for the build to complete and fetches its status, and
  4. Updates the commit status on GitHub based on the build result

This ensures that every push to the repository automatically runs the latest build in Jenkins and surfaces its outcome directly within the GitHub interface.

4.2. Creating the GitHub Actions Workflow

Firstly, let’s create a new workflow file by running these commands in the root directory of our Node.js project:

$ mkdir -p .github/workflows
$ cd .github/workflows
$ touch trigger-jenkins.yml

Next, copy and paste the following code to the trigger-jenkins.yml file.

name: GitHub Actions + Jenkins Integration

on:
    push:
        branches:
            - main

jobs:
    trigger-jenkins:
        runs-on: ubuntu-latest

        steps:
            - name: Securely Trigger Jenkins Build
              env:
                  JENKINS_URL: ${{ secrets.JENKINS_URL }}
                  JENKINS_USER: ${{ secrets.JENKINS_USER }}
                  JENKINS_API_TOKEN: ${{ secrets.JENKINS_API_TOKEN }}
                  JENKINS_JOB_NAME: ${{ secrets.JENKINS_JOB_NAME }}
                  JENKINS_SECRET_TOKEN: ${{ secrets.JENKINS_SECRET_TOKEN }}
              run: |
                  RESPONSE=$(curl -s -w "%{http_code}" -o output.txt \
                  -X POST "$JENKINS_URL/job/$JENKINS_JOB_NAME/build?token=$JENKINS_SECRET_TOKEN" \
                  --user "$JENKINS_USER:$JENKINS_API_TOKEN")

                  if [[ $RESPONSE -ne 201 ]]; then
                    echo "❌ Jenkins build trigger failed!"
                    cat output.txt
                    exit 1
                  fi

            - name: Monitor Jenkins Build Status
              env:
                  JENKINS_URL: ${{ secrets.JENKINS_URL }}
                  JENKINS_USER: ${{ secrets.JENKINS_USER }}
                  JENKINS_API_TOKEN: ${{ secrets.JENKINS_API_TOKEN }}
                  JENKINS_JOB_NAME: ${{ secrets.JENKINS_JOB_NAME }}
              run: |
                  echo "🔍 Waiting for Jenkins build to start..."
                  sleep 10  # Wait before checking status

                  BUILD_URL="$JENKINS_URL/job/$JENKINS_JOB_NAME/lastBuild/api/json"

                  while true; do
                    STATUS=$(curl -s --user "$JENKINS_USER:$JENKINS_API_TOKEN" $BUILD_URL | jq -r '.result')

                    if [[ "$STATUS" == "SUCCESS" ]]; then
                      echo "✅ Jenkins Build Successful!"
                      exit 0
                    elif [[ "$STATUS" == "FAILURE" ]]; then
                      echo "❌ Jenkins Build Failed!"
                      exit 1
                    elif [[ "$STATUS" == "null" ]]; then
                      echo "⏳ Jenkins build still running..."
                      sleep 10
                    else
                      echo "⚠️ Unexpected status: $STATUS"
                      exit 1
                    fi
                  done

The above workflow listens for pushes to the main branch and securely triggers a Jenkins build by sending an authenticated API request. Once the build is triggered, it enters a polling loop where it continuously checks the Jenkins API to determine the result of the most recent build. Depending on the result—SUCCESS, FAILURE, or still running—it logs an appropriate message and either passes or fails the GitHub Actions job accordingly.

This workflow ensures that each push to main triggers a Jenkins build and tracks its outcome. If the build fails, GitHub Actions fails as well, making it easier to catch regressions and errors early.

4.3. Pros and Cons

Before moving on, let’s weigh the benefits and limitations of this GitHub Actions + Jenkins integration approach. Understanding where this setup excels and where it might fall short will help us make better architectural decisions for future CI/CD improvements.

Here is what works well with this setup:

  • We can easily modify the workflow or Jenkins job logic independently
  • All sensitive data is stored as GitHub secrets
  • GitHub Actions handles orchestration, while Jenkins runs the build and tests
  • We receive immediate build feedback on GitHub for every push

Here are some trade-offs to consider:

  • Build results are shown only in GitHub Actions logs unless further integrated
  • Jenkins must be up and accessible from GitHub when a workflow runs
  • Jenkins jobs must be created and configured manually or scripted separately

This method offers a straightforward way to trigger Jenkins builds from GitHub without adding unnecessary complexity. It works independently and doesn’t rely on visual badges or other integrations to be effective.

5. Jenkins Embeddable Build Status Badge

Another effective method to track Jenkins builds is by using the embeddable build status badge. This approach independently provides a clear, visual indication of the latest Jenkins build status directly within our GitHub repository, eliminating the need to manually check Jenkins.

5.1. How It Works

The Jenkins Embeddable Build Status plugin generates a dynamic badge image that reflects the latest build status of a specific job. We can embed this badge in our GitHub README.md file using Markdown.

However, there are a few important things to keep in mind:

  • The badge requires public access to Jenkins or a Jenkins instance with anonymous ViewStatus permission enabled
  • If authentication is required to access Jenkins, the badge image may not render properly on GitHub

5.2. Enabling Badge Support in Jenkins

First, we need to install the Embeddable Build Status plugin. Let’s navigate to Manage Jenkins and select Plugins:

Plugins homepage

Next, let’s search for embeddable-build-status. Then, check the Install option and click the Install button to install:

Embeddable Build Search

Jenkins notifies us as to which actions succeeded:

Embeddable Build Installation

With the installation complete, let’s head to our job page, https://YOUR-JENKINS-URL/job/YOUR-JOB-NAME. In the left sidebar, click Embeddable Build Status, then choose the badge style you prefer, for example, flatplastic, or ball-size. Next, let’s copy the provided Markdown snippet and add it to our README.md.

If the Jenkins instance isn’t publicly accessible, GitHub won’t be able to load the badge image. To handle this situation, we have two options:

The first one is to allow anonymous access. Here, we navigate to Manage Jenkins -> Security. Next, under the Authorization section, we select Matrix-based security. Then, grant the user Anonymous the ViewStatus permission:
View status

Or we can expose Jenkins publicly via reverse proxy. We can set up a secure reverse proxy, for example, using NGINX or Apache to forward external requests to our Jenkins server. Then, we configure SSL/TLS to ensure secure communication.

5.3. Pros and Cons

Let’s weigh the benefits and drawbacks of using the Jenkins embeddable build status badge.

This method offers a few simple but useful advantages:

  • We can see the build status without leaving GitHub
  • It is easy to embed directly into README.md files
  • This method minimizes the need for manual status verification

There are also some limitations to keep in mind.

  • It requires careful handling if Jenkins isn’t publicly accessible
  • It only provides basic build status (like success and failure) without detailed logs
  • If Jenkins is behind authentication, the badge may not render properly

Overall, the Jenkins embeddable build status badge is an efficient, visually intuitive method for quickly assessing the health of our Jenkins builds.

6. Conclusion

In this article, we demonstrated two efficient methods for tracking Jenkins build status directly within GitHub. First, we configured GitHub Actions to automatically trigger and monitor Jenkins builds, ensuring seamless integration and real-time feedback. Second, we leveraged the Jenkins Embeddable Build Status Badge to visually display build statuses within our GitHub repositories.

These integrations help streamline our CI/CD workflow by eliminating the need for constant manual checks in Jenkins, allowing us to quickly detect and resolve issues. The complete code for this article is available over on GitHub.