Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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}'
            }

        }
    }
}
like image 441
ishan Avatar asked May 03 '17 08:05

ishan


People also ask

Which syntax does the declarative pipeline follow?

The basic statements and expressions which are valid in Declarative Pipeline follow the same rules as Groovy's syntax with the following exceptions: The top-level of the Pipeline must be a block, specifically: pipeline { } . No semicolons as statement separators. Each statement has to be on its own line.

What is declarative pipeline syntax?

Declarative Pipeline is a relatively recent addition to Jenkins Pipeline which presents a more simplified and opinionated syntax on top of the Pipeline sub-systems. All valid Declarative Pipelines must be enclosed within a pipeline block, for example: pipeline { /* insert Declarative Pipeline here */ }


3 Answers

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
            }

        }
    }
}
like image 117
ishan Avatar answered Oct 19 '22 05:10

ishan


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

like image 3
hagits Avatar answered Oct 19 '22 05:10

hagits


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}
      }
   }
}
like image 1
dpinya Avatar answered Oct 19 '22 06:10

dpinya