从属性文件加载属性并使它们在整个 job/pipeline - Jenkins 声明语法中可用
Load properties from properties file and make them available throughout the job/pipeline - Jenkins declarative syntax
我的要求很简单,我只想外部化一些 'values' 以使我的 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}'
}
}
}
}
我找到了几种在 Jenkins 管道中外部化属性的方法。您可以根据主要差异选择您的选择。
1) 完全使用 groovy 代码。此代码片段需要您在脚本安全插件附带的 'In-process script approval' 中启用多个方法签名,因此只有在适当考虑后才应这样做。
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
}
}
}
}
感谢您的回答 #1。它有很大帮助,我使用了选项 2。
我遇到了一些问题,想分享我的解决方案:
1) 我在声明性管道的管道部分内添加了一个 "prepare" 阶段:
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
请注意,该物业没有报价。
我在其他步骤、阶段和 post 中也使用了 ${properties.nextBranchName} 的属性。
如答案 1 所述:需要安装 "pipeline utility steps" 插件
使用 "pipeline utility steps" 插件,您可以定义适用于所有阶段的通用变量。例如,让 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}
}
}
}
我的要求很简单,我只想外部化一些 'values' 以使我的 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}'
}
}
}
}
我找到了几种在 Jenkins 管道中外部化属性的方法。您可以根据主要差异选择您的选择。
1) 完全使用 groovy 代码。此代码片段需要您在脚本安全插件附带的 'In-process script approval' 中启用多个方法签名,因此只有在适当考虑后才应这样做。
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
}
}
}
}
感谢您的回答 #1。它有很大帮助,我使用了选项 2。 我遇到了一些问题,想分享我的解决方案:
1) 我在声明性管道的管道部分内添加了一个 "prepare" 阶段:
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
请注意,该物业没有报价。
我在其他步骤、阶段和 post 中也使用了 ${properties.nextBranchName} 的属性。 如答案 1 所述:需要安装 "pipeline utility steps" 插件
使用 "pipeline utility steps" 插件,您可以定义适用于所有阶段的通用变量。例如,让 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}
}
}
}