02. CI/CD - Jenkins Pipeline(声明式语法)

Pipeline

Pipeline 是一套运行在 Jenkins 上的工作流框架,它能将原来独立运行于单个或者多个节点的任务连接起来,实现单个任务难以完成的复杂流程编排和可视化的工作。

关于 Jenkins Pipeline:

  • Pipeline 脚本是由 Groovy 语言实现的,但是没必要单独去学习 Groovy。
  • Pipeline 支持两种语法:Declarative(声明式)和 Scripted Pipeline(脚本式)。
  • Pipeline 有两种创建方法:直接在 Jenkins 的 Web UI 中输入脚本,通过创建一个 Jenkinsfile 脚本文件放入项目源码库中使用。
  • 一般推荐在 Jenkins 中直接从源代码控制(SCMD)中直接载入 Jenkinsfile Pipeline 这种方法。

在使用之前,需要在 Jenkins 中安装三个插件:

  • Blue Ocean:相当于 Jenkins 的 Pipeline 流水线主题。
  • Pipeline:Pipeline 支持的核心插件。
  • Pipeline: Stage View:用于在传统界面查看 Pipeline Stage。

安装后从侧边栏打开 Blue Ocean 如图所示:

更多关于 Pipeline 的信息可以在官方文档中看到:

https://www.jenkins.io/doc/book/pipeline/

创建 Pipeline

安装 Pipeline 插件之后,再次创建构建就需要选择 流水线 方式的构建了:

如图所示:


这是系统提供的 hello world pipeline 示例:

pipeline {
    agent any

    stages {
        stage('Hello') {
            steps {
                echo 'Hello World'
            }
        }
    }
}

通过该示例可以发现,Pipeline 核心概念包含三个:

  • agent:指定执行节点。
  • stages:声明步骤。
  • steps:该步骤具体执行的方法。

执行后查看:

如果 Pipeline 存在问题,可以通过左边的 回放 进行修改调试,等到没问题之后再复制 Pipeline 到配置里面去。


注意,当项目很多的时候,流水线也会很多。它们大致的信息是一样的,如果后期想要修改某个公共的方法,就需要一个一个的去修改构建项目,很麻烦。所以推荐使用版本仓库 Git 对 Pipeline 文件进行统一管理。

声明式语法

声明式语法是 Jenkins Pipeline 内置的方法,它包含系统本身自带的和安装插件之后新增的。

想要使用声明式语法很简单,直接打开 Jenkins 流水线语法生成即可:


用法如图:


其中系统自带的变量也非常重要,这里主要列举几个常用的:

  • env:
    • BRANCH_NAME:Git 分支名称
    • TAG_NAME:标签名称
    • BUILD_NUMBER:本次构建的 ID
    • JOB_NAME:完整的任务名称,可以是 foo 或者 foo/bar
    • JOB_BASE_NAME:精简的任务名称,如果名称是 foo/bar,则值是 bar
    • NODE_NAME:执行节点的名称
    • JENKINS_URL:访问地址 http://server:port/
    • JOB_URL:任务地址 http://server:port/job/foo/
    • BUILD_URL:构建地址 http://server:port/job/foo/15/

节点选择(agent)

支持在 pipelinestage 模块中定义,示例:

pipeline {
    // 任意 agent 上面执行
    agent any

    // 在指定标签的 agent 上运行,在 Kubernetes 环境下比较实用
    // agent {
    //     label 'base'
    // }

    // 步骤
    stages {
        stage('节点选择测试') {
            steps {
                echo "Hello World"
            }
        }
    }
}

变量定义(environment)

支持在 pipelinestage 模块中定义,示例:

pipeline {
    // 定义全局环境变量,
    environment {
        NAME_GLOBAL = "hello"
        AGE_GLOBAL = "18"
    }
    
    agent any
    stages {
        stage('环境变量测试') {
            // 定义局部环境变量
            environment {
                NAME_LOCAL = "world"
                AGE_LOCAL = "20"
            }

            steps {
                // 输出变量信息,注意,变量使用和 Shell 中一样,单引号则会原样输出
                echo "全局变量:${NAME_GLOBAL}-${AGE_GLOBAL}"
                echo "局部变量:${NAME_LOCAL}-${AGE_LOCAL}"
                // 输出系统变量,在使用的时候也可以使用 ${env.BUILD_NUMBER} 这种形式
                echo "构建ID:${BUILD_NUMBER}"
                echo "任务名称:${JOB_NAME}"
                echo "任务名称简写:${JOB_BASE_NAME}"
                echo "节点名称:${NODE_NAME}"
                echo "Jenkins 地址:${JENKINS_URL}"
                echo "任务地址:${JOB_URL}"
                echo "构建地址:${BUILD_URL}"
            }
        }
    }
}

参数化构建(parameters)

支持在 pipeline 模块中定义,示例:

