如何在声明管道中等待用户输入而不阻塞重量级执行程序

Lau*_*res 19 jenkins jenkins-pipeline

我正在重建现有的构建管道作为jenkins声明管道(多分支管道)并且在处理构建传播时遇到问题.

在打包并存储所有相关文件之后,管道应该等待用户输入以触发部署.

如果我只是添加一个输入步骤,则阻止当前的构建节点.由于这个执行器很重,我想将这一步移到更轻量级的机器上.

最初我做了一个脚本管道工作,只创建了两个不同的node('label')块.有没有办法让我用声明性语法做类似的事情?

node('spine') { 
    stage('builder') {
        sh 'mvn clean compile'
        stash name: 'artifact', includes: 'target/*.war'
    }
}
node('lightweight') {
    stage('wait') {
        timeout(time:5, unit:'DAYS') {
            input message:'Approve deployment?'
        }
    }
    // add deployment stages
}
Run Code Online (Sandbox Code Playgroud)

我已经尝试了几件事:

在顶层配置代理并将其他代理配置添加到传播步骤,但随后我有两个执行器阻塞,因为顶级定义的构建节点未停止.

agent none在顶级设置并按步骤配置代理.那么git checkout就不存在于第一个节点上.

编辑1

我根据你的建议重新配置了我的管道,它目前看起来像这样:

pipeline {
agent none
tools {
    maven 'M3'
}
stages {
    stage('Build') {
        agent { label 'spine' }
        steps {
            checkout scm // needed, otherwise the workspace on the first step is empty
            sh "mvn clean compile"
        }
    }
    stage('Test') {
        agent { label 'spine' }
        steps {
            sh "mvn verify" // fails because the workspace is empty aggain
            junit '**/target/surefire-reports/TEST-*.xml'
        }
    }
}
}
Run Code Online (Sandbox Code Playgroud)

此构建将失败,因为工作区不会在步骤之间进行,因为它们不在同一执行程序上运行.

编辑2

显然,有时步骤在同一执行器上运行,有时则不会.(我们根据需要在我们的mesos/dcos集群上生成构建从属,因此更改执行者中间构建将是一个问题)

只要代理定义中的标签不变,我希望jenkins只运行当前执行程序.

Ber*_*ert 28

请参阅最佳实践7:不:在节点块中使用输入.在声明性管道中,节点选择是通过agent指令完成的.

此处的文档描述了如何none为pipline 定义,然后使用阶段级agent指令在所需节点上运行阶段.我也尝试了相反的方法(在某个节点上定义一个全局代理,然后none在阶段级别为输入定义),但这不起作用.如果管道分配了从属,则无法释放一个或多个特定阶段的从属.

这是我们管道的结构:

pipeline {
  agent none
  stages {
    stage('Build') {
      agent { label 'yona' }
      steps {
        ...
      }
    }
    stage('Decide tag on Docker Hub') {
      agent none
      steps {
        script {
          env.TAG_ON_DOCKER_HUB = input message: 'User input required',
              parameters: [choice(name: 'Tag on Docker Hub', choices: 'no\nyes', description: 'Choose "yes" if you want to deploy this build')]
        }
      }
    }
    stage('Tag on Docker Hub') {
      agent { label 'yona' }
      when {
        environment name: 'TAG_ON_DOCKER_HUB', value: 'yes'
      }
      steps {
        ...
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

通常,构建阶段在标记为"yona"的构建从属上执行,但输入阶段在主服务器上运行.

  • 所以这相当于这个脚本化的管道:https://gist.github.com/mryan43/a823a57d91f49afb989155c7decbe6be.这是14行代码而不是29行...不是声明性管道应该更简单吗? (2认同)

eme*_*ino 15

另一种方法是使用表达式指令和 beforeAgent,它跳过“决定”步骤并避免与“env”全局混淆:

pipeline {
    agent none

    stages {
        stage('Tag on Docker Hub') {
            when {
                expression {
                    input message: 'Tag on Docker Hub?'
                    // if input is Aborted, the whole build will fail, otherwise
                    // we must return true to continue
                    return true
                }
                beforeAgent true
            }

            agent { label 'yona' }

            steps {
                ...
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这是迄今为止最好的答案。 (2认同)

GDe*_*der 5

我知道这个线程很旧,但我相信除了隐藏之外,“编辑 2”问题的解决方案是使用嵌套阶段。

https://jenkins.io/blog/2018/07/02/whats-new-declarative-piepline-13x-sequential-stages/#running-multiple-stages-with-the-same-agent-or-environment-or -选项

根据这个页面:

...如果您在管道中使用多个代理,但希望确保使用相同代理的阶段使用相同的工作区,则可以使用带有代理指令的父阶段,然后使用其内的所有阶段stage 指令将在同一个工作区中的同一个执行器上运行。

这是提供的示例:

pipeline {
    agent none

    stages {
        stage("build and test the project") {
            agent {
                docker "our-build-tools-image"
            }
            stages {
               stage("build") {
                   steps {
                       sh "./build.sh"
                   }
               }
               stage("test") {
                   steps {
                       sh "./test.sh"
                   }
               }
            }
            post {
                success {
                    stash name: "artifacts", includes: "artifacts/**/*"
                }
            }
        }

        stage("deploy the artifacts if a user confirms") {
            input {
                message "Should we deploy the project?"
            }
            agent {
                docker "our-deploy-tools-image"
            }
            steps {
                sh "./deploy.sh"
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)