Skip to content

Jenkins Shared Libraries: Best Practices

  • 12 min read

Tired of wrestling with repetitive code in your Jenkins pipelines? You’re not alone. Many teams find themselves copying and pasting the same snippets across multiple jobs, leading to a maintenance nightmare. It’s like trying to build a house with a different set of blueprints for each room. But what if you had a central place to store and reuse that code? That’s where Jenkins Shared Libraries come in. They act as a powerhouse for your pipeline code, turning chaos into order, which lets you focus on what truly matters, delivering software.

What Are Jenkins Shared Libraries?

Jenkins Shared Libraries are a way to create reusable pipeline code. Think of them as custom extensions to your Jenkins environment. Instead of writing the same logic over and over again in each pipeline, you can define it once in a library and then call that library from any pipeline that needs it. This cuts down on duplication, makes your code easier to maintain, and promotes consistency across all your projects.

These libraries can hold anything from simple utility functions to complex build processes. They’re like building blocks that you can assemble to fit your unique workflow. This makes your pipelines more streamlined, easier to understand, and simpler to modify. Using a Jenkins Shared Library also means you’re moving towards a more modular approach in your CI/CD.

Why Should You Use Jenkins Shared Libraries?

You might be thinking, “My pipelines work fine without shared libraries. Why bother?” Here’s a look at the benefits:

  • Reduced Code Duplication: This is perhaps the most obvious advantage. You’ll no longer be copying and pasting chunks of code between jobs. This means less time spent on tedious tasks and more time on crafting better pipelines.
  • Simplified Maintenance: When you have a single source of truth for your pipeline logic, making changes becomes far easier. Update the library, and all pipelines that use it receive those changes.
  • Increased Consistency: Ensure that all your projects follow the same rules and standards. This is vital for teams that want to deliver quality and consistency across projects.
  • Enhanced Readability: By moving complex logic into shared libraries, your pipelines become shorter and easier to read. This makes debugging and troubleshooting much simpler.
  • Faster Development: Reuse existing code rather than building things from scratch. This accelerates the development process and allows teams to move quicker.

In essence, shared libraries bring order to the chaos of pipeline management. They improve efficiency, reduce errors, and allow teams to focus more on value delivery. When used right, Jenkins Shared Libraries can shift your whole approach to automation.

Core Concepts of Jenkins Shared Libraries

Before diving into how to make your own shared library, let’s look at some key concepts:

  • Library Structure: Shared libraries follow a certain directory structure. You have a vars directory for global variables and a src directory for classes and other code. It’s like having a specific filing system for all the pieces of your library.
  • Global Variables: In vars, you place files that define global variables which you can call from any pipeline. They often act as entry points into your library. They’re like the main door to your library, easy to find and use.
  • Classes and Functions: These exist in the src directory. Here you place the actual logic and functions you want to reuse in your pipelines. They’re like the tools in your toolbox, ready for action.
  • Library Loading: You need to tell Jenkins where to find your shared library. This is often done through the Jenkins configuration panel. It’s how you plug your toolbox into your Jenkins setup.
  • Version Control: Your library must be kept in version control. This allows you to keep track of changes, revert to earlier versions, and collaborate with other developers. It’s like keeping a journal of your code.

Understanding these concepts is key to creating effective shared libraries. It gives you a framework to build upon and lets you leverage the full power of code reusability.

Setting Up Your First Jenkins Shared Library

Now that we’ve covered the basics, let’s dive into the practical side. Here’s how to set up your first Jenkins shared library:

Step 1: Create a Git Repository

Start by creating a Git repository for your shared library, often on GitHub, GitLab, or Bitbucket. This repository will hold all the files and folders of your library. This is where the backbone of your library will live and breathe.

Step 2: Create the Library Directory Structure

Within the repository, create the following directory structure:

my-shared-library/
├── src/
│   └── com/
│       └── mycompany/
│           └── utils/
│               └── MyUtils.groovy
└── vars/
    └── myGlobalVar.groovy
  • src: This directory contains your Groovy classes. Note that your classes must be under folder names corresponding to the package structure you plan to use. This makes code easy to manage.
  • vars: This directory holds your global variables. Each .groovy file in this folder will define a variable available in your pipeline. This is the place for your custom pipeline functions.

Step 3: Implement Your Code

Within the src directory, add a Groovy class. For example, MyUtils.groovy:

package com.mycompany.utils

class MyUtils {
    static String sayHello(String name) {
        return "Hello, ${name}!"
    }
}

In the vars directory, add your global variable file, like myGlobalVar.groovy:

#!groovy
def call(String name = 'World') {
  com.mycompany.utils.MyUtils.sayHello(name)
}

This call method is what you’ll use from your Jenkinsfile. It acts as a gateway to the core logic of your library.

Step 4: Load the Shared Library in Jenkins

  1. Go to Jenkins.
  2. Go to “Manage Jenkins” > “System Configuration”.
  3. Scroll to the “Global Pipeline Libraries” section.
  4. Click “Add”.
  5. Fill in a name, like my-shared-library.
  6. Select “Modern SCM.”
  7. Select “Git”.
  8. Enter the repository URL (from step 1).
  9. Choose the branch (e.g. main).
  10. Click “Save”.

This step is vital. It tells Jenkins where your code lives and how to access it. Jenkins knows to read your custom toolbox.

Step 5: Use Your Shared Library in a Pipeline

In your Jenkinsfile, load and use the shared library like this:

@Library('my-shared-library@main') _

pipeline {
    agent any
    stages {
        stage('Hello') {
            steps {
                script {
                    echo myGlobalVar()
                    echo myGlobalVar(name: 'Jenkins User')
                }
            }
        }
    }
}

@Library loads your code from Git. You are ready to go.

Best Practices for Jenkins Shared Libraries

Creating a shared library is one thing, making it a good library is another. Here are a few best practices to keep in mind:

Versioning

Always version your library. Use Git tags to mark releases and specify which version to use in your pipeline. This lets you manage changes and roll back if needed.
The library tag allows you to control versions in a pipeline like this:

@Library('[email protected]') _

Using version control for your shared library is also key for audits and understanding the history of your pipeline code changes. Think of this as the documented history of your infrastructure.

Avoid Complex Logic in Global Variables

Use global variables (vars) primarily to call other functions. Keep the logic in your src files. This helps to keep your code more organized and makes it easier to test and debug. It’s like having a well-organized kitchen, with the main chef being the src files and the vars acting like assistants.

Keep Libraries Focused

Each shared library should have a clear purpose. Avoid creating mega-libraries that contain code for everything. Instead, break them down into smaller libraries each with a defined scope. This is like having a set of specialty tools for different projects instead of one enormous and unwieldy toolset.

Document Your Library

Good documentation is crucial. Explain how to use the library, what functions are available, and provide examples. This makes it easier for other people to adopt the library and use it correctly. Treat your library like an open source project, with documentation and clear examples.

Test Your Library

Write unit tests for your library functions. You want to be sure that changes don’t break things. This helps to maintain your library’s quality. This is a vital practice, as a poorly tested library can cause lots of issues across your pipelines.

Use Semantic Versioning

Semantic versioning (major.minor.patch) is a good standard to adopt. It clearly indicates what kind of change you’re pushing. Major version upgrades mean breaking changes. Minor releases mean new additions. Patch means bug fixes. This gives people who are using the libraries a clear signal as to the impact of the update.

Secure Sensitive Data

Be careful with sensitive data, like passwords. Do not store these in the shared library files. Instead, use Jenkins credentials. This keeps your information safe. Treating sensitive data as critical protects your systems.

Code Reviews

Get your code reviewed by other team members. This will catch errors, enhance code quality, and share the knowledge within the team. This collaborative approach means everyone benefits.

