If you find yourself copy-pasting code snippets and pipeline sections in different
Jenkins pipelines,
then it is time to ensure that the code is written correctly and properly. You usually have multiple software
projects with a similar CI/CD setup. What I have often observed is duplicated code all over the Jenkins pipelines,
even if all project structures are almost the same. In order to avoid duplicating the same code snippets in all
Jenkins pipelines and make the pipeline code clean, I use a library that provides steps, such as
awsCloudPackerBuildImage. This step has almost 200 lines of code, but using it makes the Jenkins pipeline
definition much easier to maintain and understand.
A Jenkins library is a simple git repository with certain file/folder structure.
1
2
3
4
5
6
7
8
9
10
11
12
(root)
+- src # Groovy source files
| +- org
| +- foo
| +- Bar.groovy # for org.foo.Bar class
+- vars
| +- foo.groovy # for global 'foo' variable
| +- foo.txt # help for 'foo' variable
+- resources # resource files (external libraries only)
| +- org
| +- foo
| +- bar.json # static helper data for org.foo.Bar
I usually write the core logic of the library in (different) classes and store them in src folder.
For example the class T12sTeamRotor has the following content:
The steps for Jenkins are written in the var folder.
For example, the code for the t12sRotationRun step is stored in a file called t12sRotationRun.groovy.
This file contains a script that performs the following actions:
@Library('t12s-team-rotor-jenkins-library')_// do not forget the underscore "_"
pipeline{stages{stage('Stand-Up Presenter'){steps{script{runRotation('9EF37F04-0301-4D14-B69C-672DF6C9BAE4')}}}stage('Sprint Review Presenter'){steps{script{runRotation('49A73189-2BB2-4DB5-9BBE-CA04231DE76E')}}}}}privatevoidrunRotation(finalStringrotationId){// the following step "t12sRotationRun" is defined in the t12s-team-rotor-jenkins-library
finaldefresult=t12sRotationRun(['teamId':'your-team-id','teamSecret':'your-team-secret','rotationId':rotationId])finaldefresultAsString=result.toString()echoresultAsStringfinaldefchosenName=(result.memberOrder[0]asString).capitalize()finaldefrotationName=(result.rotationNameasString).capitalize()finaldefmessage="""
${rotationName} is :magic_wand: *${chosenName}* :party:.
Decision was made at `${result.createdAt}`.
_Fallback_: If *${chosenName}* can not do it, the next persons in line would be
*`${result.memberOrder.subList(1, result.memberOrder.size())}`*.
The order of the fallback persons could _change_ on next rotation run.
""".stripIndent()currentBuild.description="${rotationName}: <b>${chosenName}</b>"slackSend(channel:'your-slack-channel-id_name',color:'#00FF00',message:message)}