带有文件参数的Jenkins管道作业

带有文件参数的Jenkins管道作业,jenkins,parameters,jenkins-pipeline,Jenkins,Parameters,Jenkins Pipeline,我正在准备一个Jenkins管道作业,它将接受一个文件参数。我可以触发作业并将其指向一个文件,但我找不到文件的结尾(在普通自由式作业中,它将位于工作区中) 上传的文件到哪里去了?或者文件参数当前不适用于管道 管道和文件参数当前存在问题 ()。解决方法如下: node { deleteDir() stage("upload") { def inputFile = input message: 'Upload file', parameters: [file(name

我正在准备一个Jenkins管道作业,它将接受一个文件参数。我可以触发作业并将其指向一个文件,但我找不到文件的结尾(在普通自由式作业中,它将位于工作区中)


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

管道和文件参数当前存在问题
()。

解决方法如下:

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”存储在jobs目录中,而不是工作区中(不知道为什么)

我尝试使用@Christoph Forster提供的解决方案,但输入文件没有被复制到工作区的任何地方。 因此,我使用了中提供的变通方法

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

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

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

我还尝试使用@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")]
        }

我在这里找到了一个全局库形式的解决方案:

它包含对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"

在那里

尝试了克里斯托夫的建议,但对我不起作用。这是我的工作和设置,我有,他的应该帮助别人知道该怎么做

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

解决方案:

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'
            }
        }
    }
  • 执行Christoph建议的文件复制解决方案。这将文件存储在主节点上的作业工作区中
  • 允许在“管理Jenkins”>“过程中脚本批准”中使用脚本
  • 使用“隐藏”步骤隐藏上载的文件
  • 在目标阶段“在不同节点上运行”中,使用unstash

  • 希望这有助于

    处理管道中的可选文件参数(处理不应接受任何文件的用例)。您可以使用jenkinsci unstashParam库(在Jenkins>Manage Jenkins>Configure System>Global pipeline Libraries中添加它),并在脚本中使用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.."
                        }
                    }
                }
            }
    

    如果文件上载到主节点,而需要从节点,则我无法使Christoph的解决方案工作。解决办法是把它藏在主机上,然后把它从主机上取下来。不要忘记删除主节点上上载的文件。

    java.nio.file.NoSuchFileException:jenkins/workspace/job/data.zip
    我遇到了另一个问题:
    脚本不允许使用新的java.io.file java.lang.String
    您需要首先允许这些方法。可以在这里完成,但无法可靠地使用此解决方法--文件不会随机复制到工作区。
    java.io.FileNotFoundException:/var/lib/jenkins/workspaces/some project/data.zip(没有这样的文件或目录)
    我在jenkins主服务器上找到了该文件(不在workers/executors上)在这个路径上:/var/lib/jenkins/jobs/$JOB\u NAME/builds/$BUILD\u NUMBER/example.txt注意,我没有在def inputFile=input message中指定完整路径:“Upload file”,参数:[file(NAME:“example.txt”)]对我来说非常有用。脚本将在上载步骤暂停,直到您转到批准并上载文件。神奇而简单!