Automating Continuous Integration (CI) with Jenkins: A Step-by-Step Guide

Automate your code builds and testing with Jenkins CI. Set up pipelines, connect to GitHub, and bring automation and efficiency to your DevOps process.

Integration

Welcome back to the DevOps Pipeline series! Now that you’ve set up Source Code Management (SCM) with Git and GitHub (if not, make sure to check out the first post), it’s time to take the next step: automating your workflow with Continuous Integration (CI) using Jenkins.

In this guide, you’ll learn how to:

  • Set up Jenkins to build your code automatically.
  • Create Jenkins pipelines for CI.
  • Integrate Jenkins with your GitHub repository for smooth automation.

Let’s get started with CI to bring your development process to the next level of efficiency!

Jenkins is a highly customizable CI tool that’s widely used in DevOps due to its:

  • Flexibility: Able to automate virtually any part of your development process.
  • Extensibility: Over 1,700 plugins are available to connect to a range of tools for building, testing, and deploying your code.
  • Ease of Use: Intuitive UI and scripted pipelines allow both beginners and advanced users to set up CI/CD workflows.

In a typical CI workflow with Jenkins, code is automatically built and tested after every commit to a Git repository, ensuring quick feedback and fewer defects.

Fun Fact: Jenkins originally started as “Hudson” and was rebranded in 2011.

2.1 Installing Jenkins on Different Platforms

Option 1: Installing Jenkins with Docker

Docker simplifies the Jenkins installation process and allows easy management of the environment.

1. Pull the Jenkins Image from Docker Hub:

docker pull jenkins/jenkins:lts

This command pulls the latest long-term support (LTS) Jenkins image.

2. Run Jenkins Container:

docker run -d -p 8080:8080 -p 50000:50000 -v jenkins_home:/var/jenkins_home jenkins/jenkins:lts
  • -d: Runs the container in detached mode.
  • -p 8080:8080: Maps Jenkins UI port.
  • -p 50000:50000: Maps Jenkins slave communication port.
  • -v jenkins_home:/var/jenkins_home: Creates a volume to persist Jenkins data.

3. Access Jenkins: Open your browser and go to http://localhost:8080.

Option 2: Installing Jenkins on Ubuntu/Debian

If you prefer a traditional setup:

1. Add the Jenkins Repository Key and Source:

curl -fsSL https://pkg.jenkins.io/debian/jenkins.io.key | sudo tee \
  /usr/share/keyrings/jenkins-archive-keyring.asc > /dev/null
echo deb [signed-by=/usr/share/keyrings/jenkins-archive-keyring.asc] \
  https://pkg.jenkins.io/debian binary/ | sudo tee \
  /etc/apt/sources.list.d/jenkins.list > /dev/null

2. Install Jenkins and Its Dependencies

sudo apt update
sudo apt install jenkins -y

3. Start Jenkins and Enable It to Start on Boot:

sudo systemctl start jenkins
sudo systemctl enable jenkins

4. Access Jenkins: Open your browser and go to http://localhost:8080.

2.2 Initial Setup and Configuration

After accessing Jenkins in your browser, follow these steps:

1. Unlock Jenkins: You will see a screen asking for an initial admin password. Find it with

sudo cat /var/lib/jenkins/secrets/initialAdminPassword

2. Install Suggested Plugins: Select Install Suggested Plugins to set up a basic environment quickly.

3. Create an Admin User: Fill in the initial admin account details.

