课程内如记录:
sharedlib → saveReportToDB
import groovy.grape.Grape
/**
* Created by sungaofei on 19/3/1.
*/
@Grab(group = 'org.codehaus.groovy.modules.http-builder', module = 'http-builder', version = '0.7')
@Grab(group = 'org.jsoup', module = 'jsoup', version = '1.10.3')
import org.jsoup.Jsoup
import groovyx.net.http.HTTPBuilder
import static groovyx.net.http.ContentType.*
import static groovyx.net.http.Method.*
import groovy.transform.Field
//可以指定maven仓库
//@GrabResolver(name = 'aliyun', root = 'http://maven.aliyun.com/nexus/content/groups/public/')
//加载数据库连接驱动包
//@Grab('mysql:mysql-connector-java:5.1.25')
//@GrabConfig(systemClassLoader=true)
//global variable
@Field jenkinsURL = "http://k8s.testing-studio.com:5003"
@Field int passed
@Field int failed
@Field int skipped
@Field int broken
@Field int unknown
@Field int total
@Field Map<String, Map<String, Integer>> map = new HashMap<>()
@NonCPS
def getResultFromAllure() {
def reportURL = "/job/DailyBuild/${BUILD_NUMBER}/allure/"
// if (env.BRANCH_NAME != "" && env.BRANCH_NAME != null) {
// reportURL = "http://k8s.testing-studio.com:5003/job/Daily%20Build/allure/"
// } else {
// reportURL = "/view/API/job/${JOB_NAME}/${BUILD_NUMBER}/allure/"
// }
// reportURL = "/view/API/job/sage-sdk-test/185/allure/"
println(jenkinsURL+"${reportURL}widgets/summary.json")
HTTPBuilder http = new HTTPBuilder("http://k8s.testing-studio.com:5003")
//根据responsedata中的Content-Type header,调用json解析器处理responsedata
http.get(path: "${reportURL}widgets/summary.json") { resp, json ->
println resp.status
passed = Integer.parseInt((String) json.statistic.passed)
failed = Integer.parseInt((String) json.statistic.failed)
skipped = Integer.parseInt((String) json.statistic.skipped)
broken = Integer.parseInt((String) json.statistic.broken)
unknown = Integer.parseInt((String) json.statistic.unknown)
total = Integer.parseInt((String) json.statistic.total)
}
}
def call() {
getResultFromAllure()
getDatabaseConnection(type: 'GLOBAL') {
// map.each { feature, valueMap ->
// def sqlString = "INSERT INTO func_test (name, build_id, feature, version, total, passed, unknown, skipped, failed, broken, create_time) VALUES ('${JOB_NAME}', '${BUILD_ID}', '${feature}', '${version}', " +
// "${valueMap['total']}, ${valueMap['passed']}, ${valueMap['unknown']}, ${valueMap['skipped']}, ${valueMap['failed']}, ${valueMap['broken']}, NOW())"
// println(sqlString)
//
// sql sql: sqlString
// }
// def lineCov = 0
// def branchCov = 0
// if (coverage != null && coverage != ""){
// lineCov = getLineCov()
// branchCov = getBranchCov() * 100
//
// }
def sqlString = "INSERT INTO func_test_summary (name, build_id, total, passed, unknown, skipped, failed, broken, create_time) VALUES ('${JOB_NAME}', '${BUILD_ID}', " +
"${total}, ${passed}, ${unknown}, ${skipped}, ${failed}, ${broken}, NOW())"
sql sql: sqlString
}
}
sendEmail:
/**
* Created by sungaofei on 20/2/8.
*/
@Grab(group = 'org.codehaus.groovy.modules.http-builder', module = 'http-builder', version = '0.7')
import groovyx.net.http.HTTPBuilder
import static groovyx.net.http.ContentType.*
import static groovyx.net.http.Method.*
import groovy.transform.Field
//global variable
@Field jenkinsURL = "http://auto.4paradigm.com"
@Field failed = "FAILED"
@Field success = "SUCCESS"
@Field inProgress = "IN_PROGRESS"
@Field abort = "ABORTED"
@NonCPS
def String checkJobStatus() {
def url = ""
if (env.BRANCH_NAME!= "" && env.BRANCH_NAME != null){
String jobName = "${JOB_NAME}".split("/")[0]
url = "/view/API/job/${jobName}/job/${env.BRANCH_NAME}/${BUILD_NUMBER}/wfapi/describe"
}else {
url = "/view/API/job/${JOB_NAME}/${BUILD_NUMBER}/wfapi/describe"
}
HTTPBuilder http = new HTTPBuilder(jenkinsURL)
String status = success
println("1111111111")
println("${JOB_NAME}")
println(url)
http.get(path: url) { resp, json ->
if (resp.status != 200) {
throw new RuntimeException("请求 ${url} 返回 ${resp.status} ")
}
List stages = json.stages
for (int i = 0; i < stages.size(); i++) {
def stageStatus = json.stages[i].status
if (stageStatus == failed) {
status = failed
break
}
if (stageStatus == abort) {
status = abort
break
}
}
}
return status;
}
@NonCPS
def call(String to) {
println("邮件列表:${to}")
def reportURL = ""
String jobName = "${JOB_NAME}"
String blueOCeanURL = ""
if (env.BRANCH_NAME!= "" && env.BRANCH_NAME != null){
jobName = "${JOB_NAME}".split("/")[0]
reportURL = "/view/API/job/${jobName}/job/${env.BRANCH_NAME}/${BUILD_NUMBER}/allure/"
// http://auto.4paradigm.com/blue/organizations/jenkins/gitlabtest/detail/master/217/pipeline
blueOCeanURL = "${jenkinsURL}/blue/organizations/jenkins/${jobName}/detail/${env.BRANCH_NAME}/${BUILD_NUMBER}/pipeline"
}else{
reportURL = "/view/API/job/${JOB_NAME}/${BUILD_NUMBER}/allure/"
blueOCeanURL = "${jenkinsURL}/blue/organizations/jenkins/${JOB_NAME}/detail/${JOB_NAME}/${BUILD_NUMBER}/pipeline"
}
def sendSuccess = {
// blueOCeanURL = "${jenkinsURL}/blue/organizations/jenkins/${JOB_NAME}/detail/${JOB_NAME}/${BUILD_NUMBER}/pipeline"
def fileContents = ""
def passed = ""
def failed = ""
def skipped = ""
def broken = ""
def unknown = ""
def total = ""
HTTPBuilder http = new HTTPBuilder('http://auto.4paradigm.com')
//根据responsedata中的Content-Type header,调用json解析器处理responsedata
http.get(path: "${reportURL}widgets/summary.json") { resp, json ->
println resp.status
passed = json.statistic.passed
failed = json.statistic.failed
skipped = json.statistic.skipped
broken = json.statistic.broken
unknown = json.statistic.unknown
total = json.statistic.total
}
println(passed)
emailext body: """
<html>
<style type="text/css">
<!--
${fileContents}
-->
</style>
<body>
<div id="content">
<h1>Summary</h1>
<div id="sum2">
<h2>Jenkins Build</h2>
<ul>
<li>Job 地址 : <a href='${BUILD_URL}'>${BUILD_URL}</a></li>
<li>测试报告地址 : <a href='${jenkinsURL}${reportURL}'>${jenkinsURL}${reportURL}</a></li>
<li>Pipeline 流程地址 : <a href='${blueOCeanURL}'>${blueOCeanURL}</a></li>
</ul>
<h2>测试结果汇总</h2>
<ul>
<li>用例总数 : ${total}</li>
<li>pass数量 : ${passed}</li>
<li>failed数量 :${failed} </li>
<li>skip数量 : ${skipped}</li>
<li>broken数量 : ${broken}</li>
</ul>
</div>
</div></body></html>
""", mimeType: 'text/html', subject: "${JOB_NAME} 测试结束", to: to
}
def send = { String subject ->
emailext body: """
<html>
<style type="text/css">
<!--
-->
</style>
<body>
<div id="sum2">
<h2>Jenkins Build</h2>
<ul>
<li>Job 地址 : <a href='${BUILD_URL}'>${BUILD_URL}</a></li>
<li>测试报告地址 : <a href='${jenkinsURL}${reportURL}'>${jenkinsURL}${reportURL}</a></li>
<li>Pipeline 流程地址 : <a href='${blueOCeanURL}'>${blueOCeanURL}</a></li>
</ul>
</div>
</div></body></html>
""", mimeType: 'text/html', subject: subject, to: to
}
String status = checkJobStatus()
// String status = $BUILD_STATUS
println("当前job 的运行状态为: ${status}")
switch (status) {
case ["SUCCESS", "UNSTABLE"]:
sendSuccess()
break
case "FAILED":
send("Job运行失败")
break
case "ABORTED":
send("Job在运行中被取消")
break
default:
send("Job运行结束")
}
}
sendWeChart:
import groovy.grape.Grape
@Grab(group = 'org.codehaus.groovy.modules.http-builder', module = 'http-builder', version = '0.7')
@Grab(group = 'org.jsoup', module = 'jsoup', version = '1.10.3')
import org.jsoup.Jsoup
import groovyx.net.http.HTTPBuilder
import static groovyx.net.http.ContentType.*
import static groovyx.net.http.Method.*
import groovy.transform.Field
import java.io.BufferedReader
import java.io.InputStreamReader
import java.io.OutputStreamWriter
import java.net.URL
import java.net.URLConnection
//import com.alibaba.fastjson.JSONObject;
//可以指定maven仓库
//@GrabResolver(name = 'aliyun', root = 'http://maven.aliyun.com/nexus/content/groups/public/')
//加载数据库连接驱动包
//@Grab('mysql:mysql-connector-java:5.1.25')
//@GrabConfig(systemClassLoader=true)
//global variable
@Field jenkinsURL = "http://auto.4paradigm.com"
@Field int passed
@Field int failed
@Field int skipped
@Field int broken
@Field int unknown
@Field int total
@Field Map<String, Map<String, Integer>> map = new HashMap<>()
@NonCPS
def sendWechatAlarm() {
def reportURL = ""
if (env.BRANCH_NAME != "" && env.BRANCH_NAME != null) {
reportURL = "/view/API/job/${jobName}/job/${env.BRANCH_NAME}/${BUILD_NUMBER}/allure/"
} else {
reportURL = "/view/API/job/${JOB_NAME}/${BUILD_NUMBER}/allure/"
}
def s1=''
def pic1 = 'https://a1.qpic.cn/psc?/V50K8Aj22Pi7jG1cQHUv13mYFX1nzj4i/ruAMsa53pVQWN7FLK88i5tD45cdngcdQjsTSVi5*o5lEyjoe7mOItBetTiR97DTcNquldh*u9wz8kCo8hgP9NIufqR5EyOROUWzZNvoLrRE!/m&ek=1&kp=1&pt=0&bo=2wEJAQAAAAABF.I!&tl=3&vuin=1677684467&tm=1597251600&sce=60-3-3&rf=0-0'
def pic2 = 'http://a1.qpic.cn/psc?/V50K8Aj22Pi7jG1cQHUv13mYFX1nzj4i/ruAMsa53pVQWN7FLK88i5tHP1AzYWSQYCpP9GLLjmX2kVPpmgDpWYZyT7qEjJ9gca9K5NwjMAhXGJm7RwGD61afF2eRZuzBuLTCavKor4Pw!/m&ek=1&kp=1&pt=0&bo=2wEJAQAAAAABF.I!&tl=3&vuin=1677684467&tm=1597251600&sce=60-3-3&rf=0-0'
def pic = ''
def total=0
def passed=0
//reportURL = "/view/API/job/${JOB_NAME}/${BUILD_NUMBER}/allure/"
//reportURL = "/view/SDP/job/ui-auto-linkoop/9/allure/"
HTTPBuilder http = new HTTPBuilder(jenkinsURL)
http.get(path: "${reportURL}widgets/summary.json") { resp, json ->
println resp.status
passed = Integer.parseInt((String) json.statistic.passed)
failed = Integer.parseInt((String) json.statistic.failed)
skipped = Integer.parseInt((String) json.statistic.skipped)
broken = Integer.parseInt((String) json.statistic.broken)
unknown = Integer.parseInt((String) json.statistic.unknown)
total = Integer.parseInt((String) json.statistic.total)
s1="""Passed:${passed} Failed:${failed} Broken:${broken}\n环境信息 ${SGAE_URL}\n\n[查看测试报告]"""
}
if(total==passed && passed!=0) {
pic=pic1
} else{
pic=pic2
}
// webURL="https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=c916b757-a1a2-416d-bf63-10fb8cf769e5"
HTTPBuilder http1 = new HTTPBuilder("${WEBHOOK_URL}")
String s="""
{
"msgtype": "news",
"news": {
"articles" : [
{
"title" : "${VERSION}自动化运行结果",
"description" : "${s1}",
"url" : "${JENKINS_URL}/job/${JOB_NAME}/${BUILD_NUMBER}/allure/#/behaviors",
"picurl" : "${pic}"
}
]
}
}
"""
println s
def jsonSlurper = new groovy.json.JsonSlurper()
def object1 = jsonSlurper.parseText(s)
print object1
http1.request( POST, JSON ) { req ->
String picurl="http://a1.qpic.cn/psc?/V50K8Aj22Pi7jG1cQHUv13mYFX1nzj4i/ruAMsa53pVQWN7FLK88i5tHP1AzYWSQYCpP9GLLjmX2kVPpmgDpWYZyT7qEjJ9gca9K5NwjMAhXGJm7RwGD61afF2eRZuzBuLTCavKor4Pw!/m&ek=1&kp=1&pt=0&bo=2wEJAQAAAAABF.I!&tl=3&vuin=1677684467&tm=1597251600&sce=60-3-3&rf=0-0"
Map<String, String> bodyParam = new HashMap<>()
bodyParam['picurl'] = picurl
bodyParam['title'] = "测试title"
bodyParam['description'] = "测试description"
Map<String, Map<String, String>> articles = new HashMap<>()
articles['articles']=bodyParam
articles1 = [ articles ]
body = object1
response.success = { resp, json ->
// TODO process json data
println resp.status
}
}
}
def sendPostRequest(urlString, paramString) {
def url = new URL(urlString)
def conn = url.openConnection()
conn.setDoOutput(true)
def writer = new OutputStreamWriter(conn.getOutputStream())
writer.write(paramString)
writer.flush()
String line
def reader = new BufferedReader(new InputStreamReader(conn.getInputStream()))
while ((line = reader.readLine()) != null) {
println line
}
writer.close()
reader.close()
}
def call(String coverage = null, String version="release/3.8.2") {
sendWechatAlarm()
//sendPostRequest("https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=c916b757-a1a2-416d-bf63-10fb8cf769e5", "msgtype=markdown&markdown={\"content\": \"test2\"}")
}
pipeline:
library 'test-lib'
pipeline {
parameters {
choice(name: 'ENV', choices: ['http', 'https'], description: '环境协议')
string(name: 'SGAE_URL', defaultValue: '172.27.128.8:40126', description: '测试环境')
booleanParam(name: 'IF_START', defaultValue: false, description: '是否初始化环境,适用于一个啥都没有的环境,会步创建hadoop资源,创建workspace、创建租户->上传lincese->配置zk等信息-> 更新内置算子api接口;创建工作区名称为:aios_test')
booleanParam(name: 'DEPLOY_FLINK', defaultValue: false, description: '是否需要部署Flink')
choice(name: 'VERSION', choices: ['4.x', '3.x'], description: '上传lincese版本;执行初始化环境才需要选这个')
string(name: 'WORKSPACE_ID', defaultValue: '1', description: '工作区ID,如果是非空环境,则需填写wsid')
string(name: 'TEST_VERSION', defaultValue: 'release/4.0.3', description: '测试代码分支')
string(name: 'TEST_RUN_OP', defaultValue: 'sh run.sh', description: '测试用例运行命令;运行所有case输入:sh run.sh;分组运行case例如:sh run-group.sh "not aio"')
string(name: 'TUNING_PARAM', defaultValue: '1', description: '由于有些算子由于默认的num-epoch、batch_size等参数设置较大,想快速验证算子是否正常较慢,因此通过该参数来调整不同的大小。其中设置default表示使用默认设置。目前只对paddlex算子')
string(name: 'WE_TITLE', defaultValue: 'SAGE-SDK 自动化结果', description: '给企业微信发消息的标题,标题名称要控制10个字符以内,不然微信显示的标题就会截取显示了')
}
environment {
WEBHOOK_URL = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=997aa130-57f8-42c5-bae7-e69111b67950"
// WEBHOOK_URL = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=fff6a47f-0c07-453b-b6a3-92ca08cacfe4"
}
agent { label 'tech' }
stages {
stage('pull testing code') {
steps {
checkout([$class: 'GitSCM', branches: [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions: [[$class: 'RelativeTargetDirectory', relativeTargetDir: 'techUI']], submoduleCfg: [], userRemoteConfigs: [[credentialsId: 'root', url: 'http://k8s.testing-studio.com:8880/root/uiautomation.git']]])
}
}
stage('UI testing') {
steps {
sh '''
cd techUI
mvn clean test -Dmaven.test.failure.ignore=true -DsuiteXmlFile=testng-parallel.xml
'''
allure commandline: 'allure2.13', includeProperties: false, jdk: '', results: [[path: 'techUI/target/allure-results']]
saveReportToDB()
script {
env.RELEASE_SCOPE = input message: '是否通过QA测试', ok: '发布!', submitter: 'admin,root',
parameters: [choice(name: 'RELEASE_SCOPE', choices: 'patch\nminor\nmajor', description: 'What is the release scope?')]
}
}
}
}
post {
always {
sh 'echo 11111111'
}
}
}