VM部署实践 02 CI 流水线设计

 Jenkins作业


Jenkins作业

文件夹: anyops

作业命名: 后端 anyops-devops-service 前端 anyops-devops-ui

 现在就可以在该项目下面创建子项目了。

CI构建规范


CI构建规范

前端项目采用npm打包后统一放到dist目录下, 静态文件以tgz打包。(将静态文件打包上传到制品库)

后端项目采用maven打包后统一放到target目录下,以jar包。

CI/CD流水线设计


总体目标:

我们将CI和CD分成两条流水线作业。

CI:用户输入了分支之后,然后流水线下载代码,然后去构建生成包,之后扫描生成了报告。然后将这个包传到了制品仓库里面,这就是CI要做的一些事情。

传到仓库之后又会有一条CD的流水线,也是需要用户手动去触发的,拿到版本号去下载哪个包,将包下载下来,通过ansible或者slatstack发布到主机,然后通过脚本启动起来,然后做一些健康检查,甚至还有一些回滚的操作。

  • CI作业: 用户输入版本分支后下载代码,进行构建扫描最终将制品上传到制品仓库, 生成版本文件
  • CD作业: 用户输入发布版本和选择要发布的主机IP后,下载制品,将制品和服务启动脚本cp到目标机器的发布目录, 远程执行启动脚本启动服务并进行健康检查。

质量规则(项目扫描之前配置好)


后期在做Java代码扫描的时候用的是anyops


质量阈(项目扫描之前配置好)


builds.groovy 

package org.devops


// 构建函数
def Build(buildTools,buildType){
    switch(buildType){
        case "maven":
            sh "${buildTools["maven"]}/bin/mvn clean package"
            break
        case "gradle":
            sh "${buildTools["gradle"]}/bin/gradle build -x test"
            break
        
        case "golang":
            sh "${buildTools["golang"]}/bin/go build demo.go"
            break
        
        case "npm":
            sh """ ${buildTools["npm"]}/bin/npm install  && ${buildTools["npm"]}/bin/npm run build """
            break
        
        default :
            println("buildType ==> [maven|gralde|golang|npm]")
            break
    }
}

 mytools.groovy

package org.devops

def GetCode(srcType,branchName,gitHttpURL,credentialsId){

    if (srcType == "git"){
        println("下载代码 --> 分支: ${branchName}")
        checkout([$class: 'GitSCM', branches: [[name: "${branchName}"]],
                    extensions: [], 
                    userRemoteConfigs: [[credentialsId: "${credentialsId}", 
                                        url: "${gitHttpURL}"]]])
    }

}

sonarqube.groovy 

package org.devops


//封装HTTP
def HttpReq(reqType,reqUrl,reqBody){
    def sonarServer = "http://139.198.170.122:9000/api"
   
    response = httpRequest authentication: 'e89c6fa4-d9a2-4042-b3a5-8b00ff372d92',
            httpMode: reqType, 
            contentType: "APPLICATION_JSON",
            consoleLogResponseBody: true,
            ignoreSslErrors: true, 
            requestBody: reqBody,
            url: "${sonarServer}/${reqUrl}"
            //quiet: true
    
    return response
}

//搜索Sonar项目
def SerarchProject(projectName){
    apiUrl = "projects/search?projects=${projectName}"
    response = HttpReq("GET",apiUrl,'')

    response = readJSON text: """${response.content}"""
    result = response["paging"]["total"]

    if(result.toString() == "0"){
       return "false"
    } else {
       return "true"
    }
}


//获取Sonar质量阈状态
def GetProjectStatus(projectName){
    apiUrl = "project_branches/list?project=${projectName}"
    response = HttpReq("GET",apiUrl,'')
    
    response = readJSON text: """${response.content}"""
    result = response["branches"][0]["status"]["qualityGateStatus"]
    
    //println(response)
    
   return result
}



//创建Sonar项目
def CreateProject(projectName){
    apiUrl =  "projects/create?name=${projectName}&project=${projectName}"
    response = HttpReq("POST",apiUrl,'')
    println(response)
}

//配置项目质量规则
def ConfigQualityProfiles(projectName,lang,qpname){
    apiUrl = "qualityprofiles/add_project?language=${lang}&project=${projectName}&qualityProfile=${qpname}"
    response = HttpReq("POST",apiUrl,'')
    println(response)
}