4. Set Up Jenkins URL: Confirm the Jenkins URL (default is http://localhost:8080).

3.1 Freestyle vs. Pipeline Projects

  • Freestyle Projects: Easier for beginners; uses a simple UI to set up builds, but less flexible.
  • Pipeline Projects: Define your build and deployment stages as code in a Jenkinsfile. This approach is more powerful and version-controlled.

Pro Tip: Choose Pipeline Projects for complex workflows and when you need flexibility or CI/CD as code.

3.2 Creating a Jenkins Pipeline Project

  1. Create a New Item in Jenkins:
    • Go to the Jenkins Dashboard and click on New Item.
    • Enter a name for your project, select Pipeline, and click OK.
  2. Pipeline Configuration:
    • Under the Pipeline section, choose Pipeline script from SCM to integrate with Git.
    • SCM: Select Git and enter the repository URL.
    • Script Path: Specify the location of the Jenkinsfile (default is Jenkinsfile in the repo root).

3.3 Understanding the Jenkinsfile

The Jenkinsfile is a text file where you define your CI/CD process in Groovy-based syntax. Below is a simple example of a Node.js application:

pipeline {
    agent any

    stages {
        stage('Clone Repository') {
            steps {
                // Clone the repository
                git 'https://github.com/username/my-devops-project.git'
            }
        }
        stage('Build') {
            steps {
                // Install dependencies
                sh 'npm install'
            }
        }
        stage('Test') {
            steps {
                // Run tests
                sh 'npm test'
            }
        }
    }
    post {
        always {
            // Save artifacts and test results
            archiveArtifacts artifacts: '**/target/*.jar', allowEmptyArchive: true
            junit '**/target/test-*.xml'
        }
    }
}

Breaking Down the Jenkinsfile

  • pipeline: Defines the entire process.
  • agent any: Specifies any available Jenkins agent (node).
  • stages: Group the different phases of your pipeline.
  • steps: Contain the actions to perform, like shell commands (sh).

4.1 Setting Up GitHub Webhooks

To trigger Jenkins builds on code changes:

  1. Go to your GitHub repository settings > Webhooks.
  2. Add a Webhook:
    • Payload URL: Enter http://<your-jenkins-url>/github-webhook/.
    • Content type: Set to application/json.
    • Select events: Choose Just the push event.

Security Tip: Use a secret token for your webhook to verify the payload from GitHub.

4.2 Configuring Build Triggers in Jenkins

  1. In your Jenkins project configuration, navigate to Build Triggers.
  2. Enable GitHub hook trigger for GITScm polling.

This configuration ensures that any code push to your GitHub repo triggers an automatic Jenkins build.

5.1 Adding Build Steps to the Pipeline

Add a Build stage to your Jenkinsfile to compile or build your application:

stage('Build') {
    steps {
        sh 'npm install'
    }
}

This command installs your project dependencies.

5.2 Running Automated Tests

Include a Test stage to run your unit tests:

stage('Test') {
    steps {
        sh 'npm test'
    }
}

Pro Tip: Use test coverage tools like Istanbul for JavaScript or JUnit for Java to ensure your tests cover all code paths.

5.3 Handling Build Failures and Notifications

To handle failures effectively, configure Jenkins to send build notifications:

  • Use plugins like Email Extension or Slack Notification.
  • Example Slack notification setup in post:
post {
    failure {
        slackSend (color: '#FF0000', message: "Build Failed: ${env.JOB_NAME} - ${env.BUILD_NUMBER}")
    }
}

6.1 Parallel Builds

Speed up your pipeline by running multiple stages concurrently:

stage('Testing') {
    parallel {
        stage('Unit Tests') {
            steps {
                sh 'npm run test:unit'
            }
        }
        stage('Integration Tests') {
            steps {
                sh 'npm run test:integration'
            }
        }
    }
}

This splits testing into Unit Tests and Integration Tests, running them in parallel.

6.2 Archiving Build Artifacts

Store build outputs for later use (e.g., .jar, .war files):

stage('Archive Artifacts') {
    steps {
        archiveArtifacts artifacts: '**/build/*.jar'
    }
}
  • Leverage Jenkins Plugins: Use plugins for SonarQube (code quality), Blue Ocean (UI improvements), and Docker.
  • Use Declarative Pipelines: They are more readable and easier to manage than scripted pipelines.
  • Keep Pipelines DRY (Don’t Repeat Yourself): Use shared libraries to reuse code across multiple Jenkinsfiles.

By integrating Jenkins into your DevOps pipeline, you’ve automated your Continuous Integration (CI), enhancing your code validation process and accelerating your development workflow. From installing Jenkins to creating pipelines and connecting them with GitHub, you’ve taken a crucial step toward a fully automated DevOps lifecycle.

Next Up: The next stage of your journey is all about improving code reliability through automated testing. We’ll cover how to add unit, integration, and end-to-end tests to your pipeline and ensure your code is always ready for deployment.

Let’s Keep the CI Conversation Going!

What challenges did you face while setting up Jenkins, or what plugins do you recommend for CI automation? Share your experience and insights below! And if you enjoyed this post, consider sharing it with your team and community! 🚀

Read “Implementing Automated Testing in Your DevOps Pipeline” →


Discover more from Abdelrahman Algazzar

Subscribe to get the latest posts sent to your email.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top