Jenkins Pipeline

Jenkins 2.x的核心能力是Pipeline as code。在Jenkins 1.x中,我们通过简单便捷的配置,可以快速完成基本CI、CD的Job创建和管理,但对于复杂的流程,Jenkins 1.x则无从下手。在软件的发布过程中,通常会有一整套复杂的流程,来支持从代码提交到最终的软件交付。通过Jenkins pipeline,我们可以用代码的方式,定义我们的工作流,从而在代码中编写工程的CI、CD业务逻辑。同时,Pipeline支持在不同节点运行不同的步骤,使得整个DevOps流程更加灵活。

Jenkins pipeline支持两种模式,一种是Declarative Pipeline,另一种是Scripted Pipeline。两种模式都遵循的是groovy语法,但在编写上会有差别。

Declarative Pipeline

Declarative Pipeline必须被包含在pipeline语句块中:

pipeline {
    /* insert Declarative Pipeline here */
}

一个完整的Hello World!示例如下:

pipeline {
    agent any
    stages {
        stage('Example') {
            steps {
                echo 'Hello World'
            }
        }
    }
    post { 
        always { 
            echo 'I will always say Hello again!'
        }
    }
}

agent指定整个Pipeline或特定stage将在Jenkins环境中被执行的节点,如Jenkins 的master节点或某个cluster节点。

在Declarative Pipeline模式的代码中,可能会在一个stages{…}中声明一窜嵌套的stages{…}, 并以顺序执行。需要指出的是,一个stage{…}必须有且只有一个steps{…}, 或者parallel{…} 或者stages{…}。

post用来定义将在Pipeline结束或stage结束时运行的操作。支持的post有: always,changed,failure,success,unstable,aborted。这些块允许在Pipeline运行或stage结束时执行步骤,具体取决于Pipeline的状态。

还可以在parallel块中声明多个嵌套stage,这些stage将并行执行。需要注意的是一个stage有且只能有一个stepsstagesparallel。示例如下:

pipeline {
    agent any
    stages {
        stage('Non-Parallel Stage') {
            steps {
                echo 'This stage will be executed first.'
            }
        }
        stage('Parallel Stage') {
            parallel {
                stage('Branch A') {
                    agent {
                        label "for-branch-a"
                    }
                    steps {
                        echo "On Branch A"
                    }
                }
                stage('Branch B') {
                    agent {
                        label "for-branch-b"
                    }
                    steps {
                        echo "On Branch B"
                    }
                }
                stage('Branch C') {
                    agent {
                        label "for-branch-c"
                    }
                    stages {
                        stage('Nested 1') {
                            steps {
                                echo "In stage Nested 1 within Branch C"
                            }
                        }
                        stage('Nested 2') {
                            steps {
                                echo "In stage Nested 2 within Branch C"
                            }
                        }
                    }
                }
            }
        }
    }
}

如果想在Declarative Pipeline中使用if判断、for循环等语句,那么需要使用script语句块,示例如下:

pipeline {
    agent any
    stages {
        stage('Example') {
            steps {
                echo 'Hello World'
​
                script {
                    def browsers = ['chrome', 'firefox']
                    for (int i = 0; i < browsers.size(); ++i) {
                        echo "Testing the ${browsers[i]} browser"
                    }
                }
            }
        }
    }
}

Scripted Pipeline

Scripted Pipeline是基于Groovy来编码的pipeline,Groovy是基于JVM的脚本语言。由Groovy语言提供的大多数功能,都可以在Scripted Pipeline中使用。这使得Scripted Pipeline成为了一个非常富有表现力和灵活性的模式。在Scripted Pipeline可以自由的使用if、for语句,还可以调用各种Groovy中的函数,比如String.split、String.replace等等。一个简单的Scripted Pipeline示例如下:

node {
    stage('Example') {
        if (env.BRANCH_NAME == 'master') {
            echo 'I only execute on the master branch'
        } else {
            echo 'I execute elsewhere'
        }
    }
}

该pipeline也可以node('Node name') {}来开头,Node name就是从节点或master节点的名称。

Scripted Pipeline自身没有过多限制,可以自由组织代码流程。

在Scripted Pipeline中,处理错误行为需要使用Groovy 中的try/catch/finally块,例如:

node {
    stage('Example') {
        try {
            sh 'exit 1'
        }
        catch (exc) {
            echo 'Something failed, I should sound the klaxons!'
            throw
        }
    }
}

Declarative Pipeline vs Scripted Pipeline

在pipeline模式支持先后上,Scripted Pipeline是最开始被Jenkins支持的,Declarative Pipeline稍晚。如果是简单的工作流,那么可以选择使用Declarative Pipeline,如果是复杂的工作流或者掺杂了复杂的业务逻辑,那么Scripted Pipeline是更为灵活的一种编写方式。

有关两种Pipeline模式的详细语法,可以参考官方文档:Pipeline Syntax

在SCM中管理Pipeline

对于复杂的Pipeline,在Jenkins的UI中去编写和维护Pipeline是非常困难的。为了解决这个问题,Jenkins pipeline支持编写Jenkinsfile,然后将Jenkinsfile存放在SCM中,这样便增加了协作性,而且也可以享受到用IDE编写Pipeline job的好处。


版权声明:本文为csflying原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。