CI/CD-云主机场景CI篇-[jenkinslib库|Gitlab API使用|环境库]

root
233
文章
0
评论
2021年11月10日11:33:59 评论 11040字阅读36分48秒

CI/CD-云主机场景CI篇-[jenkinslib库|Gitlab API使用|环境库]

此次在CI/CD实践中引入集成模板库,和环境库

## 定义一个模板文件

集成模板库名称:hwf-app-jenkinslib
  • 有了这个库以后,所有项目的jenkinsfile,class,property都可以统一在一起,对应项目目录里只需要存放项目就可以了,jenkins执行的时候checkout项目

jenkinsfile

@Library("hwf-jenkins@main") _    

import hwf.devops.*           // 导入库

def checkout = new Checkout()
def build = new Build()
def unittest = new UnitTest()
def sonar = new Sonar()
def nexuspackage =  new Nexuspackage()
def gitlab =  new Gitlab()

currentBuild.description = "Trigger by Gitlab \n branch: ${env.branchName} \n user: ${env.commitUser} "
currentBuild.displayName = "${env.commitId}"

env.releaseVersion = "${env.branchName}".split("-")[-1]
env.appName = "${JOB_NAME}".split('/')[-1]    // Day5/acmp-myapp-service
env.repoName = "${JOB_NAME}".split("/")[0]


pipeline {
    agent { label "build" }

    stages{
        stage("Checkout"){
            steps{
                script {
                    println("GetCode")
                    checkout.GetCode("${env.srcUrl}", "${env.branchName}")
                }
            }
        }

        stage("Build"){
            steps{
                script{
                    println("Build")
                    build.CodeBuild("${env.buildTool}")
                }
            }
        }

        stage("UnitTest"){
            steps{
                script{
                    unittest.CodeTest("${env.buildTool}")
                }
            }
        }

        stage("SonarScan"){
            steps {
                script{
                    groupName = "${JOB_NAME}".split("/")[0]
                    projectName = "${JOB_NAME}".split("/")[-1] //devops03/devops03-maven-service
                    sonar.CodeSonar("${env.buildTool}", projectName, groupName)

                }
            }
        }

        stage("Nexuspackage"){
            steps{
                script{
                    repoName = "${JOB_NAME}".split("/")[0] //hwf-app/
                    projectName = "${JOB_NAME}".split("/")[-1].split("_")[0] //hwf-app/hwf-app-service
                    version = "${env.branchName}".split("-")[-1]     //RELEASE-1.1.1
                    targetDir = "${projectName}/${version}/" //hwf-app/hwf-app-service/1.1.1

                    println("upload nexus")
                    if ("${env.buildTool}" == "maven"){
                    filePath="./demo/target"
                    sh "ls -l demo/target/"
                    pkgName=sh returnStdout: true, script: "cd demo/target/;ls *.jar;cd ../../"
                    pkgName = pkgName.trim()
                    newPkgName="${projectName}-${version}.jar"
                    sh "cd demo/target; mv ${pkgName} ${newPkgName}"
                    type = "application/java-archive"
                   }

                    if ("${env.buildTool}" == "npm"){
                        filePath="./npm/dist"
                        newPkgName = "${projectName}-${version}.tar.gz"
                        sh """
                            ls -l 
                            pwd
                            cd ${filePath}
                            [ -f ${newPkgName} ] && rm -fr ${newPkgName}
                            echo "${version}"  >index.html
                            tar zcf ${newPkgName} *
                        """
                        type = "application/x-gzip"
                    }
                    env.artifactUrl = nexuspackage.PushRawArtifacts(repoName,targetDir, filePath, newPkgName, type )
                    println("${env.artifactUrl}")
                }
            }
        }
        // 生成版本文件
        stage("ReleaseFile"){
            steps {
                script {
          
                    //下载版本库文件 devops02-env/release.yaml
                    response = gitlab.GetRepoFile(17,"release.yaml", "main")
                    //println(response)
                    
                    //替换文件中内容
                    yamlData = readYaml text: """${response}"""

                    println(yamlData)
                    yamlData.version   = "${env.releaseVersion}"
                    yamlData.artifact  = "${env.artifactUrl}"
                    yamlData.repoName    = "${env.repoName}"
                    yamlData.appname   = "${env.appName}"
                    println(yamlData.toString())

                    sh "rm -fr test.yaml"
                    writeYaml charset: 'UTF-8', data: yamlData, file: 'test.yaml'
                    newYaml = sh returnStdout: true, script: 'cat test.yaml'
                    
                    println(newYaml)
                    //更新gitlab文件内容
                    base64Content = newYaml.bytes.encodeBase64().toString()

                    // 会有并行问题,同时更新报错
                    try {
                        gitlab.UpdateRepoFile(17,"${env.appName}%2f${env.branchName}.yaml",base64Content, "main")
                    } catch(e){
                        gitlab.CreateRepoFile(17,"${env.appName}%2f${env.branchName}.yaml",base64Content, "main")
                    }
                }
            }
        }
    }
}

