【问题标题】:Jenkins multi-branch pipeline workspace location: shell versus GroovyJenkins 多分支管道工作空间位置:shell 与 Groovy
【发布时间】:2017-10-16 04:02:41
【问题描述】:

总结:当使用并行构建时,Groovy 中的工作空间路径与 shell 不同。如何从 DSL 或 Groovy 获取实际的工作空间?

详情:

我们的工作区是通过ws( '/path/to/workspace' ) 定义的。

我正在尝试使用相对路径,即package.json,在当前目录(通常是工作区根目录)中打开该文件。当作为 shell 运行时,sh 'jq -r ".version" package.json' 工作正常,我可以毫无问题地阅读package.json

但是使用 Groovy:

def version = new groovy.json.JsonSlurper().parseText( new File( "package.json" ).text )[ 'version' ]

注意new File( "package.json" ) 然后它会因为声称$WORKSPACE/package.json 不存在而失败。尽管我们使用ws 设置了上面的工作区,但我可以看到它最终会变成类似于 /path/to/workspace/my_job-SOMERANDOMCHARS... 而不是ws 中指定的目录。 p>

我了解,在并行工作负载中,我们需要使工作区独一无二,因此这并不意外。但是我应该如何从 Groovy 确定工作空间?还是期望总是突破到实际在节点上运行的 shell?

更新:更多上下文

有关如何使用它的更多信息。我们的 Groovy(非声明式)管道按照以下方式进行操作:

stage('tests') {
  parallel(
    'Unit Tests': {
       node('unitNode') {
         ws('/path/to/workspace') {
           new file("${env.WORKSPACE}/package.json") // does not work 
           sh 'cat $WORKSPACE/package.json' // works OK
         }
       }
    },
    'E2E Tests': {
       node('e2eNode') {
         ws('/path/to/workspace') {
           new file("${env.WORKSPACE}/package.json") // does not work 
           sh 'cat $WORKSPACE/package.json' // works OK
         }
       }
    }
  )
}

【问题讨论】:

    标签: jenkins jenkins-pipeline


    【解决方案1】:

    我正在假设您如何使用 ws()。在没有看到您的实际代码的情况下,您的描述暗示您正在做这样的事情:

    ws(/new/path/to/workspace) {
        sh "cat package.json"
    }
    
    def version = new groovy.json.JsonSlurper().parseText( new File( "package.json" ).text )[ 'version' ]
    

    如果您是这样做的,那么工作区将不再适用于 ws{} 块之外。

    您显示的路径 ( /path/to/workspace/my_job-SOMERANDOMCHARS ) 似乎是您运行 ws() 之前的原始工作区路径。或者它可能是您的管道文件正在签出的地方。如果没有看到您的代码,很难猜测您尝试将工作区文件放在哪里。

    无论哪种方式,如果使用 WORKSPACE 变量,都可以获得当前工作空间。运行以下管道代码并检查输出。这应该解释这一切是如何工作的。

    pipeline {
        agent any
    
        stages {
            stage('first'){
                steps {
                    ws('/tmp/foobar') {
                        sh "pwd"
                        sh 'echo New Workspace - ${WORKSPACE}' //environment variable
                        echo 'New Workspace' + WORKSPACE //groovy variable
                    }
                    sh "pwd"
                    sh "echo Original Workspace - ${WORKSPACE}"  //interpolated groovy variable
                    echo "Original Workspace - ${WORKSPACE}"       //interpolated groovy variable
                }
            }
        }
    
    }
    

    编辑:我将您的示例修改为在我的机器上运行的示例以尝试重现,但它工作得很好。这可以在您的 Jenkins 上运行吗?

    stage('tests') {
      parallel(
        'Unit Tests': {
           node('Linux') {
             ws('/tmp/foobar') {
               def file1 = new File("${env.WORKSPACE}/package.json")
               println 'File1 is: ' + file1
               echo "${env.WORKSPACE}"
               sh 'echo $WORKSPACE/package.json'
             }
           }
        },
        'E2E Tests': {
           node('Linux') {
             ws('/tmp/baz') {
               def file2 = new File("${env.WORKSPACE}/package.json")
               println 'File2 is: ' + file2
               echo "${env.WORKSPACE}"
               sh 'echo $WORKSPACE/package.json'
             }
           }
        }
      )
    }
    

    也许问题不在您认为的位置,或者您正在使用的 Jenkins 版本或插件中存在错误。如果文件句柄的 println 显示正确的路径,则可能是其他问题。

    【讨论】:

    • 我添加了更多关于我如何尝试使用工作区位置的上下文。
    • 我玩过你的额外细节。我似乎无法重现。这段代码对你有用吗?
    • 如果将两个并行分支的“ws”位置设置为同一目录会怎样?
    • 如果它们位于不同的节点上(如您在示例中所使用的那样),那么它可以正常工作。如果它们在同一个节点上,则第二阶段获取目录上的@2。这就是 Jenkins 的设计方式。它不能将同一工作区用于 2 个并发作业。你强迫工作空间的原因是什么?通常最好避免这种情况,原因有几个。也许你可以在不强迫工作空间的情况下实现你的目标?
    • 它们实际上在两个不同的节点上运行,因此写入不同的物理位置,所以不用担心。如果需要,我将对此进行更多回顾并更新我的示例。
    【解决方案2】:

    访问与工作区相关的文件的最佳方法是使用readFile,或者在这种情况下更方便地使用readJSON。这对我有用,我不必关心工作区的实际绝对路径。

    还有其他 readXXXX 方法,例如 readYAML、readManifest、readMavenPom 等。有关完整列表和示例,请参阅 Pipeline Utility Steps 文档。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-11-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多