Load properties from properties file and make them available throughout the job/pipeline - Jenkins declarative syntax

22,765

Solution 1

I figured out a couple of ways to externalize properties in Jenkins pipelines. You can choose your pick based on the main difference.

1) Using groovy code entirely. This code snippet would require you to enable several method signatures in 'In-process script approval' which comes in with script security plugin, and hence this should be done only after due consideration.

properties = null     

def loadProperties() {
    node {
        checkout scm
        properties = new Properties()
        File propertiesFile = new File("${workspace}/pipeline.properties")
        properties.load(propertiesFile.newDataInputStream())
        echo "Immediate one ${properties.repo}"
    }
}

pipeline {
    agent none

    stages {
        stage ('prepare') {
            agent any

            steps {
                script {
                    loadProperties()
                    echo "Later one ${properties.branch}"
                }
            }
        }
        stage('Build') {
            agent { label 'master'  }

            steps {
                // works fine. properties is available everywhere
                echo properties.branch
            }           
        }
    }
}

2) Using pipeline utility steps plugin - Pipeline suite of plugins include this by default and it allows a better way to load properties without requiring to enable security exceptions. I would recommend this method.

properties = null

def loadProperties() {
    node {
        checkout scm
        properties = readProperties file: 'pipeline.properties'
        echo "Immediate one ${properties.repo}"
    }
}

pipeline {
    agent none

    stages {           
        stage ('prepare') {
            agent any

            steps {
                script {
                    loadProperties()
                    echo "Later one ${properties.ansible}"
                }
            }
        }
        stage('Build') {

            agent any

            steps {
                echo properties.branch
            }

        }
    }
}

Solution 2

Thanks for Answer #1. It helped a lot, I used option 2. I faced some problems, and would like to share my solution:

1) I added a "prepare" stage, inside the pipeline section of the declarative pipeline:

stage ('Prepare') {
   steps {
      script {
         properties = readProperties file: 'scripts/jenkins-pipelines/branch-specific.properties'
         echo "Running build ${JOB_NAME} # ${BUILD_NUMBER} on git repo ${properties.GitURL} branch ${properties.nextBranchName}"
       }
     }
   }
}

The format of the properties file is:

nextBranchName=next
stableBranchName=master
[email protected]:foo.git

Please note that there are no quote on the properties.

I used the properties as ${properties.nextBranchName} also on other steps, stages and post. As mentioned on answer 1: there is a need to install "pipeline utility steps" plugin

Solution 3

Using the "pipeline utility steps" plugin, you can define general vars available to all stages. For example, let props.txt as:

version=1.0
fix=alfa

and mix script and declarative Jenkins pipeline as:

def props
def VERSION
def FIX
def RELEASE

node {
   props = readProperties file:'props.txt'
   VERSION = props['version']
   FIX = props['fix']
   RELEASE = VERSION + "_" + FIX
}

pipeline {
   stages {
      stage('Build') {
         echo ${RELEASE}
      }
   }
}
Share:
22,765
ishan
Author by

ishan

Updated on December 04, 2020

Comments

  • ishan
    ishan over 3 years

    My requirement is simple, i just want to externalize some 'values' to make my Jenkinsfile more re usable and for this i need to load the properties from a file which is going to be right next to Jenkinsfile, and make sure that these properties are available anywhere in the pipeline. I am still new to groovy and Jenkins code but never thought such a simple thing would be so difficult. I enabled some methods in script security plugin but the following code (and several variations i tried around it) always pose errors or print null or give me NPE. I have tried multiple combinations and the below code is just one of them.

    properties = null
    
    @NonCPS
    def loadProperties() {
        checkout scm
        File propertiesFile = new File('${workspace}/pipeline.properties')
        propertiesFile.withInputStream {
                properties.load(propertiesFile)
        }
    }
    
    pipeline {
        agent none
    
        stages {
    
            stage ('prepare') {
                agent any
    
                steps {
                    script {
                    loadProperties()
                    echo "${properties['repo']}"
                    }
                }
            }
            stage('Build') {
    
                agent any
    
                steps {
                    sh 'echo ${properties.repo}'
                }
    
            }
        }
    }