jenkins 多分枝流水线(pipeline)及 美化通知消息

之前 我们已经通过 Jenkinsfile 完成了最简单的项目的构建和部署(部署这里暂时没有更新文章),那么我们来思考目前的方式:

  1. 目前都是在项目的单一分支下进行操作,企业内一般会使用feature、develop、release、master 等多个分支来管理整个代码提交流程,如何根据不同的分支来做构建?
  2. 构建视图中如何区分不同的分支?
  3. 如何不配置webhook的方式实现构建?
  4. 如何根据不同的分支选择发布到不同的环境(开发、测试、生产)?

多分枝流水线

官方示例

我们简化一下流程,假如使用develop分支作为开发分支,master分支作为集成测试分支,看一下如何 使用多分支流水线来管理。

多分支流水线的使用

  1. 提交develop分支:

    # 直接创建分枝并提交
    git checkout -b dev
    git push --set-upstream origin dev
    
  2. jenkins 创建一个多分支项目

    image-20220726144036480

    image-20220726144226322

    1. 增加git分支源

    2. 发现标签、分支

    3. 根据名称过滤,develop|master|v.*

      可以根据正则表达式,选择哪些分支可以去构建jenkins任务

      image-20220726164011123

    4. 高级克隆,设置浅克隆

      浅克隆深度为2,表示只拉取最近两次的变更记录;节约磁盘;

      image-20220726144748786

    保存后,会自动检索项目中所有存在Jenkinsfile文件的分支和标签,若匹配我们设置的过滤正则表达 式,则会添加到多分支的构建视图中。所有添加到视图中的分支和标签,会默认执行一次构建任务。

image-20220726144940553

上图表示,这次匹配的分支中带有jenkinsfile 的分支。继续形成构建视图;往下走;没有jenkinsfile 的分支被丢弃;不参与构建任务;

image-20220726145128323

表示 创建一个触发器,每分钟去扫描符合上述条件的分支;

这样的话,就不需要去配置触发器了;这里使用jenkins自己的扫描来做;这就可能会带来延迟;并且给jenkins带来一些额外的扫描压力;

当我们保存项目后,默认jenkins会自动去扫描一次;识别到匹配的扫描,jenkins就会触发构建任务;

保存后如下图:

image-20220726145802216

识别了两个分支,一个为 dev 另外一个为 main;

因为我们没有为测试代码打标签;所以没有扫描到标签;

美化通知消息

因为以前是单分支,现在是多分枝;

所以推送的消息也应该做一些格式上的修改;

  • 增加分支消息;
  • 将推送消息写成markdown格式(支持加粗、等)
  • 增加 gitlog 输出

如下:

