持续集成交付CICD:Jenkins使用GitLab共享库实现基于SaltStack的CD流水线部署前后端应用

目录

一、实验

1.Jenkins使用GitLab共享库实现基于SaltStack的CD流水线部署前后端应用

2.优化共享库代码

二、问题

1.Jenkins手动构建后端项目流水线报错


一、实验

1.Jenkins使用GitLab共享库实现基于SaltStack的CD流水线部署前后端应用

(1)GitLab共享库更新代码

① 更新共享库目录结构

② 修改制品类Artifacts.grovvy

bash 复制代码
package org.devops

//上传制品
    def PushRawArtifacts(repoName,targetDir, filePath, pkgName,type ){
        withCredentials([usernamePassword(credentialsId: '318df1ad-083b-4158-ac88-2f584446563e', passwordVariable: 'TOKEN', usernameVariable: 'USER')]) {
            sh """
                curl -X POST "http://192.168.204.13:8081/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}"
             """
        }
    }

//下载制品
def PullArtifacts(version,projectName,repoName,type){
    withCredentials([usernamePassword(credentialsId: '318df1ad-083b-4158-ac88-2f584446563e', passwordVariable: 'TOKEN', usernameVariable: 'USER')]) {
        repoUrl = "http://192.168.204.13:8081/repository"
        pkgPath = "${repoUrl}/${repoName}/${projectName}/${version}/${projectName}-${version}.${type}"
        sh "wget --http-user=${user} --http-passwd=${TOKEN} ${pkgPath} -q"
    }
}

③ 修改文件类Gitlab.groovy

bash 复制代码
package org.devops

