Skip to content

Jenkins Pipeline 配置企业微信通知

目前 Jenkins 有自带的 qy-wechat-notification-plugin这个插件可以直接配置企业微信机器人的 Webhook 地址,即可实现build之后进行企业微信通知的功能。但是这个插件只能在 Freestyle project 等带有 Post build action 的Project中调用 若 Project 为 Pipeline ,那么是无法直接调用此插件,原因是Pipeline中没有Post-build Actions这个参数

send_message.sh

#!/bin/sh
# 此脚本可实现jenkins往企业微信和钉钉推送消息

usage(){
	echo "usage: $0 TYPE TITLE CONTENT [URL]"
	echo "       TYPE: wechat|dingtalk"
}

TYPE="$1"
TITLE="$2"
CONTENT="$3"
URL="$4"

CHAT_CONTENT_TYPE='Content-Type: application/json'
DEFAULT_PIC_URL="https://img-blog.csdnimg.cn/20191227152859635.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9saXVtaWFvY24uYmxvZy5jc2RuLm5ldA==,size_16,color_FFFFFF,t_70"
DINGTALK_DEFAULT_WORDS=" [LiuMiaoMsg]"
if [ $# -lt 3 ]; then
  usage
  exit 1
fi

if [ _"${TYPE}" = _"wechat" ]; then
  CHAT_WEBHOOK_URL='https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key'
elif [ _"${TYPE}" = _"dingtalk" ]; then
  CHAT_WEBHOOK_URL='https://oapi.dingtalk.com/robot/send?access_token'
else
  usage
  exit 1
fi

if [ _"${CHAT_WEBHOOK_KEY}" = _"" ]; then
  echo "please make sure CHAT_WEBHOOK_KEY has been exported as environment variable"
  usage
  exit 1
fi

if [ _"${URL}" = _"" ]; then
  URL="https://blog.csdn.net/Mr_rsq/article/details/110956983"
fi

echo "## send message for : ${TYPE}"
if [ _"${TYPE}" = _"wechat" ]; then
  curl "${CHAT_WEBHOOK_URL}=${CHAT_WEBHOOK_KEY}" \
   -H "${CHAT_CONTENT_TYPE}" \
   -d '
   {
        "msgtype": "news",
        "news": {
           "articles" : [
              {
                  "title" : "'"${TITLE}"'",
                  "description" : "'"${CONTENT}"'",
                  "url" : "'"${URL}"'",
                  "picurl" : "'"${DEFAULT_PIC_URL}"'"
              }
           ]
        }
   }'
elif [ _"${TYPE}" = _"dingtalk" ]; then
  curl "${CHAT_WEBHOOK_URL}=${CHAT_WEBHOOK_KEY}" \
   -H "${CHAT_CONTENT_TYPE}" \
   -d '
   {
    "msgtype": "link", 
    "link": {
        "text": "'"${CONTENT}${DINGTALK_DEFAULT_WORDS}"'", 
        "title": "'"${TITLE}"'", 
        "picUrl": "'"${DEFAULT_PIC_URL}"'", 
        "messageUrl": "'"${URL}"'"
    }
   }'
else
  usage
  exit 1
fi
#!/bin/sh
# 此脚本可实现jenkins往企业微信和钉钉推送消息

usage(){
	echo "usage: $0 TYPE TITLE CONTENT [URL]"
	echo "       TYPE: wechat|dingtalk"
}

TYPE="$1"
TITLE="$2"
CONTENT="$3"
URL="$4"

CHAT_CONTENT_TYPE='Content-Type: application/json'
DEFAULT_PIC_URL="https://img-blog.csdnimg.cn/20191227152859635.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9saXVtaWFvY24uYmxvZy5jc2RuLm5ldA==,size_16,color_FFFFFF,t_70"
DINGTALK_DEFAULT_WORDS=" [LiuMiaoMsg]"
if [ $# -lt 3 ]; then
  usage
  exit 1
fi

if [ _"${TYPE}" = _"wechat" ]; then
  CHAT_WEBHOOK_URL='https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key'
elif [ _"${TYPE}" = _"dingtalk" ]; then
  CHAT_WEBHOOK_URL='https://oapi.dingtalk.com/robot/send?access_token'
else
  usage
  exit 1
fi

if [ _"${CHAT_WEBHOOK_KEY}" = _"" ]; then
  echo "please make sure CHAT_WEBHOOK_KEY has been exported as environment variable"
  usage
  exit 1
fi

if [ _"${URL}" = _"" ]; then
  URL="https://blog.csdn.net/Mr_rsq/article/details/110956983"
fi

echo "## send message for : ${TYPE}"
if [ _"${TYPE}" = _"wechat" ]; then
  curl "${CHAT_WEBHOOK_URL}=${CHAT_WEBHOOK_KEY}" \
   -H "${CHAT_CONTENT_TYPE}" \
   -d '
   {
        "msgtype": "news",
        "news": {
           "articles" : [
              {
                  "title" : "'"${TITLE}"'",
                  "description" : "'"${CONTENT}"'",
                  "url" : "'"${URL}"'",
                  "picurl" : "'"${DEFAULT_PIC_URL}"'"
              }
           ]
        }
   }'
elif [ _"${TYPE}" = _"dingtalk" ]; then
  curl "${CHAT_WEBHOOK_URL}=${CHAT_WEBHOOK_KEY}" \
   -H "${CHAT_CONTENT_TYPE}" \
   -d '
   {
    "msgtype": "link", 
    "link": {
        "text": "'"${CONTENT}${DINGTALK_DEFAULT_WORDS}"'", 
        "title": "'"${TITLE}"'", 
        "picUrl": "'"${DEFAULT_PIC_URL}"'", 
        "messageUrl": "'"${URL}"'"
    }
   }'
else
  usage
  exit 1
fi

过使用curl命令的-d-H参数去模拟json格式的post请求,通过往send_message.sh脚本中传入titlepicUrl等参数,从而实现企业微信通知的功能

脚本使用: (1)在使用send_message脚本之前需要先配置CHAT_WEBHOOK_KEY

export CHAT_WEBHOOK_KEY=xxxxxxxxxx (2)然后直接执行脚本

bash send_message.sh wechat "rsq_test" "This is a test messages."

try-catch捕获build failed

try{
	node(LINUX) {
		stage('Build - Linux'){
			// build scripts ...
		} // stage
	} //node
} //try

catch (e){
	// 捕获错误,当Failed的时候给currentBuild.result赋值
	currentBuild.result = 'FAILURE'
} //catch

if(currentBuild.result == 'FAILURE') {
	node(env.BuildMachineLabel){
		stage("Post Build") {
			dir(env.ws_linux) {
				// 在使用send_message脚本之前需要先配置CHAT_WEBHOOK_KEY
				sh '''
				export CHAT_WEBHOOK_KEY=xxxxxxxxxx
				bash send_message.sh wechat "Linux %JOB_NAME% build failed." "URL: %BUILD_URL%" "%BUILD_URL%"
				'''
			} // dir
		} // stage
	} // node
} // if
try{
	node(LINUX) {
		stage('Build - Linux'){
			// build scripts ...
		} // stage
	} //node
} //try

catch (e){
	// 捕获错误,当Failed的时候给currentBuild.result赋值
	currentBuild.result = 'FAILURE'
} //catch

if(currentBuild.result == 'FAILURE') {
	node(env.BuildMachineLabel){
		stage("Post Build") {
			dir(env.ws_linux) {
				// 在使用send_message脚本之前需要先配置CHAT_WEBHOOK_KEY
				sh '''
				export CHAT_WEBHOOK_KEY=xxxxxxxxxx
				bash send_message.sh wechat "Linux %JOB_NAME% build failed." "URL: %BUILD_URL%" "%BUILD_URL%"
				'''
			} // dir
		} // stage
	} // node
} // if

通过Jenkins的内置变量,最后可以直接推送build failed的Job_url,执行如下命令

bash send_message.sh wechat "Ubuntu %JOB_NAME% build failed." "URL: %BUILD_URL%" "%BUILD_URL%"
bash send_message.sh wechat "Ubuntu %JOB_NAME% build failed." "URL: %BUILD_URL%" "%BUILD_URL%"

声明式脚本

pipeline {
    agent any 

    stages {
        stage('Build') { 
            steps { 
                sh 'echo Build stage ...' 
                sh 'export CHAT_WEBHOOK_KEY=your_owen_wechat_key_info; send_message.sh wechat "Build Stage" "Build Stage has been successfully completed..."'
            }
        }
        stage('Test'){
            steps {
                sh 'echo Test stage ...' 
                sh 'export CHAT_WEBHOOK_KEY=your_owen_wechat_key_info; send_message.sh wechat "Test Stage" "Test Stage has been successfully completed..."'

            }
        }
        stage('Deploy') {
            steps {
                sh 'echo Deploy stage ...' 
                sh 'export CHAT_WEBHOOK_KEY=your_owen_wechat_key_info; send_message.sh wechat "Deploy Stage" "Deploy Stage has been successfully completed..."'
            }
        }
    }
  }
pipeline {
    agent any 

    stages {
        stage('Build') { 
            steps { 
                sh 'echo Build stage ...' 
                sh 'export CHAT_WEBHOOK_KEY=your_owen_wechat_key_info; send_message.sh wechat "Build Stage" "Build Stage has been successfully completed..."'
            }
        }
        stage('Test'){
            steps {
                sh 'echo Test stage ...' 
                sh 'export CHAT_WEBHOOK_KEY=your_owen_wechat_key_info; send_message.sh wechat "Test Stage" "Test Stage has been successfully completed..."'

            }
        }
        stage('Deploy') {
            steps {
                sh 'echo Deploy stage ...' 
                sh 'export CHAT_WEBHOOK_KEY=your_owen_wechat_key_info; send_message.sh wechat "Deploy Stage" "Deploy Stage has been successfully completed..."'
            }
        }
    }
  }

try-catch支持的命令

acceptGitLabMR, addGitLabMRComment, archive, bat, build, catchError, checkout, container, containerLog, deleteDir, dir, dockerFingerprintFrom, dockerFingerprintRun, dockerNode, echo, emailext, emailextrecipients, envVarsForTool, error, fileExists, findBuildScans, getContext, git, gitlabBuilds, gitlabCommitStatus, httpRequest, input, isUnix, junit, library, libraryResource, load, lock, mail, milestone, node, p4, p4approve, p4publish, p4sync, p4tag, p4unshelve, parallel, podTemplate, powershell, properties, publishHTML, pwd, pwsh, readFile, readTrusted, resolveScm, retry, script, sh, sleep, stage, stash, step, svn, timeout, timestamps, tm, tool, unarchive, unstable, unstash, updateGitlabCommitStatus, validateDeclarativePipeline, waitUntil, warnError, withContext, withCredentials, withDockerContainer, withDockerRegistry, withDockerServer, withEnv, wrap, writeFile, ws] or symbols [all, allOf, allure, always, ant, antFromApache, antOutcome, antTarget, any, anyOf, apiToken, approve, architecture, archiveArtifacts, artifactManager, attach, authorizationMatrix, autoClean, batchFile, bitbucket, booleanParam, branch, brokenBuildSuspects, brokenTestsSuspects, buildButton, buildDescription, buildDiscarder, buildName, buildTimestamp, buildTimestampExtraProperties, buildingTag, caseInsensitive, caseSensitive, certificate, changeRequest, changelog, changeset, checkoutToSubdirectory, choice, choiceParam, cleanWs, cleanup, clientSpec, clock, cloud, command, configMapVolume, containerEnvVar, containerLivenessProbe, containerTemplate, credentials, cron, crumb, culprits, default, defaultView, demand, depotSource, developers, disableConcurrentBuilds, disableResume, docker, dockerCert, dockerfile, downloadSettings, downstream, dumb, durabilityHint, dynamicPVC, emptyDirVolume, emptyDirWorkspaceVolume, envVar, envVars, environment, equals, expression, file, fileParam, filePath, fingerprint, fishEye, flushOnly, forceClean, frameOptions, freeStyle, freeStyleJob, fromScm, fromSource, git, gitBranchDiscovery, gitHubBranchDiscovery, gitHubBranchHeadAuthority, gitHubForkDiscovery, gitHubSshCheckout, gitHubTagDiscovery, gitHubTrustContributors, gitHubTrustEveryone, gitHubTrustNobody, gitHubTrustPermissions, gitLabConnection, gitTagDiscovery, github, githubPush, gitlab, globalLib, gradle, graphClean, graphSource, headRegexFilter, headWildcardFilter, hostPathVolume, hostPathWorkspaceVolume, hyperlink, hyperlinkToModels, incremental, inheriting, inheritingGlobal, installSource, isRestartedRun, jdk, jdkInstaller, jgit, jgitapache, jnlp, jobName, kubernetes, label, lastDuration, lastFailure, lastGrantedAuthorities, lastStable, lastSuccess, legacy, legacySCM, list, local, location, logRotator, loggedInUsersCanDoAnything, manualSpec, masterBuild, matrix, maven, maven3Mojos, mavenErrors, mavenMojos, mavenWarnings, merge, modernSCM, multiBranch, multiGraph, multiStreams, multiSwarm, myView, never, newContainerPerStage, nfsVolume, nfsWorkspaceVolume, node, nodeProperties, nonInheriting, none, not, note, onFailure, openGrok, override, overrideIndexTriggers, p4Trigger, p4Web, p4cleanup, p4groovy, p4sync, paneStatus, parallel, parallelsAlwaysFailFast, parameterizedCron, parameters, password, pathFilter, pattern, perforce, permanent, persistentVolumeClaim, persistentVolumeClaimWorkspaceVolume, pipeline-model, pipelineTriggers, plainText, plugin, podAnnotation, podEnvVar, podLabel, pollSCM, portMapping, preserveStashes, previewOnly, projectNamingStrategy, proxy, publish, queueItemAuthenticator, quietPeriod, qyWechatNotification, rateLimitBuilds, recipients, requestor, run, runParam, sSHLauncher, schedule, scmRetryCount, scriptApproval, scriptApprovalLink, search, secretEnvVar, secretVolume, security, shell, shelve, skipDefaultCheckout, skipStagesAfterUnstable, slave, sourceRegexFilter, sourceWildcardFilter, specFileSpec, ssh, sshUserPrivateKey, stackTrace, standard, staticSpec, status, streamSource, streamSpec, string, stringParam, submit, swapSpace, swarm, syncOnly, tag, templateSource, templateSpec, text, textParam, ticket, ticketMode, tmpSpace, toolLocation, triggeredBy, trust, unsecured, unshelve, upstream, upstreamDevelopers, user, userFilter, userSeed, usernameColonPassword, usernamePassword, viewFilter, viewPattern, viewsTabBar, weather, withAnt, zfs, zip] or globals [currentBuild, docker, env, params, pipeline, scm]
acceptGitLabMR, addGitLabMRComment, archive, bat, build, catchError, checkout, container, containerLog, deleteDir, dir, dockerFingerprintFrom, dockerFingerprintRun, dockerNode, echo, emailext, emailextrecipients, envVarsForTool, error, fileExists, findBuildScans, getContext, git, gitlabBuilds, gitlabCommitStatus, httpRequest, input, isUnix, junit, library, libraryResource, load, lock, mail, milestone, node, p4, p4approve, p4publish, p4sync, p4tag, p4unshelve, parallel, podTemplate, powershell, properties, publishHTML, pwd, pwsh, readFile, readTrusted, resolveScm, retry, script, sh, sleep, stage, stash, step, svn, timeout, timestamps, tm, tool, unarchive, unstable, unstash, updateGitlabCommitStatus, validateDeclarativePipeline, waitUntil, warnError, withContext, withCredentials, withDockerContainer, withDockerRegistry, withDockerServer, withEnv, wrap, writeFile, ws] or symbols [all, allOf, allure, always, ant, antFromApache, antOutcome, antTarget, any, anyOf, apiToken, approve, architecture, archiveArtifacts, artifactManager, attach, authorizationMatrix, autoClean, batchFile, bitbucket, booleanParam, branch, brokenBuildSuspects, brokenTestsSuspects, buildButton, buildDescription, buildDiscarder, buildName, buildTimestamp, buildTimestampExtraProperties, buildingTag, caseInsensitive, caseSensitive, certificate, changeRequest, changelog, changeset, checkoutToSubdirectory, choice, choiceParam, cleanWs, cleanup, clientSpec, clock, cloud, command, configMapVolume, containerEnvVar, containerLivenessProbe, containerTemplate, credentials, cron, crumb, culprits, default, defaultView, demand, depotSource, developers, disableConcurrentBuilds, disableResume, docker, dockerCert, dockerfile, downloadSettings, downstream, dumb, durabilityHint, dynamicPVC, emptyDirVolume, emptyDirWorkspaceVolume, envVar, envVars, environment, equals, expression, file, fileParam, filePath, fingerprint, fishEye, flushOnly, forceClean, frameOptions, freeStyle, freeStyleJob, fromScm, fromSource, git, gitBranchDiscovery, gitHubBranchDiscovery, gitHubBranchHeadAuthority, gitHubForkDiscovery, gitHubSshCheckout, gitHubTagDiscovery, gitHubTrustContributors, gitHubTrustEveryone, gitHubTrustNobody, gitHubTrustPermissions, gitLabConnection, gitTagDiscovery, github, githubPush, gitlab, globalLib, gradle, graphClean, graphSource, headRegexFilter, headWildcardFilter, hostPathVolume, hostPathWorkspaceVolume, hyperlink, hyperlinkToModels, incremental, inheriting, inheritingGlobal, installSource, isRestartedRun, jdk, jdkInstaller, jgit, jgitapache, jnlp, jobName, kubernetes, label, lastDuration, lastFailure, lastGrantedAuthorities, lastStable, lastSuccess, legacy, legacySCM, list, local, location, logRotator, loggedInUsersCanDoAnything, manualSpec, masterBuild, matrix, maven, maven3Mojos, mavenErrors, mavenMojos, mavenWarnings, merge, modernSCM, multiBranch, multiGraph, multiStreams, multiSwarm, myView, never, newContainerPerStage, nfsVolume, nfsWorkspaceVolume, node, nodeProperties, nonInheriting, none, not, note, onFailure, openGrok, override, overrideIndexTriggers, p4Trigger, p4Web, p4cleanup, p4groovy, p4sync, paneStatus, parallel, parallelsAlwaysFailFast, parameterizedCron, parameters, password, pathFilter, pattern, perforce, permanent, persistentVolumeClaim, persistentVolumeClaimWorkspaceVolume, pipeline-model, pipelineTriggers, plainText, plugin, podAnnotation, podEnvVar, podLabel, pollSCM, portMapping, preserveStashes, previewOnly, projectNamingStrategy, proxy, publish, queueItemAuthenticator, quietPeriod, qyWechatNotification, rateLimitBuilds, recipients, requestor, run, runParam, sSHLauncher, schedule, scmRetryCount, scriptApproval, scriptApprovalLink, search, secretEnvVar, secretVolume, security, shell, shelve, skipDefaultCheckout, skipStagesAfterUnstable, slave, sourceRegexFilter, sourceWildcardFilter, specFileSpec, ssh, sshUserPrivateKey, stackTrace, standard, staticSpec, status, streamSource, streamSpec, string, stringParam, submit, swapSpace, swarm, syncOnly, tag, templateSource, templateSpec, text, textParam, ticket, ticketMode, tmpSpace, toolLocation, triggeredBy, trust, unsecured, unshelve, upstream, upstreamDevelopers, user, userFilter, userSeed, usernameColonPassword, usernamePassword, viewFilter, viewPattern, viewsTabBar, weather, withAnt, zfs, zip] or globals [currentBuild, docker, env, params, pipeline, scm]