Build.groovy

package hwf.devops


//Maven
def MavenBuild(){
    def buildTools = ["maven": "/data/apache-maven-3.8.3"]
    sh "${buildTools["maven"]}/bin/mvn clean package -DskipTests -f demo/pom.xml \
                        -s settings.xml"
}

//Gradle
def GradleBuild(){
    def buildTools = ["gradle": "/data/gradle-7.2"]
    sh "${buildTools["gradle"]}/bin/gradle clean && ${buildTools["gradle"]}/bin/gradle build -x test"
}

//Ant
def AntBuild(configPath="./build.xml"){
    sh "ant -f ${configPath}"
}

//Golang
def GoBuild(){
    def buildTools = ["go": "/data/go" ]
    sh "${buildTools["go"]}/bin/go build demo.go"
}

//Npm
def NpmBuild(){
    def buildTools = ["npm": "/data/node-v14.18.0-linux-x64" ]
    sh """
                    cd npm
                    export PATH=\$PATH:${buildTools["npm"]}/bin
                    ${buildTools["npm"]}/bin/npm install
                    ${buildTools["npm"]}/bin/npm run build
    """
}

//Yarn
def YarnBuild(){
    sh "yarn install && yarn build "
}

//Main
def CodeBuild(type){
    switch(type){
        case "maven":
            MavenBuild()
            break;
        case "gradle":
            GradleBuild()
            break;
        case "npm":
            NpmBuild()
            break;
        case "yarn":
            YarnBuild()
            break;
        default:
            error "No such tools ... [maven/ant/gradle/npm/yarn/go]"
            break
    }
}

Checkout.groovy

package hwf.devops
//下载代码
 def GetCode(srcUrl, branchName){
    checkout([$class: 'GitSCM', 
            branches: [[name: branchName]], 
            extensions: [], 
            userRemoteConfigs: [[
            credentialsId: '6ac312c6-9282-42ec-89a3-680356304ea2', 
            url: srcUrl]]])
}

Nexuspackage.groovy

package hwf.devops
 
def PushRawArtifacts(repoName,targetDir, filePath, pkgName, type ){
     withCredentials([usernamePassword(credentialsId: '8a3c99b1-a165-4ac6-a972-2355e6cc14a7', passwordVariable: 'TOKEN', usernameVariable: 'USER')]) {
        sh """
            curl -X POST "http://192.168.1.110:8081/nexus/service/rest/v1/components?repository=${repoName}" \
            -H "accept: application/json" \
            -H "Content-Type: multipart/form-data" \
            -F "raw.directory=${targetDir}" \
            -F "raw.asset1=@${filePath}/${pkgName};type=${type}" \
            -F "raw.asset1.filename=${pkgName}" \
            -u "${USER}":"${TOKEN}"
       
        """
    // 返回包下载地址
    artifactUrl = "http://192.168.1.110:8081/nexus/repository/${repoName}/${targetDir}${pkgName}"
    return artifactUrl
    }
}

Sonar.groovy

package hwf.devops

def SonarRequest(apiUrl,method){
    withCredentials([string(credentialsId: "16ed65f2-1b1e-4fbb-b976-a5fd60698d60", variable: 'SONAR_TOKEN')]) {
        sonarApi = "http://192.168.1.110:9000/api"
        response = sh  returnStdout: true, 
            script: """
            curl --location \
                 --request ${method} \
                 "${sonarApi}/${apiUrl}" \
                 --header "Authorization: Basic ${SONAR_TOKEN}"
            """
        // json格式化
        try {
            response = readJSON text: """ ${response - "\n"} """
        } catch(e){
            response = readJSON text: """{"errors" : true}"""
        }
        return response
        
    }
}

//查找项目
def SearchProject(projectName){
    apiUrl = "projects/search?projects=${projectName}"
    response = SonarRequest(apiUrl,"GET")
    if (response.paging.total == 0){
        return false
    }
    return true 
}


