Jenkins Shared Libraries
Of course, when working with a multitude of projects creating such Jenkinsfiles might easily become repetitive and thus error-prone. Shared Libraries to the rescue.
Shared Libraries
- provide reusable functions
- that may be utilized in multiple projects
- and help with DRY (Don’t Repeat Yourself)
- code changes need to be done at one spot only, if something were to change
- => Standardization, Consistency
- for example: Maven Build, Docker Build, …
- but:
- these libraries will need to remain usable for all projects consuming them!
- these libraries will need to be trusted as they run without any “sandbox” restrictions!
Exercise - utilize a remote Shared Library
Just as experienced before create a new Pipeline in Jenkins, again with a unique identifier such as your user-login studentX with the X representing your individual number.
For example a good pipeline name would be student1_sharedLibs.
Lets start with following pipeline definition:
def myLib = library(
identifier: 'myLib@main', retriever: modernSCM(
[
$class: 'GitSCMSource',
remote: 'https://github.com/Exzelsios/jenkins-shared-libs-test',
credentialsId: 'none'
]
)
)
pipeline {
agent any
stages {
stage('Hello') {
steps {
helloWorld 'test'
}
}
}
}As we can see this definition is referencing a GitHub repository as a library, and it is making use of a helloWorld step including providing a parameter test.
Feel free to explore that repository a bit, for instance check its corresponding vars/helloWorld.groovy
as shown below:
def call(String name = 'human') {
// Any valid steps can be called from this code, just like in other
// Scripted Pipeline
echo "Hello, ${name}."
}Now execute your newly created pipeline and you will see in the run’s Console Output that this call resulted in log lines similar to the following:
[Pipeline] Start of Pipeline
[Pipeline] library
Loading library myLib@main
Attempting to resolve main from remote references...
[...]
Waiting for next available executor
Agent default-8ncvf is provisioned from template default
[...]
Running on default-8ncvf in /home/jenkins/agent/workspace/librarytest
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Hello)
[Pipeline] echo
Hello, test.
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESSSo, in other words, by utilizing that remote Shared Library we have gained additional building blocks, and we were even able to pass a parameter to it.
Exercise - attempt to build Docker images via Shared Library
Well, for such a simple Hello we wouldn’t need a Shared Library.
But the more complex our individual tasks get the more it makes sense to consolidate certain repeating structures in a standardized library.
For instance, consider what the following could do:
def myLib = library(
identifier: 'myLib@main', retriever: modernSCM(
[
$class: 'GitSCMSource',
remote: 'https://github.com/Exzelsios/jenkins-shared-libs-test',
credentialsId: 'none'
]
)
)
node {
compileAndDockerimageCustomstep 'todobackend', 'testtag'
compileAndDockerimageCustomstep 'todoui', 'testtag'
}Yes, you will need to check the vars/compileAndDockerimageCustomstep.groovy file for details. Now update your Pipeline from this and build it. Oh, it will fail, but why?
And of course, the even bigger issue remains: we include code from some other repository and execute it, but do we know what exactly this repository contains or what changes might have been applied recently …?
Summary
Jenkins Shared Libraries allow us to consolidate repeating tasks in a single spot. However, as usual when consolidating as such, we need to ensure that this new building block remains usable for all projects, i.e. it is providing enough flexibility.
Some best practices in this context:
- when using a Shared Library then consolidate on a single one
- this will be a software project on its own and needs to be maintained carefully (including documentation!)
- the library should only contain common and non-trivial tasks but nothing else so as to remain lean (i.e. fast)
But these considerations are not unique to Jenkins Shared Libraries but apply to Shared Libraries in general, don’t they …?