2.企业微信python

企业微信配置

如上图,首先创建一个群组,然后通过“...”,弹出快捷菜单,创建机器人,然后使用webhook地址进行配置。详细的机器人配置方式地址: https://work.weixin.qq.com/api/doc/90000/90136/91770

3、jenkins插件

'Extended Choice Parameter':实现复选框功能

'Execute Python script':实现获取jenkins内置环境变量

'Build Timestamp Plugin':实现获取job构建时间

任务中,多选框配置如下图:

name:AlarmContact,用于下面Python环境变量中获取value值

Description:选择发布联系人,解释说明

Parameter Type:Check Boxes,表示多选或单选

Number of Visible Items:10,表示当前页面展示10条

Delimiter:,表示value的分隔符

value:企业微信的’weixin_id‘,特别注意

Python环境变量配置如下图:

#!/usr/bin/python3
# -*- coding: iso-8859-15 -*-
import os
# 获取的都是jenkins内置环境变量
BuildTime=os.getenv("BUILD_TIMESTAMP")
BuildNumber=os.getenv("BUILD_NUMBER")
JobName=os.getenv("JOB_NAME")
UrlJob=os.getenv("BUILD_URL")
alarm_contact=os.getenv("AlarmContact")
GitCommit=os.getenv("GIT_COMMIT")
GIT_BRANCH=os.getenv("GIT_BRANCH")



