How to Use Jenkins with GitHub

How to Use Jenkins with GitHub

If you’ve been writing code and pushing it to GitHub, you already know how quickly things can get messy without automation. I remember the first time I manually built and deployed a project after every push — it was tedious, error-prone, and honestly just boring. That’s exactly the gap Jenkins fills. In this guide, I’ll walk you through everything I know about using Jenkins with GitHub, from the basic concepts all the way to production-grade pipelines.

What Is Jenkins and Why Pair It With GitHub?

Jenkins is an open-source automation server written in Java. Its entire purpose is to automate the parts of software development related to building, testing, and deploying code — commonly called CI/CD (Continuous Integration/Continuous Delivery). GitHub, on the other hand, is where most of us store and version our code today.

When you connect Jenkins with GitHub, you get a workflow where every push, pull request, or merge can automatically trigger a build, run your test suite, and even deploy your application. I’ve found this combination to be one of the most common setups in the industry because GitHub’s massive adoption pairs naturally with Jenkins’ flexibility.

Jenkins Architecture in Brief

Before diving into GitHub integration, it helps to understand how Jenkins works internally:

Understanding this separation matters because when you’re connecting GitHub, you’re really configuring how the controller receives event notifications and how it assigns the resulting build work to an agent.

Step 1: Install Jenkins

If you haven’t installed Jenkins yet, grab the WAR file or use your OS package manager. On Ubuntu, for example:

sudo apt update
sudo apt install openjdk-17-jdk -y
curl -fsSL https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key | sudo tee \
  /usr/share/keyrings/jenkins-keyring.asc > /dev/null
echo "deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc]" \
  https://pkg.jenkins.io/debian-stable binary/ | sudo tee \
  /etc/apt/sources.list.d/jenkins.list > /dev/null
sudo apt update
sudo apt install jenkins -y
sudo systemctl start jenkins

Once installed, Jenkins runs on port 8080 by default. Unlock it using the initial admin password found at /var/lib/jenkins/secrets/initialAdminPassword.

Step 2: Install the Required Plugins

From Manage Jenkins > Plugins, install:

These plugins let Jenkins understand GitHub webhooks, clone repositories, and track commit statuses back on GitHub.

Step 3: Generate a GitHub Personal Access Token

Jenkins needs credentials to talk to GitHub’s API (for things like reporting build status or accessing private repos). Go to GitHub Settings > Developer Settings > Personal Access Tokens and generate one with repo and admin:repo_hook scopes.

In Jenkins, go to Manage Jenkins > Credentials, add a new credential of type “Secret text” or “Username with password,” and paste your token.

Step 4: Connect Jenkins to Your GitHub Repository

Create a new Item in Jenkins (Freestyle or Pipeline), and under “Source Code Management,” select Git. Paste your repository URL:

https://github.com/yourusername/your-repo.git

Select the credentials you just created. If your repo is private, this step is essential — public repos work fine without it.

Step 5: Set Up Webhooks for Automatic Triggers

This is where the real magic happens. Instead of manually clicking “Build Now” every time, you want GitHub to notify Jenkins the moment something changes.

In your GitHub repository, go to Settings > Webhooks > Add webhook, and set the Payload URL to:

http://your-jenkins-url/github-webhook/

Set the content type to application/json and choose “Just the push event” (or customize based on your needs, like pull requests).

Back in Jenkins, under your job configuration, check “GitHub hook trigger for GITScm polling” in the Build Triggers section.

Now, every push to GitHub will instantly trigger a Jenkins build — no polling delay, no manual clicks.

Step 6: Writing a Jenkinsfile for GitHub-Triggered Pipelines

For anything beyond a simple freestyle job, I strongly recommend using a Jenkinsfile. Here’s a basic example:

pipeline {
    agent any

    stages {
        stage('Checkout') {
            steps {
                git branch: 'main', url: 'https://github.com/yourusername/your-repo.git'
            }
        }
        stage('Build') {
            steps {
                sh 'npm install'
            }
        }
        stage('Test') {
            steps {
                sh 'npm test'
            }
        }
        stage('Deploy') {
            steps {
                echo 'Deploying application...'
            }
        }
    }

    post {
        success {
            echo 'Build succeeded!'
        }
        failure {
            echo 'Build failed!'
        }
    }
}