//创建项目
def CreateProject(projectName){
    apiUrl = "projects/create?name=${projectName}&project=${projectName}"
    response = SonarRequest(apiUrl,"POST")
    try{
        if (response.project.key == projectName ) {
            println("Project Create success!...")
            return true
        }
    }catch(e){
        println(response.errors)
        return false
    }
}

// 更新质量阈
def UpdateQualityProfiles(lang, projectName, profileName){
    apiUrl = "qualityprofiles/add_project?language=${lang}&project=${projectName}&qualityProfile=${profileName}"
    response = SonarRequest(apiUrl,"POST")
    
    if (response.errors != true){
        println("ERROR: UpdateQualityProfiles ${response.errors}...")
        return false
    } else {
        println("SUCCESS: UpdateQualityProfiles ${lang} > ${projectName} > ${profileName}" )
        return true
    }
}

def SonarJava(projectName, groupName ){
    withCredentials([string(credentialsId: '9a2fd415-eebb-403b-9116-db07f9ae2605', variable: 'AUTH_TOKEN')]) {
        sh """
            sonar-scanner -Dsonar.host.url=http://192.168.1.110:9000 \
                -Dsonar.projectKey=${projectName} \
                -Dsonar.projectName=${projectName} \
                -Dsonar.projectVersion=${BUILD_ID} \
                -Dsonar.login=${AUTH_TOKEN} \
                -Dsonar.ws.timeout=30 \
                -Dsonar.projectDescription="my first project!" \
                -Dsonar.links.homepage=http://192.168.1.110:9080/${groupName}/${projectName} \
                -Dsonar.links.ci=http://192.168.1.110:8080/job/${groupName}/job/${projectName}/ \
                -Dsonar.sources=./demo/src \
                -Dsonar.sourceEncoding=UTF-8 \
                -Dsonar.java.binaries=./demo/target/classes \
                -Dsonar.java.test.binaries=./demo/target/test-classes 
        """
    }
}


def SonarWeb(projectName, groupName ){
    withCredentials([string(credentialsId: '9a2fd415-eebb-403b-9116-db07f9ae2605', variable: 'AUTH_TOKEN')]) {
        sh """
            sonar-scanner -Dsonar.host.url=http://192.168.1.110:9000 \
                -Dsonar.projectKey=${projectName} \
                -Dsonar.projectName=${projectName} \
                -Dsonar.projectVersion=${BUILD_ID} \
                -Dsonar.login=${AUTH_TOKEN} \
                -Dsonar.ws.timeout=30 \
                -Dsonar.projectDescription="my first project!" \
                -Dsonar.links.homepage=http://192.168.1.110:9080/${groupName}/${projectName} \
                -Dsonar.links.ci=http://192.168.1.110:8080/job/${groupName}/job/${projectName}/ \
                -Dsonar.sources=./npm/src \
                -Dsonar.sourceEncoding=UTF-8 
        """
    }
}

//Main
def CodeSonar(type, projectName, groupName){
    if (SearchProject(projectName)){
        println("${projectName} exists....")
    } else {
        // 项目不存在
        println("${projectName} not found....")

        //创建项目
        CreateProject(projectName)
    }
    //质量配置
    profileMap = ["maven": "java", "npm": "js"]
    UpdateQualityProfiles(profileMap[type], projectName, groupName)

    switch(type){
        case "maven":
            
            SonarJava(projectName, groupName)
            break;
        case "gradle":
            SonarJava(projectName, groupName)
            break;
        case "npm":
            SonarWeb(projectName, groupName)
            break;
        default:
            println("No such tools ... [maven/ant/gradle/npm/yarn/go]")
            break
    }
}

UnitTest.groovy

package hwf.devops

//Maven
def MavenTest(){
    def buildTools = ["maven": "/data/apache-maven-3.8.3"]
    sh """
    ${buildTools["maven"]}/bin/mvn test -f demo/pom.xml -s settings.xml

    """
}

//Gradle
def GradleTest(){
    def buildTools = ["gradle": "/data/gradle-7.2"]
    sh """
        ${buildTools["gradle"]}/bin/gradle test
      junit 'build/test-results/test/*.xml'
    """
}

//Ant
//def AntBuild(configPath="./build.xml"){
//    sh "ant -f ${configPath}"
//}

//Golang
//def GoTest(){
    //sh " go test"
//}

//Npm
def NpmTest(){
    def buildTools = ["npm": "/data/node-v14.18.0-linux-x64" ]
    sh """
            export PATH=\$PATH:${buildTools["npm"]}/bin
            ${buildTools["npm"]}/bin/npm test"
    """
}

