目录
一、实验
1.Jenkins使用GitLab共享库实现基于SaltStack的CD流水线部署前后端应用
2.优化共享库代码
二、问题
1.Jenkins手动构建后端项目流水线报错
一、实验
1.Jenkins使用GitLab共享库实现基于SaltStack的CD流水线部署前后端应用
(1)GitLab共享库更新代码
① 更新共享库目录结构
② 修改制品类Artifacts.grovvy
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
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/rawapiUrl = "/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
@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 5salt -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流水线
⑤ 成功
⑥ 命令观察
# 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
package org.devops//SaltStackdef 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 5salt -L "${targetHosts}" cmd.run "cd ${targetDir}/${env.projectName} ;source /etc/profile && sh service.sh ${env.projectName} ${env.releaseVersion} ${env.port} check""""}
}
(3)精简代码的 cd.jenkinsfile
@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)解决方法
初始化函数。
修改前:
response = Gitlab.GetRepoFile(21, "service.sh", "master")
修改后:
gitlab = new Gitlab()
response = gitlab.GetRepoFile(21, "service.sh", "master")
成功: