如何在Jenkinsfile中设置和引用变量

42

我有一个多分支项目的声明式流水线脚本,我想读取一个文本文件并将结果存储为字符串变量,以便在管道中的后续步骤中访问。使用代码片段生成器,我尝试像这样做:

filename = readFile 'output.txt'

我的字符串是针对哪个文件名的。

Jenkins控制台输出中出现了错误:

org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
WorkflowScript: 30: Expected a step @ line 30, column 5.
            filename = readFile 'output.txt'

我需要使用withEnv步骤将readFile的输出设置为Jenkins环境变量吗?如果是,该如何操作?

谢谢


你能否根据 mcve 指南编辑你的问题? - Yuri G.
5个回答

68

错误是由于您只能在steps指令内使用管道步骤。我知道的一个解决方法是使用script步骤,并将任意管道脚本包装在其中,并将结果保存在环境变量中,以便以后使用。

所以在您的情况下:

pipeline {
    agent any
    stages {
        stage("foo") {
            steps {
                script {
                    env.FILENAME = readFile 'output.txt'
                }
                echo "${env.FILENAME}"
            }
        }
    }
}

奇怪的是,当我运行这个(Jenkins 2.32.2)时,我得到了预期的结果(在readFile之前添加了writeFile file:'output.txt',text:'asdsad',我得到了[Pipeline] echo asdsad,就像预期的那样)。你确定文件里有内容吗? - Jon S
是的,它是空白的,那是因为我的逻辑中有其他问题,但我认为你的答案就是我在寻找的。谢谢。 - Dalton Sweeney
4
一个提示:你可能想要像这样修剪 readFile('output.txt').trim() - hao
1
请注意,您不能像这样将credential(...)分配给变量。它转换为字符串“"@credentials(<anonymous>=BLAHBLAH>"”,然后会悄悄地不起作用。 - shuckc
是的,env变量不是由普通的映射支持的,而是完全使用字符串操作,即分配给env变量键的所有值都会转换为字符串(我猜是使用toString())。 - Jon S

28

根据文档,如果你之后想在脚本的其他部分使用变量的值,你还可以设置全局环境变量。在您的情况下,可以在根流水线中设置它:

pipeline {
  ...
  environment {
    FILENAME = readFile ...
  }
  ...
}

1
只是为了澄清,在其他答案中已经说明,value 可能会在后面被引用为 "${env.FILENAME}"。 - Mauricio

12

我们通过将函数添加到环境步骤来解决这个问题,即:

environment {
    ENVIRONMENT_NAME = defineEnvironment() 
}
...
def defineEnvironment() {
    def branchName = "${env.BRANCH_NAME}"
    if (branchName == "master") {
        return 'staging'
    }
    else {
        return 'test'
    }
}

如果BRANCH_NAME已经是一个字符串,那么${env.BRANCH_NAME}env.BRANCH_NAME是相同的吗? - undefined

2

一个脚本化管道的完整示例:

       stage('Build'){
            withEnv(["GOPATH=/ws","PATH=/ws/bin:${env.PATH}"]) {
                sh 'bash build.sh'
            }
        }

1
这个问题并没有提到运行构建脚本或添加到PATH。 - daemone
1
真的,但这是唯一带有脚本语法的答案,而且这是一个很好的示例代码。 - Kyle

2

我现在不能发表评论,但是我有一个提示:使用try/catch子句可以避免破坏管道(如果您确定文件存在,则忽略此操作)。

    pipeline {
        agent any
            stages {
                stage("foo") {
                    steps {
                        script {
                            try {                    
                                env.FILENAME = readFile 'output.txt'
                                echo "${env.FILENAME}"
                            }
                            catch(Exception e) {
                                //do something, e.g. echo 'File not found'
                            }
                        }
                   }
    }

另一个提示(由@hao评论,我认为值得分享):您可能希望像这样修剪readFile('output.txt')。trim()


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接