背景
刚来公司的时候,前端项目的部署都是人工直接手动部署,是直接本地打包之后拖拽到服务器上去,个人觉得有很多隐患。存在多个项目同时部署时的混乱,多人直接接触服务器的不安全,误操作等,及开发部署流程的不规范等。
在联合多人的建议下,及开发经理的带头下,换成了Jenkins部署。但是Jenkins部署又总不能一直等着,于是Jenkins部署通知的想法油然而生。
创建部署机器人
公司的工作通讯软件的是飞书,因而必须借助飞书群组自定义机器人的能力。
新建一个群 ---> 设置里面找到群机器人 ---> 点击添加机器人 ---> 选择自定义机器人
机器人的设置里面有很多配置项,其中出于安全考虑,在安全设置里面选择了签名校验(如果你不需要,也可以不用)
接着开始发挥API工程师的能力开始翻阅对应API了。
编写脚本
经过大量反复的查找,飞书官方提供了一份详细的 说明,但是官方的demo里面没有JS的版本,思考再三,决定使用Python版本来编写脚本。但现在看来,完全是可以用JS来写的,毕竟有NodeJS在。也因此还学了几天Python
代码简单直接上
js
#!/usr/bin/env python #Pyhon脚本的开头,设置utf-8能保证输入中文不会乱码
#-*- coding:utf-8 -*-
import sys #用于获取Python脚本外部参数
import requests #用于发送请求
import time #时间戳工具
import hashlib #加密工具
import base64 #base64处理
import hmac #加密工具
import jenkins #用于连接Jenkins
jenkinsUrl = 'http://xxx.xxx.xxx.xxx:xxxx' #Jenkins服务器地址
userName = 'userName' #用户名
password = 'password' #密码
#飞书webhook地址 和 签名校验密钥,可在自定义机器人上面获取
url = 'https://open.feishu.cn/open-apis/bot/v2/hook/XXXXXXXX'
secret = 'secret'
timestamp = int(time.time()) #秒级
#通过类的方式实现
class Assistant():
def __init__ (self):
#连接Jenkins 服务器
self.server = jenkins.Jenkins(jenkinsUrl, userName, password)
#获取外部部署项目名称
self.jobName = sys.argv[1]
#获取部署项目版本,即第几次部署
self.buildNumber = self.server.get_job_info(self.jobName)['nextBuildNumber'] - 1
#项目部署后的信息
self.jobInfo = self.server.get_build_info(self.jobName, self.buildNumber)
#部署结果
self.result = '成功' if(self.jobInfo['result'] == 'SUCCESS') else '失败'
#部署后的结果地址
self.jobUrl = self.jobInfo['url']
#部署时间
self.startTime = self.getTime('startTime')
#部署经历时间
self.duration = self.getTime('duration')
#获取git提交人姓名,即这个分支功能是谁做的
self.fullName = ''
nameList = []
if len(self.jobInfo['culprits']):
for item in self.jobInfo['culprits']:
nameList.append(item['fullName'])
self.fullName = ','.join(nameList)
#获取分支名
for item in self.jobInfo['actions']:
if item.get('lastBuiltRevision'):
self.branchName = item['lastBuiltRevision']['branch'][0]['name']
# 获取时间相关数据的函数
def getTime(self,value):
jobTime = self.jobInfo['timestamp']
startTime = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(round(jobTime / 1000)))
duration = int(round(time.time() - round(jobTime / 1000) ))
timeObj = {
'startTime': startTime,
'duration': duration
}
if timeObj[value]:
return timeObj[value]
# 签名函数,参照官方文档
def gen_sign(self):
# 拼接timestamp和secret
string_to_sign = '{}\n{}'.format(timestamp, secret)
hmac_code = hmac.new(string_to_sign.encode("utf-8"), digestmod=hashlib.sha256).digest()
# 对结果进行base64处理
sign = base64.b64encode(hmac_code).decode('utf-8')
return sign
# 消息发送函数
def sendNotificate(self):
conStr = '项目名称:{0} \n分支名:{1}\n构建编号:第{2}次构建\n开始时间:{3}\n构建持续时间:{4}秒\n构建结果:{5}\n最近git提交人:{6}'
content = conStr.format(self.jobName,self.branchName,self.buildNumber,self.startTime,self.duration,self.result,self.fullName);
method = 'post'
headers = {
'Content-Type': 'application/json',
}
# 飞书接收消息的格式
json = {
"timestamp": timestamp,
"sign": self.gen_sign(),
"msg_type": "interactive",
"card": {
"config": {
"wide_screen_mode": True,
"enable_forward": True
},
"elements": [{
"tag": "div",
"text": {
"content":content,
"tag": "lark_md"
}
}, {
"actions": [{
"tag": "button",
"text": {
"content": "查看报告",
"tag": "lark_md"
},
"url": self.jobUrl,
"type": "default",
"value": {}
}],
"tag": "action"
}],
"header": {
"title": {
"content": self.jobName + " 构建报告",
"tag": "plain_text"
}
}
}
}
try:
res = requests.request(method=method, url=url, headers=headers, json=json)
print(res.json())
except ValueError as e:
print(ValueError)
assistant = Assistant()
assistant.sendNotificate()
飞书提供了很多种消息格式,包括有文本,富文本,照片,群名片等。
效果如下
脚本部署
最后得把这个脚本放到Jenkins部署的hook上去。在Jenkins的项目配置里面,增加构建步骤里面选择 Execute shell ---> 然后在下方的输入框里面编写 python notice.py $项目名
注意这个部署脚本的引用位置必须相对于Jenkins的位置,不然可能会导致文件查找不到。
最后
文章主要是记录实现一个飞书部署通知助手的过程,文章不长,但当时还是费了好大劲,也查找了网上的很多资料,最后才实现出现,也希望能够对有此需求的伙伴一些帮助。期间最大的感悟是,有机会去接触其他的语言,是一件特别有趣的事情
文章更多的是一种实现思路,因为对Jenkins 和 python的不熟悉,都是非常新手的写法,也欢迎有好的实现方式来进行交流。
最后的脚本部署写的很简单,主要是后面因为种种原因,Jenkins的部署通知功能不再需要了,原先的网址也被主公司回收,后台服务还做了迁移。Jenkins的系统和配置也不知道去哪里了[笑哭],所以也就没有截图[泪奔]。