# -*- coding:utf-8 -*- import sys import xml.etree.ElementTree as ET WORKSPACE = sys.argv[1] sys.path.append(WORKSPACE) import json import requests import os import re from bs4 import BeautifulSoup from html.parser import HTMLParser handle_parser = HTMLParser() BUILD_INFO = {} class handle_to_jenkins(): ''' 处理关于jenkins的执行相关方法 ''' def __init__(self): self.dict_info = {} self.list_info = [] def GetJenkinsVar(self, key): ''' 获取jenkins上获得的参数信息 ''' try: value = os.environ.get(key) except Exception: value = os.environ.get(key.upper()) if (not value): value = '' return value def kw_to_get_dd_token(self, environment): """ 功能: 根据传入环境获取不同的token信息 """ sim = "40696c86-264a-4222-a40c-cfd64a05dffd" product = "40696c86-264a-4222-a40c-cfd64a05dffd" if environment.lower() == "sim" or environment.lower() == "qa": return sim else: return product def send_message_by_dingding(self, data, environment="qa"): ''' 发送钉钉消息 ''' token = self.kw_to_get_dd_token(environment=environment) # web_hook = "https://oapi.dingtalk.com/robot/send?access_token={}".format(token) web_hook = "https://open.feishu.cn/open-apis/bot/v2/hook/{}".format(token) headers = {"Content-Type": "application/json"} json_data = json.dumps(data) rsp = requests.post(url=web_hook, data=json_data, headers=headers) return rsp # print(data) def send_feishu(self,inferfaces): ''' 发送飞书 :return: ''' at_user_list = [{"tag": "at", "user_id": "{}".format("7020366259502153730")}] message_data = {"msg_type": "post", "content": { "post": {"zh_cn": {"title": "有存在的接口未实现自动化哦", "content": [[{"tag": "text", "text": "问题数据:"}], [{"tag": "text", "text": "{}".format(inferfaces)}], at_user_list]}}}} web_hook = "https://open.feishu.cn/open-apis/bot/v2/hook/40696c86-264a-4222-a40c-cfd64a05dffd" headers = {"Content-Type": "application/json"} json_data = json.dumps(message_data) print(json_data) rsp = requests.post(url=web_hook, data=json_data, headers=headers) return rsp def handle_send_message(self,root): ''' 处理对应所有人,根据job名称匹配来发送@的消息 ''' list_name_phone = {"陈江": "13458500234", "张楠": "", "罗志鹏": "", "蒲思宇": "", "陈洁": "15328118883", "刘涛婷": "18328504751", "谯新久": "18202810506"} job_name = self.GetJenkinsVar("JOB_TO_NAME") job_url = self.GetJenkinsVar("JOB_TO_URL") enviroment = self.GetJenkinsVar("JOB_ENVIRONMENT") # job_name = "123" # job_url = "http://10.250.200.1:8080/jenkins/job/QA%E7%8E%AF%E5%A2%83%E5%B7%A1%E6%A3%80/2387/robot/report/report.html" # enviroment = "PRODUCT" dict_info = self.get_fail_test_case(son_node=root) BUILD_INFO = dict_info.get("BUILD_INFO") fail_info = dict_info.get("INFO") list_phone = [] if BUILD_INFO: for key, value in BUILD_INFO.items(): list_phone.append(list_name_phone.get(key)) print(list_phone) print("+++++++{0}+++++{1}".format(job_name, job_url)) if re.search("PRODUCT", enviroment): # message_data = {"msg_type": "text", "content": { # "text": "线上巡检:线上环境出现了问题,请点击进行查看{0},以下是错误日志:{1}".format(job_url + "robot/report/report.html",fail_info)}, # "at": {"atMobiles": list_phone}} at_user_list = [{"tag": "at", "user_id": "{}".format("7020366258071715842")}] message_data = {"msg_type": "post", "content": { "post": {"zh_cn": {"title": "线上环境巡检", "content": [[{"tag": "text", "text": "线上环境出现了问题:"}], [{"tag": "a", "text": "点击查看","href":"".format(job_url + "robot/report/report.html")}], at_user_list]}}}} print(message_data) self.send_message_by_dingding(message_data,environment="product") return enviroment if re.search("QA", enviroment) or re.search("SIM", enviroment): message_data = {"msg_type": "text", "content": { "text": "{0}环境构建出问题了哦,请点击进行查看{1},以下是错误日志:{2}".format(enviroment, job_url + "robot/report/report.html",fail_info)}, "at": {"atMobiles": list_phone}} print(message_data) self.send_message_by_dingding(message_data) return enviroment for key, value in list_name_phone.items(): if re.search(key, job_name): message_data = {"msg_type": "text", "content": { "text": "亲爱的{0}同学,你的独立环境构建出问题了哦,请点击进行查看{1}".format(key, job_url + "robot/report/report.html")}, "at": {"atMobiles": [value]}} self.send_message_by_dingding(message_data) return value else: return "这个job:{}没有找到人".format(job_name) def get_fail_test_case(self,son_node, father_node=None, grandpa_node=None): """ 功能:遍历xml文件的所有节点,搜索构建失败的用例信息 """ children_node = son_node.getchildren() if len(children_node) == 0: # if son_node.tag == 'doc': # print(son_node.text) # if son_node.tag == 'msg' and son_node.attrib['level'] == 'FAIL': # # print(son_node.text) # # print(son_node.attrib['timestamp']) # print(children_node) if son_node.tag == 'status' and son_node.attrib['status'] == 'FAIL' and 'critical' in son_node.attrib: # print(father_node.attrib["name"]) tag = self.find_tags(father_node) # a = self.find_error(father_node) # print(a) info_error = self.check_log_info(son_node.text) INFO = "用例名称:" + father_node.attrib["name"] +"。人员:" + tag + "。失败日志:" + str(info_error) run_time = son_node.attrib['endtime'] # print(info_error) # print(son_node.text) # self.check_log_info(text=son_node.text) run_time = "{}-{}-{} {}".format(run_time[0:4], run_time[4:6], run_time[6:8], run_time[9:17]) reason = son_node.text.replace('"', '\\"') # 满足构建时间,同时数据库中没有数据,才入库 # print(run_time) if tag in BUILD_INFO: BUILD_INFO[tag] += 1 else: BUILD_INFO[tag] = 1 # print(BUILD_INFO) # print(tag) self.list_info.append(INFO) self.dict_info["BUILD_INFO"] = BUILD_INFO self.dict_info["INFO"] = self.list_info # print(tag) run_time = run_time author = tag case_name = father_node.attrib['name'] file_path = grandpa_node.attrib['source'] reason = reason[0:4500] return self.dict_info for child in children_node: self.dict_info = self.get_fail_test_case(child, son_node, father_node) return self.dict_info def check_log_info(self,text): ''' 过滤精确日志信息 ''' soup = BeautifulSoup(text, features="lxml") list_info = [] for a in soup.find_all(name='span'): dict_info = {} if a.text == "Old message:": dict_info["old_message"] = a.nextSibling list_info.append(dict_info) elif a.text == "New message:": dict_info["new_message"] = a.nextSibling list_info.append(dict_info) # print(a.nextSibling) if list_info: return list_info else: return text def find_tags(self,root): """ 功能:在xml文件中搜索失败用对应的作者 """ children_node = root.getchildren() for child in children_node: if child.tag == 'tags': tags = child.getchildren() for tag in tags: if 'qa-' in tag.text.lower(): return tag.text[3:len(tag.text)] return "无作者标签" def find_error(self,root): """ 功能:在xml文件中查询失败日志 """ children_node = root.getchildren() for child in children_node: if child.tag == 'kw': msgs = child.getchildren() for msg in msgs: a = msg.tag # t = msg.attrib['level'] l = msg.text # print(msg.attrib['timestamp']) if msg.tag == 'msg' and msg.attrib['level'] == 'FAIL': print(msg.attrib) s = msg.text return msg.text return "" def run(self): ''' 运行入口 ''' # FILE_PATH = "D:/output2.xml" FILE_PATH = os.path.abspath(os.path.join(WORKSPACE, 'Report/out/output.xml')) root = ET.parse(FILE_PATH).getroot() # self.get_fail_test_case(son_node=root) self.handle_send_message(root=root) if __name__ == '__main__': test = handle_to_jenkins() # FILE_PATH = "D:/output1.xml" # FILE_PATH = os.path.abspath(os.path.join(WORKSPACE, 'Report/out/output.xml')) # root = ET.parse(FILE_PATH).getroot() # print(test.get_fail_test_case(son_node=root)) test.run() # test.handle_send_message(root=root)