Regular Updates

Keep your library up to date. Regularly check for out-of-date code and new needs to make the library as helpful as possible. The tech world evolves quickly and this practice makes your library stay on the cutting edge.

Advanced Techniques

Once you get comfortable with shared libraries, you might want to explore more advanced techniques:

Using Different Branches

Use different Git branches for different development streams. This allows you to test out new code or features in an isolated environment without affecting your production pipelines. Branching is a core Git concept that provides for a high level of code management.

Nested Libraries

If a team needs more specific libraries that relate to larger shared libraries, consider nested libraries. Use different repositories or folders to organize them. This helps to divide code logically and makes complex codebases easier to manage.

Combining With Other Jenkins Features

Integrate shared libraries with other features in Jenkins. For example, use Jenkins pipeline parameters with shared library functions. Or create a custom DSL using a shared library to express complex logic in short, concise and readable steps. These integrations provide better versatility.

Working With Configuration as Code

Define your shared library setup via Configuration as Code plugins. This lets you easily apply consistent settings across your Jenkins environments. This avoids the need to perform the set up through the GUI.

Dynamic Library Loading

Explore dynamic library loading, which allows you to load a library based on a certain condition. For example, load different libraries depending on the project. This provides greater flexibility to adapt to many needs.

Using Templates

Use templates to reuse code snippets within shared libraries. This helps to standardize common patterns and can greatly reduce code duplication. This takes code reusability to another level.

Troubleshooting Common Issues

Even with the best intentions, you might run into problems. Here are some common issues and how to fix them:

  • Library Not Found: Double-check the library name and Git URL. Confirm that the library is configured correctly in Jenkins. Make sure that the library name in the @Library() statement matches the name specified in the Jenkins configuration and the code is located in Git, if not, you will get this error.
  • Class Not Found: Check your package name. Make sure your class files are in the src directory, within the package structure. The package name of a groovy file located in /src/com/mycompany/MyFile.groovy should have the following line: package com.mycompany.
  • Global Variable Not Found: Ensure your global variable file is in the vars directory, and that the name in the Jenkinsfile matches the file’s name (minus the .groovy extension). The global variable file must contain the call method.
  • Incorrect Version: If you get a version related error, check if the specific version of the library exists in your Git repository.
  • Authentication Issues: If you have an authentication error, ensure Jenkins has permission to access the library’s Git repository, this is a very common error with private Git repositories.
  • Compilation Errors: Compile errors mean you need to review the Groovy code for syntax errors, make sure that your code is valid before committing the code.
  • Performance Issues: If your shared libraries slow down the pipeline, optimize your code and consider using caching if needed.

Troubleshooting can be tricky at times. Check the logs, verify configuration, and ensure code is correct.

Real-World Examples

Let’s look at a few real-world examples:

  • Utility Functions: Think functions that help you deploy an app. These tasks can be defined as steps in a shared library. Such functions include deployment to a Kubernetes cluster, or deployment of serverless functions.
  • Environment Set-up: Prepare your environment. Create variables to control the different steps in your pipeline.
  • Notification Services: Create functions that send notifications to Slack, email, or other communication tools.
  • Code Analysis: Create a shared function that triggers static code analysis or vulnerability scanning.
  • Build and Deployment: Implement a shared library that handles the build and deployment steps for all of your applications.

These use cases demonstrate how diverse the use cases of shared libraries can be, providing a better starting point for any team’s requirements.

The Right Step for a Future-Proof Setup

Jenkins Shared Libraries are more than just a nice-to-have; they’re a core element for any team that wants to improve their pipeline automation. From cutting down code duplication and making your code easier to maintain, to making sure your workflow is consistent, shared libraries bring a lot of value. By adhering to good practices and constantly evolving your use of libraries, you create a more adaptable, reliable, and efficient delivery system. Whether you are building software for enterprise or building a pet project, shared libraries are the best move to make when it comes to managing your pipeline code.