//获取质量阈ID
def GetQualtyGateId(gateName){
    apiUrl= "qualitygates/show?name=${gateName}"
    response = HttpReq("GET",apiUrl,'')
    response = readJSON text: """${response.content}"""
    result = response["id"]
    
    return result
}

//配置项目质量阈
def ConfigQualityGates(projectName,gateName){
    gateId = GetQualtyGateId(gateName)
    apiUrl = "qualitygates/select?gateId=${gateId}&projectKey=${projectName}"
    response = HttpReq("POST",apiUrl,'')
    println(response)println(response)
}

 jenkinsfile


// 加载名称为devopslib的共享库的master版本
@Library("devopslib@master") _


//导入共享库中的方法类
def mytools = new org.devops.mytools()
def builds  = new org.devops.builds()
def sonar = new org.devops.sonarqube()


//定义sonar里面的链接
def homepage = "http://139.198.170.122:81/anyops/anyops-devops-service"
def ci = "http://139.198.170.122:8080/job/anyops"


//定义构建工具类型与路径map
def buildTools = [  "maven": "/usr/local/apache-maven-3.8.1",
          "gradle": "/usr/local/gradle-6.8.3/",
          "golang": "/usr/local/go",
          "npm" : "/usr/local/node-v14.16.1-linux-x64/",
          "sonar": "/usr/local/sonar-scanner-4.6.0.2311-linux/"]

//定义UI上面的参数(用户去选择构建那个项目的那个分支的构建类型)
String branchName = "${env.branchName}"
String gitHttpURL = "${env.gitHttpURL}"
String buildType  = "${env.buildType}"
String credentialsId = "${env.credentialsId}"
String skipSonar = "${env.skipSonar}"


// 以下是流水线阶段
pipeline {
  agent { label  "build" }  
  options {
    skipDefaultCheckout true
  }

  stages {
    stage("GetCode"){
      steps{
        script{
        
          // 调用GetCode方法进行代码下载 
          mytools.GetCode("git",branchName,gitHttpURL,credentialsId)
        }
      }
      
    }

    stage("Build"){
      steps {
        script {
          // 调用Build方法进行代码构建
          builds.Build(buildTools, buildType)
        }
      }
    }

    stage("SonarScan"){
       when {
           environment name: 'skipSonar', value: 'false'
        }
      steps {
        script {
          //定义项目名称
          projectName= "${env.JOB_NAME}".split("/")[1]

         //搜索项目
          result = sonar.SerarchProject(projectName)
          println(result)

         //判断项目是否存在
          if(result == "false"){
            println("${projectName}----->项目不存在,准备创建项目${projectName}")  
            sonar.CreateProject(projectName)    
          }else{
            println("${projectName}----->项目已存在!")
          }

          println(projectName)
          qpname = "${projectName}".split("-")[0] 
          println(qpname)
          
         //配置项目质量规则
         sonar.ConfigQualityProfiles(projectName,"java",qpname)
         
        //配置质量阈
        sonar.ConfigQualityGates(projectName,qpname)
        
        //扫描
        sh """
        ${buildTools["sonar"]}/bin/sonar-scanner -Dsonar.host.url=http://139.198.170.122:9000 \
        -Dsonar.projectKey="${projectName}" \
        -Dsonar.projectName="${projectName}" \
        -Dsonar.projectVersion=1.0 \
        -Dsonar.login=admin \
        -Dsonar.password=admin \
        -Dsonar.ws.timeout=30 \
        -Dsonar.projectDescription="my first project!" \
        -Dsonar.links.homepage="${homepage}" \
        -Dsonar.links.ci="${ci}" \
        -Dsonar.sources=src/main \
        -Dsonar.sourceEncoding=UTF-8 \
        -Dsonar.java.binaries=target/classes \
        -Dsonar.java.test.binaries=target/test-classes \
        -Dsonar.java.surefire.report=target/surefire-reports 
        """
        sleep 10
        //获取扫描结果
        result = sonar.GetProjectStatus(projectName)
        println(result)
        if (result.toString() == "ERROR"){
           error "代码质量阈失败,请及时修复"
        } else {
           println(result) 
        }
        
        }
      }
    }

  }

  post {
    always {
      script{
        echo "always......"

      }
    }

    success {
      script {
        echo "success....."
      }
    }
  }

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值