6

我的要求很简单,我只想将一些“值”外部化以使我的 Jenkinsfile 更可重用,为此我需要从 Jenkinsfile 旁边的文件中加载属性,并确保这些属性是可在管道中的任何地方使用。我对 groovy 和 Jenkins 代码仍然很陌生,但从未想过这么简单的事情会如此困难。我在脚本安全插件中启用了一些方法,但以下代码(以及我尝试过的几种变体)总是会出现错误或打印 null 或给我 NPE。我尝试了多种组合,下面的代码只是其中之一。

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

        }
    }
}
4

3 回答 3

7

我想出了几种方法来外部化 Jenkins 管道中的属性。您可以根据主要区别选择您的选择。

1) 完全使用 groovy 代码。此代码段将要求您在脚本安全插件附带的“进程内脚本批准”中启用多个方法签名,因此只有在适当考虑后才能这样做。

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) 使用管道实用程序步骤插件 - 管道插件套件默认包含此插件,它允许更好的方式加载属性而无需启用安全异常。我会推荐这种方法。

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
            }

        }
    }
}
于 2017-05-04T12:59:10.257 回答
3

感谢您的答案#1。它帮助很大,我使用了选项 2。我遇到了一些问题,并想分享我的解决方案:

1)我在声明性管道的管道部分内添加了一个“准备”阶段:

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

属性文件的格式为:

nextBranchName=next
stableBranchName=master
GitURL=git@github.com:foo.git

请注意,该物业没有报价。

我在其他步骤、阶段和帖子中也将属性用作 ${properties.nextBranchName}。如答案1所述:需要安装“管道实用程序步骤”插件

于 2018-08-09T13:03:02.473 回答
1

使用“管道实用程序步骤”插件,您可以定义可用于所有阶段的通用变量。例如,让props.txt为:

version=1.0
fix=alfa

并将脚本和声明性 Jenkins 管道混合为:

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}
      }
   }
}
于 2018-12-03T16:25:39.450 回答