// # Jekinsfile 中调用
// # cat Jenkinsfile
pipeline {
    agent { label '10.23.1.33'}

    environment {
    		IMAGE_REPO = "myblog"
        //顶层流水线块中使用的 environment 指令将适用于流水线中的所有步骤。
        // 获取 dingTalk 的密文
        DINGTALK_CREDS = credentials('97bd1f06-a2c7-48fa-83aa-b10de2c6a2fd')
        // 做了个换行
        TAB_STR = "\n                 \n                    "
    }

    stages {
        stage('printenv') {
            steps {
            		script{
                    sh "git log --oneline -n 1 > gitlog.file"
                    env.GIT_LOG = readFile("gitlog.file").trim()
                }
                echo 'Hello World'
                sh 'printenv'
            }
        }
        stage('check') {
            steps {
                checkout scm
                script{
                		// 每个 stage 环节都更新了一个 env.BUILD_TASKS 环境变量
                		// 在哪个 stage 中,该环境变量就是谁,在该stage中 该变量 == check
                    env.BUILD_TASKS = env.STAGE_NAME + "✓..." + env.TAB_STR
                }
            }
        }
        stage('build-image') {
            steps {
            		// 重试两次
            		retry(2) { sh 'docker build . -t ${IMAGE_REPO}:${GIT_COMMIT}'}
                script{
                    env.BUILD_TASKS += env.STAGE_NAME + "✓..." + env.TAB_STR
                }
            }
        }
        stage('push-image') {
            steps {
            		// 因为这里咱们没有做 容器仓库,所以这里不 push ,写出来只为了线上可以参考
                // retry(2) { sh 'docker push ${IMAGE_REPO}:${GIT_COMMIT}'}
                script{
                    env.BUILD_TASKS += env.STAGE_NAME + "✓..." + env.TAB_STR
                }
            }
        }
        stage('deploy') {
            steps {
            		// 同样这里没有部署的环节,写出来只为了线上参考
                // sh "sed -i 's#{{IMAGE_URL}}#${IMAGE_REPO}:${GIT_COMMIT}#g' deploy/*"
                // timeout(time: 1, unit: 'MINUTES') {
                //     sh "kubectl apply -f deploy/"
                // }
                script{
                    env.BUILD_TASKS += env.STAGE_NAME + "✓..." + env.TAB_STR
                }
            }
        }
    }
    post {
        success {
            echo 'Congratulations!'
            sh """
                curl 'https://oapi.dingtalk.com/robot/send?access_token=${DINGTALK_CREDS_PSW}' \
                    -H 'Content-Type: application/json' \
                    -d '{
                        "msgtype": "markdown",
                        "markdown": {
                            "title":"myblog",
                            "text": "🐮 构建成功 🐮  \n**项目关键字**:jenkins-hk  \n**Git log**: ${GIT_LOG}   \n**构建分支**: ${GIT_BRANCH}  \n**构建地址**:${RUN_DISPLAY_URL}  \n**构建任务**:${BUILD_TASKS}"
                        }
                    }'
            """
        }
        failure {
            echo 'Oh no!'
            sh """
                curl 'https://oapi.dingtalk.com/robot/send?access_token=${DINGTALK_CREDS_PSW}' \
                    -H 'Content-Type: application/json' \
                    -d '{
                        "msgtype": "markdown",
                        "markdown": {
                            "title":"myblog",
                            "text": "😖❌ 构建失败 ❌😖  \n**项目关键字**:jenkins-hk  \n**Git log**: ${GIT_LOG}   \n**构建分支**: ${GIT_BRANCH}  \n**构建地址**:${RUN_DISPLAY_URL}  \n**构建任务**:${BUILD_TASKS}"
                        }
                    }'
            """
        }
        always {
            echo 'I will always say Hello again!'
        }
    }
}

消息通知界面:

image-20220726164127129

通知gitlab构建状态

Jenkins端做了构建,可以通过gitlab的api将构建状态通知过去,作为开发人员发起Merge Request或者合并Merge Request的依据之一。

注意一定要指定 gitLabConnection (gitlab),不然没法认证到 Gitlab 端

gitlab 配置

需要用的如下的 gitlab 名称:gitlab-hk

系统管理 -> 系统配置 -> gitlab

image-20220726155950744

