【问题标题】:How to lock multiple stages of declarative Jenkins pipeline?如何锁定声明式 Jenkins 管道的多个阶段?
【发布时间】:2017-05-21 16:06:13
【问题描述】:

我想在声明性 Jenkins 管道内的锁内运行多个阶段:

pipeline {
    agent any
    stages {
        lock(resource: 'myResource') {
            stage('Stage 1') {
                steps {
                  echo "my first step"
                }
            }

            stage('Stage 2') {
                steps {
                  echo "my second step"
                }
            }

        }
    }
}

我收到以下错误:

Started by user anonymous
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
WorkflowScript: 10: Expected a stage @ line 10, column 9.
           lock(resource: 'myResource') {
           ^

WorkflowScript: 10: Stage does not have a name @ line 10, column 9.
           lock(resource: 'myResource') {
           ^

WorkflowScript: 10: Nothing to execute within stage "null" @ line 10, column 9.
           lock(resource: 'myResource') {
           ^

3 errors

    at org.codehaus.groovy.control.ErrorCollector.failIfErrors(ErrorCollector.java:310)
    at org.codehaus.groovy.control.CompilationUnit.applyToPrimaryClassNodes(CompilationUnit.java:1085)
    at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:603)
    at org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:581)
    at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:558)
    at groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:298)
    at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:268)
    at groovy.lang.GroovyShell.parseClass(GroovyShell.java:688)
    at groovy.lang.GroovyShell.parse(GroovyShell.java:700)
    at org.jenkinsci.plugins.workflow.cps.CpsGroovyShell.reparse(CpsGroovyShell.java:116)
    at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution.parseScript(CpsFlowExecution.java:430)
    at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution.start(CpsFlowExecution.java:393)
    at org.jenkinsci.plugins.workflow.job.WorkflowRun.run(WorkflowRun.java:257)
    at hudson.model.ResourceController.execute(ResourceController.java:97)
    at hudson.model.Executor.run(Executor.java:405)
Finished: FAILURE

这里有什么问题? documentation 明确指出:

lock 也可用于将多个阶段包装成一个 并发单元

【问题讨论】:

    标签: jenkins jenkins-pipeline


    【解决方案1】:

    需要注意的是,您可以使用 lock 选项锁定管道中的所有阶段:

    pipeline {
        agent any
        options {
            lock resource: 'shared_resource_lock'
        }
        stages {
            stage('will_already_be_locked') {
                steps {
                    echo "I am locked before I enter the stage!"
                }
            }
            stage('will_also_be_locked') {
                steps {
                    echo "I am still locked!"
                }
            }
        }
    }
    

    【讨论】:

    • 不错!我试过这个,但不幸的是它不会阻止额外的管道构建占用一个执行器插槽,这是我需要的。从那以后,我将一个本地构建代理与一个执行器插槽连接起来,专门负责管道构建。
    • 我花了很多时间来搜索如何在多分支管道中阻止并发构建。而这简单的一行代码正是我要找的。​​span>
    • 这应该是不被批准的答案!
    • 很棒的答案,3 年后使用它,它完全符合我的需要。
    • 完美,这应该是现在公认的答案了。
    【解决方案2】:

    此问题已得到解决。

    您可以通过将多个阶段分组到父阶段来锁定多个阶段,如下所示:

    stage('Parent') {
      options {
        lock('something')
      }
      stages {
        stage('one') {
          ...
        }
        stage('two') {
          ...
        }
      }
    }
    

    (别忘了你需要 Lockable Resources 插件)

    【讨论】:

    • 嗨 Samuel,我无法使用声明性管道插件版本 2.5 (wiki.jenkins.io/display/JENKINS/Pipeline+Plugin) 来完成这项工作。你有什么版本?或者,也许您正在使用脚本化管道?谢谢!
    • @gusgonnet 我让它在声明式管道中工作,在 Jenkins 2.121.2、管道 2.5 和可锁定资源 2.3 上
    • 工作就像一个魅力!我有一个平行舞台,我需要锁定整个场景
    【解决方案3】:

    问题在于,尽管声明性管道是 technically available in beta in September, 2016,但您引用的博客文章(从 10 月开始)记录的是脚本化管道,而不是声明性的(它没有说太多,所以我觉得你很痛苦) .可锁定资源尚未作为声明性管道步骤以启用您正在寻找的功能的方式加入。

    你可以这样做:

    pipeline {
      agent { label 'docker' }
      stages {
        stage('one') {
          steps {
            lock('something') {
              echo 'stage one'
            }
          }
        }
      }
    }
    

    但你不能这样做:

    pipeline {
      agent { label 'docker' }
      stages {
        lock('something') {
          stage('one') {
            steps {
              echo 'stage one'
            }
          }
          stage('two') {
            steps {
              echo 'stage two'
            }
          }
        }
      }
    }
    

    你不能这样做:

    pipeline {
      agent { label 'docker' }
      stages {
        stage('one') {
          lock('something') {
            steps {
              echo 'stage one'
            }
          }
        }
      }
    }
    

    您可以为此用例使用脚本化管道。

    【讨论】:

    【解决方案4】:

    如果资源仅由该管道使用,您还可以禁用并发构建:

    pipeline {
        agent any
        options {
            disableConcurrentBuilds()
        }
        stages {
            stage('will_already_be_locked') {
                steps {
                    echo "I am locked before I enter the stage!"
                }
            }
            stage('will_also_be_locked') {
                steps {
                    echo "I am still locked!"
                }
            }
       }
    }
    

    【讨论】:

    • 此解决方案不会阻止针对不同分支的构建
    【解决方案5】:

    我在同一个构建节点上运行多个构建和测试容器。测试容器必须将节点名称锁定为测试的数据库用户名。

    lock(resource: "${env.NODE_NAME}" as String, variable: 'DBUSER')
    

    选项中的锁定是在加载时计算的,但 NODE_NAME 是未知的。为了锁定多个阶段以获得视觉效果,我们可以在脚本块内创建阶段,即 sn-p 中的“运行测试”阶段。舞台可视化与其他舞台块一样好。

    pipeline {
        agent any
        stages {
            stage('refresh') {
                steps {
                    echo "freshing on $NODE_NAME"
                    lock(resource: "${env.NODE_NAME}" as String, variable: 'DBUSER') {
                        sh '''
                            printenv | sort
                        '''
                        script {
                            stage('run test')
                            sh '''
                                printenv | sort
                            '''
                        }
                    }
                }
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2021-08-02
      • 2022-10-27
      • 1970-01-01
      • 2018-08-21
      • 1970-01-01
      • 2017-12-05
      • 2017-10-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多