Jenkins 实现Pipeline生产审批
如果你想实现以下内容,请看此文:1、代码一提交,就自动发布测试环境---jenkins触发器实现2、可以指定版本号、分支名,拉取代码---git命令实现3、部署生产之前,发一份邮件给老板,请他审核同意发布--jenkins的邮件功能实现4、不依赖harbor,加快镜像的io传输速度 ---scp和ssh命令实现前提部署好你的jenkins下载好以下插件设置构建时输入的参数发布模式参数分支参数代码提
·
如果你想实现以下内容,请看此文:
1、代码一提交,就自动发布测试环境 ---jenkins触发器实现
2、可以指定版本号、分支名,拉取代码 ---git命令实现
3、部署生产之前,发一份邮件给老板,请他审核同意发布 --jenkins的邮件功能实现
4、不依赖harbor,加快镜像的io传输速度 ---scp和ssh命令实现
前提
1、部署好你的jenkins
https://www.jenkins.io/zh/doc/book/installing/
2、容器内安装好maven
3、下载好下图的红框的插件
4、配置好ssh、email插件,配置好git凭证
下载好以下插件
设置构建时输入的参数
发布模式参数
分支参数
代码提交的版本号
部署的测试机器列表参数
部署的生产机器列表参数
审核人邮件参数
其实建议审核人邮件写死,但为了快速测试,所有使用手填
构建页面展示
配置好上面这些构建参数后,你的界面应该如下所示:
流水线jenkinsfile文件
我自己写的jenkinsfile,仅供参考
def skipProd = true //是否跳过生产部署
def timeout_mins = 5 //超时时间
def input_message //提示语
def randomToken //发布秘钥
//系统个人信息
def Applier_id
def Applier_name
def Applier_mail
// 项目信息
def project_name = "test"
def version = "0.1.0"
// 系统凭证
def git_auth = "git_auth"
pipeline{
agent any
options { //调用颜色插件
ansiColor('xterm')
skipDefaultCheckout(true)
}
environment {
Applier_name = ""
Applier_mail = ""
Operator_mail = ""
input_message = ""
}
stages{
stage('构建初始化') {
parallel {
stage("拉取代码"){
steps{
withCredentials([usernamePassword(credentialsId: "${git_auth}", usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD')]) {
echo "\033[32m ******开始拉取代码${branch}分支代码,revision为${commit}的代码(revision为空时拉取该分支最新代码)****** \033[0m"
sh "rm -rf zzw; mkdir zzw;cd zzw;rm -rf test;git clone https://${USERNAME}:${PASSWORD}@gitee.com/mylittlebrother/test.git;cd test;git pull origin ${branch};git reset --hard ${commit} "
}
}
}
stage("是否发送token邮件"){
steps{
wrap([$class: 'BuildUser']) {
script {
//获取当前登录用户账户、姓名、邮箱
Applier_id = "${BUILD_USER_ID}"
Applier_name = "${env.BUILD_USER}"
Applier_mail = "${env.BUILD_USER_EMAIL}"
}
}
script{
// 判断是否需要审批
if ("$Mode" == "test" || "$Mode" == "" ){
echo "\033[32m ******发布测试操作无需审批,待自动执行测试****** \033[0m"
skipProd = true
}else{
skipProd = false
echo "\033[32m ******发布生产操作需审批,待自动执行测试环境后,同时还将执行生产审批流程****** \033[0m"
randomToken = sh (script: "echo \$RANDOM" , returnStdout: true).trim()
input_message = " $Applier_name 申请发布生产"
emailext(
subject:"【请审批】${env.JOB_NAME}(#${env.BUILD_NUMBER})生产部署任务",
body:"""$input_message,随机验证码是:${randomToken}!!! <br> <a href="${BUILD_URL}input">请点击该链接登录后审批填入token发布</a><br><h3>或者将token值${randomToken}告诉${Applier_name},让其输入token</h3>""",
to:"${emails}"
)
echo "\033[32m ******申请邮件已经发送,待$adminUser 审批****** \033[0m"
}
}
}
}
}
}
stage('编译测试镜像') {
steps{
sh "source /etc/profile;java -version;mvn -v;cd zzw/test; mvn clean package -P test dockerfile:build -Dmaven.test.skip=true"
}
}
stage('上传测试镜像') {
steps{
script{
def imageName = "${project_name}-test:${version}"
sh "docker tag ${project_name}:latest ${imageName}"
try { //删除镜像
sh "docker images|grep none|awk '{print \$3 }'|xargs docker rmi"
}catch(err) {
echo "\033[31m 警告!!!该镜像可能不存在 \033[0m"
}
sh "pwd; docker save -o ${project_name}-test.tar ${imageName};ls" //生成测试镜像
echo "\033[32m ******测试机器输入是 ${testMachines}****** \033[0m"
def host = "$testMachines".split('@')
echo "\033[32m ******测试机器ip是 ${host}****** \033[0m"
for (machine in host){
if(machine!=null && machine !=''){
def ip = machine.split(':')[0]
sh " scp -r ${project_name}-test.tar root@${ip}:/opt/"
echo "\033[32m ******${ip}拷贝镜像文件${project_name}-test.tar完成****** \033[0m"
}
}
}
}
}
stage('发布测试') {
steps{
script{
def imageName = "${project_name}-test:${version}" //测试镜像
def delete_running_container = "docker rm -f \$(docker ps | grep ${project_name}-test | awk '{print \$1}')" //删除指定镜像的容器
def delete_iamge = "docker rmi -f \$(docker images | grep ${project_name}-test | awk '{print \$3}')" //删除指定镜像
def load_image = "cd /opt; docker load -i ${project_name}-test.tar " //加载指定image
def run_test = "docker run -di -p 1993:1993 ${imageName} "
try { //停止镜像
sshPublisher(publishers: [sshPublisherDesc(configName: 'node01', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "${delete_running_container}", execTimeout: 60000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}catch(err) {
echo "\033[31m 警告!!!该容器可能不存在 \033[0m"
}
try { //停止镜像
sshPublisher(publishers: [sshPublisherDesc(configName: 'node01', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "${delete_iamge}", execTimeout: 60000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}catch(err) {
echo "\033[31m 警告!!!该镜像可能不存在 \033[0m"
}
try { // 加载镜像
sshPublisher(publishers: [sshPublisherDesc(configName: 'node01', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "${load_image}", execTimeout: 60000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}catch(err) {
}
echo "******开始发布测试环境*****"
sshPublisher(publishers: [sshPublisherDesc(configName: 'node01', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "${run_test}", execTimeout: 60000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}
}
}
stage("请输入生产token"){
when { expression {!skipProd}}
steps{
script{
def isAbort = false //取消按钮
timeout(timeout_mins){ //等待审批人审批,并通过timeout设置任务过期时间,防止任务永远挂起
try {
def userInput = input(
id: 'inputap', message: "$input_message", ok:"确认token", submitter:"$adminUser", parameters: [
[$class: 'StringParameterDefinition',defaultValue: "", name: 'token',description: '请输入发布的秘钥' ]
])
if (userInput == randomToken) {
skipProd = false
} else {
skipProd = true
echo "\033[31m 秘钥错误 \033[0m"
}
echo "\033[31m 当前输入秘钥为: ${userInput} \033[0m"
}catch(err) { // input false
echo "******主动拒绝*****"
skipProd = true
}
}
}
}
}
stage('编译生产镜像') {
when { expression {!skipProd} }
steps{
sh "source /etc/profile;java -version;mvn -v;cd zzw/test; mvn clean package -P prod dockerfile:build -Dmaven.test.skip=true"
}
}
stage("上传生产镜像"){
when { expression {!skipProd} }
steps{
script{
def imageName = "${project_name}-prod:${version}"
sh "docker tag ${project_name}:latest ${imageName}"
try { //删除镜像
sh "docker images|grep none|awk '{print \$3 }'|xargs docker rmi"
}catch(err) {
echo "\033[31m 警告!!!该镜像可能不存在 \033[0m"
}
sh "pwd; docker save -o ${project_name}-prod.tar ${imageName};ls" //生成生产镜像
def host = "$prodMachines".split('@')
echo "\033[32m ******测试机器ip是 ${host}****** \033[0m"
for (machine in host){
if(machine!=null && machine !=''){
def ip = machine.split(':')[0]
sh " scp -r ${project_name}-prod.tar root@${ip}:/opt/"
echo "\033[32m ******${ip}拷贝镜像文件${project_name}-prod.tar完成****** \033[0m"
}
}
}
}
}
stage("发布生产"){
when { expression {!skipProd} }
steps{
script{
def imageName = "${project_name}-prod:${version}" //测试镜像
def delete_running_container = "docker rm -f \$(docker ps | grep ${project_name}-prod | awk '{print \$1}')" //删除指定镜像的容器
def delete_iamge = "docker rmi -f \$(docker images | grep ${project_name}-prod | awk '{print \$3}')" //删除指定镜像
def load_image = "cd /opt; docker load -i ${project_name}-prod.tar " //加载指定image
def run_prod = "docker run -di -p 1999:1999 ${imageName} "
try { //停止镜像
sshPublisher(publishers: [sshPublisherDesc(configName: 'node01', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "${delete_running_container}", execTimeout: 60000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}catch(err) {
echo "\033[31m 警告!!!该容器可能不存在 \033[0m"
}
try { //停止镜像
sshPublisher(publishers: [sshPublisherDesc(configName: 'node01', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "${delete_iamge}", execTimeout: 60000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}catch(err) {
echo "\033[31m 警告!!!该镜像可能不存在 \033[0m"
}
try { // 加载镜像
sshPublisher(publishers: [sshPublisherDesc(configName: 'node01', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "${load_image}", execTimeout: 60000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}catch(err) {
}
echo "******开始发布生产环境*****"
sshPublisher(publishers: [sshPublisherDesc(configName: 'node01', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "${run_prod}", execTimeout: 60000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}
}
}
}
}
执行情况
更多推荐
已为社区贡献2条内容
所有评论(0)