{"id":1288,"date":"2019-09-04T19:48:00","date_gmt":"2019-09-04T14:18:00","guid":{"rendered":"http:\/\/blogs.opstree.com\/?p=1288"},"modified":"2020-02-17T19:58:23","modified_gmt":"2020-02-17T14:28:23","slug":"jenkins-pipeline-global-shared-libraries","status":"publish","type":"post","link":"https:\/\/opstree.com\/blog\/2019\/09\/04\/jenkins-pipeline-global-shared-libraries\/","title":{"rendered":"Jenkins Pipeline Global Shared Libraries"},"content":{"rendered":"\n<figure class=\"wp-block-image\"><a href=\"https:\/\/opstree.com\/blog\/\/wp-content\/uploads\/2019\/09\/41e8e-jenkins-shared-lib.png\"><img decoding=\"async\" src=\"https:\/\/opstree.com\/blog\/\/wp-content\/uploads\/2019\/09\/41e8e-jenkins-shared-lib.png\" alt=\"\" \/><\/a><\/figure>\n\n\n\n<p>When we say CI\/CD as code, it should have modularity and reusability which results in Reducing integration problems and allowing you to deliver software more rapidly.<\/p>\n\n\n\n<p>Jenkins\u00a0Shared library is the concept of having a common pipeline code in the version control system that can be used by any number of pipelines just by referencing it. In fact, multiple teams can use the same library for their pipelines.<br><br>Our thought is putting all pipeline functions in vars is much more practical approach, while there is no other good way to do inheritance, we wanted to use Jenkins Pipelines the right way but it has turned out to be far more practical\u00a0to use vars for global functions.<\/p>\n\n\n\n<p>Practical Strategy<br>As we know&nbsp;Jenkins Pipeline&#8217;s shared library support allows us to define and develop a set of shared pipeline helpers in this repository and provides a straightforward way of using those functions in a Jenkinsfile.This simple example will just illustrate how you can provide input to a pipeline with a simple YAML file so you can centralize all of your pipelines into one library.&nbsp;The Jenkins shared library example:And the example app that uses it:<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"BestPracticesforJenkinsPipelineGlobalSharedLibraries-DirectoryStructure\">Directory Structure<\/h2>\n\n\n\n<p>You would have the following folder structure in a git repo:<br><\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">\u2514\u2500\u2500 vars\n    \u251c\u2500\u2500 opstreePipeline.groovy\n    \u251c\u2500\u2500 opstreeStatefulPipeline.groovy\n    \u251c\u2500\u2500 opstreeStubsPipeline.groovy\n    \u2514\u2500\u2500 pipelineConfig.groovy\n<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"BestPracticesforJenkinsPipelineGlobalSharedLibraries-SettingupLibraryinJenkinsConsole.\">Setting up Library in Jenkins Console.<\/h2>\n\n\n\n<p>This repo would be configured in under&nbsp;<em>Manage Jenkins<\/em>&nbsp;&gt;&nbsp;<em>Configure System<\/em>&nbsp;in the&nbsp;<em>Global Pipeline Libraries<\/em>&nbsp;section. In that section Jenkins requires you give this library a&nbsp;Name. Example opstree-library<\/p>\n\n\n\n<p><\/p>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/opstree.com\/blog\/\/wp-content\/uploads\/2019\/09\/3175d-screen2bshot2b2019-08-292bat2b3.14.282bpm.png\"><img decoding=\"async\" src=\"https:\/\/opstree.com\/blog\/\/wp-content\/uploads\/2019\/09\/3175d-screen2bshot2b2019-08-292bat2b3.14.282bpm.png?w=300\" alt=\"\" \/><\/a><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"BestPracticesforJenkinsPipelineGlobalSharedLibraries-Pipeline.yaml\">Pipeline.yaml<\/h2>\n\n\n\n<p>Let\u2019s assume that project repository would have a&nbsp;pipeline.yaml&nbsp;file in the project root that would provide input to the pipeline:<strong>Pipeline.yaml<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">ENVIRONMENT_NAME: test\nSERVICE_NAME: opstree-service\nDB_PORT: 3079\nREDIS_PORT: 6079<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"BestPracticesforJenkinsPipelineGlobalSharedLibraries-Jenkinsfile\">Jenkinsfile<\/h2>\n\n\n\n<p>Then, to utilize the shared pipeline library, the&nbsp;Jenkinsfile&nbsp;in the root of the project repo would look like:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">@Library ('opstree-library@master') _\nopstreePipeline()<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"BestPracticesforJenkinsPipelineGlobalSharedLibraries-PipelineCfg.groovy\">PipelineConfig.groovy<\/h2>\n\n\n\n<p>So how does it all work? First, the following function is called to get all of the configuration data from the&nbsp;pipeline.yaml&nbsp;file:<br><\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">def call() {\n  Map pipelineConfig = readYaml(file: \"${WORKSPACE}\/pipeline.yaml\")\n  return pipelineConfig\n}<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"BestPracticesforJenkinsPipelineGlobalSharedLibraries-noonPipeline.groovy\">opstreePipeline.groovy<\/h2>\n\n\n\n<p>You can see the call to this function in opstreePipeline(), which is called by the&nbsp;Jenkinsfile.<br><\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">def call() {\n    node('Slave1') {\n\n        stage('Checkout') {\n            checkout scm\n        }\n\n         def p = pipelineConfig()\n\n        stage('Prerequistes'){\n            serviceName = sh (\n                    script: \"echo ${p.SERVICE_NAME}|cut -d '-' -f 1\",\n                    returnStdout: true\n                ).trim()\n        }\n\n        stage('Build &amp; Test') {\n                sh \"mvn --version\"\n                sh \"mvn -Ddb_port=${p.DB_PORT} -Dredis_port=${p.REDIS_PORT} clean install\"\n        }\n\n        stage ('Push Docker Image') {\n            docker.withRegistry('https:\/\/registry-opstree.com', 'dockerhub') {\n                sh \"docker build -t opstree\/${p.SERVICE_NAME}:${BUILD_NUMBER} .\"\n                sh \"docker push opstree\/${p.SERVICE_NAME}:${BUILD_NUMBER}\"\n            }\n        }\n\n        stage ('Deploy') {\n            echo \"We are going to deploy ${p.SERVICE_NAME}\"\n            sh \"kubectl set image deployment\/${p.SERVICE_NAME} ${p.SERVICE_NAME}=opstree\/${p.SERVICE_NAME}:${BUILD_NUMBER} \"\n            sh \"kubectl rollout status deployment\/${p.SERVICE_NAME} -n ${p.ENVIRONMENT_NAME} \"\n\n    }\n}<\/pre>\n\n\n\n<p>You can see the logic easily here. The pipeline is checking if the developer wants to&nbsp;deploy on which environment what db_port needs to be there.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"BestPracticesforJenkinsPipelineGlobalSharedLibraries-Benifits\">Benefits<\/h2>\n\n\n\n<p>The benefits of this approach are many, some of them are as mentioned below:<\/p>\n\n\n\n<ul><li>How to write groovy code is now none of the developer&#8217;s perspective.<\/li><li>Structure of the Pipeline.yaml is really flexible, where entire data structures can be passed as input to the pipeline.<\/li><li>Code redundancy saved to a large extent.<\/li><\/ul>\n\n\n\n<p>&nbsp;Jenkinsfiles&nbsp;could actually just look more commonly, like this:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">@Library ('opstree-library@master') _\nopstreePipeline()<\/pre>\n\n\n\n<p>and opstreePipeline()&nbsp;would just read the the project type from&nbsp;pipeline.yaml&nbsp;and dynamically run the exact function, like opstreeStatefulPipeline(), opstreeStubsPipeline.groovy() . since pipeline are not exactly groovy, this isn\u2019t possible.&nbsp;So one of the drawback is that each project would have to have a different-looking&nbsp;Jenkinsfile. The solution is in progress!So, what do you think?<\/p>\n\n\n\n<p>Reference links:&nbsp;<br>Image: Google image search (jenkins.io)\n\n<\/p>\n","protected":false},"excerpt":{"rendered":"<p>When we say CI\/CD as code, it should have modularity and reusability which results in Reducing integration problems and allowing you to deliver software more rapidly. Jenkins\u00a0Shared library is the concept of having a common pipeline code in the version control system that can be used by any number of pipelines just by referencing it. &hellip; <a href=\"https:\/\/opstree.com\/blog\/2019\/09\/04\/jenkins-pipeline-global-shared-libraries\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Jenkins Pipeline Global Shared Libraries&#8221;<\/span><\/a><\/p>\n","protected":false},"author":159458069,"featured_media":29900,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_coblocks_attr":"","_coblocks_dimensions":"","_coblocks_responsive_height":"","_coblocks_accordion_ie_support":"","jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false},"version":2}},"categories":[28070474,351789,1],"tags":[2185,27998418,676319247,768739299,434439981,2011560],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/opstree.com\/blog\/wp-content\/uploads\/2025\/11\/DevSecOps-1.jpg","jetpack_likes_enabled":true,"jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/pfDBOm-kM","jetpack-related-posts":[],"_links":{"self":[{"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/posts\/1288"}],"collection":[{"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/users\/159458069"}],"replies":[{"embeddable":true,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/comments?post=1288"}],"version-history":[{"count":8,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/posts\/1288\/revisions"}],"predecessor-version":[{"id":2302,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/posts\/1288\/revisions\/2302"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/media\/29900"}],"wp:attachment":[{"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/media?parent=1288"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/categories?post=1288"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/tags?post=1288"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}