首页 > 解决方案 > Jenkins 管道中的开关返回 null,普通 Groovy 中的相同开关返回预期输出

问题描述

我的代码中有这个switch(上下文:Jenkins 管道库):

def installOptions(filePath) {
    switch (filePath) {
        case ~/.*\.pom/:
            "-Dpackaging=pom -DpomFile=$filePath"
            break
        case ~/.*\.jar/:
            '-Dpackaging=jar'
            break
        case ~/.*-exe-archive.zip/:
            filePath = filePath.replace '-exe-archive.zip', '.pom'
            "-Dpackaging=zip -DpomFile=$filePath"
            break
        default:
            ''
            break
    }
}

的价值filePath'temp_downloads/merge/QA-9344/itextcore/java/main.pom'

期望值:

-Dpackaging=pom -DpomFile=temp_downloads/merge/QA-9344/itextcore/java/main.pom

实际价值:

null

当我在“普通”Groovy 中使用完全相同时switch,我确实得到了预期的输出:

import org.codehaus.groovy.runtime.InvokerHelper

class InstallJavaBranchArtifacts extends Script {

    static void main(String[] args) {
        InvokerHelper.runScript(InstallJavaBranchArtifacts, args)
    }

    def run() {
        println installOptions('temp_downloads/merge/QA-9344/itextcore/java/main.pom')
        println installOptions('temp_downloads/merge/QA-9344/itextcore/java/barcodes.pom')
        println installOptions('temp_downloads/merge/QA-9344/itextcore/java/itext7-barcodes-7.1.12-SNAPSHOT.jar')
    }

    def installOptions(filePath) {
        switch (filePath) {
            case ~/.*\.pom/:
                "-Dpackaging=pom -DpomFile=$filePath"
                break
            case ~/.*\.jar/:
                '-Dpackaging=jar'
                break
            case ~/.*-exe-archive.zip/:
                filePath = filePath.replace '-exe-archive.zip', '.pom'
                "-Dpackaging=zip -DpomFile=$filePath"
                break
            default:
                ''
                break
        }
    }
}

那么这是我的输出:

/usr/lib/jvm/java-1.11.0-openjdk-amd64/bin/java ...
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.codehaus.groovy.reflection.CachedClass (file:/usr/share/java/groovy-2.4.17.jar) to method java.lang.Object.finalize()
WARNING: Please consider reporting this to the maintainers of org.codehaus.groovy.reflection.CachedClass
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
-Dpackaging=pom -DpomFile=temp_downloads/merge/QA-9344/itextcore/java/main.pom
-Dpackaging=pom -DpomFile=temp_downloads/merge/QA-9344/itextcore/java/barcodes.pom
-Dpackaging=jar

Process finished with exit code 0

这是(除了非法的反射访问 mumbo jumbo)预期的输出。

那么我需要做什么,才能switch在 Jenkins 管道库中以与“正常”Groovy 中相同的方式进行行为?

标签: jenkinsgroovyjenkins-pipelinejenkins-groovy

解决方案


Jenkins 管道使用 Groovy CPS 解释器运行您的 Groovy 代码,它将您的代码解构为多个部分并以连续传递的方式评估它们。在您的示例中,您的switch语句错过了明确的return,这就是为什么评估您的函数体返回的原因null

有两个选项可以修复它。

  1. 您可以为函数实现添加@NonCPS注释installOptions,这样您将使用常规的 Groovy Shell 解释器运行此函数的主体。这可能对您有用,因为在此函数的主体中,您没有调用任何 Jenkins Pipeline 工作流程步骤,而只是调用了普通的 Groovy 代码。

       @NonCPS
       def installOptions(filePath) {
            switch (filePath) {
                case ~/.*\.pom/:
                    "-Dpackaging=pom -DpomFile=$filePath"
                    break
                case ~/.*\.jar/:
                    '-Dpackaging=jar'
                    break
                case ~/.*-exe-archive.zip/:
                    filePath = filePath.replace '-exe-archive.zip', '.pom'
                    "-Dpackaging=zip -DpomFile=$filePath"
                    break
                default:
                    ''
                    break
            }
        }
    
  2. 如果您想在 Groovy CPS 模式下继续执行此代码,请从每个 case 中删除并在您从 switch case 返回的每个字符串之前break添加显式。return

       def installOptions(filePath) {
            switch (filePath) {
                case ~/.*\.pom/:
                    return "-Dpackaging=pom -DpomFile=$filePath"                        
                case ~/.*\.jar/:
                    return '-Dpackaging=jar'
                case ~/.*-exe-archive.zip/:
                    filePath = filePath.replace '-exe-archive.zip', '.pom'
                    return "-Dpackaging=zip -DpomFile=$filePath"
                default:
                    return ''
            }
        }
    

如果您想了解更多有关 Groovy CPS 的信息,请前往此处查看文档 - https://github.com/cloudbees/groovy-cps


推荐阅读