WeChat_url = "企业微信上webhook地址"

import json
import requests
import sys

data = json.dumps(
            {
                "msgtype": "markdown",
                "markdown": {
                    "content": "# <font color=\"warning\">jenkins发布提醒</font> \n"
                               ">任务名称:<font color=\"info\">%s</font> \n"
                               ">构建时间:<font color=\"info\">%s</font> \n"
                               ">任务分支:<font color=\"comment\">%s</font> \n"
                               ">构建次数:<font color=\"comment\">%s</font> \n"
                               ">任务地址:[%s](%s) \n"
                               ">构建版本:<font color=\"comment\">%s</font> \n"
                               ">任务已构建完成确认:<font color=\"info\">%s</font> \n"  %(JobName, BuildTime,GIT_BRANCH,BuildNumber,UrlJob, UrlJob,GitCommit,alarm_contact),
                },
            }
        )
requests.post(WeChat_url, data, auth=('Content-Type', 'application/json'))
#!/usr/bin/python3
# -*- coding: iso-8859-15 -*-
import os
# 获取的都是jenkins内置环境变量
BuildTime=os.getenv("BUILD_TIMESTAMP")
BuildNumber=os.getenv("BUILD_NUMBER")
JobName=os.getenv("JOB_NAME")
UrlJob=os.getenv("BUILD_URL")
alarm_contact=os.getenv("AlarmContact")
GitCommit=os.getenv("GIT_COMMIT")
GIT_BRANCH=os.getenv("GIT_BRANCH")



WeChat_url = "企业微信上webhook地址"

import json
import requests
import sys

data = json.dumps(
            {
                "msgtype": "markdown",
                "markdown": {
                    "content": "# <font color=\"warning\">jenkins发布提醒</font> \n"
                               ">任务名称:<font color=\"info\">%s</font> \n"
                               ">构建时间:<font color=\"info\">%s</font> \n"
                               ">任务分支:<font color=\"comment\">%s</font> \n"
                               ">构建次数:<font color=\"comment\">%s</font> \n"
                               ">任务地址:[%s](%s) \n"
                               ">构建版本:<font color=\"comment\">%s</font> \n"
                               ">任务已构建完成确认:<font color=\"info\">%s</font> \n"  %(JobName, BuildTime,GIT_BRANCH,BuildNumber,UrlJob, UrlJob,GitCommit,alarm_contact),
                },
            }
        )
requests.post(WeChat_url, data, auth=('Content-Type', 'application/json'))