// 封装HTTP
def HttpReq(reqType, reqUrl,reqBody ){
    def gitServer = "http://192.168.204.8:82/api/v4"
    withCredentials([string(credentialsId: '02dce3ff-4e46-4de2-b079-5dd6093d4f64', 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)

}

④ CI流水线更名: ci.jenkinsfile

⑤新增CD流水线: cd.jenkinsfile

bash 复制代码
@Library("mylib@master") _
import org.devops.*

def artifacts = new Artifacts()
def gitlabutil = new Gitlab()

pipeline {
    agent { label "build" }
    
    options {
      skipDefaultCheckout true
    }

    stages{
        stage("PullArtifacts"){
            steps{
                script{
                    repoName = "${JOB_NAME}".split("/")[0]
                    env.projectName ="${JOB_NAME}".split("/")[-1].split("_")[0]

                    if ("${env.projectType}" == "maven"){
                        type="jar"
                    }
                    if ("${env.projectType}" == "npm"){
                        type="tar.gz"
                    }
                    artifacts.PullArtifacts("${env.releaseVersion}","${env.projectName}",repoName,type)

                    env.pkgName="${env.projectName}-${env.releaseVersion}.${type}"
                }
            }
        }
        stage("DeployHost"){
            steps{
                script{
                    print("DeployHost")


                    if ("${env.deployTool}" == "saltstack"){

                        targetHosts = "${env.saltHosts}"
                        println(targetHosts)
                        localDeployDir = "/srv/salt/${env.projectName}"
                        sh """
                            [ -d ${localDeployDir} ] || mkdir -p ${localDeployDir}
                            mv ${env.pkgName} ${localDeployDir}
        
                            # 清理发布目录
                            salt -L "${targetHosts}" cmd.run  "rm -fr ${targetDir}/${env.projectName}/* &&  mkdir -p ${targetDir}/${env.projectName} || echo file is exists"
            
                            # 发布应用
                            salt -L "${targetHosts}" cp.get_file salt://${env.projectName}/${env.pkgName} ${targetDir}/${env.projectName}
                   
                           """

                        if ("${env.projectType}" == "npm") {
                            sh """
                             # 解压
                             salt -L "${targetHosts}" cmd.run  "cd ${targetDir}/${env.projectName} ;tar zxf ${env.pkgName}"

                            """

                        }
                    }
                }
            }
        }
        stage("ServiceCtrl"){
            steps{
                script{
                    print("ServiceCtrl")
                    localDeployDir = "/srv/salt/${env.projectName}"

                    if ("${env.projectType}" == "maven") {
                        // 文件内容写到本地
                        response = gitlabutil.GetRepoFile(21, "service.sh", "master")
                        writeFile file: 'service.sh', text: "${response}"
                        sh "ls -a "

                        sh """
                             mv service.sh  ${localDeployDir}
                             # 发布启动脚本
                             salt -L "${targetHosts}" cp.get_file salt://${env.projectName}/service.sh ${targetDir}/${env.projectName}
                             
                             # 启动服务
                             salt -L "${targetHosts}" cmd.run  "cd ${targetDir}/${env.projectName} ;source /etc/profile  && sh service.sh ${env.projectName} ${env.releaseVersion} ${env.port} start"
    
                             # 检查服务
                             sleep 5
                             salt -L "${targetHosts}" cmd.run  "cd ${targetDir}/${env.projectName} ;source /etc/profile  && sh service.sh ${env.projectName} ${env.releaseVersion} ${env.port} check"
                            
                            
                        """
                    }

                }
            }
        }
        stage("HealthCheck"){
            steps{
                script{
                    print("HealthCheck")
                }
            }
        }
    }
}

⑥ 更新提交到master

(2) Jenkins修改后端流水线

① 流水线设置SCM

② 手动构建CD流水线

③ 成功

④ ⑤ ⑥ ⑦ ⑧

(3)Jenkins修改前端流水线

① 流水线设置SCM

② 手动构建CD流水线

③ 成功

④ 再次手动构建CD流水线

⑤ 成功

⑥ 命令观察

bash 复制代码
# for i in `seq 1000`; do sleep 1 ; curl http://127.0.0.1:8099; echo -e "\n\n\n";done

2.优化共享库代码

(1)共享库新建部署类 Deploy.groovy

(2)修改Deploy.groovy

bash 复制代码
package org.devops

//SaltStack

def SaltCP(){
    targetHosts = "${env.saltHosts}"
    localDeployDir = "/srv/salt/${env.projectName}"
    sh """
        [ -d ${localDeployDir} ] || mkdir -p ${localDeployDir}
        mv ${env.pkgName} ${localDeployDir}
        
        # 清理发布目录
        salt -L "${targetHosts}" cmd.run  "rm -fr ${targetDir}/${env.projectName}/* &&  mkdir -p ${targetDir}/${env.projectName} || echo file is exists"
            
        # 发布应用
        salt -L "${targetHosts}" cp.get_file salt://${env.projectName}/${env.pkgName} ${targetDir}/${env.projectName}
                   
    """

    if ("${env.projectType}" == "npm") {
        sh """
        # 解压
        salt -L "${targetHosts}" cmd.run  "cd ${targetDir}/${env.projectName} ;tar zxf ${env.pkgName}"

        """

    }
}


//启动服务
def ServiceCtrl(){
    localDeployDir = "/srv/salt/${env.projectName}"
    if ("${env.projectType}" == "maven") {
    // 文件内容写到本地
    gitlab = new Gitlab()
    response = gitlab.GetRepoFile(21, "service.sh", "master")
    writeFile file: 'service.sh', text: "${response}"
    sh "ls -a "

    sh """
        mv service.sh  ${localDeployDir}
        # 发布启动脚本
        salt -L "${targetHosts}" cp.get_file salt://${env.projectName}/service.sh ${targetDir}/${env.projectName}
                             
        # 启动服务
        salt -L "${targetHosts}" cmd.run  "cd ${targetDir}/${env.projectName} ;source /etc/profile  && sh service.sh ${env.projectName} ${env.releaseVersion} ${env.port} start"
    
        # 检查服务
        sleep 5
        salt -L "${targetHosts}" cmd.run  "cd ${targetDir}/${env.projectName} ;source /etc/profile  && sh service.sh ${env.projectName} ${env.releaseVersion} ${env.port} check"
                                
    """
    }
}

(3)精简代码的 cd.jenkinsfile

bash 复制代码
@Library("mylib@master") _
import org.devops.*

def artifacts = new Artifacts()
def gitlabutil = new Gitlab()
def deployer = new Deploy()

pipeline {
    agent { label "build" }
    
    options {
      skipDefaultCheckout true
    }

    stages{
        stage("PullArtifacts"){
            steps{
                script{
                    repoName = "${JOB_NAME}".split("/")[0]
                    env.projectName ="${JOB_NAME}".split("/")[-1].split("_")[0]

                    if ("${env.projectType}" == "maven"){
                        type="jar"
                    }
                    if ("${env.projectType}" == "npm"){
                        type="tar.gz"
                    }
                    artifacts.PullArtifacts("${env.releaseVersion}","${env.projectName}",repoName,type)

                    env.pkgName="${env.projectName}-${env.releaseVersion}.${type}"
                }
            }
        }
        stage("DeployHost"){
            steps{
                script{
                    print("DeployHost")
                    if ("${env.deployTool}" == "saltstack"){
                        deployer.SaltCP()            
                    }
                }
            }
        }
        stage("ServiceCtrl"){
            steps{
                script{
                    print("ServiceCtrl")
                    deployer.ServiceCtrl()
                }
            }
        }
    }
}

(4)Jenkins手动构建后端项目流水线

(5)Jenkins手动构建前端项目流水线

二、问题

1.Jenkins手动构建后端项目流水线报错

(1)报错

复制代码
No signature of method: static org.devops.Gitlab.GetRepoFile()

(2)原因分析

GitLab共享库调用其他类未初始化函数

(3)解决方法

初始化函数。

修改前:

bash 复制代码
response = Gitlab.GetRepoFile(21, "service.sh", "master")

修改后:

bash 复制代码
gitlab = new Gitlab()
response = gitlab.GetRepoFile(21, "service.sh", "master")

成功:

相关推荐
高旭的旭2 小时前
GitLab Omnibus Docker 内存优化实战:从 4.7 GiB 降到 3.2 GiB
docker·容器·gitlab
梵得儿SHI16 小时前
(第三篇)Spring AI 架构设计与优化:容器化与云原生部署,基于 K8s 的 AI 应用全生命周期管理
java·ci/cd·docker·云原生·kubernetes·容器化·spring ai
zhangfeng11331 天前
CI/CD 是软件开发中的两个核心实践,合起来指代一套自动化的软件交付流程
运维·ci/cd·自动化
前端不太难2 天前
鸿蒙游戏 CI/CD:为什么你还在手动打包?
游戏·ci/cd·harmonyos
牛奶咖啡132 天前
CI/CD——使用Jenkins自动化构建java项目之使用传统方式部署java web项目jpress
ci/cd·jenkins·jenkins创建任务·实现jpress的自动化部署·git的ssh主机密钥问题解决·配置ssh免密登录·在线安装jdk1.8环境
弹简特2 天前
【精通Postman接口测试】04-Postman的CLI命令+Jenkins和Newman+Allure+Jenkins自动化接口持续集成
自动化·jenkins·接口测试·postman
弹简特2 天前
安装Jenkins保姆级教程
jenkins
牛奶咖啡132 天前
CI/CD——使用Jenkins实现自动化部署与持续集成之jenkins插件与凭据配置
ci/cd·jenkins·jenkins必备插件安装·jenkins全局工具配置·jenkins的凭据配置·jenkins自动化部署流程·jenkinsgitlab集成
摇滚侠2 天前
DSL 学习 ElasticSearch 主要就是学习 DSL 查询语言
学习·elasticsearch·jenkins
牛奶咖啡134 天前
Git实践——GitLab服务器的部署与使用
gitlab·gitlab是什么·gitlab有啥用·gitlab适用场景·gitlab的版本如何选·安装部署gitlab·gitlab的使用