Skip to content

1. Lark Notice介绍

Lark Notice Plugin 是一个用于 Jenkins 的构建通知插件,可以将 Jenkins构建过程以及结果通知推送到 Lark、飞书、钉钉 协作平台。 可配置多个的通知时机,包括 构建启动时、构建中断、构建失败、构建成功时、构建不稳定 等。 支持多种不同类型的消息,包括 文本消息、图片消息, 群名片消息、富文本消息、卡片消息; 同时该插件还提供了自定义模板和变量的功能,使您能够根据自己的需求来定制通知消息的内容和格式

2. 安装插件

版本依赖,jenkins-2.414.x

Lark Notice(通过上传文件的方式安装)https://721806280.github.io/lark-notice-plugin-doc/

从 Jenkins 首页开始,点击 系统管理 -> 插件管理 , 找到 Deploy Plugin 选项后输入插件地址后点击 deploy 即可

下载地址,https://nnaigos.oss-cn-hangzhou.aliyuncs.com/lark-notice.hpi

3. 机器人配置

3.2 申请机器人

准备工作,在飞书群新建一个机器人(https://open.feishu.cn/document/client-docs/bot-v3/add-custom-bot)

image-20240806152312416

  • 配置关键字

image-20240806152402605

之后保存即可

3.2 配置

打开 Manage Jenkins 页面,找到 Lark Notice 配置项,如下图所示:

image-20240806151104482

点进去

image-20240806151920843

image-20240806152150780

  • 测试

image-20240806152439213

  • 效果

image-20240806152507635

  • 重启jenkins服务
bash
http://url/safeRestart
http://url/safeRestart

4. 线上案例

bash
def git_address = "http://house.freehan.ink/root/springdemo.git"
def git_auth = "02d72dd6-0eab-4261-b0c0-12824e083421"
def tag = "latest"
def harbor_url = "registry.cn-zhangjiakou.aliyuncs.com"
def harbor_project_name = "spring"
def harbor_auth = "1e7ee468-9da7-469b-a43a-56556b56f308"
def start = new Date().format('yyyy-MM-dd HH:mm:ss')

// 通知机器人配置
def lark_robot_id = "55d84e77-d1c5-4b1c-9e0f-ea1630b4e236'"  // 飞书机器人ID

podTemplate(label: 'jenkins-slave-java', cloud: 'kubernetes', containers: [ 
    containerTemplate(
        name: 'jnlp',
        image: "registry.cn-zhangjiakou.aliyuncs.com/hsuing/jenkins-slave-maven:v1",
        ttyEnabled: true
    ),
    containerTemplate(
        name: 'docker',
        image: "registry.cn-zhangjiakou.aliyuncs.com/hsuing/docker:stable",
        ttyEnabled: true,
        command: 'cat'
    )
  ],
  volumes: [
    hostPathVolume(mountPath: '/var/run/docker.sock', hostPath:'/var/run/docker.sock'),
  ],
)
{
    node("jenkins-slave-java") {
        try {
            stage('拉取代码') {
                checkout([$class: 'GitSCM', branches: [[name: '*/main']], extensions: [], userRemoteConfigs: [[credentialsId: git_auth, url: git_address]]])
            }
            //定义全局newTag
			def newTag = sh(returnStdout: true,script: 'echo `date +"%Y%m%d%H%M"_``git describe --tags --always`').trim()
			stage('编译描述') {
				// 自定义设置构建历史显示的名称和描述信息
				// 不同的部署方式设置构建历史显示的名称和描述信息方式不一样,根据自己的部署方式自行百度找到设置方法
				script {
					//设置buildName
					wrap([$class: 'BuildUser']) {
						//修改Description
						buildDescription "${BUILD_USER} > ${project_name} > ${branch}"
					}
				}
			}
            stage('代码编译') {
                def selectedProjects = project_name.split(',')
                selectedProjects.each { currentProjectName ->
                    def imageName = "${currentProjectName}:${tag}"
                    //def newTag = sh(returnStdout: true, script: 'echo `date +"%Y%m%d%H%M"_``git describe --tags --always`').trim()
                    sh "mvn clean package -Dmaven.test.skip=true"
                }
            }
			
            stage('构建镜像') {
                def selectedProjects = project_name.split(',')
                container('docker') {
                    selectedProjects.each { currentProjectName ->
                        def imageName = "${currentProjectName}:${tag}"
                        //def newTag = sh(returnStdout: true, script: 'echo `date +"%Y%m%d%H%M"_``git describe --tags --always`').trim()
                        sh "docker build -t ${imageName} ."
                        sh "docker tag ${imageName} ${harbor_url}/hsuing/${harbor_project_name}:${newTag}"
                        withCredentials([usernamePassword(credentialsId: harbor_auth, passwordVariable: 'password', usernameVariable: 'username')]) {
							//登录
                            sh "docker login -u ${username} -p ${password} ${harbor_url}"
                            //上传镜像
                            sh "docker push ${harbor_url}/hsuing/${harbor_project_name}:${newTag}"
                        }
                        //删除本地镜像
                        sh "docker rmi -f ${imageName}"
                        sh "docker rmi -f ${harbor_url}/hsuing/${harbor_project_name}:${newTag}"
                    }
                }
            }

            stage('部署到k8s平台') {
                def selectedProjects = project_name.split(',')
                selectedProjects.each { currentProjectName ->
                    //def newTag = sh(returnStdout: true, script: 'echo `date +"%Y%m%d%H%M"_``git describe --tags --always`').trim()
                    def deploy_image_name = "${harbor_url}/hsuing/${harbor_project_name}:${newTag}"
                    sh """
                        sed -i 's#\$IMAGE_NAME#${deploy_image_name}#' deployment.yaml
                        sed -i 's#\$APP_NAME#${currentProjectName}#'  deployment.yaml
                        sed -i 's#\$APP_REPLICAS#${replicas}#' deployment.yaml
                        sed -i 's#\$NAMESPACE#${namespaces}#' deployment.yaml
                        sed -i 's#\$SPRINGENV#${springProfilesActive}#' deployment.yaml
                        sed -i 's#\$PODMEMORY#${podsMem}#' deployment.yaml
                        sed -i 's#\$PODCPU#${podsCpu}#' deployment.yaml
                        cat deployment.yaml
                    """
                    kubernetesDeploy(kubeconfigId: "55a88b59-fd12-4bf0-ba57-8a664fed2f71", configs: "deployment.yaml")
                }
            }

            stage('发送飞书通知') {
                // 获取执行用户
                wrap([$class: 'BuildUser']) {
                    // 发送飞书通知
                    lark (
                        robot: "$lark_robot_id",
                        type: "CARD",
                        title: "📢  Jenkins 镜像构建成功",
                        text: [
                            "📋 **任务名称**:[${JOB_NAME}](${JOB_URL})",
                            "🔢 **任务编号**:[${BUILD_DISPLAY_NAME}](${BUILD_URL})",
                            "🌟 **构建状态**: <font color='green'>成功</font>",
                            "🤩 **镜像版本**: ${newTag}",
                            "😎 **镜像仓库**: ${harbor_url}/hsuing/${harbor_project_name}",
                            "🕐 **构建用时**: ${currentBuild.duration} ms",
                            "👤 **执行者**: ${env.BUILD_USER}",
                            "<at id=all></at>"
                        ],
                        buttons: [
                            [
                                title: "更改记录",
                                url: "${BUILD_URL}changes"
                            ],
                            [
                                title: "控制台",
                                type: "danger",
                                url: "${BUILD_URL}console"
                            ]
                        ]
                    )
                }
            }

        } catch (Exception e) {
            currentBuild.result = 'FAILURE'
            error "Pipeline failed: ${e.message}"
        }
    }
}
def git_address = "http://house.freehan.ink/root/springdemo.git"
def git_auth = "02d72dd6-0eab-4261-b0c0-12824e083421"
def tag = "latest"
def harbor_url = "registry.cn-zhangjiakou.aliyuncs.com"
def harbor_project_name = "spring"
def harbor_auth = "1e7ee468-9da7-469b-a43a-56556b56f308"
def start = new Date().format('yyyy-MM-dd HH:mm:ss')

// 通知机器人配置
def lark_robot_id = "55d84e77-d1c5-4b1c-9e0f-ea1630b4e236'"  // 飞书机器人ID

podTemplate(label: 'jenkins-slave-java', cloud: 'kubernetes', containers: [ 
    containerTemplate(
        name: 'jnlp',
        image: "registry.cn-zhangjiakou.aliyuncs.com/hsuing/jenkins-slave-maven:v1",
        ttyEnabled: true
    ),
    containerTemplate(
        name: 'docker',
        image: "registry.cn-zhangjiakou.aliyuncs.com/hsuing/docker:stable",
        ttyEnabled: true,
        command: 'cat'
    )
  ],
  volumes: [
    hostPathVolume(mountPath: '/var/run/docker.sock', hostPath:'/var/run/docker.sock'),
  ],
)
{
    node("jenkins-slave-java") {
        try {
            stage('拉取代码') {
                checkout([$class: 'GitSCM', branches: [[name: '*/main']], extensions: [], userRemoteConfigs: [[credentialsId: git_auth, url: git_address]]])
            }
            //定义全局newTag
			def newTag = sh(returnStdout: true,script: 'echo `date +"%Y%m%d%H%M"_``git describe --tags --always`').trim()
			stage('编译描述') {
				// 自定义设置构建历史显示的名称和描述信息
				// 不同的部署方式设置构建历史显示的名称和描述信息方式不一样,根据自己的部署方式自行百度找到设置方法
				script {
					//设置buildName
					wrap([$class: 'BuildUser']) {
						//修改Description
						buildDescription "${BUILD_USER} > ${project_name} > ${branch}"
					}
				}
			}
            stage('代码编译') {
                def selectedProjects = project_name.split(',')
                selectedProjects.each { currentProjectName ->
                    def imageName = "${currentProjectName}:${tag}"
                    //def newTag = sh(returnStdout: true, script: 'echo `date +"%Y%m%d%H%M"_``git describe --tags --always`').trim()
                    sh "mvn clean package -Dmaven.test.skip=true"
                }
            }
			
            stage('构建镜像') {
                def selectedProjects = project_name.split(',')
                container('docker') {
                    selectedProjects.each { currentProjectName ->
                        def imageName = "${currentProjectName}:${tag}"
                        //def newTag = sh(returnStdout: true, script: 'echo `date +"%Y%m%d%H%M"_``git describe --tags --always`').trim()
                        sh "docker build -t ${imageName} ."
                        sh "docker tag ${imageName} ${harbor_url}/hsuing/${harbor_project_name}:${newTag}"
                        withCredentials([usernamePassword(credentialsId: harbor_auth, passwordVariable: 'password', usernameVariable: 'username')]) {
							//登录
                            sh "docker login -u ${username} -p ${password} ${harbor_url}"
                            //上传镜像
                            sh "docker push ${harbor_url}/hsuing/${harbor_project_name}:${newTag}"
                        }
                        //删除本地镜像
                        sh "docker rmi -f ${imageName}"
                        sh "docker rmi -f ${harbor_url}/hsuing/${harbor_project_name}:${newTag}"
                    }
                }
            }

            stage('部署到k8s平台') {
                def selectedProjects = project_name.split(',')
                selectedProjects.each { currentProjectName ->
                    //def newTag = sh(returnStdout: true, script: 'echo `date +"%Y%m%d%H%M"_``git describe --tags --always`').trim()
                    def deploy_image_name = "${harbor_url}/hsuing/${harbor_project_name}:${newTag}"
                    sh """
                        sed -i 's#\$IMAGE_NAME#${deploy_image_name}#' deployment.yaml
                        sed -i 's#\$APP_NAME#${currentProjectName}#'  deployment.yaml
                        sed -i 's#\$APP_REPLICAS#${replicas}#' deployment.yaml
                        sed -i 's#\$NAMESPACE#${namespaces}#' deployment.yaml
                        sed -i 's#\$SPRINGENV#${springProfilesActive}#' deployment.yaml
                        sed -i 's#\$PODMEMORY#${podsMem}#' deployment.yaml
                        sed -i 's#\$PODCPU#${podsCpu}#' deployment.yaml
                        cat deployment.yaml
                    """
                    kubernetesDeploy(kubeconfigId: "55a88b59-fd12-4bf0-ba57-8a664fed2f71", configs: "deployment.yaml")
                }
            }

            stage('发送飞书通知') {
                // 获取执行用户
                wrap([$class: 'BuildUser']) {
                    // 发送飞书通知
                    lark (
                        robot: "$lark_robot_id",
                        type: "CARD",
                        title: "📢  Jenkins 镜像构建成功",
                        text: [
                            "📋 **任务名称**:[${JOB_NAME}](${JOB_URL})",
                            "🔢 **任务编号**:[${BUILD_DISPLAY_NAME}](${BUILD_URL})",
                            "🌟 **构建状态**: <font color='green'>成功</font>",
                            "🤩 **镜像版本**: ${newTag}",
                            "😎 **镜像仓库**: ${harbor_url}/hsuing/${harbor_project_name}",
                            "🕐 **构建用时**: ${currentBuild.duration} ms",
                            "👤 **执行者**: ${env.BUILD_USER}",
                            "<at id=all></at>"
                        ],
                        buttons: [
                            [
                                title: "更改记录",
                                url: "${BUILD_URL}changes"
                            ],
                            [
                                title: "控制台",
                                type: "danger",
                                url: "${BUILD_URL}console"
                            ]
                        ]
                    )
                }
            }

        } catch (Exception e) {
            currentBuild.result = 'FAILURE'
            error "Pipeline failed: ${e.message}"
        }
    }
}
  • 效果

image-20240815150401558

  • 报警效果

image-20240815150447789