#!/usr/bin/env python # -*- coding: utf-8 -*- import sys import json import requests import base64 import pymysql import time from jira import JIRA def GetSendFlagAndWebhook(job_name,env,job_status,autoType,is_patrol): # default send_flag is True & feishu_webhook(TiDB Cloud Auto Test) send_flag = True feishu_webhook = 'https://open.feishu.cn/open-apis/bot/v2/hook/52dc5527-74a7-4635-a0af-dd68d3b1d981' # P0 feishu_webhook(TiDB Cloud Prod Patrol) if is_patrol == 'Y': if job_status == 'SUCCESS': send_flag = False feishu_webhook = "https://open.feishu.cn/open-apis/bot/v2/hook/716e98f8-aa85-496d-a617-06a2d3a88ddb" return send_flag,feishu_webhook # P1 feishu_webhook(billing 正确性 & 资源探测) if "resource" in autoType: feishu_webhook = "https://open.feishu.cn/open-apis/bot/v2/hook/455e8fc6-09e3-48d5-97df-7cbe10ceff05" return send_flag,feishu_webhook # P2 feishu_webhook(Dataservice Auto Test) if "platform-cd" in job_name: feishu_webhook = "https://open.feishu.cn/open-apis/bot/v2/hook/eedcc92f-ba07-43d4-936c-933b17392e14" return send_flag,feishu_webhook # P3 won't send message if autoType is reminder or CD if "reminder" in autoType or "CD" in autoType: if job_status == 'SUCCESS': send_flag = False # P4 feishu_webhook(Dev Auto Test) if "dev" in env: feishu_webhook = "https://open.feishu.cn/open-apis/bot/v2/hook/9a2def56-4b32-4d23-b853-e3f52a24236c" return send_flag,feishu_webhook return send_flag,feishu_webhook def send_msg(job_name, job_status, job_url, build_num, failCase, isSame, env, user, autoType,is_patrol='N'): job_url = job_url + '/' + build_num + '/allure' # get send_flag and feishu_webhook url send_flag, feishu_webhook = GetSendFlagAndWebhook(job_name,env,job_status,autoType,is_patrol) msg_dict = dict() msg_dict['msg_type'] = 'post' print(failCase) if len(failCase) > 0: result = "failed case is: \n" + '\n'.join(failCase) if isSame == True: result = result + "\n the failed case is same as pre auto run result" else: result = result + "\n The failed case is NOT same as pre auto run result" else: result = "" userData = "run by [" + user + "] \n" msg_dict['content'] ={ "post": { "zh_cn": { "title": job_name, "content": [ [{ "tag": "text", "text": userData }, { "tag": "text", "text": "result" }, { "tag": "a", "text": job_status, "href": job_url },{ "tag": "text", "text": result }] ] } } } msg_j = json.dumps(msg_dict) if send_flag == True: requests.post(feishu_webhook, data=msg_j, headers={'Content-Type': 'application/json'}) def analyzeResult(job_url, build_num, env, autoType, result, runner, is_patrol='N'): if autoType == 'reminder': return [], True failCases = 0 passCases = 0 failedName = [] preFailCases = 0 prePassCases = 0 preFailedName = [] url = "ci.pingcap.net" if url in job_url: uname = "zhongmin@pingcap.com" pat = "110e13388441baf9ab99bf992c3403b81d" else: uname = "zhongmin@pingcap.com" pat = "114c4d42b19028f4cafe1f73bcf4890924" auth = base64.b64encode((uname + ':' + pat).encode('utf-8')).decode('utf-8') headers = {'Authorization': 'Basic ' + auth, "Accept": "application/vnd.github.v3+json"} curCsvApi = job_url + '/' + build_num + '/allure/data/suites.csv' try: response = requests.get(curCsvApi, headers=headers) except: print('Get current build report failed') return if response.status_code != 200: print('Get current build report failed') return csv = response.text.split('\n') for line in csv: if line.split(',')[0] == '"failed"' or line.split(',')[0] == '"broken"': failCases += 1 failedName.append(eval(line.split(',')[9])) if line.split(',')[0] == '"passed"': passCases += 1 insertResultToMysql(job_url, build_num, result, env, autoType, headers, failCases, passCases, runner, is_patrol) if failCases != 0: #if env != "dev": #sendJiraIssue(job_url, build_num, failedName, headers, env, autoType) preCsvApi = job_url + '/' + str(int(build_num)-1) + '/allure/data/suites.csv' try: response = requests.get(preCsvApi, headers=headers) except: print('Get pre build report failed') return failedName, False if response.status_code != 200: print('Get pre build report failed') return failedName, False csv = response.text.split('\n') for line in csv: if line.split(',')[0] == '"failed"' or line.split(',')[0] == '"broken"': preFailCases += 1 preFailedName.append(eval(line.split(',')[9])) if line.split(',')[0] == '"passed"': prePassCases += 1 if preFailCases == failCases and failedName.sort() == preFailedName.sort(): return failedName, True else: return failedName, False return [], True def sendJiraIssue(job_url, build_num, failedName, headers, env, autoType): if autoType == 'reminder': return behaviorsApi = job_url + '/' + build_num + '/allure/data/behaviors.json' uidDir = {} print("failedName:", failedName) try: response = requests.get(behaviorsApi, headers=headers) except: print('Get behaviors report failed') data = json.loads(response.text).get('children') for case in data: if case.__contains__('children'): for subCase in case['children']: for failedCase in failedName: if 'children' in subCase: print("subCase:", subCase['children'][0]['name']) print("failedCase:", failedCase) if subCase['children'][0]['name'] == failedCase: print("failedCase:", failedCase) uidDir[failedCase] = subCase['children'][0]['uid'] else: if subCase['name'] == failedCase: uidDir[failedCase] = subCase['uid'] print("uidDir:", uidDir) jira = JIRA('https://jira.tidbcloud.com/', basic_auth=('', '')) for failedCase in uidDir: print("************", failedCase) url = job_url + '/' + build_num + '/allure/data/test-cases/' + uidDir[failedCase] + '.json' try: response = requests.get(url, headers=headers) print("response:", response) except: print('Get failedCase report failed') describe = json.loads(response.text).get('description') + "\n\n" + json.dumps(json.loads(response.text).get('testStage')) + "\n\n" + job_url + '/' + build_num + '/allure' jiraHeader = {'Content': 'application/json'} data = {'project':'DM', 'issuetype':{'name':'Bug'}, 'summary': failedCase, 'description': describe, 'customfield_10601':{'value': env}, 'labels': [env+'-'+autoType+'-auto'], 'priority': {'name': 'High'}} print("data:", json.dumps(data)) #try: #jira.create_issue(fields=data) #print(response) #except: #print('post jira failed') def insertResultToMysql(job_url, build_num, result, env, autoType, headers, failCases, passCases, runner, is_patrol): #mysqlHost = "qedb.pingcap.net" #user = "case_owner" #password = "FUxIeIEhBIcUL1pwUIh" if autoType == 'reminder': return mysqlHost = "34.208.189.148" user = "root" password = "test123456!" behaviorsApi = job_url + '/' + build_num + '/allure/widgets/suites.json' try: response = requests.get(behaviorsApi, headers=headers) except: print('Get behaviors report failed') case_num = json.loads(response.text).get('total') localTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) if result == "SUCCESS": is_success = 1 else: is_success = 0 sql = 'insert into auto_case_result(run_date, is_success, type, env, case_num, jenkins_id, fail_case_num, runner, is_patrol) ' \ 'values(\'%s\', %s, \'%s\', \'%s\', %s, %s, %s, \'%s\',\'%s\');' % ( localTime, is_success, autoType, env, case_num, build_num, failCases, runner, is_patrol) if is_patrol == 'Y': mysqlHost = "qedb.pingcap.net" user = "case_owner" password = "FUxIeIEhBIcUL1pwUIh" sql = 'insert into probe_result(run_date, is_success, type, env, case_num, fail_case_num, jenkins_id, runner,is_patrol) values' \ '(\'%s\', %s, \'%s\', \'%s\', %s, %s, %s, \'%s\',\'%s\');' % (localTime, is_success, autoType, env, case_num, failCases, build_num, runner,is_patrol) db = pymysql.connect(host=mysqlHost, user=user, password=password, db="case_manager",write_timeout=30) cursor = db.cursor() print("sql:", sql) try: cursor.execute(sql) db.commit() except: db.rollback() db.close() if __name__ == '__main__': print(sys.argv[1]) jobList = sys.argv[1:] # jobList = ['staging-scene-staging-new-arch', 'FAILURE', 'http://cicd.tidbcloud.com/job/staging-scene-staging-new-arch', '26', 'staging', 'debug', 'debug'] #analyzeResult(jobList[2], jobList[3], jobList[4], jobList[5]) if len(jobList) == 8: # jobList[7] is is_patrol flag faileCaseList, isSame = analyzeResult(jobList[2], jobList[3], jobList[4], jobList[5], jobList[1], jobList[6], jobList[7]) send_msg(jobList[0], jobList[1], jobList[2], jobList[3], faileCaseList, isSame, jobList[4], jobList[6], jobList[5],jobList[7]) else: faileCaseList, isSame = analyzeResult(jobList[2], jobList[3], jobList[4], jobList[5], jobList[1], jobList[6]) send_msg(jobList[0], jobList[1], jobList[2], jobList[3], faileCaseList, isSame, jobList[4], jobList[6], jobList[5])