【Jenkins学习 】如何编写Python脚本来调用企业微信的api通知企业微信成员关于Jenkins的编译结果?
一、需求描述最近公司将RTX更新为了企业微信,并且准备将之前的OA邮箱之类的都废弃掉了。而之前我们的Jenkins编译结果都是通过发送到OA邮箱来进行通知的,因此后面OA邮箱被废弃掉的话,那么我们就无法收到Jenkins的编译结果了。因此我们得想其他办法来通知相关人员关于Jenkins的编译结果。和公司负责企业微信推广的同事聊了聊之后,发现可以通过企业微信提供的api来进行开发,然后实现将Je..
一、需求描述
最近公司将RTX更新为了企业微信,并且准备将之前的OA邮箱之类的都废弃掉了。而之前我们的Jenkins编译结果都是通过发送到OA邮箱来进行通知的,因此后面OA邮箱被废弃掉的话,那么我们就无法收到Jenkins的编译结果了。
因此我们得想其他办法来通知相关人员关于Jenkins的编译结果。和公司负责企业微信推广的同事聊了聊之后,发现可以通过企业微信提供的api来进行开发,然后实现将Jenkins的编译结果通过企业微信来发送消息。
二、了解企业微信的api
2.1 api相关参考资料
在腾讯,能够看到的信息如下
没有更多的消息,企业微信发消息的api和微信企业号发送的有点类似,大致看下即可。
2.2 公司封装的企业微信发消息的api文档
公司负责企业微信推广的同事对企业微信发送消息的api进行了再次封装,然后发送了一篇api文档给我,大致如下:
2.2.1 请求接口步骤
-
1 获取apid与Secret
请联系公司内部推广企业微信的同事,可得到调用所需的ClientId与Secret -
2 获取token的api
请求api
POST: http://ip地址:8000/connect/token
{
client_id:步骤1中获得,
client_secret:步骤1中获得,
grant_type:"client_credentials",
scope:"ApiGateway"
}
注:body使用x-www-form-urlencoded
返回的内容
返回内容:
{
"access_token":"",
"expires_in": 3600,
"token_type":"Bearer"
}
- 3 使用步骤2中得到的Bearer Token请求资源.
2.2.2 请求接口步骤发送微信消息接口说明
-
- 发送图文信息
POST: http://ip地址:8000/api/wechat/news
{
"toUser" : "工号1|工号2....",
"agentId" : 0,
"news" : {
"articles" : [
{
"title" : "中秋节礼品领取",
"description" : "今年中秋节公司有豪礼相送",
"url" : "URL",
"picurl" : "http://res.mail.qq.com/node/ww/wwopenmng/images/independent/doc/test_pic_msg1.png",
"btntxt":"更多"
}
]
}
}
-
- 发送文本消息
POST: http://ip地址:8000/api/wechat/text
{
"toUser" : "工号1|工号2....",
"agentId" : 0,
"content":"xxxxxx"
}
-
- 文本卡片消息
POST: http://ip地址:8000/api/wechat/textcard
{
"toUser" : "工号1|工号2....",
"agentId" : 0,
"title" : "领奖通知",
"description" : "<div class=\"gray\">2016年9月26日</div> <div class=\"normal\">恭喜你抽中iPhone 7一台,领奖码:xxxx</div><div class=\"highlight\">请于2016年10月10日前联系行政同事领取</div>",
"url":"http://www.baidu.com",
"btntxt":"更多"
}
三、编写python脚本来调用企业微信api
在你的项目中,加入一个python脚本和一个jenkins账号和企业微信工号的配置文件,如下所示
3.1 编写Jenkins账户对应的企业微信的工号映射表
上面的python脚本在执行的时候,会将Jenkins账户转换为企业微信的工号,这个转换过程是通过读取Jenkins账户对应的企业微信的工号映射表jenkins_users.xml来进行的。
jenkins_users.xml的格式如下:
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<users>
<user>
<name>欧阳鹏</name>
<wechat>000001</wechat>
</user>
<user>
<name>员工2</name>
<wechat>000002</wechat>
</user>
<user>
<name>员工3</name>
<wechat>000003</wechat>
</user>
<user>
<name>员工4</name>
<wechat>000004</wechat>
</user>
<user>
<name>员工4</name>
<wechat>000005</wechat>
</user>
</users>
3.2 python脚本 xutils.py 内容如下
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
import json
import os
import sys
import time
import urllib
import urllib2
import xml.dom.minidom
reload(sys)
sys.setdefaultencoding('utf-8')
ISOTIMEFORMAT = "%Y-%m%d-%H%M"
TIMEFORMAT = "%Y-%m-%d %H:%M:%S"
# %Y 四位数的年份表示(000-9999)
# %m 月份(01-12)
# %d 月内中的一天(0-31)
FTP_TIMEFORMAT = "%Y-%m-%d"
def getNowTimeForFTP():
nowtime = time.strftime(FTP_TIMEFORMAT, time.localtime(time.time()))
return nowtime
def getNowTimeFormat():
nowtime = time.strftime(ISOTIMEFORMAT, time.localtime(time.time()))
return nowtime
def getNowTime():
nowtime = time.strftime(TIMEFORMAT, time.localtime(time.time()))
return nowtime
class XTCMessage:
""" ESB接入说明 企业微信接口对接
1.获取apid与Secret,请联系系统管理部架构及IT可得到调用所需的ClientId与Secret
2.获取token
POST: http://ip地址/connect/token
{
client_id:步骤1中获得,
client_secret:步骤1中获得,
grant_type:"client_credentials",
scope:"ApiGateway"
}
注:body使用x-www-form-urlencoded
返回内容:
{
"access_token":"",
"expires_in": 3600,
"token_type":"Bearer"
}
3.使用步骤2中得到的Bearer Token请求资源.
"""
def __init__(self):
self.access_token = ''
auth_data = {"client_id": "xxxxxxxxx", "client_secret": "xxxxxxxxx",
"grant_type": "client_credentials", "scope": "ApiGateway"}
auth_url = 'http://ip地址:8000/connect/token'
# x-www-form-urlencoded
def __post_xwwwformurlencoded(self, url, body_value):
body_value = urllib.urlencode(body_value)
request = urllib2.Request(url, body_value)
response = urllib2.urlopen(request)
print response.getcode()
print response.geturl()
ret = response.read()
return ret
def login(self):
data = self.__post_xwwwformurlencoded(self.auth_url, self.auth_data)
json_data = json.loads(data)
self.access_token = 'Bearer ' + json_data['access_token']
return
# x-www-form-urlencoded
def __post(self, url, body, token):
request = urllib2.Request(url)
request.add_header('Content-TYPE', 'application/json')
request.add_header('Authorization', self.access_token)
response = urllib2.urlopen(request, json.dumps(body))
print response.getcode()
print response.geturl()
ret = response.read()
return ret
def send_text(self, users, message):
msg_text_url = 'http://ip地址:8000/api/wechat/text'
""" 发送文本消息
POST: http://ip地址/api/wechat/text
{
"toUser" : "工号1|工号2",
"agentId" : 0,
"content":"xxxxxx"
}
"""
data = {"toUser": users, "agentId": 0, "content": message}
print('send_text():url = %s ,data = %s' % (msg_text_url, data))
self.__post(msg_text_url, data, self.access_token)
def send_card(self, users, title, detail, link='http://www.baidu.com'):
""" 发送图文信息
POST: http://ip地址/api/wechat/textcard
{
"toUser" : "工号1|工号2....",
"agentId" : 0,
"title" : "领奖通知",
"description" : "<div class=\"gray\">2016年9月26日</div> <div class=\"normal\">恭喜你抽中iPhone 7一台,领奖码:xxxx</div><div class=\"highlight\">请于2016年10月10日前联系行政同事领取</div>",
"url":"http://www.baidu.com",
"btntxt":"更多"
}
"""
msg_card_url = 'http://ip地址:8000/api/wechat/textcard'
data = {"toUser": users, "agentId": 0, "title": title, "description": detail, "url": link}
print('send_card():url = %s ,data = %s' % (msg_card_url, data))
self.__post(msg_card_url, data, self.access_token)
def send_news(self, users, title, detail, url, picurl):
""" 发送图文信息
POST: http://ip地址/api/wechat/news
{
"toUser" : "工号1|工号2....",
"agentId" : 0,
"news" : {
"articles" : [
{
"title" : "中秋节礼品领取",
"description" : "今年中秋节公司有豪礼相送",
"url" : "URL",
"picurl" : "http://res.mail.qq.com/node/ww/wwopenmng/images/independent/doc/test_pic_msg1.png",
"btntxt":"更多"
}
]
}
}
"""
msg_news_url = 'http://ip地址:8000/api/wechat/news'
data = {"toUser": users, "agentId": 0, "news": {
"articles": [{"title": title, "description": detail, "url": url, "picUrl": picurl}]}}
print('send_news():url = %s ,data = %s' % (msg_news_url, data))
self.__post(msg_news_url, data, self.access_token)
def call_xtcmessager(argv):
xtcmsger = XTCMessage()
xtcmsger.login()
if len(argv) == 3:
xtcmsger.send_text(argv[1], argv[2])
elif len(argv) == 5:
xtcmsger.send_card(argv[1], argv[2], argv[3], argv[4])
elif len(argv) == 6:
xtcmsger.send_news(argv[1], argv[2], argv[3], argv[4], argv[5])
else:
print('error: parameter wrong!')
print(argv)
class Jenkins():
def __init__(self):
self.argv = []
def get_wechat(self, fname, username):
"""
获取jenkins用户名对应的企业微信的工号 ,比如:jenkins用户名 【欧阳鹏】对应的工号是【0000001】
参数:
fname 配置文件名
username:Jenins用户名
"""
if os.path.exists(fname):
# filecontent = XmlReader.read_content(self,fname)
# if None != filecontent:
# dom = xml.dom.minidom.parseString(filecontent)
dom = xml.dom.minidom.parse(fname)
collection = dom.documentElement
users = collection.getElementsByTagName("user")
for idx in range(0, len(users)):
user = users[idx]
name = user.getElementsByTagName('name')[0].childNodes[0].data
wechat = user.getElementsByTagName('wechat')[0].childNodes[0].data
if username == name:
return wechat
print('wechat of user ' + username + ' can not be found!')
return ''
def sendmessage(self, title, job_name, build_number, branch, user, git_commit, build_url,
weichat_receivers):
"""
发送jenkins编译消息给企业微信
参数:
title 提醒标题
job_name:Jenins任务名
build_number: Jenins编译次数
branch: git分支
user: Jenins编译触发者
git_commit: git commit sha1码
build_url: Jenins编译的url地址
weichat_receivers:企业微信接收者 , 比如:"欧阳鹏|员工2" 用 | 分隔
"""
self.argv.append('vrix')
message = """
<li><font color="#0B610B">%(TITLE)s</font><li>
<li><font color="#0B610B">构建信息</font><li>
<li>------------------------<li>
<li>%(TIME)s<li>
<li>------------------------<li>
<li>用户名 :%(USER)s</li>
<li>任务名 :%(PROJECT_NAME)s</li>
<li>分支名 :%(GIT_BRANCH)s</li>
<li>构建编号 :第%(BUILD_NUMBER)s次构建</li>
<li>GIT SHA1 :%(GIT_COMMIT)s</li>
<li>构建日志 :<a href="%(BUILD_URL)sconsole">%(BUILD_URL)sconsole</a></li>
<li>FTP归档地址如下所示:(用户名:xxxx 密码:xxxx)</li>
<li>ftp://ftp的ip地址/project/AndroidPhone/%(PROJECT_NAME)s/%(FTP_TIME)s-git-%(GIT_COMMIT)s-build-%(BUILD_NUMBER)s<li>
<li>静态代码分析报告</li>
<li>Android Lint 报告 : <a href="%(BUILD_URL)sandroidLintResult">%(BUILD_URL)sandroidLintResult </a></li>
<li>FindBugs 报告 :<a href="%(BUILD_URL)sfindbugsResult">%(BUILD_URL)sfindbugsResult </a></li>
<li>发送企业微信信息给 :%(WEICHAT_RECEIVERS)s</li>
""" % dict(
TITLE=title,
TIME=getNowTime(),
USER=user,
GIT_BRANCH=branch,
PROJECT_NAME=job_name,
BUILD_NUMBER=build_number,
GIT_COMMIT=git_commit,
BUILD_URL=build_url,
WEICHAT_RECEIVERS=weichat_receivers,
FTP_TIME = getNowTimeForFTP()
)
# 最终要发送的企业微信user拼接列表
wechat_receiver_users_string = ''
# 分隔外面传进来的 企业微信接收者
weichat_receivers_list = weichat_receivers.split('|')
for weichat_receiver_user in weichat_receivers_list:
wechat_user = self.get_wechat('jenkins_users.xml', weichat_receiver_user)
print('Jenkins user:' + weichat_receiver_user + " weichat user_number:" + wechat_user)
if wechat_user == '':
print('Jenkins user:' + weichat_receiver_user + " weichat user_number is null")
else:
# 拼接成格式: "工号1|工号2"
wechat_receiver_users_string = wechat_receiver_users_string + wechat_user + "|"
if wechat_receiver_users_string != '':
print('-----------send msg to user ' + wechat_receiver_users_string)
self.argv.append(wechat_receiver_users_string)
self.argv.append(message)
else:
print('-----------send to vrix')
# 默认发送给 00001 如果要加人的话 用 | 分开
# self.argv.append('工号1|工号1')
self.argv.append('00001')
self.argv.append(message)
call_xtcmessager(self.argv)
def call_jenkins(argv):
"""
发送jenkins编译消息给企业微信
参数:
title 提醒标题
jobname:Jenins任务名
build_number: Jenins编译次数
branch: git分支
user: Jenins编译触发者
git_commit: git commit sha1码
build_url: Jenins编译的url地址
"""
job_name = argv[2]
build_number = argv[3]
branch = argv[4]
user = argv[5]
git_commit = argv[6]
build_url = argv[7]
weichat_receivers = argv[8]
jenkins = Jenkins()
jenkins.sendmessage('---Jenkins 构建提醒----', job_name, build_number, branch, user, git_commit,
build_url, weichat_receivers)
if __name__ == "__main__":
if len(sys.argv) > 1:
print(sys.argv)
if sys.argv[1] == 'jenkins':
print('--- jenkins')
call_jenkins(sys.argv)
else:
call_xtcmessager(sys.argv)
else:
print('usage:')
print('测试 python xutils.py "00001|00002" \"hello world!\" ')
print('测试 Jenkins的话 python xutils.py jenkins ${JOB_NAME} ${BUILD_NUMBER} ${GIT_BRANCH} ${BUILD_USER} ${JOB_DESCRIPTION} ${GIT_COMMIT} ${CAUSE} ${BUILD_URL} ${PROJECT_URL} ${WEICHAT_RECEIVERS} ')
该脚本在jenkins的任务中,通过shell脚本进行调用,具体怎么调用,继续看下面的内容。
四 、配置jenkins的任务
4.1 勾选【Set jenkins user build variables】
【构建环境】中 勾选【Set jenkins user build variables】,不然jenkins的环境变量无法读取
4.2 添加一个【参数构建化过程】
在【General】中,添加一个【参数构建化过程】,增加一个参数,如下所示:
-
参数名
参数名为 WEICHAT_RECEIVERS, -
默认值
默认值为要发送给企业微信的人员列表,
可以是一个列表,用 | 分隔符分开即可,比如
员工1|员工2|员工3|员工4|欧阳鹏|员工5|员工6|员工7
也可以只写一个人,比如欧阳鹏
- 描述
要发送给企业微信的人员列表
4.3 增加一个构建过程 【Execute Shell】
如下图所示,在 jenkins的具体任务中,【构建】最后加入一个【Execute shell】,然后复制脚本进入即可
# 进入workspace
cd ${WORKSPACE}
# 执行python脚本,发送编译结果给企业微信
python xutils.py jenkins ${JOB_NAME} ${BUILD_NUMBER} ${GIT_BRANCH} ${BUILD_USER} ${JOB_DESCRIPTION} ${GIT_COMMIT} ${CAUSE} ${BUILD_URL} ${PROJECT_URL} ${WEICHAT_RECEIVERS}
4.4 删除原来的发送邮件到OA的模块,因为已经没意义了。
【构建后操作】–>【Editable Email Notification】 然后点击右上角的 红色叉号,直接删除邮件发送模块
4.5 配置FTP地址
【构建后操作】–>【Send build artifacts over FTP 】
配置地址为 下面的内容,因为脚本中是读取这个地址的
AndroidPhone/${JOB_NAME}/'yyyy-MM-dd-HH-mm-ss-'git-${GIT_COMMIT}-build-${BUILD_NUMBER}
五、执行Jenkins任务
5.1 执行jenkins
1、因为添加了 动态参数化构建,所以点击这个 【Build with Parameters】进行构建
2、点击之后,会让你修改 要通知的企业微信的人员列表,如果不修改的话,直接点击【开始构建】,如果要修改的话,请按提示的格式来即可。
5.2 执行完毕
发送给单个用户
1、当jenkins项目执行完毕之后,就会自动发送消息给企业微信
2、在你的企业微信中,会收到 【门户君】发送给你的消息,如下所示。
如上所示,ftp的地址直接打印出来了,这样就可以直接方便提测,直接复制地址即可。
发送给多个用户
配置发送给多个用户
编译过程中
多人接收到该消息
六、总结
使用到的技术有:Python、Shell、XML、Jenkins,大家可以了解了解!
关于使用shell脚本实现该功能的,可以参考下面的链接:
- 【Linux学习】如何编写Shell脚本调用企业微信api来发消息给企业微信成员?
https://blog.csdn.net/qq446282412/article/details/86495251
作者:欧阳鹏 欢迎转载,与人分享是进步的源泉!
转载请保留原文地址:https://blog.csdn.net/qq446282412/article/details/86361318
☞ 本人QQ: 3024665621
☞ QQ交流群: 123133153
☞ github.com/ouyangpeng
☞ oypcz@foxmail.com
如果本文对您有所帮助,欢迎您扫码下图所示的支付宝和微信支付二维码对本文进行打赏。
更多推荐
所有评论(0)