Store this file at the root of your repository as Jenkinsfile, then create a “Pipeline” job in Jenkins and point it to “Pipeline script from SCM,” selecting Git and your repo URL.

Reporting Build Status Back to GitHub

Once you’re using GitHub with Jenkins, it’s genuinely useful to see build status directly on your commits and pull requests. The GitHub Plugin automatically posts these statuses (pending, success, failure) as checks on your PRs, provided your webhook and credentials are configured correctly.

Integrating Docker and Kubernetes

Many teams take this further by having Jenkins build Docker images after tests pass, then push them to a registry, and finally deploy to Kubernetes. A simplified pipeline stage might look like:

stage('Docker Build & Push') {
    steps {
        sh 'docker build -t yourdockerhub/app:latest .'
        sh 'docker push yourdockerhub/app:latest'
    }
}
stage('Deploy to Kubernetes') {
    steps {
        sh 'kubectl apply -f k8s/deployment.yaml'
    }
}

This kind of pipeline turns your GitHub repo into a fully automated deployment source of truth.

Common Real-World Scenarios

Troubleshooting Common Issues

Security Best Practices

Working with GitHub Enterprise and Private Instances

If your organization runs GitHub Enterprise Server rather than the public github.com, the setup is nearly identical, but you’ll need to configure the GitHub Plugin’s endpoint under Manage Jenkins > System > GitHub > GitHub Servers to point at your internal instance URL rather than the default public API endpoint. This matters because Jenkins uses that endpoint for API calls like posting commit statuses, not just for cloning.

Handling Monorepos and Multiple Services from One Repository

A pattern I run into often is a single GitHub repository containing multiple services or packages (a monorepo). In this case, a single Jenkinsfile can conditionally build only the parts that changed:

stage('Detect Changes') {
    steps {
        script {
            env.CHANGED_FILES = sh(script: 'git diff --name-only HEAD~1 HEAD', returnStdout: true).trim()
        }
    }
}
stage('Build Service A') {
    when {
        expression { env.CHANGED_FILES.contains('service-a/') }
    }
    steps {
        dir('service-a') {
            sh 'npm ci && npm test'
        }
    }
}

This avoids rebuilding every service on every commit, which can save significant CI time on larger monorepos.

GitHub Checks API and Advanced Status Reporting

Beyond simple pass/fail commit statuses, the GitHub Checks API (supported through the GitHub Checks Plugin) lets Jenkins post richer, more detailed feedback directly on a pull request — including annotations pointing to specific lines of code where lint or test failures occurred. This is particularly useful for large teams where reviewers want failure context without leaving the PR page.

FAQs

Q: Do I need a public IP to connect Jenkins with GitHub? Not necessarily — you can use tunneling tools like ngrok for testing, though production setups typically use a reachable Jenkins URL or GitHub Enterprise webhooks within a private network.

Q: Can I use Jenkins with private GitHub repositories? Yes, as long as you configure proper credentials (SSH key or personal access token) in Jenkins.

Q: What’s the difference between the GitHub Plugin and the Git Plugin? The Git Plugin handles generic Git operations (clone, checkout), while the GitHub Plugin adds GitHub-specific features like webhook triggers and commit status reporting.

Q: Is Jenkins better than GitHub Actions? Both have their place. Jenkins offers more flexibility and self-hosting control, while GitHub Actions is more tightly integrated and easier to set up for GitHub-only workflows.

Summary

Connecting Jenkins with GitHub transforms your development workflow from manual and reactive to automated and proactive. Once you’ve got webhooks, credentials, and a Jenkinsfile in place, every push can trigger builds, tests, and deployments without you lifting a finger. I’ve seen this setup save countless hours across teams of all sizes, and it scales nicely from a solo developer’s side project to enterprise-grade CI/CD pipelines.

References

Exit mobile version