// # Jekinsfile 中调用
// # cat Jenkinsfile
pipeline {
    agent { label '10.23.1.33'}

    options {
    		// 构建历史 保留 10 条
        buildDiscarder(logRotator(numToKeepStr: '10'))
        disableConcurrentBuilds()
        timeout(time: 20, unit: 'MINUTES')
        // gitlab connection 
        gitLabConnection('gitlab-hk')
		}

    environment {
    		IMAGE_REPO = "myblog"
        //顶层流水线块中使用的 environment 指令将适用于流水线中的所有步骤。
        // 获取 dingTalk 的密文
        DINGTALK_CREDS = credentials('97bd1f06-a2c7-48fa-83aa-b10de2c6a2fd')
        // 做了个换行
        TAB_STR = "\n                 \n                    "
    }

    stages {
        stage('printenv') {
            steps {
            		script{
                    sh "git log --oneline -n 1 > gitlog.file"
                    env.GIT_LOG = readFile("gitlog.file").trim()
                }
                echo 'Hello World'
                sh 'printenv'
            }
        }
        stage('check') {
            steps {
                checkout scm
                updateGitlabCommitStatus(name: env.STAGE_NAME, state: 'success')
                script{
                		// 每个 stage 环节都更新了一个 env.BUILD_TASKS 环境变量
                		// 在哪个 stage 中,该环境变量就是谁,在该stage中 该变量 == check
                    env.BUILD_TASKS = env.STAGE_NAME + "✓..." + env.TAB_STR
                }
            }
        }
        stage('build-image') {
            steps {
            		// 重试两次
            		retry(2) { sh 'docker build . -t ${IMAGE_REPO}:${GIT_COMMIT}'}
                updateGitlabCommitStatus(name: env.STAGE_NAME, state: 'success')
                script{
                    env.BUILD_TASKS += env.STAGE_NAME + "✓..." + env.TAB_STR
                }
            }
        }
        stage('push-image') {
            steps {
            		// 因为这里咱们没有做 容器仓库,所以这里不 push ,写出来只为了线上可以参考
                // retry(2) { sh 'docker push ${IMAGE_REPO}:${GIT_COMMIT}'}
                updateGitlabCommitStatus(name: env.STAGE_NAME, state: 'success')
                script{
                    env.BUILD_TASKS += env.STAGE_NAME + "✓..." + env.TAB_STR
                }
            }
        }
        stage('deploy') {
            steps {
            		// 同样这里没有部署的环节,写出来只为了线上参考
                // sh "sed -i 's#{{IMAGE_URL}}#${IMAGE_REPO}:${GIT_COMMIT}#g' deploy/*"
                // timeout(time: 1, unit: 'MINUTES') {
                //     sh "kubectl apply -f deploy/"
                // }
                updateGitlabCommitStatus(name: env.STAGE_NAME, state: 'success')
                script{
                    env.BUILD_TASKS += env.STAGE_NAME + "✓..." + env.TAB_STR
                }
            }
        }
    }
    post {
        success {
            echo 'Congratulations!'
            sh """
                curl 'https://oapi.dingtalk.com/robot/send?access_token=${DINGTALK_CREDS_PSW}' \
                    -H 'Content-Type: application/json' \
                    -d '{
                        "msgtype": "markdown",
                        "markdown": {
                            "title":"myblog",
                            "text": "🐮 构建成功 🐮  \n**项目关键字**:jenkins-hk  \n**Git log**: ${GIT_LOG}   \n**构建分支**: ${GIT_BRANCH}  \n**构建地址**:${RUN_DISPLAY_URL}  \n**构建任务**:${BUILD_TASKS}"
                        }
                    }'
            """
        }
        failure {
            echo 'Oh no!'
            sh """
                curl 'https://oapi.dingtalk.com/robot/send?access_token=${DINGTALK_CREDS_PSW}' \
                    -H 'Content-Type: application/json' \
                    -d '{
                        "msgtype": "markdown",
                        "markdown": {
                            "title":"myblog",
                            "text": "😖❌ 构建失败 ❌😖  \n**项目关键字**:jenkins-hk  \n**Git log**: ${GIT_LOG}   \n**构建分支**: ${GIT_BRANCH}  \n**构建地址**:${RUN_DISPLAY_URL}  \n**构建任务**:${BUILD_TASKS}"
                        }
                    }'
            """
        }
        always {
            echo 'I will always say Hello again!'
        }
    }
}

image-20220726163525715

构建之后,会有一个这样的状态;

提交merge request,也可以查看到相关的任务状态,可以作为项目owner合并代码的依据之一:

posted @ 2022-07-26 16:38  Star-Hitian  阅读(1093)  评论(0编辑  收藏  举报