当前位置: 首页 > 知识库问答 >
问题:

对声明性管道阶段使用轻量级执行器(代理无)

韦阳辉
2023-03-14

我正在使用声明性语法的Jenkins Pipeline,目前有以下阶段:

  1. 准备
  2. 构建(两组平行的步骤)
  3. 测试(也是两组平行的步骤)
  4. 询问是否/在何处部署
  5. 部署

对于步骤1、2、3和5,我需要和代理(一个执行者),因为他们在工作区上做实际工作。对于步骤4,我不需要一个,并且我不希望在等待用户输入时阻止可用的执行器。对于经典的脚本语法,这似乎被称为“flyweight”或“lightweight”执行器,但我找不到任何关于如何使用声明性语法实现这一点的信息。

到目前为止,我已经尝试:

  1. 直接在管道选项中设置代理,然后在舞台上设置agent none。这没有效果,管道以normalt运行,在等待输入时阻塞执行器。文档中也提到它不会有任何效果,但我想我还是要试一试

以下是我的Jenkins文件的概要:

pipeline {
    agent {
        label 'build-slave'
    }
    stages {
        stage("Prepare build") {
            steps {
                // ...
            }
        }
        stage("Build") {
            steps {
                parallel(
                    frontend: {
                        // ...
                    },
                    backend: {
                        // ...
                    }
                )
            }
        }
        stage("Test") {
            steps {
                parallel(
                    jslint: {
                        // ...
                    },
                    phpcs: {
                        // ...
                    },
                )
            }
            post {
                // ...
            }
        }
        stage("Select deploy target") {
            steps {
                script {
                    // ... code that determines choiceParameterDefinition based on branch name ...
                    try {
                        timeout(time: 5, unit: 'MINUTES') {
                            deployEnvironment = input message: 'Deploy target', parameters: [choiceParameterDefinition]
                        }
                    } catch(ex) {
                        deployEnvironment = null
                    }
                }
            }
        }
        stage("Deploy") {
            when {
                expression {
                    return binding.variables.get("deployEnvironment")
                }
            }
            steps {
                // ...
            }
        }
    }
    post {
        // ...
    }
}

我在这里遗漏了什么,还是在当前版本中不可能?

共有3个答案

叶卓君
2023-03-14

