zoukankan      html  css  js  c++  java
  • 这些年我们一起搞过的持续集成~Jenkins+Perl and Shell script

    这些年我们一起搞过的持续集成~Jenkins+Perl and Shell script

    ##转载注明出处:http://www.cnblogs.com/wade-xu/p/4378224.html 

    部门用持续集成已经很久了,但其实使用起来还是很麻烦的,每当要给一个新项目set up持续集成的环境,虽然是Copy一些现有的jobs, 但是许多参数,变量需要去改,然后还有调试,少说3,4天搞一下,非常不方便。

    最近比较空,就把现有的持续集成系统升级改造下,job用一套模板,全部参数化,只要修改配置文件,就可以为新项目配置好环境。

    本文的重点是一些经验,想法的分享,并不是一篇手把手教你搭建持续集成环境的教程,而且阅读本文需要一定的Jenkins, perl, shell脚本的基础知识, 所用到的知识有:Jenkins+Maven+Git+Sonar+Perl+Shell script

    下图很好的说明了我们现有的Job流, 以往是每个项目都有一套这样的job流,现在我改成这个Template_service job流,供所有的项目使用,项目名也是作为参数传递进来的,每个job都是用Jenkins Execute shell这个组件来实现功能的,像check out code,Email Notification, Publish Junit test results, code coverage report 等Jenkins自带组件都没有使用。 

    运行环境:  apache-maven-3.0.5, jdk1.7.0_15, git 1.8.2.1, SonarQube 4.0, perl v5.8.8

     ##转载注明出处:http://www.cnblogs.com/wade-xu/p/4378224.html 

    接下来简单的说明一下各个Job的功能,以及贴出详细的脚本供大家参考。

    除了上图里面的job, 还有一个Config job, export一些环境变量

    0)Template_Service_Config (one time run)

    用来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}
    
    export PROJECT_LIST=${PROJECT_LIST}
     
    export SHARED_FOLDER=~/jenkins/common
    " > ${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"$'
    '$'
    '"Alerts : Unit Tests Coverage: ${code_coverage} < CoverageThreshold: ${SONAR_MIN_COVERAGE}%, the latest build package cannot be allowed to install to service - ${SERVICE_NAME} [$INSTANCES]"'!'$'
    '$'
    '"For details please refer to SonarQube - ${sonar_path}"$'
    '$'
    '"The latest code author list as below:"$'
    '"${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"$'
    '$'
    '"Alerts : Sonar major above issues != 0, the latest build package cannot be allowed to install to service - ${SERVICE_NAME} [$INSTANCES]"'!'$'
    '$'
    '"Blocker issues: ${blocker_num}"$'
    '"Critical issues: ${critical_num}"$'
    '"Major issues: ${major_num}"$'
    '"Minor issues: ${minor_num}"$'
    '"Info issues: ${info_num}"$'
    '$'
    '"For details please refer to SonarQube - ${sonar_path}"$'
    '$'
    '"The latest code author list as below:"$'
    '"${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'42/){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"$'
    '$'
    '"Build Failure"'!'$'
    '$'
    '"For details please refer to Console Output - ${build_job_console_output}"$'
    '$'
    '"The latest code author list as below:"$'
    '"${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"$'
    '$'
    '"Service Restart Failure"'!'$'
    '$'
    '"For details please refer to Console Output - ${polling_job_console_output}"$'
    '$'
    '"The latest code author list as below:"$'
    '"${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

    流程图更新如下所示:

     

    感谢阅读,如果您觉得本文的内容对您的学习有所帮助,您可以点击右下方的推荐按钮,您的鼓励是我创作的动力。

    ##转载注明出处:http://www.cnblogs.com/wade-xu/p/4378224.html 

  • 相关阅读:
    Could A New Linux Base For Tablets/Smartphones Succeed In 2017?
    使用libhybris,glibc和bionic共存时的TLS冲突的问题
    6 Open Source Mobile OS Alternatives To Android in 2018
    Using MultiROM
    GPU drivers are written by the GPU IP vendors and they only provide Android drivers
    Jolla Brings Wayland Atop Android GPU Drivers
    How to Use Libhybris and Android GPU Libraries with Mer (Linux) on the Cubieboard
    闲聊Libhybris
    【ARM-Linux开发】wayland和weston的介绍
    Wayland and X.org problem : Why not following the Android Solution ?
  • 原文地址:https://www.cnblogs.com/wade-xu/p/4378224.html
Copyright © 2011-2022 走看看