pipeline {
    // 参数和变量的使用方法类似,但是参数支持更多的类型
    parameters {
        booleanParam defaultValue: true, description: '布尔参数', name: 'BOOL_PARAM'
        choice choices: ['java', 'python', 'golang'], description: '选项参数', name: 'CHOICE_PARAM'
        string defaultValue: 'hello world', description: '字符串参数', name: 'STRING_PARAM', trim: true
    }

    agent any
    stages {
        stage('参数化构建测试') {
            steps {
                // 参数化构建的值调用需要 ${params.xxx} 的方式
                echo "布尔参数:${params.BOOL_PARAM}"
                echo "选项参数:${params.CHOICE_PARAM}"
                echo "字符串参数:${params.STRING_PARAM}"
            }
        }
    }
}

在参数化构建第一次执行后,Jenkins 任务会变成参数化构建配置:

构建设置(options)

支持在 pipeline 模块中定义,示例:

pipeline {
    // 构建设置
    options {
        // 用的比较多的就是 buildDiscarder(丢弃旧的构建)
        buildDiscarder logRotator(artifactDaysToKeepStr: '', artifactNumToKeepStr: '', daysToKeepStr: '7', numToKeepStr: '10')
        disableConcurrentBuilds()
    }
    agent any
    stages {
        stage('构建设置') {
            steps {
                echo "hello world"
            }
        }
    }
}

构建后续(post)

根据构建结果判断下一步做什么,支持在 pipelinestage 模块中定义,示例:

pipeline {
    agent any
    stages {
        stage('构建后续') {
            steps {
                echo "hello world"
                sleep 30
            }
        }
    }

    // 该配置类似与其它编程语言的 switch,在 Jenkins 中一般用于发通知
    post {
        // 无论如何都会执行
        always {
            echo "always"
        }
        // 构建终止执行
        aborted {
            echo "aborted"
        }
        // 构建成功执行
        success {
            echo "success"
        }
        // 构建失败执行
        failure {
            echo "failure"
        }
    }
}

触发构建(triggers)

一般用于配置定时构建,支持在 pipeline 模块中定义,示例:

pipeline {
    // 每五分钟触发一次构建
    triggers {
        cron 'H/5 * * * *'
    }

    agent any
    stages {
        stage('触发构建') {
            steps {
                echo "hello world"
            }
        }
    }
}

用户输入(input)

用的不多,一般不会使用这种方法配置,支持在 stage 模块中定义,示例:

pipeline {
    agent any
    stages {
        stage('用户输入') {
            // 用户输入
            input {
                message '请选择想要发布的环境'
                ok '确认'
                // 用于接收执行这个 input 的用户
                submitterParameter 'INPUT_USER'
                parameters {
                    choice choices: ['test', 'dev', 'prod'], description: '发布环境', name: 'ENV_NAME'
                }
            }

            steps {
                echo "执行的用户是:${INPUT_USER}"
            }
        }
    }
}

根据情况执行(when)

一般在多条件的情况下会使用到它,支持在 stage 模块中定义,示例:

pipeline {
    agent any
    stages {
        stage('用户输入') {
            // 用户输入
            input {
                message '请选择想要发布的环境'
                ok '确认'
                parameters {
                    choice choices: ['test', 'dev', 'prod'], description: '发布环境', name: 'ENV_NAME'
                }
            }
            steps {
                echo "hello world"
                // 定义全局变量,让后面使用到它,注意,变量需要括起来
                script {
                    env.ENV_NAME = "${ENV_NAME}"
                }
            }
        }

        stage('生产环境') {
            when {
                environment name: 'ENV_NAME', value: 'prod'
            }
            steps {
                echo "开始发布生产环境"
            }
        }

        stage('其它环境') {
            when {
                anyOf {
                    environment name: 'ENV_NAME', value: 'test'
                    environment name: 'ENV_NAME', value: 'dev'
                }
            }
            steps {
                echo "开始发布其它环境"
            }
        }

        stage('发布完成') {
            steps {
                echo "发布完成"
            }
        }
    }
}

以上就是 Jenkins Pipeline 自带的常用声明式语法。

其它方法

除此上面自带的方法之外,用户在安装插件之后也会新增一些语法。这些都可以使用 片段生成器 直接生成。

其中常用的包含:

  • build:触发另外一个构建
  • deleteDir:删除目录
  • dir:切换目录,然后执行
  • echo:输出自定义内容
  • error:手动抛出错误
  • fileExists:判断文件是否存在
  • git:用于拉取代代码
  • parallel:用于并行执行
  • retry:重试
  • script:嵌入 Groovy 脚本
  • sh:执行脚本
  • sleep:等待时间
  • timeout:超时时间
posted @ 2023-04-07 17:24  Dy1an  阅读(335)  评论(0编辑  收藏  举报