//Yarn
//def YarnTest(){
//    sh "yarn test "
//}

//Main
def CodeTest(type){
    switch(type){
        case "maven":
            MavenTest()
            break;
        case "gradle":
            GradleTest()
            break;
        default:
            println("No such tools ... [maven/ant/gradle/npm/yarn/go]")
            break
    }
}

 

jenkins CI流水线设置

hwf-app-service

  • srcUrl
    • http://192.168.1.110:9080/hwf-app/hwf-app-service.git
  • Repository URL
    • http://192.168.1.110:9080/hwf-app/hwf-app-jenkinslib.git

hwf-app-web

  • srcUrl
    • http://192.168.1.110:9080/hwf-app/hwf-app-web.git
  • Repository URL
    • http://192.168.1.110:9080/hwf-app/hwf-app-jenkinslib.git

 

## CI生成版本文件
0.获取gitlab本地模板文件(gitlab下载文件API接口)
1.将配置信息写入本地的一个文件中 (yaml语法更改)
2.将文件上传到gitlab (gitlab上传文件API接口)
## CD 获取版本文件
1.从gitlab上面下载版本文件
2.读取本地的这个版本文件进行发布
Gitlab.groovy
package hwf.devops


// 封装HTTP
def HttpReq(reqType, reqUrl,reqBody ){
    def gitServer = "http://192.168.1.110:9080/api/v4"
    withCredentials([string(credentialsId: '515d16fb-c888-4649-af09-f1a8bf57b211', variable: 'GITLABTOKEN')]) {
        response = httpRequest acceptType: 'APPLICATION_JSON_UTF8', 
                          consoleLogResponseBody: true, 
                          contentType: 'APPLICATION_JSON_UTF8', 
                          customHeaders: [[maskValue: false, name: 'PRIVATE-TOKEN', value: "${GITLABTOKEN}"]], 
                          httpMode: "${reqType}", 
                          url: "${gitServer}/${reqUrl}", 
                          wrapAsMultipart: false,
                          requestBody: "${reqBody}"

    }
    return response
}

//获取文件内容
def GetRepoFile(projectId,filePath, branchName ){
   //GET /projects/:id/repository/files/:file_path/raw
   apiUrl = "/projects/${projectId}/repository/files/${filePath}/raw?ref=${branchName}"
   response = HttpReq('GET', apiUrl, "")

   return response.content

}

//更新文件内容
def UpdateRepoFile(projectId,filePath,fileContent, branchName){
    apiUrl = "projects/${projectId}/repository/files/${filePath}"
    reqBody = """{"branch": "${branchName}","encoding":"base64", "content": "${fileContent}", "commit_message": "update a new file"}"""
    response = HttpReq('PUT',apiUrl,reqBody)
    println(response)

}

//创建文件
def CreateRepoFile(projectId,filePath,fileContent, branchName){
    apiUrl = "projects/${projectId}/repository/files/${filePath}"
    reqBody = """{"branch": "${branchName}","encoding":"base64", "content": "${fileContent}", "commit_message": "update a new file"}"""
    response = HttpReq('POST',apiUrl,reqBody)
    println(response)

}

##jenkins 创建gitlab api凭据

jenkins创建凭据

jenkinsfile使用token方法

执行流水线错误解方法:

执行流水线报错解决方法
org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: Scripts not permitted to use staticMethod org.codehaus.groovy.runtime.EncodingGroovyMethods encodeBase64 byte[]
  • 点击连接,进去会允许就可以了
流水线运行成功

创建环境库

库名称:hwf-app-env

  • 被画横线的是不用创建的,流水线跑起来会自动生成项目目录
release.yaml
version: __NULL__
appname: __NULL__
repoName: __NULL__
artifact: __NULL__
继续阅读
weinxin
我的微信
这是我的微信扫一扫
  • 文本由 发表于 2021年11月10日11:33:59
  • 除非特殊声明,本站文章均为原创,转载请务必保留本文链接
CI/CD-云主机场景-[持续部署|cicd设计] CI/CD实践

CI/CD-云主机场景-[持续部署|cicd设计]

CI/CD-云主机场景的持续部署实践 0. 准备工作项目标准化 公司里面要使用流水线要做持续集成CI/CD的项目越来越多,这对流水线的设计和开发有不同的要求。我们经常听到用户的反馈: 各种不同语言的技...
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: