##轉載註明出處:http://www.cnblogs.com/wade-xu/p/4378224.html html
部門用持續集成已經好久了,但其實使用起來仍是很麻煩的,每當要給一個新項目set up持續集成的環境,雖然是Copy一些現有的jobs, 可是許多參數,變量須要去改,而後還有調試,少說3,4天搞一下,很是不方便。java
最近比較空,就把現有的持續集成系統升級改造下,job用一套模板,所有參數化,只要修改配置文件,就能夠爲新項目配置好環境。linux
本文的重點是一些經驗,想法的分享,並非一篇手把手教你搭建持續集成環境的教程,並且閱讀本文須要必定的Jenkins, perl, shell腳本的基礎知識, 所用到的知識有:Jenkins+Maven+Git+Sonar+Perl+Shell scriptgit
下圖很好的說明了咱們現有的Job流, 以往是每一個項目都有一套這樣的job流,如今我改爲這個Template_service job流,供全部的項目使用,項目名也是做爲參數傳遞進來的,每一個job都是用Jenkins Execute shell這個組件來實現功能的,像check out code,Email Notification, Publish Junit test results, code coverage report 等Jenkins自帶組件都沒有使用。 spring
運行環境: apache-maven-3.0.5, jdk1.7.0_15, git 1.8.2.1, SonarQube 4.0, perl v5.8.8shell
##轉載註明出處:http://www.cnblogs.com/wade-xu/p/4378224.html 數據庫
接下來簡單的說明一下各個Job的功能,以及貼出詳細的腳本供你們參考。apache
除了上圖裏面的job, 還有一個Config job, export一些環境變量json
0)Template_Service_Config (one time run)ssh
用來Export 環境變量的,好比Project list, project git 地址,
export PROJECT_LIST=PROJECTA,PROJECTB
export PROJECTA_GIT_PROJECT_URL=ssh://git@stash.xxx.com:7999/Project/ProjectA.git
export PROJECTA_BRANCH=development
export PROJECTA_SERVICE_NAME=China_Template_Service
export PROJECTA_EMAIL_LIST=wadexu@xxx.com,xxx@xxx.com
export PROJECTA_EMAIL_CC_LIST=wadexu@xxx.com
......
export PROJECTB_GIT_PROJECT_URL=ssh://git@stash.xxx.com:7999/abc/ProjectB.git
export PROJECTB_BRANCH=perf
export PROJECTB_SERVICE_NAME=China_ProjectB_DEV
export PROJECTB_EMAIL_LIST=wadexu@xxx.com,xxx@xxx.com
export PROJECTB_EMAIL_CC_LIST=wadexu@xxx.com
......
Build 這個job 的時候須要Parameters
代碼以下:主要做用就是將輸入的Parameters寫入到一個文件,以便後續全部job 一上來source一下
TEST=${WORKSPACE}/test
CONFIG_FILE=Project_Config.txt rm -rf ${TEST} git clone ssh://git@stash.xxx.com:7999/project/test.git cd ${TEST} cd Config if [ ! -f "${CONFIG_FILE}" ]; then touch "${CONFIG_FILE}" fi ##########Rewrite the config file base on the project list########### CURRENT_TIME=`date +"%m/%d/%Y/%T"` echo -e "export CONFIG_TIME=${CURRENT_TIME}\n export PROJECT_LIST=${PROJECT_LIST}\n export SHARED_FOLDER=~/jenkins/common\n" > ${CONFIG_FILE} ###########List the project1 parameters########### echo -e "${PROJECTA_PARAMETERS}" >> ${CONFIG_FILE} ###########List the project2 parameters########### echo -e "${PROJECTB_PARAMETERS}" >> ${CONFIG_FILE} git add ${CONFIG_FILE} git commit -m "config file" git push origin master cp ${CONFIG_FILE} ~/jenkins/common/Config cd .. cp Scripts/* ~/jenkins/common/Scripts chmod 755 ~/jenkins/common/Scripts/*
還有就是將一些perl寫的腳本從git clone下來放到某一個公共目錄下,以便後續job使用, 有以下腳本,好比發送email, Unit test analyzer
部分腳本像gridService, packageService是操做公司一個網格雲計算平臺,安裝rpm包,重啓service用的,不方便貼出來。
[wadexu@vm10226 common]$ cd Scripts/ [wadexu@vm10226 Scripts]$ ll total 404 -rwxr-xr-x 1 wadexu wadexu 37853 Mar 27 09:12 gridService -rwxr-xr-x 1 wadexu wadexu 4991 Mar 27 09:12 packageService -rwxr-xr-x 1 wadexu wadexu 1628 Mar 27 09:12 queryDB.pl -rwxr-xr-x 1 wadexu wadexu 317183 Mar 27 09:12 Reporter.jar -rwxr-xr-x 1 wadexu wadexu 2190 Mar 27 09:12 report.pl -rwxr-xr-x 1 wadexu wadexu 3415 Mar 27 09:12 sendEmail.pl -rwxr-xr-x 1 wadexu wadexu 1210 Mar 27 09:12 ServiceInfoProvider.pl
-rwxr-xr-x 1 wadexu wadexu 3418 Mar 27 09:12 UnitTestAnalyzer.pl
1)Template_Service_Initial
遍歷Project list 列出的項目, 使用curl 調用下一個job (Commit_Auto_Build) 的Rest API, Build job with parameter接口
每一個項目的Job流都是經過Project name + Initial job的Build number 來貫穿的, 這點很重要,多項目一塊兒運行時各項目之間不會錯亂,好比寫Log文件,分析Log文件生成report
rm -rf ${WORKSPACE}/* ####### Import config file ####### cd ~/jenkins/common/Config . Project_Config.txt cd ~/jenkins/common/Temp ####### Get the Project list and traverse the list ###### id=1 list_size=`echo $PROJECT_LIST | awk -F "," '{print NF;}'` let list_size=list_size+1 while [ $id -lt $list_size ] do projectName=`echo "${PROJECT_LIST}"|awk -v id=$id -F "," '{print $id}'` if [ "$projectName " != ' ' ]; then curl -X POST --user "jadmin:71103407" -s http://vm10686.global.xxx.net:8080/view/Template/job/Template_Service_Commit_Auto_Build/build --data json='{"parameter": [{"name":"PROJECT_NAME","value":"'$projectName'"},{"name":"PIPELINE_NUM","value":"'$BUILD_NUMBER'"}]}' id=`expr $id + 1` else break fi done
2)Template_Service_Commit_Auto_Build
這個Job的做用是用來比較代碼版本有沒有更新,若是有更新(或者是第一次run這個job)就會調用後續的-- Build job
還有就是列出此次Build和上次Build之間改動過代碼的做者。
若是將Initial job 設置成每幾分鐘run一下,其實這個job就起到了 每當有人提交代碼,則自動Build的做用了。
### Import config file ### cd ~/jenkins/common/Config . Project_Config.txt ### Initial parameters ### GIT_PROJECT_URL=${PROJECT_NAME}"_GIT_PROJECT_URL" GIT_PROJECT_URL=$(eval echo \${$GIT_PROJECT_URL}) BRANCH=${PROJECT_NAME}"_BRANCH" BRANCH=$(eval echo \${$BRANCH}) LOG_NAME=${PROJECT_NAME}"_BUILD_"${PIPELINE_NUM}".log" BUILD_LOG_FOLDER=${SHARED_FOLDER}/Log/${PROJECT_NAME}"_"${PIPELINE_NUM} BUILD_LOG=${SHARED_FOLDER}/Log/${PROJECT_NAME}"_"${PIPELINE_NUM}/$LOG_NAME mkdir $BUILD_LOG_FOLDER GIT_PROJECT_NAME=${PROJECT_NAME}"_GIT_PROJECT_NAME" GIT_PROJECT_NAME=$(eval echo \${$GIT_PROJECT_NAME}) #### setup #### export CURRENT_RESOURCE_DIR=${WORKSPACE}/${GIT_PROJECT_NAME} export CURRENT_MD5_FILE=${WORKSPACE}/${PROJECT_NAME}"_Code_Current" export BASE_MD5_FILE=${WORKSPACE}/${PROJECT_NAME}"_Code_Base" export CURRENT_AUTHOR_LIST=${WORKSPACE}/${PROJECT_NAME}"_Author_Current" export BASE_AUTHOR_LIST=${WORKSPACE}/${PROJECT_NAME}"_Author_Base" #### cd resource,get log commit MD5 #### cd ${WORKSPACE} rm -rf ${CURRENT_RESOURCE_DIR} git clone ${GIT_PROJECT_URL} cd ${CURRENT_RESOURCE_DIR} git checkout -b ci origin/${BRANCH} if [ ! -f "${BASE_AUTHOR_LIST}" ]; then touch "${BASE_AUTHOR_LIST}" fi if [ ! -f "${BASE_MD5_FILE}" ]; then touch "${BASE_MD5_FILE}" ########call build job###### curl -d --user "jadmin:71103407" -s http://vm10686.global.xxx.net:8080/view/Template/job/Template_Service_Build/build --data json='{"parameter":[{"name":"PROJECT_NAME","value":"'${PROJECT_NAME}'"},{"name":"PIPELINE_NUM","value":"'${PIPELINE_NUM}'"}]}' git log --pretty=format:"Author: %an" > ${BASE_AUTHOR_LIST} sort -u ${BASE_AUTHOR_LIST} > ${BUILD_LOG} git log --max-count=1 --pretty=format:"%H" > ${BASE_MD5_FILE} exit 0 else git log --max-count=1 --pretty=format:"%H" > ${CURRENT_MD5_FILE} git log --pretty=format:"Author: %an" > ${CURRENT_AUTHOR_LIST} fi #### compare the md5 file, and run the job.#### ## -a means && ## if cmp -s ${CURRENT_MD5_FILE} ${BASE_MD5_FILE} then echo "same,no changes!" else mv ${CURRENT_MD5_FILE} ${BASE_MD5_FILE} diff -b $CURRENT_AUTHOR_LIST $BASE_AUTHOR_LIST | grep "<" | sed 's/^< //g' > Update_Author.txt mv ${CURRENT_AUTHOR_LIST} ${BASE_AUTHOR_LIST} sort -u Update_Author.txt > ${BUILD_LOG} ########call build job###### curl -d --user "jadmin:71103407" -s http://vm10686.global.xxx.net:8080/view/Template/job/Template_service_Build/build --data json='{"parameter": [{"name":"PROJECT_NAME","value":"'${PROJECT_NAME}'"},{"name":"PIPELINE_NUM","value":"'${PIPELINE_NUM}'"}]}' fi
這裏用到了--pretty=format 這個參數, %H就是打印出哈希字串, %an是打印出Author, --max-count=1 取最近的一條log 記錄
##轉載註明出處:http://www.cnblogs.com/wade-xu/p/4378224.html
3) Template_Service_Build
這個job是最核心的job, 執行rpm build, 將rpm包丟到公司內部網格雲計算平臺的Repository下, 分析單元測試結果, 運行Sonar, 從Sonar的首頁上拿到這個項目的一些信息,好比Sonar上 blocker, critical, major 等issues, 還有code coverage,所有打印到log裏, 以便後續的腳本生成report, 另外就是Sonar issue, code coverage 不達標,則發送相應的email 給相應的project email list
rm -rf ${WORKSPACE}/* ###### Import config file ###### cd ~/jenkins/common/Config . Project_Config.txt ###### Initial parameters ###### GIT_PROJECT_NAME=${PROJECT_NAME}"_GIT_PROJECT_NAME" GIT_PROJECT_NAME=$(eval echo \${$GIT_PROJECT_NAME}) LOG_NAME=${PROJECT_NAME}"_BUILD_"${PIPELINE_NUM}".log" BUILD_LOG=${SHARED_FOLDER}/Log/${PROJECT_NAME}"_"${PIPELINE_NUM}/$LOG_NAME BRANCH=${PROJECT_NAME}"_BRANCH" BRANCH=$(eval echo \${$BRANCH}) GIT_PROJECT_URL=${PROJECT_NAME}"_GIT_PROJECT_URL" GIT_PROJECT_URL=$(eval echo \${$GIT_PROJECT_URL}) REPOSITORY=${PROJECT_NAME}"_REPOSITORY" REPOSITORY=$(eval echo \${$REPOSITORY}) INSTANCES=${PROJECT_NAME}"_INSTANCES" INSTANCES=$(eval echo \${$INSTANCES}) COVERAGE_URL=${PROJECT_NAME}"_COVERAGE_URL" COVERAGE_URL=$(eval echo \${$COVERAGE_URL}) SONAR_MIN_COVERAGE=${PROJECT_NAME}"_SONAR_MIN_COVERAGE" SONAR_MIN_COVERAGE=$(eval echo \${$SONAR_MIN_COVERAGE}) MAX_MAJOR_ISSUE_NUM=${PROJECT_NAME}"_MAX_MAJOR_ISSUE_NUM" MAX_MAJOR_ISSUE_NUM=$(eval echo \${$MAX_MAJOR_ISSUE_NUM}) MAX_CRITICAL_ISSUE_NUM=${PROJECT_NAME}"_MAX_CRITICAL_ISSUE_NUM" MAX_CRITICAL_ISSUE_NUM=$(eval echo \${$MAX_CRITICAL_ISSUE_NUM}) SERVICE_NAME=${PROJECT_NAME}"_SERVICE_NAME" SERVICE_NAME=$(eval echo \${$SERVICE_NAME}) EMAIL_LIST=${PROJECT_NAME}"_EMAIL_LIST" EMAIL_LIST=$(eval echo \${$EMAIL_LIST}) author_list=`cat $BUILD_LOG | grep "Author"` || true ######### SET ENVIRONMENT VARIABLE ############## export BASE_DIR=${WORKSPACE}/${GIT_PROJECT_NAME} export SCRIPTS_HOME=${SHARED_FOLDER}/Scripts cd ${SCRIPTS_HOME} chmod 755 * export PATH=$PATH:`pwd` ####### Build Job ###### cd ${WORKSPACE} START_TIME=`date +"%m/%d/%Y %T"` echo "overview->startTime: ${START_TIME}" >> ${BUILD_LOG} echo "overview->logURL: ${BUILD_URL}" >> ${BUILD_LOG} echo "overview->serviceType: ${PROJECT_NAME} Service" >> ${BUILD_LOG} git clone ${GIT_PROJECT_URL} BUILD_FILE=rpmbuild.sh cd ${BASE_DIR} git checkout origin/${BRANCH} let BUILD_NUMBER=100+${BUILD_NUMBER} sed -i -r "s/^RELEASE.+/RELEASE=${BUILD_NUMBER}_Dev/g" ${BUILD_FILE} sh ${BUILD_FILE} cd ${WORKSPACE} rm -rf *.rpm mv `find . -type f -name "*.rpm" | egrep -v '(\.src\.)' | egrep -v 'BUILD'` . RPM=`ls *.rpm` packageService --addPackages --repository ${REPOSITORY} --packages "${RPM}" ############# Unit test analyze ############### UnitTestAnalyzer.pl --path "${BASE_DIR}/.rpm/BUILD" --sufix xml >> ${BUILD_LOG} ################Run Sonar################ cd ${BASE_DIR} mvn clean install -f ${BASE_DIR}/pom.xml -DPASSWORD=$ENV{PASSWORD} -DUSERNAME=$ENV{USERNAME} -e -B sonar:sonar ################Get project in Sonar ################ sonarProjectName=`sed -ne '/name/{s/.*<name>\(.*\)<\/name>.*/\1/p;q;}' pom.xml` lowerProjectName=`echo $sonarProjectName | awk '{print tolower($0)}'` sonarId=`queryDB.pl --query="select * from resource_index where kee = '$lowerProjectName' order by resource_id;"` echo $sonarId sonar_path=http://vm10686.global.xxx.net:9000/dashboard/index/${sonarId} echo "SonarPath: ${sonar_path}" >> ${BUILD_LOG} ################Function for get Sonar home page info################ ##Key for what you want to find ##column to print function get_html_value() { html=$1 key=$2 column=$3 echo `cat $html | sed -n '/'$key'/p' | awk -v column=$column -F "[><]" '{print $column}'` } ##############Sonar issues analyze ############### curl ${sonar_path} > html.txt blocker_num=`get_html_value html.txt m_blocker_violations 3` critical_num=`get_html_value html.txt m_critical_violations 3` major_num=`get_html_value html.txt m_major_violations 3` minor_num=`get_html_value html.txt m_minor_violations 3` info_num=`get_html_value html.txt m_info_violations 3` echo "SonarIssues->Blocker: ${blocker_num}" >> ${BUILD_LOG} echo "SonarIssues->Critical: ${critical_num}" >> ${BUILD_LOG} echo "SonarIssues->Major: ${major_num}" >> ${BUILD_LOG} echo "SonarIssues->Minor: ${minor_num}" >> ${BUILD_LOG} echo "SonarIssues->Info: ${info_num}" >> ${BUILD_LOG} ##############Sonar Code Coverage analyze ############### code_coverage=`get_html_value html.txt m_coverage 7` code_coverage_integer=`echo $code_coverage | sed -n 's/%//p'` line_coverage=`get_html_value html.txt m_line_coverage 5` branch_coverage=`get_html_value html.txt m_branch_coverage 5` echo "CoverageInfo->UnitTestsCoverage: ${code_coverage}" >> ${BUILD_LOG} echo "CoverageInfo->LineCoverage: ${line_coverage}" >> ${BUILD_LOG} echo "CoverageInfo->BranchCoverage: ${branch_coverage}" >> ${BUILD_LOG} echo "CoverageInfo->CoverageThreshold: ${SONAR_MIN_COVERAGE}%" >> ${BUILD_LOG} ################Send Email Code Coverage < Threshold ################ if (( $(echo "$code_coverage_integer < $SONAR_MIN_COVERAGE" | bc -l) )) then mail_subject=${PROJECT_NAME}"_Service_Build Job - Build # "${BUILD_NUMBER}" Failure"'!' mail_body="Hi, ${PROJECT_NAME}"" project member"$'\n'$'\n'"Alerts : Unit Tests Coverage: ${code_coverage} < CoverageThreshold: ${SONAR_MIN_COVERAGE}%, the latest build package cannot be allowed to install to service - ${SERVICE_NAME} [$INSTANCES]"'!'$'\n'$'\n'"For details please refer to SonarQube - ${sonar_path}"$'\n'$'\n'"The latest code author list as below:"$'\n'"${author_list}" sendEmail.pl --subject "${mail_subject}" --emaillist "${EMAIL_LIST}" --mailbody "$mail_body" --msg_type "text" exit 0 fi ################Send Email when Sonar has major above issue################ if [ ${blocker_num} -gt 0 ] || [ ${critical_num} -gt ${MAX_CRITICAL_ISSUE_NUM} ] || [ ${major_num} -gt ${MAX_MAJOR_ISSUE_NUM} ] then mail_subject=${PROJECT_NAME}"_Service_Build Job - Build # "${BUILD_NUMBER}" Failure"'!' mail_body="Hi, ${PROJECT_NAME}"" project member"$'\n'$'\n'"Alerts : Sonar major above issues != 0, the latest build package cannot be allowed to install to service - ${SERVICE_NAME} [$INSTANCES]"'!'$'\n'$'\n'"Blocker issues: ${blocker_num}"$'\n'"Critical issues: ${critical_num}"$'\n'"Major issues: ${major_num}"$'\n'"Minor issues: ${minor_num}"$'\n'"Info issues: ${info_num}"$'\n'$'\n'"For details please refer to SonarQube - ${sonar_path}"$'\n'$'\n'"The latest code author list as below:"$'\n'"${author_list}" sendEmail.pl --subject "${mail_subject}" --emaillist "${EMAIL_LIST}" --mailbody "$mail_body" --msg_type "text" exit 0 fi ####### Call Deploy Job ###### curl -d --user "jadmin:71103407" -s http://vm10686.global.xxx.net:8080/view/Template/job/Template_Service_Deploy/build --data json='{"parameter": [{"name":"PROJECT_NAME","value":"'${PROJECT_NAME}'"},{"name":"PIPELINE_NUM","value":"'${PIPELINE_NUM}'"}]}'
mvn clean install -f ${BASE_DIR}/pom.xml -DPASSWORD=$ENV{PASSWORD} -DUSERNAME=$ENV{USERNAME} -e -B sonar:sonar
運行Sonar 的一些數據庫配置信息,是放在maven/conf/settings.xml文件裏的。
另一點:每一個項目在Sonar裏的名稱是 項目pom文件的<name></name>標籤裏的值,根據這個值去數據庫裏搜出id, 有了這個id就能夠直接訪問到Sonar上的這個項目 好比http://vm10686.global.xxx.net:9000/dashboard/index/1234
4)Template_Service_Deploy
Build完以後 就是要Deploy了, 將rpm包裝到相應Service的instance上,而後重啓service
rm -rf ${WORKSPACE}/* ###### Import config file ###### cd ~/jenkins/common/Config . Project_Config.txt ###### Initial parameters ###### SERVICE_NAME=${PROJECT_NAME}"_SERVICE_NAME" SERVICE_NAME=$(eval echo \${$SERVICE_NAME}) INSTANCES=${PROJECT_NAME}"_INSTANCES" INSTANCES=$(eval echo \${$INSTANCES}) PATTERN=${PROJECT_NAME}"_RPM_GREP_PATTERN" PATTERN=$(eval echo \${$PATTERN}) LOG_NAME=${PROJECT_NAME}"_BUILD_"${PIPELINE_NUM}".log" BUILD_LOG=${SHARED_FOLDER}/Log/${PROJECT_NAME}"_"${PIPELINE_NUM}/$LOG_NAME ##########SET ENVIRONMENT VARIABLE############## SCRIPTS_HOME=~/jenkins/common/Scripts cd ${SCRIPTS_HOME} chmod 755 * export PATH=$PATH:`pwd` InstallTime=`date +"%m/%d/%Y %T"` echo "Installation->InstallTime: ${InstallTime}" >> ${BUILD_LOG} ############ Deploy ############### gridService --add-service --service ${SERVICE_NAME} --instance ${INSTANCES} sleep 60 gridService --start-service --service ${SERVICE_NAME} Endpoint="${INSTANCES}:8080" echo "Installation->Endpoint: ${Endpoint}" >> ${BUILD_LOG} echo "Installation->LogURL: ${BUILD_URL}" >> ${BUILD_LOG} UpdateTime=`date +"%m/%d/%Y %T"` echo "ServiceInfo->UpdateTime: ${UpdateTime}" >> ${BUILD_LOG} ServiceInfoProvider.pl --service ${SERVICE_NAME} --pattern ${PATTERN} >> ${BUILD_LOG} ###### Call Polling Job ###### curl -d --user "jadmin:71103407" -s http://vm10686.global.xxx.net:8080/view/Template/job/Template_Service_Polling/build --data json='{"parameter": [{"name":"PROJECT_NAME","value":"'$PROJECT_NAME'"},{"name":"PIPELINE_NUM","value":"'$PIPELINE_NUM'"}]}'
5)Template_Service_Polling
接下來經過這個Polling job 輪詢service有沒有啓動好, 每1分鐘 判斷一下,timeout時間10分鐘, 腳本其實很簡單,就是調一個接口,查看狀態是否status=200
rm -rf ${WORKSPACE}/* ######## Import config file ######### cd ~/jenkins/common/Config . Project_Config.txt ####### SET ENV ############# export SCRIPTS_HOME=${SHARED_FOLDER}/Scripts cd ${SCRIPTS_HOME} chmod 755 * export PATH=$PATH:`pwd` ###### Initial parameters ############# SERVICE_NAME=${PROJECT_NAME}"_SERVICE_NAME" SERVICE_NAME=$(eval echo \${$SERVICE_NAME}) LOG_NAME=${PROJECT_NAME}"_BUILD_"${PIPELINE_NUM}".log" BUILD_LOG=${SHARED_FOLDER}/Log/${PROJECT_NAME}"_"${PIPELINE_NUM}/$LOG_NAME echo "pollingjob->logURL: ${BUILD_URL}" >> ${BUILD_LOG} ###### Polling service whether start ############# sleep 30 gridService --ping --timeout 600 --interval 60 --service ${SERVICE_NAME} ###### Call API Testing Job ###### curl -d --user "jadmin:71103407" -s http://vm10686.global.xxx.net:8080/view/Template/job/Template_Service_APITesting/build --data json='{"parameter": [{"name":"PROJECT_NAME","value":"'${PROJECT_NAME}'"},{"name":"PIPELINE_NUM","value":"'${PIPELINE_NUM}'"}]}'
6)Template_Service_APITesting
Polling以後 就是調用藉口測試的內部測試系統,若是export 的變量有 TestPlan 就會執行,不然直接調用最後一個job--Report
rm -rf ${WORKSPACE}/* ###### Import config file ###### cd ~/jenkins/common/Config . Project_Config.txt ###### Initial parameters ###### LOG_NAME=${PROJECT_NAME}"_BUILD_"${PIPELINE_NUM}".log" BUILD_LOG=${SHARED_FOLDER}/Log/${PROJECT_NAME}"_"${PIPELINE_NUM}/$LOG_NAME TESTPLAN_ID=${PROJECT_NAME}"_TESTPLAN_ID" TESTPLAN_ID=$(eval echo \${$TESTPLAN_ID}) SERVICE_NAME=${PROJECT_NAME}"_SERVICE_NAME" SERVICE_NAME=$(eval echo \${$SERVICE_NAME}) EMAIL_LIST=${PROJECT_NAME}"_EMAIL_LIST" EMAIL_LIST=$(eval echo \${$EMAIL_LIST}) EMAIL_CC_LIST=${PROJECT_NAME}"_EMAIL_CC_LIST" EMAIL_CC_LIST=$(eval echo \${$EMAIL_CC_LIST}) ###########Set Env ############# export SCRIPTS_HOME=${SHARED_FOLDER}/Scripts/ cd ${SCRIPTS_HOME} chmod 755 * export PATH=$PATH:`pwd` ################Function################ ##Key for what you want to find ##num occurrence of value if it multiple time function jsonValue() { KEY=$1 num=$2 awk -F"[,:}]" '{for(i=1;i<=NF;i++){if($i~/'$KEY'\042/){print $(i+1)}}}' | tr -d '"' | sed -n ${num}p } ############### Main ###################### if [[ $TESTPLAN_ID == "" ]]; then echo "TestPlan ID is blank" ###### Call Report Job ###### curl -d --user "jadmin:71103407" -s http://vm10686.global.xxx.net:8080/view/Template/job/Template_Service_Report/build --data json='{"parameter": [{"name":"PROJECT_NAME","value":"'$PROJECT_NAME'"},{"name":"PIPELINE_NUM","value":"'$PIPELINE_NUM'"}]}' else processID=$(curl -X GET http://vm10765.global.xxx.net:8080/tms/project/testPlan/run.spring?ids=$TESTPLAN_ID) if [[ $processID != TestPlan-* ]]; then mail_subject=${PROJECT_NAME}"_Service_TMS_APITesting Job - Build # "${BUILD_NUMBER}" Failure"'!' mail_body="TMS Server is not available now, please contact adminstrator." echo $mail_body sendEmail.pl --subject "${mail_subject}" --emaillist "${EMAIL_LIST}" --emailcclist "${EMAIL_CC_LIST}" --mailbody "$mail_body" --msg_type "text" else while [ 1 ] do response=$(curl -X GET http://vm10765.global.xxx.net:8080/tms/project/getProcessResult.spring?processID=$processID) totalCounts=`echo $response | jsonValue totalCounts` notStartCounts=`echo $response | jsonValue notStartCounts` processingCounts=`echo $response | jsonValue processingCounts` faildCounts=`echo $response | jsonValue faildCounts` comparedCounts=`echo $response | jsonValue comparedCounts` comparedFaildCounts=`echo $response | jsonValue comparedFaildCounts` unComparedCounts=`echo $response | jsonValue unComparedCounts` if [ $notStartCounts == 0 ] && [ $processingCounts == 0 ]; then echo "End of run." break else echo "API Testing is still running, please wait..." sleep 5 fi done ############# Print Log ################### echo "APITestingInfo->TotalCounts: $totalCounts" >> ${BUILD_LOG} echo "APITestingInfo->ErrorCounts: $faildCounts" >> ${BUILD_LOG} echo "APITestingInfo->ComparedPassedCounts: $comparedCounts" >> ${BUILD_LOG} echo "APITestingInfo->ComparedFailedCounts: $comparedFaildCounts" >> ${BUILD_LOG} echo "APITestingInfo->UnComparedCounts: $unComparedCounts" >> ${BUILD_LOG} ###### Call Report Job ###### curl -d --user "jadmin:71103407" -s http://vm10686.global.xxx.net:8080/view/Template/job/Template_Service_Report/build --data json='{"parameter": [{"name":"PROJECT_NAME","value":"'$PROJECT_NAME'"},{"name":"PIPELINE_NUM","value":"'$PIPELINE_NUM'"}]}' fi fi
##轉載註明出處:http://www.cnblogs.com/wade-xu/p/4378224.html
7)Template_Service_Report
這裏主要是生成Report而且發送Email,用Java寫的一個jar放到linux上執行的,用html直接貼在郵件裏發送email的,簡單的其實能夠用Perl寫個excel,統計下測試狀況,作個報表。
rm -rf ${WORKSPACE}/* ###### Import config file ###### cd ~/jenkins/common/Config . Project_Config.txt ###### Initial parameters ###### LOG_NAME=${PROJECT_NAME}"_BUILD_"${PIPELINE_NUM}".log" BUILD_LOG_FOLDER=${SHARED_FOLDER}/Log/${PROJECT_NAME}"_"${PIPELINE_NUM} BUILD_LOG=${SHARED_FOLDER}/Log/${PROJECT_NAME}"_"${PIPELINE_NUM}/$LOG_NAME SERVICE_NAME=${PROJECT_NAME}"_SERVICE_NAME" SERVICE_NAME=$(eval echo \${$SERVICE_NAME}) INSTANCES=${PROJECT_NAME}"_INSTANCES" INSTANCES=$(eval echo \${$INSTANCES}) EMAIL_LIST=${PROJECT_NAME}"_EMAIL_LIST" EMAIL_LIST=$(eval echo \${$EMAIL_LIST}) EMAIL_CC_LIST=${PROJECT_NAME}"_EMAIL_CC_LIST" EMAIL_CC_LIST=$(eval echo \${$EMAIL_CC_LIST}) TESTPLAN_ID=${PROJECT_NAME}"_TESTPLAN_ID" TESTPLAN_ID=$(eval echo \${$TESTPLAN_ID}) export SCRIPTS_HOME=${SHARED_FOLDER}/Scripts/ cd ${SCRIPTS_HOME} chmod 755 * export PATH=$PATH:`pwd` export XML_REPORT=${WORKSPACE}/interface.xml report.pl --log-path="$BUILD_LOG_FOLDER" --output ${XML_REPORT} REPORT_PATH=${WORKSPACE}/Report.html echo ${REPORT_PATH} java -Dxmlpath="${XML_REPORT}" -Dreport="${REPORT_PATH}" -jar Reporter.jar report_context=`cat $REPORT_PATH` errorCounts=`cat $BUILD_LOG | grep "APITestingInfo->ErrorCounts" | awk -F ": " '{print $2}'` comparedFailedCounts=`cat $BUILD_LOG | grep "APITestingInfo->ComparedFailedCounts" | awk -F ": " '{print $2}'` sonarPath=`cat $BUILD_LOG | grep "SonarPath" | awk -F ": " '{print $2}'` ############## Send Email ################## if [ ${errorCounts} -gt 0 ] || [ ${comparedFailedCounts} -gt 0 ] then mail_subject=${PROJECT_NAME}"_Service_Report Job - Build # "${BUILD_NUMBER}" Failure"'!' mail_body="Hi, ${PROJECT_NAME} project member <BR><BR>The latest build package has been installed to service - ${SERVICE_NAME} [$INSTANCES], but the API testing has some test case failed.<BR><BR>Errored Test Case: ${errorCounts}<BR>Failed Test Case: ${comparedFailedCounts}<BR><BR>For details please refer to Test Management System - http://vm10765.global.xxx.net:8080/tms/login.spring<BR><BR>SonarQube - $sonarPath<BR><BR>Report as below:<BR><BR>""$report_context" sendEmail.pl --subject "${mail_subject}" --emaillist "${EMAIL_LIST}" --emailcclist "${EMAIL_CC_LIST}" --mailbody "$mail_body" --attached ${REPORT_PATH} else if [[ $TESTPLAN_ID == "" ]]; then mail_subject=${PROJECT_NAME}"_Service_Report Job - Build # "${BUILD_NUMBER}" Success"'!'" [No TestPlan for API testing]" mail_body="Hi, ${PROJECT_NAME} project member <BR><BR>The latest build package has been installed to service - ${SERVICE_NAME} [$INSTANCES].<BR><BR>SonarQube - $sonarPath<BR><BR>Report as below:<BR><BR>""$report_context" else mail_subject=${PROJECT_NAME}"_Service_Report Job - Build # "${BUILD_NUMBER}" Success"'!' mail_body="Hi, ${PROJECT_NAME} project member <BR><BR>The latest build package has been installed to service - ${SERVICE_NAME} [$INSTANCES] and API testing has passed.<BR><BR>For detailed test results, please refer to Test Management System - http://vm10765.global.xxx.net:8080/tms/login.spring<BR><BR>SonarQube - $sonarPath<BR><BR>Report as below:<BR><BR>""$report_context" fi sendEmail.pl --subject "${mail_subject}" --emaillist "${EMAIL_LIST}" --emailcclist "${EMAIL_CC_LIST}" --mailbody "$mail_body" --attached ${REPORT_PATH} fi ########### Tear Down ########### rm -rf ${BUILD_LOG_FOLDER}
我設置的是天天運行一次全部的project的持續集成, 收到的Email以下圖所示:
Report中的不少信息都是來源於Sonar
##轉載註明出處:http://www.cnblogs.com/wade-xu/p/4378224.html
到這裏就結束了嗎,尚未, 若是Build job,單元測試不經過或者其餘緣由致使Build Failure, 那怎麼辦?
再加一個Post Build job, 來監控Build job, 若是掛了,發email通知項目人員。
下圖爲Build job 加一個Action, 當Job Failed時觸發Template_Service_Post_Build job
Template_Service_Post_Build 腳本以下:
rm -rf ${WORKSPACE}/* ######## Import config file ######### cd ~/jenkins/common/Config . Project_Config.txt ####### SET ENV ############# export SCRIPTS_HOME=${SHARED_FOLDER}/Scripts cd ${SCRIPTS_HOME} chmod 755 * export PATH=$PATH:`pwd` ###### Initial parameters ############# LOG_NAME=${PROJECT_NAME}"_BUILD_"${PIPELINE_NUM}".log" BUILD_LOG=${SHARED_FOLDER}/Log/${PROJECT_NAME}"_"${PIPELINE_NUM}/$LOG_NAME EMAIL_LIST=${PROJECT_NAME}"_EMAIL_LIST" EMAIL_LIST=$(eval echo \${$EMAIL_LIST}) EMAIL_CC_LIST=${PROJECT_NAME}"_EMAIL_CC_LIST" EMAIL_CC_LIST=$(eval echo \${$EMAIL_CC_LIST}) author_list=`cat $BUILD_LOG | grep "Author"` || true ###### Monitor Service Build Job ######## build_job_url=`cat $BUILD_LOG | sed -n '/overview->logURL/p' | awk -F ": " '{print $2}'` build_job_build_number=`echo $build_job_url | awk -F "/" '{print $(NF-1)}'` build_job_log_url=$build_job_url"logText/progressiveText?start=0" build_job_console_output=$build_job_url"console" mail_subject=${PROJECT_NAME}"_Service_Build Job - Build # "${build_job_build_number}" Failure"'!' mail_body="Hi, ${PROJECT_NAME}"" project member"$'\n'$'\n'"Build Failure"'!'$'\n'$'\n'"For details please refer to Console Output - ${build_job_console_output}"$'\n'$'\n'"The latest code author list as below:"$'\n'"${author_list}" sendEmail.pl --subject "${mail_subject}" --emaillist "${EMAIL_LIST}" --emailcclist "${EMAIL_CC_LIST}" --mailbody "$mail_body" --msg_type "text"
同理還須要加一個Template_Service_Post_Polling job來監控Template_Service_Polling job, 若是輪詢Service的結果是重啓失敗,則郵件通知項目組人員。
腳本以下:
rm -rf ${WORKSPACE}/* ######## Import config file ######### cd ~/jenkins/common/Config . Project_Config.txt ####### SET ENV ############# export SCRIPTS_HOME=${SHARED_FOLDER}/Scripts cd ${SCRIPTS_HOME} chmod 755 * export PATH=$PATH:`pwd` ###### Initial parameters ############# LOG_NAME=${PROJECT_NAME}"_BUILD_"${PIPELINE_NUM}".log" BUILD_LOG=${SHARED_FOLDER}/Log/${PROJECT_NAME}"_"${PIPELINE_NUM}/$LOG_NAME EMAIL_LIST=${PROJECT_NAME}"_EMAIL_LIST" EMAIL_LIST=$(eval echo \${$EMAIL_LIST}) EMAIL_CC_LIST=${PROJECT_NAME}"_EMAIL_CC_LIST" EMAIL_CC_LIST=$(eval echo \${$EMAIL_CC_LIST}) author_list=`cat $BUILD_LOG | grep "Author"` ###### Monitor Service Polling Job ######## polling_job_url=`cat $BUILD_LOG | sed -n '/pollingjob->logURL/p' | awk -F ": " '{print $2}'` polling_job_build_number=`echo $polling_job_url | awk -F "/" '{print $(NF-1)}'` polling_job_log_url=$polling_job_url"logText/progressiveText?start=0" polling_job_console_output=$polling_job_url"console" mail_subject=${PROJECT_NAME}"_Service_Polling Job - Build # "${polling_job_build_number}" Failure"'!' mail_body="Hi, ${PROJECT_NAME}"" project member"$'\n'$'\n'"Service Restart Failure"'!'$'\n'$'\n'"For details please refer to Console Output - ${polling_job_console_output}"$'\n'$'\n'"The latest code author list as below:"$'\n'"${author_list}" sendEmail.pl --subject "${mail_subject}" --emaillist "${EMAIL_LIST}" --emailcclist "${EMAIL_CC_LIST}" --mailbody "$mail_body" --msg_type "text"
##轉載註明出處:http://www.cnblogs.com/wade-xu/p/4378224.html
如今咱們來看一下更新後的CI 流程圖
那麼,這個flow的前提是 全部的項目都是按這個流程來的,萬一有些特別的項目呢? 好比一個項目,它在Build以前 須要Pre-Build一個CommonUtils包, 那怎麼辦呢,簡單一點就是爲了這個項目定製一下。
爲了更具通用性,擴展性,方便的插入一些special job, 咱們能夠在每一個job之間加入 Exit Point, 以適應一些特別的項目想在任意點Plug in一些特別的job,
除了要在Config job 加上一些規則, 好比 export ProjectX_EXIT_POINT=Template_Service_Commit_Auto_Build|Special ProjectX-PreBuild job
還要在每一個job里加一些判斷語句,好比當前run的job name 等於ProjectX_EXIT_POINT以豎線分割的第一個值,則代表要在這個job退出, 第二個值代表要去調的special job name,固然 special job 裏作完了本身的事以後仍是要回調原來flow的下一個job
流程圖更新以下所示:
感謝閱讀,若是您以爲本文的內容對您的學習有所幫助,您能夠點擊右下方的推薦按鈕,您的鼓勵是我創做的動力。