Advanced Jenkins

Shared Libraries in Jenkins

WhatWhyCreate LibraryResource

Library Resources let you bundle non-Groovy static assets—such as shell scripts, YAML files, or configuration templates—inside your shared library’s resources directory. By using the libraryResource step in Jenkins pipelines, you can load these files at runtime, write them to the workspace, and execute or parse them as needed.

In this guide, we’ll replace multiple hard-coded Trivy scan invocations with a single parameterized shell script (trivy.sh) stored under resources/scripts. You’ll learn how to load it dynamically from your shared library, keeping your pipeline code DRY and maintainable.


1. The Hardcoded Approach

Here’s a typical vars/TrivyScan.groovy with duplicated logic for different severities:

// vars/TrivyScan.groovy
def vulnerability(String imageName) {
    sh """
    trivy image ${imageName} \
        --severity LOW,MEDIUM,HIGH \
        --exit-code 0 \
        --quiet \
        --format json -o trivy-image-MEDIUM-results.json

    trivy image ${imageName} \
        --severity CRITICAL \
        --exit-code 1 \
        --quiet \
        --format json -o trivy-image-CRITICAL-results.json
    """
}

def reportsConverter() {
    sh '''
    trivy convert \
        --format template --template "@/usr/local/share/trivy/templates/html.tpl"
    '''
}

Each variation (severity, exit code, output) requires its own method or string interpolation—leading to code duplication and maintenance headaches.


2. Extracting a Parameterized Shell Script

Instead of embedding multiple commands in Groovy, create a flexible Bash script that accepts arguments:

File Structure

PathDescription
resources/scripts/trivy.shParameterized Trivy scan script
vars/loadScript.groovyGeneric loader for any script in resources
vars/TrivyScanScript.groovyEntry point for vulnerability scans

resources/scripts/trivy.sh

#!/bin/bash
#
# Usage:
#   trivy.sh <imageName> <severity> <exitCode>
#

echo "imageName  = $1"
echo "severity   = $2"
echo "exitCode   = $3"

trivy image "$1" \
  --severity "$2" \
  --exit-code "$3" \
  --quiet \
  --format json \
  -o "trivy-image-$2-results.json"

Warning

Ensure you commit trivy.sh with executable permissions (chmod +x trivy.sh). Otherwise, Jenkins won’t be able to run it.


3. Creating a Generic Loader: loadScript.groovy

Place the following in vars/loadScript.groovy. This step reads any file from resources/scripts and writes it to the workspace:

// vars/loadScript.groovy
def call(Map config = [:]) {
    // config.name: filename under resources/scripts (e.g. "trivy.sh")
    def scriptData = libraryResource "scripts/${config.name}"
    writeFile file: config.name, text: scriptData
    sh "chmod +x ./${config.name}"
}
  • libraryResource: Reads the script content as a string.
  • writeFile: Persists it to the workspace.
  • chmod +x: Makes it executable.

For more details, see Jenkins libraryResource documentation.


4. Wiring It Together: TrivyScanScript.groovy

Use your generic loader and invoke the script with parameters:

// vars/TrivyScanScript.groovy
def vulnerability(Map config = [:]) {
    // Load trivy.sh from resources/scripts
    loadScript(name: 'trivy.sh')

    // Execute the script with user-supplied arguments
    sh "./trivy.sh ${config.imageName} ${config.severity} ${config.exitCode}"
}
  • config.imageName, config.severity, config.exitCode are passed from the Jenkinsfile.
  • Omitting any required key triggers a clear Groovy map-handling error.

Note

You can extend this pattern to other scripts or configuration files without changing your library code.


5. Invoking from a Jenkinsfile

Here’s how to call your new step in a declarative pipeline:

@Library('shared-libraries') _
pipeline {
    agent any

    stages {
        stage('Vulnerability Scan') {
            steps {
                TrivyScanScript.vulnerability(
                    imageName: 'nginx:latest',
                    severity: 'HIGH',
                    exitCode: 1
                )
            }
        }
    }
}

6. Summary

  1. Extract repeated shell logic into resources/scripts/trivy.sh.
  2. Load it via a generic loadScript step using libraryResource.
  3. Invoke it parametrically in your Groovy entrypoint (TrivyScanScript.groovy).
  4. Customize severity levels, exit codes, and image names without editing library code.

By following this pattern, your shared library remains DRY, maintainable, and flexible for future scan configurations.


Watch Video

Watch video content

Previous
Load TrivyScan Library in Jenkins Pipeline