Jenkins Pipeline Job with file parameter

时间:2016-06-28 15:51:57

标签: jenkins parameters jenkins-pipeline

我正在整理一个Jenkins管道作业,它将获取一个文件参数。我可以触发作业并将其指向一个文件但是我无法找到文件的最终位置(在普通的自由式作业中,它将在工作区中)。

上传的文件去了哪里?或者文件参数目前不适用于管道?

9 个答案:

答案 0 :(得分:13)

目前管道和文件参数存在问题 (https://issues.jenkins-ci.org/browse/JENKINS-27413)。

答案 1 :(得分:5)

通过以下方式解决:

node {
    deleteDir()
    stage("upload") {
        def inputFile = input message: 'Upload file', parameters: [file(name: 'data.zip')]
        new hudson.FilePath(new File("$workspace/data.zip")).copyFrom(inputFile)
        inputFile.delete()
    }
    stage("checkout") {
        echo fileExists('data.zip').toString()

    }
}

我知道解决方案不是那么漂亮,因为管道因上传而中断,但它可以工作。

进一步" copyFrom"是必要的,因为输入存储" data.zip"在作业目录中而不是在工作区中(不知道为什么)

答案 2 :(得分:3)

找到WA(严格用于基于文本的文件输入) 我们可以使用Jenkins多行字符串参数并要求用户将文件内容粘贴到它。 在我们的管道中,使用管道步骤writeFile写入此参数的内容,如:

stage('File Param WA') {
          writeFile file: 'demo.yaml', text: params.DEMO_YAML
}

Multi Line String Parameter

答案 3 :(得分:2)

我尝试使用@Christoph Forster提供的解决方案,但输入的文件未被复制到工作区中的任何位置。 所以我使用了提供的解决方法 https://bitbucket.org/janvrany/jenkins-27413-workaround-library/src/6b7dada8ea37?at=default

该库提供了一个新库 - unstashParam - 将文件构建参数保存到工作区中。适用于text和yaml文件。

答案 4 :(得分:1)

我在这里找到了一个全局库形式的解决方案: https://bitbucket.org/janvrany/jenkins-27413-workaround-library/src/default/

它包含对Jenkins内部方法的调用,这些方法已被弃用(我想)。 所以我做了这样的自己的版本:

import hudson.FilePath
import hudson.model.ParametersAction
import hudson.model.FileParameterValue
import hudson.model.Executor

def call(String name, String fname = null) {
    def paramsAction = currentBuild.rawBuild.getAction(ParametersAction.class);

    if (paramsAction == null) {
        error "unstashParam: No file parameter named '${name}'"
    }

    for (param in paramsAction.getParameters()) {
        if (param.getName().equals(name)) {
            if (! param instanceof FileParameterValue) {
                error "unstashParam: not a file parameter: ${name}"
            }
            if (env['NODE_NAME'] == null) {
                error "unstashParam: no node in current context"
            }
            if (env['WORKSPACE'] == null) {
                error "unstashParam: no workspace in current context"
            }
            workspace = new FilePath(getComputer(env['NODE_NAME']), env['WORKSPACE'])
            filename = fname == null ? param.getOriginalFileName() : fname
            file = workspace.child(filename)
            file.copyFrom(param.getFile())
            return filename;
        }
    }
}


def getComputer(name){

    for(computer in Jenkins.getInstance().getComputers()){ 
        if(computer.getDisplayName() == name){
            return computer.getChannel()
        }
    }

    error "Cannot find computer for file parameter workaround"
}

您可以将其插入全局库中,然后按以下方式使用它:

library "file-workaround"

node {
    def file_in_workspace = unstashParam "myFile"
    sh "cat ${file_in_workspace}"
}

这不是很漂亮,但是可以正常工作,只要没有官方补丁,这就是我最好的镜头。

更新
原来,您可能会遇到“没有这样的文件或目录”。这是因为解决方法中没有任何内容触发Jenkins创建工作区目录。如果这是在管道中其他地方触发的,那么您会抓挠头。
您可能想扔一个

touch "thisIsAFile"

在那里

答案 5 :(得分:0)

我也尝试使用@Christoph Forster的解决方案,但是启用Groovy Sandbox时收到脚本安全错误

org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: Scripts not permitted to use new hudson.FilePath java.io.File

但是,似乎我们可以通过简单地要求将文件上传到作业工作区来跳过文件复制和删除操作(并跳过Groovy沙箱限制)。只需将 workspace 变量添加到文件名中,如下所示:

stage("upload") {
def inputFile = input message: 'Upload file', parameters: [file(name: "$workspace/data.zip")]
        }

答案 6 :(得分:0)

尝试了克里斯多夫的建议,但对我没有用。这是对我有用的东西,以及我所拥有的设置,他应该帮助其他人弄清楚该怎么做。

问题: 我正在专用节点上执行管道,并使用经过清理的工作区。经过研究和故障排除后,我发现默认情况下,文件上传仅适用于主节点。在深入研究文件系统并在主服务器上的工作区中找到要上传的文件后,我意识到了这一点

解决方案:

stage('Upload Key') {
    agent { label 'master' }
    steps {
        script {
            // Uploads file via master node and stases it for other nodes to access
            def inputFile = input message: 'Upload file', parameters: [file(name: "key.p12")]
            new hudson.FilePath(new File("${workspace}/key.p12")).copyFrom(inputFile)
            inputFile.delete()
        }
        stash name: 'key.p12' , includes: "key.p12"
    }
}
    stage('Register') {
        steps {
            ws (sanitizedWorkspaceName) {
                echo "Registering"
                unstash 'key.p12'
            }
        }
    }
  1. 执行Christoph建议的文件复制解决方案。这会将文件存储在主节点上的作业工作空间中
  2. 在Manage Jenkins中允许脚本>进行中脚本批准
  3. 使用存储步骤存储上载的文件
  4. 在目标阶段“在另一个节点上运行”使用unstash

希望这会有所帮助

答案 7 :(得分:0)

要处理管道中的可选文件参数(以处理不应接受任何文件的用例),可以使用 jenkinsci-unstashParam-library (在Jenkins> Manage Jenkins>配置系统中添加它) >全球管道库https://github.com/janvrany/jenkinsci-unstashParam-library),在脚本中以try / catch作为示例阶段:

    stage('upload') {
            steps {
                // delete workspace
                cleanWs()

                // handle file parameters in pipeline (JENKINS-27413)
                script {

                    try {
                        // force workspace directory creation
                        sh "touch emptyFileToCreateWorkspace"

                        // https://stackoverflow.com/questions/59468464/fetching-uploaded-files-in-jenkins
                        def file_in_workspace = unstashParam 'MY_FILE.xlsx'

                        // https://unix.stackexchange.com/questions/125776/error-with-a-file-name-containing-parentheses
                        sh "mv '${file_in_workspace}' MY_FILE.xlsx"
                    }
                    catch (Exception e) {
                        echo e.getMessage()
                        echo "No file parameter, we will continue.."
                    }
                }
            }
        }

答案 8 :(得分:0)

如果文件上传到主节点并且在从节点上需要,我无法使 Christoph 的解决方案起作用。解决方案是将其存储在 master 上,然后将其取消存储在 slave 上。不要忘记在主节点上删除上传的文件。