Continuous Integration with Jenkins: Automating your build and deployment pipeline

Use Jenkins to streamline your development process and ensure code quality through automated testing and deployment.

Background

If you’ve worked on software projects, you know how challenging it can be to maintain code quality, especially as the team grows and the codebase expands. Manual testing and deployment processes are time-consuming, error-prone, and can lead to inconsistencies between environments.

This is where Continuous Integration (CI) comes in, and Jenkins is one of the most popular tools for implementing CI. Jenkins is an open-source automation server that helps automate the parts of software development related to building, testing, and deploying, facilitating continuous integration and continuous delivery.

The competition

If you’re considering Jenkins for your CI/CD pipeline, you might ask: “Why not use other CI tools like GitLab CI, CircleCI, or Travis CI?”. A valid question. These tools are also popular and offer their own advantages. However, Jenkins offers some unique benefits:

  1. Flexibility: Jenkins is highly customizable with a vast ecosystem of plugins, allowing you to tailor it to your specific needs.
  2. Self-Hosted: Unlike many cloud-based solutions, Jenkins can be self-hosted, giving you full control over your build environment and data.
  3. Language and Platform Agnostic: Jenkins can be used with virtually any programming language and platform.
  4. Active Community: Jenkins has a large, active community, which means plenty of resources, plugins, and support.
  5. Free and Open Source: Jenkins is completely free and open-source, which can be a significant advantage for budget-conscious teams or those who want to contribute to its development.

Getting Started with Jenkins

Now that we’ve covered the background and advantages of Jenkins, let’s dive into setting up a basic CI pipeline. We’ll create a simple pipeline for a Python project that runs tests and performs a mock deployment.

Setting Up

First, you need to install Jenkins. You can find installation instructions for your operating system in the official Jenkins documentation.

Once Jenkins is installed and running, you’ll need to install some additional plugins. Go to “Manage Jenkins” > “Manage Plugins” and install the following plugins:

  • Git plugin (for source control management)
  • Pipeline plugin (for defining pipelines as code)
  • Python plugin (for Python support)

Creating Our Project

For this example, let’s assume we have a simple Python project with a test suite. Here’s a basic structure:

my_project/
├── src/
│   └── calculator.py
├── tests/
│   └── test_calculator.py
└── Jenkinsfile

Our calculator.py might look like this:

def add(a, b):
    return a + b

def subtract(a, b):
    return a - b

And our test_calculator.py:

import unittest
from src.calculator import add, subtract

class TestCalculator(unittest.TestCase):
    def test_add(self):
        self.assertEqual(add(2, 3), 5)

    def test_subtract(self):
        self.assertEqual(subtract(5, 3), 2)

if __name__ == '__main__':
    unittest.main()

Defining Our Pipeline

Now, let’s create our Jenkinsfile, which defines our CI pipeline:

pipeline {
    agent any

    stages {
        stage('Checkout') {
            steps {
                checkout scm
            }
        }
        stage('Setup') {
            steps {
                sh 'python -m venv venv'
                sh '. venv/bin/activate'
                sh 'pip install -r requirements.txt'
            }
        }
        stage('Test') {
            steps {
                sh '. venv/bin/activate && python -m unittest discover tests'
            }
        }
        stage('Deploy') {
            steps {
                sh 'echo "Deploying to production"'
            }
        }
    }
    post {
        always {
            sh 'deactivate'
            cleanWs()
        }
    }
}

This pipeline does the following:

  1. Checks out the code from version control
  2. Sets up a Python virtual environment and installs dependencies
  3. Runs the unit tests
  4. Performs a mock deployment (in real scenarios, this would be where you deploy your application)
  5. Cleans up the workspace after the pipeline completes

Setting Up the Pipeline in Jenkins

  1. In Jenkins, click “New Item”
  2. Enter a name for your project and select “Pipeline”
  3. In the pipeline configuration, select “Pipeline script from SCM” under the Pipeline section
  4. Choose Git as the SCM, and enter your repository URL
  5. Specify the branch to build (e.g., */main)
  6. Save the configuration

Jenkins will now automatically run this pipeline whenever changes are pushed to your repository.

Advanced Features

While our example demonstrates a basic CI pipeline, Jenkins offers many more advanced features for building complex, robust pipelines. Here are a few to consider:

Parameterized Builds

Jenkins allows you to create parameterized builds, which can be useful for creating flexible, reusable pipelines:

pipeline {
    agent any
    parameters {
        string(name: 'DEPLOY_ENV', defaultValue: 'staging', description: 'Deployment environment')
    }
    stages {
        stage('Deploy') {
            steps {
                sh "echo Deploying to ${params.DEPLOY_ENV}"
            }
        }
    }
}

This allows you to specify the deployment environment when triggering the build.

Parallel Execution

For faster builds, you can run stages in parallel:

pipeline {
    agent any
    stages {
        stage('Tests') {
            parallel {
                stage('Unit Tests') {
                    steps {
                        sh 'python -m unittest discover tests/unit'
                    }
                }
                stage('Integration Tests') {
                    steps {
                        sh 'python -m unittest discover tests/integration'
                    }
                }
            }
        }
    }
}

This runs unit tests and integration tests simultaneously, potentially reducing build time.

Notifications

Jenkins can send notifications about build status via email, Slack, or other channels:

post {
    success {
        slackSend channel: '#engineering', color: 'good', message: "Build succeeded: ${env.JOB_NAME} ${env.BUILD_NUMBER}"
    }
    failure {
        slackSend channel: '#engineering', color: 'danger', message: "Build failed: ${env.JOB_NAME} ${env.BUILD_NUMBER}"
    }
}

This sends a Slack notification after each build, indicating whether it succeeded or failed.

Conclusion

We’ve only scratched the surface of what’s possible with Jenkins. Its flexibility and extensive plugin ecosystem make it a powerful tool for automating your build and deployment processes, improving code quality, and increasing development velocity.

While Jenkins offers many benefits, it also requires some effort to set up and maintain, especially for complex pipelines. It may be overkill for very small projects, and cloud-based solutions might be simpler for some teams.

As with any tool, it’s important to evaluate whether Jenkins is the right fit for your specific needs. For teams that need a highly customizable, self-hosted CI solution, Jenkins can be an excellent choice.

If you’re interested in learning more about Jenkins, I highly recommend the official Jenkins documentation, which includes tutorials and best practices. The Jenkins community is also a great resource for support and learning from others’ experiences.

Happy automating!

関連記事

カテゴリー:

ブログ

情シス求人

  1. チームメンバーで作字やってみた#1

ページ上部へ戻る