#!groovy
pipeline {
//在任何可用的代理上執行Pipeline
agent any
//參數化變量,目前只支持[booleanParam, choice, credentials, file, text, password, run, string]這幾種參數類型,其他高級參數化類型還需等待社區支持。
parameters {
//git代碼路徑【參數值對外隱藏】
string(name:'repoUrl', defaultValue: 'git@git.*****.com:*****/*****.git', description: 'git代碼路徑')
//repoBranch參數后續替換成git parameter不再依賴手工輸入,JENKINS-46451【git parameters目前還不支持pipeline】
string(name:'repoBranch', defaultValue: 'master', description: 'git分支名稱')
//pom.xml的相對路徑
string(name:'pomPath', defaultValue: 'pom.xml', description: 'pom.xml的相對路徑')
//war包的相對路徑
string(name:'warLocation', defaultValue: 'rpc/war/target/*.war', description: 'war包的相對路徑 ')
//服務器參數采用了組合方式,避免多次選擇,使用docker為更佳實踐【參數值對外隱藏】
choice(name: 'server',choices:'192.168.1.107,9090,*****,*****\n192.168.1.60,9090,*****,*****', description: '測試服務器列表選擇(IP,JettyPort,Name,Passwd)')
//測試服務器的dubbo服務端口
string(name:'dubboPort', defaultValue: '31100', description: '測試服務器的dubbo服務端口')
//單元測試代碼覆蓋率要求,各項目視要求調整參數
string(name:'lineCoverage', defaultValue: '20', description: '單元測試代碼覆蓋率要求(%),小於此值pipeline將會失敗!')
//若勾選在pipelie完成后會郵件通知測試人員進行驗收
booleanParam(name: 'isCommitQA',description: '是否郵件通知測試人員進行人工驗收',defaultValue: false )
}
//環境變量,初始確定后一般不需更改
tools {
maven 'maven3'
jdk 'jdk8'
}
//常量參數,初始確定后一般不需更改
environment{
//git服務全系統只讀賬號cred_id【參數值對外隱藏】
CRED_ID='*****-****-****-****-*********'
//測試人員郵箱地址【參數值對外隱藏】
QA_EMAIL='*****@*****.com'
//接口測試(網絡層)的job名,一般由測試人員編寫
ITEST_JOBNAME='Guahao_InterfaceTest_ExpertPatient'
}
options {
//保持構建的最大個數
buildDiscarder(logRotator(numToKeepStr: '10'))
}
//定期檢查開發代碼更新,工作日每晚4點做daily build
triggers {
pollSCM('H 4 * * 1-5')
}
//pipeline運行結果通知給觸發者
post{
success{
script {
wrap([$class: 'BuildUser']) {
mail to: "${BUILD_USER_EMAIL }",
subject: "PineLine '${JOB_NAME}' (${BUILD_NUMBER}) result",
body: "${BUILD_USER}'s pineline '${JOB_NAME}' (${BUILD_NUMBER}) run success\n請及時前往${env.BUILD_URL}進行查看"
}
}
}
failure{
script {
wrap([$class: 'BuildUser']) {
mail to: "${BUILD_USER_EMAIL }",
subject: "PineLine '${JOB_NAME}' (${BUILD_NUMBER}) result",
body: "${BUILD_USER}'s pineline '${JOB_NAME}' (${BUILD_NUMBER}) run failure\n請及時前往${env.BUILD_URL}進行查看"
}
}
}
unstable{
script {
wrap([$class: 'BuildUser']) {
mail to: "${BUILD_USER_EMAIL }",
subject: "PineLine '${JOB_NAME}' (${BUILD_NUMBER})結果",
body: "${BUILD_USER}'s pineline '${JOB_NAME}' (${BUILD_NUMBER}) run unstable\n請及時前往${env.BUILD_URL}進行查看"
}
}
}
}
//pipeline的各個階段場景
stages {
stage('代碼獲取') {
steps {
//根據param.server分割獲取參數,包括IP,jettyPort,username,password
script {
def split=params.server.split(",")
serverIP=split[0]
jettyPort=split[1]
serverName=split[2]
serverPasswd=split[3]
}
echo "starting fetchCode from ${params.repoUrl}......"
// Get some code from a GitHub repository
git credentialsId:CRED_ID, url:params.repoUrl, branch:params.repoBranch
}
}
stage('單元測試') {
steps {
echo "starting unitTest......"
//注入jacoco插件配置,clean test執行單元測試代碼. All tests should pass.
sh "mvn org.jacoco:jacoco-maven-plugin:prepare-agent -f ${params.pomPath} clean test -Dautoconfig.skip=true -Dmaven.test.skip=false -Dmaven.test.failure.ignore=true"
junit '**/target/surefire-reports/*.xml'
//配置單元測試覆蓋率要求,未達到要求pipeline將會fail,code coverage.LineCoverage>20%.
jacoco changeBuildStatus: true, maximumLineCoverage:"${params.lineCoverage}"
}
}
stage('靜態檢查') {
steps {
echo "starting codeAnalyze with SonarQube......"
//sonar:sonar.QualityGate should pass
withSonarQubeEnv('SonarQube') {
//固定使用項目根目錄${basedir}下的pom.xml進行代碼檢查
sh "mvn -f pom.xml clean compile sonar:sonar"
}
script {
timeout(10) {
//利用sonar webhook功能通知pipeline代碼檢測結果,未通過質量閾,pipeline將會fail
def qg = waitForQualityGate()
if (qg.status != 'OK') {
error "未通過Sonarqube的代碼質量閾檢查,請及時修改!failure: ${qg.status}"
}
}
}
}
}
stage('部署測試環境') {
steps {
echo "starting deploy to ${serverIP}......"
//編譯和打包
sh "mvn -f ${params.pomPath} clean package -Dautoconfig.skip=true -Dmaven.test.skip=true"
archiveArtifacts warLocation
script {
wrap([$class: 'BuildUser']) {
//發布war包到指定服務器,虛擬機文件目錄通過shell腳本初始化建立,所以目錄是固定的
sh "sshpass -p ${serverPasswd} scp ${params.warLocation} ${serverName}@${serverIP}:htdocs/war"
//這里增加了一個小功能,在服務器上記錄了基本部署信息,方便多人使用一套環境時問題排查,storge in {WORKSPACE}/deploy.log & remoteServer:htdocs/war
Date date = new Date()
def deploylog="${date.toString()},${BUILD_USER} use pipeline '${JOB_NAME}(${BUILD_NUMBER})' deploy branch ${params.repoBranch} to server ${serverIP}"
println deploylog
sh "echo ${deploylog} >>${WORKSPACE}/deploy.log"
sh "sshpass -p ${serverPasswd} scp ${WORKSPACE}/deploy.log ${serverName}@${serverIP}:htdocs/war"
//jetty restart,重啟jetty
sh "sshpass -p ${serverPasswd} ssh ${serverName}@${serverIP} 'bin/jettyrestart.sh' "
}
}
}
}
stage('接口自動化測試') {
steps{
echo "starting interfaceTest......"
script {
//為確保jetty啟動完成,加了一個判斷,確保jetty服務器啟動可以訪問后再執行接口層測試。
timeout(5) {
waitUntil {
try {
//確保jetty服務的端口啟動成功
sh "nc -z ${serverIP} ${jettyPort}"
//sh "wget -q http://${serverIP}:${jettyPort} -O /dev/null"
return true
} catch (exception) {
return false
}
}
}
//將參數IP和Port傳入到接口測試的job,需要確保接口測試的job參數可注入
build job: ITEST_JOBNAME, parameters: [string(name: "dubbourl", value: "${serverIP}:${params.dubboPort}")]
}
}
}
stage('UI自動化測試') {
steps{
echo "starting UITest......"
//這個項目不需要UI層測試,UI自動化與接口測試的pipeline腳本類似
}
}
stage('性能自動化測試 ') {
steps{
echo "starting performanceTest......"
//視項目需要增加性能的冒煙測試,具體實現后續專文闡述
}
}
stage('通知人工驗收'){
steps{
script{
wrap([$class: 'BuildUser']) {
if(params.isCommitQA==false){
echo "不需要通知測試人員人工驗收"
}else{
//郵件通知測試人員人工驗收
mail to: "${QA_EMAIL}",
subject: "PineLine '${JOB_NAME}' (${BUILD_NUMBER})人工驗收通知",
body: "${BUILD_USER}提交的PineLine '${JOB_NAME}' (${BUILD_NUMBER})進入人工驗收環節\n請及時前往${env.BUILD_URL}進行測試驗收"
}
}
}
}
}
// stage('發布系統') {
// steps{
// echo "starting deploy......"
// // TODO發布環節后續專題闡述
// }
// }
}
}