截至今天(2021年),您可以使用嵌套阶段(https://www.jenkins.io/doc/book/pipeline/syntax/#sequential-stages)对输入步骤之前必须在同一工作区中运行的所有阶段以及输入步骤之后必须在同一工作区中运行的所有阶段进行分组。当然,在输入步骤之前,您需要将工件隐藏或存储在某些外部存储库中,因为第二个工作区可能与第一个不同:

pipeline {
    agent none
    stages {
        stage('Deployment to Preproduction') { 
            agent any 
            stages {
                stage('Stage PRE.1') { 
                    steps {
                        echo "StagePRE.1"
                        sleep(10)
                    }
                }
                stage('Stage PRE.2') { 
                    steps {
                        echo "Stage PRE.2"
                        sleep(10)
                    }
                }
            }
        }
        stage('Stage Ask Deploy') { 
            steps {
                input message: 'Deploy to production?'
            }
        }
        stage('Deployment to Production') { 
            agent any 
            stages {
                stage('Stage PRO.1') { 
                    steps {
                        echo "Stage PRO.1"
                        sleep(10)
                    }
                }
                stage('Stage PRO.2') { 
                    steps {
                        echo "Stage PRO.2"
                        sleep(10)
                    }
                }
            }
        }
    }
}
糜宜民
2023-03-14

有一种变通方法可以在其他阶段使用相同的构建从属。可以使用节点名设置变量,并在其他变量中使用它。

即:

pipeline {
    agent none
    stages {
        stage('First Stage Gets Agent Dynamically') {
            agent {
                node {
                    label "some-agent"
                }
            }
            steps {
                echo "first stage running on ${NODE_NAME}"
                script {
                  BUILD_AGENT = NODE_NAME
                }
            }
        }
        stage('Second Stage Setting Node by Name') {
            agent {
                node {
                    label "${BUILD_AGENT}"
                }
            }
            steps {
                echo "Second stage using ${NODE_NAME}"
            }
        }
    }
}
史钊
2023-03-14

在顶层设置agent none,然后在每个阶段设置agent{label'foo'},在input阶段再次设置agent none,这对我来说似乎是正常的。

即。每个执行某些工作的阶段都在同一个代理上运行,而输入阶段不使用任何代理上的执行器。

pipeline {
    agent none
    stages {
        stage("Prepare build") {
            agent { label 'some-agent' }
            steps {
                echo "prepare: ${pwd()}"
            }
        }
        stage("Build") {
            agent { label 'some-agent' }
            steps {
                parallel(
                    frontend: {
                        echo "frontend: ${pwd()}"
                    },
                    backend: {
                        echo "backend: ${pwd()}"
                    }
                )
            }
        }
        stage("Test") {
            agent { label 'some-agent' }
            steps {
                parallel(
                    jslint: {
                        echo "jslint: ${pwd()}"
                    },
                    phpcs: {
                        echo "phpcs: ${pwd()}"
                    },
                )
            }
        }
        stage("Select deploy target") {
            agent none
            steps {
                input message: 'Deploy?'
            }
        }
        stage("Deploy") {
            agent { label 'some-agent' }
            steps {
                echo "deploy: ${pwd()}"
            }
        }
    }
}

但是,不能保证在管道中使用相同的代理标签将始终使用相同的工作区,例如,当第一个生成等待输入时,作为同一作业的另一个生成。

在构建步骤之后,您必须使用stash。正如您所注意到的,这目前无法通过并行正常完成,因此您必须另外使用脚本块,以便在并行步骤之后/之前为隐藏/取消隐藏编写脚本管道的片段。

 类似资料:
  • 问题内容: 我正在将Jenkins Pipeline与声明性语法一起使用,目前处于以下阶段: 准备 构建(两组并行的步骤) 测试(也是两组平行的步骤) 询问是否/在哪里部署 部署 对于步骤1、2、3和5,我需要和代理(执行者),因为它们在工作区上进行实际工作。对于步骤4,我不需要一个,并且我不想在等待用户输入时阻止我可用的执行程序。对于经典的脚本化语法,这似乎被称为“轻量级”执行器或“轻量级”执行

  • 我正在使用詹金斯声明管道,不知道是否有任何方法可以定期触发特定阶段。 我的意思是,当我们签出SCM时,管道会触发,但阶段2对我们的一些项目来说太长了。因此,我不想等待这个阶段,我只想每天运行这个阶段,但仍然将这个阶段保存在Jenkins文件中。 有没有办法做到这一点?这样做的最佳方法是什么?

  • 问题内容: 我正在尝试做这样的事情: 但这给了我这个例外: 是否可以将阶段定义为外部闭包? 问题答案: 您不能在声明式管道之外定义阶段。声明性管道的主要目的是提供经过简化且自以为是的语法,因此您可以专注于应该做什么(通过使用一些可用的步骤)而不是如何去做。 如果您对更灵活的管道实现方式感兴趣,可以选择“ 脚本化管道”方法,该语法在语法方面并不严格-仅受Groovy和CPS执行模块的限制。 您的示例

  • 我有以下管道: 不幸的是,这引发了: groovy.lang.MissingPropertyException:没有这样的属性:org.kohsuke.groovy上的类groovylang.Binding.getVariable(Binding.java:63)的master:org.jenkinsi.plugins.scriptsecurity.sandbox.groovy-SandboxIn

  • 问题内容: 目标 在同一节点上运行声明性Jenkins管道的多个阶段。 安装程序 这只是显示问题的一个最小示例。有2个Windows节点“ windows-slave1”和“ windows-slave2”,均标有“ windows”标签。 注意:我真正的Jenkinsfile无法使用全局代理,因为存在需要在不同节点上运行的阶段组(例如Windows与Linux)。 预期行为 Jenkins根据标

  • 目标 在同一节点上运行声明性Jenkins管道的多个阶段。 设置 这只是说明问题的一个最小示例。有两个Windows节点“Windows-slave1”和“Windows-slave2”都标有“Windows”标签。 注意:我的real Jenkins文件不能使用全局代理,因为需要在不同的节点(例如Windows和Linux)上运行多组阶段。 预期行为 Jenkins基于标签选择阶段1中的一个节点