|
基于Gitlab+Jenkins的代码自动化发布 |
|
|
基于Gitlab+Jenkins的代码自动化发布这里所讲的自动化发布是指代码从提交到仓库,到发布到目标服务器的整个过程。主要涉及到两个工具G itlab,Jenkins,要完成自动化还需要rsync,qqbot,log,ant、shell脚本,python等。Gitlab :我们主要用它来做代码的仓库Jenkins:用来执行任务的持续集成,构建等。一、大体的自动化思路:开发人员push代码到gitla b,触发webhook,调用jenkinsjob。jenkinsjob执行拉取代码,编译,调用loadblance,下架部 分服务器更新代码,验证更新后的可用性,上线;再下架另一部分服务器,更新代码,再上线。更新完后,将本次发布的状态信息推送给项目组。 二、实际工作中,我们遇到的比以上要复杂。服务器环境包括:测试环境,开发环境,预发布环境,生产环境等。代码仓库又分为多个分支:ma ster分支,开发分支,项目分支,本地分支等。因此要完成整个过程自动化,还需要整合多分支,多环境的情况。三、测试环境的自动化思路: 1.建一个dev分支用来专门发布测试环境,此分支只允许开发人员合并代码和push,不能直接在上面改代码。2.开发人员开发一个功能 ,先在本地建一个本地分支,写完后合并到dev,然后push到gitlab,gitlab触发钩子事件,调用jenkins完成项目的自 动化部署。以上2点看似已经实现了自动化发布,但实践发现,开发人员仍需花不少时间在代码的提交,切换分支,合并分支,push代码等重 复而繁琐的工作上。于是这里我做了对GIT操作的自动化,将提交、切换、合并、push整合整合起来成工具,后面会列出工具代码。四、预发 布环境的自动化思路:1.预发布的自动化采用和测试环境一样的思路,只是dev分支换成了master分支。2.master分支:我们 用它来发布预发布和生产环境,对没错两套环境用同一分支,此分支只有项目经理有权限push,普通开发没权限操作。以上2点看似也实现了代 码的自动化发布,但实际工作中项目经理同样也要花不少时间在代码的提交,切换分支,合并分支,push代码等重复繁琐的工作,因此这里也 要解决项目经理Git操作的自动化,后面列出工具。五、生产环境的自动化发布:生产环境的发布其实只是取消了webhook的自动触发je nkinsjob,改为手动点击发布,主要是为发布安全考虑。六、实操:1.设置webhook,对测试环境job和预发布环境job设 置相应的钩子事件:2.在jenkins中配置git插件3.配置jenkinsjob,这里我用shell脚本做一系列的job,不需 要像网上安装各种繁琐的插件。#!/bin/bash#本案例中WORKSPACE=/root/.jenkins/workspace/ dev_test#源目录src="$WORKSPACE/WebRoot/"#发布的目标目录dest="/usr/local/apa che-tomcat-6.0.39/webapps/xiangmu/"#目标主机用户user="root"#目标主机,测试机1、测 试机2host1="10.111.111.1"host2="10.111.111.2"#需要发布的文件列表cd$WORKSPA CEchange_file_list=`gitdiff--name-onlyHEAD~HEAD`echo"需要发布的文件 列表:$change_file_list"#定义机器人发布消息功能函数functionqqbot_deploy(){proj_n ame=`gitshow$commitid--pretty=format:"%s"|sed-n1p`author=`g itshow$commitid--pretty=format:"%an"|sed-n1p`now_time=`date "+%Y-%m-%d%H:%M:%S"`qqsendgroupIT群"QQ消息机器人:【测试环境】发布时间:$now _time自动化发布完成项目:$proj_name状态:$status$solution发布的文件列表:$change_fi le_list发布人:$author"&}#定义执行命令成功或失败日志记录功能函数functionlog(){if[ $?-eq0];thenecho"执行''$arg''成功"elseecho"执行''$arg''失败"status=" 发布失败"qqbot_deployexit1fi}#定义java编译功能函数functionant_shell(){ #jdk需要基于1.7,ant低于1.9编译cd$WORKSPACEarg="编译"#ant>/dev/null2>& 1antlog#一套代码,定义配置文件中心,拷贝不同的配置文件到不同的环境。这里拷贝测试环境配置文件到测试环境\cp- rfconf/xiangmu/dev/system_dev.propertiesWebRoot/WEB-INF/classes /system.properties\cp-rfconf/xiangmu/dev/ApplicationContext_de v.xmlWebRoot/WEB-INF/classes/spring/ApplicationContext.xml\cp- rfconf/xiangmu/dev//ApplicationContext-service_dev.xmlWebRoot/W EB-INF/classes/spring/ApplicationContext-service.xml}#定义java发布功能 函数functiondeploy_java(){#1.编译ant_shell#2.对e互助测试1的操作#2.1修改测试机 1的负载均衡的值为0arg="修改负载均衡的值"pythonModifyLoadBalancerBackends_test1 _value0.pylogsleep3#2.2发布测试机1的代码,rsync安静模式同步arg="发布$host1代码" rsync-e''ssh-ostricthostkeychecking=no-p22''-qapgolr--progr ess--delete$src$user@$host1:$destlog#2.3重启测试机1的tomcatssh$h ost1/home/tomcat/ver/restart_tomcat.sh&sleep18status_code1=`c url-I-m10-o/dev/null-s-w%{http_code}http://$host1/planwe b/index.do`if[$status_code1-eq200]thenecho"http://$host1 /planweb/index.do打开正常"elseecho"http://$host1/planweb/index.do 打开失败"#发布失败通知消息到qq群solution="原因和方案:可能tomcat启动时间过长的误报,延长sleep时间, 重新发布一次"status="发布失败"qqbot_deployexit1fi#3.上线测试机1,并下线测试机2,修 改测试机1的负载均衡值为10,修改测试机2的值为0arg="修改负载均衡的值"pythonModifyLoadBalance rBackends_test1_value10.pylog#4.对测试机2的操作#4.1发布代码到测试机2arg="发布$h ost2代码"rsync-e''ssh-ostricthostkeychecking=no-p22''-aqpgolr --progress--delete$src$user@$host2:$destlog#4.2重启测试机2的tomcat ssh$host2/home/tomcat/ver/restart_tomcat.sh&sleep22status_c ode2=`curl-I-m10-o/dev/null-s-w%{http_code}http://$host2 /planweb/index.do`if[$status_code2-eq200]thenecho"http:/ /www.gw638.cn打开正常"#4.3上线测试机2,修改测试1的值为10,全部上线arg="修改负载均衡的值"pyt honModifyLoadBalancerBackends_test2_value10.pylogecho"测试机$hos t1,$host2上线java代码完成"#动态文件,发布成功消息通知到qq群status="发布成功"qqbot_depl oy#退出循环exit0elseecho"http://www.44226.net打开失败"#发布失败通知消息到q q群status="发布失败"solution="原因和方案:可能tomcat启动时间过长,重置clb,查看tomcat启动l og"qqbot_deployexit1fi}#定义静态文件发布功能函数,无需重启tomcatfunctiondepl oy_static(){arg="发布$host1的静态代码"rsync-e''ssh-ostricthostkeych ecking=no-p22''-qapgolr--progress--delete$src$user@$host1:$d estlogarg="发布$host2的静态代码"rsync-e''ssh-ostricthostkeycheck ing=no-p22''-qapgolr--progress--delete$src$user@$host2:$dest log}#异步执行:代码质量分析。functioncode_quality_analysis(){if[!-f"so nar-project.properties"];thenecho-e"sonar.projectKey=dev_test \nsonar.host.url=http://localhost:9000/sonar\nsonar.projectName =dev_test\nsonar.projectVersion=1.0\nsonar.sources=src\nsonar. java.binaries=build/WEB-INF/classes">sonar-project.properties fiBUILD_ID=/usr/local/sonar-scanner/bin/sonar-scanner&echo"开 始异步运行代码质量分析"}#定义代码发布功能函数functiondeploy(){#标记静态文件出现的次数,解决遇到静态文件重 复同步多次的问题count=0#遍历发布的文件列表foriin$change_file_list;do#遇到有 java等后缀需要编译的文件,则编译发布。if["${i##.}"x="java"x]||["${i##.} "x="xml"x]||["${i##.}"x="properties"x];then#发布编译的代码de ploy_java#如果是前端静态文件,则无需编译直接发布。第一次遇到静态发布一次,再遇到静态则不发布。elif[!" ${i##.}"x="java"x]||[!"${i##.}"x="xml"x]||[!"${i# #.}"x="properties"x]&&[$count-eq0];then#发布静态文件deploy_ static#标记为1,记已同步一次代码count+=1fidone#全静态文件,发送消息通知到qq群status=" 发布成功"echo"全静态文件发布完成"qqbot_deploy}#紧急回滚措施,只是发布回滚,实际git上面没回滚,事后 得修改原先bug重新提交发布。functionrollback(){cd${WORKSPACE}echo"commiti d:$commitid"if[!$commitid]&&[!$file];thenecho"commiti d和file至少填一个"exit1elif[!$commitid]&&[$file];then#回滚某个文 件到上一次的更改num=2commitid=`gitlog-n$num--pretty=format:"%H"$fi le|sed-n${num}p`gitcheckout$commitid$filedeployelsearg= "回滚"#回滚到指定的commit版本,或者回滚指定版本的某个文件#gitlogWebRoot/campaign/da ily/share.js可以查看share.js最近修改的记录gitcheckout$commitid$filelog #发布回滚的版本deployfi}case$selectinDeploy)echo"select:$select "commitid=`gitrev-parseremotes/origin/dev`#发布deploy;;Rollb ack)echo"select:$select"#回滚rollback;;)echo"select:$sele ct"commitid=`gitrev-parseremotes/origin/dev`deploy;;esac4.实际 效果开发人员自动化git工具#coding:utf-8#author:laocao#date:20181225#测试环境运行在p ython3.6windows上importosfromtimeimportsleepcode_dir="D:\\p roj\\xiangmu"#code_dir="D:\git\xiangmu-git"print("------------提 ×××并本地分支的代码到dev----------")print("注意:本程序运行的的前提,代码必须在D:\proj\xiang mu中")print("")print("")os.chdir(code_dir)print("当前工作目录:"+os.get cwd())#输入分支名称,拉取远端dev最新代码到本地my_branch=input(''请输入您本地的分支名称:'')os.sys tem("gitcheckout%s"%my_branch)os.system("gitpullorigindev" )#输入项目描述,并提交到本地desc=input(''请输入项目描述:'')os.system("gitadd-A")os.sy stem("gitcommit-am''%s''"%desc)#切换到dev分支,拉取dev最新代码os.system(" gitcheckoutdev")os.system("gitpull")#合并本地分支到dev,并推送os.system(" gitmerge%s"%my_branch)os.system("gitpush")#返回本地分支os.system(" gitcheckout%s"%my_branch)print("提交成功,返回本地分支%s"%my_branch)in put("按任意键退出")6.项目经理自动化git工具,根据commitid合并#coding:utf-8#author:jord en#date:20181225#测试环境运行在python3.6windows上importosfromtimeim portsleepcode_dir="D:\\proj\\xiangmu"#code_dir="D:\git\xiang mu-git"print("------------合并dev的代码到master----------")print("注意:本程 序运行的的前提,代码必须在D:\proj\xiangmu中")print("")print("")os.chdir(code_di r)print("当前工作目录:"+os.getcwd())#切换到dev分支,拉取dev最新代码os.system("gi tcheckoutdev")os.system("gitpull")#切换到master分支,拉取master最新代码os .system("gitcheckoutmaster")os.system("gitpull")dev_commitid=i nput(''请输入dev中需要合并的commitid:'')print(dev_commitid)os.system("gitch erry-pick"+dev_commitid)print("dev_commitid:%s"%dev_commiti d)os.system("gitpush")print("git自动合并完成")input("按任意键退出")7.项目经理自动化 工具,根据文件合并版本。#coding:utf-8#author:laocao#date:20181225#测试环境运行在pyt hon3.6windows上importosfromtimeimportsleepcode_dir="D:\\pro j\\xiangmu"#code_dir="D:\git\xiangmu-git"print("------------合并d ev的代码到master,按文件合并----------")print("注意:本程序运行的的前提,代码必须在D:\proj\xi angmu中")print("")print("")os.chdir(code_dir)print("当前工作目录:"+os. getcwd())#切换到dev分支,拉取dev最新代码os.system("gitcheckoutdev")os.syst em("gitpull")#切换到master分支,拉取master最新代码os.system("gitcheckoutm aster")os.system("gitpull")#dev_commitid=input(''请输入dev中需要合并的comm itid:'')file_list=input(''请输入dev中需要合并的文件列表:'')os.system("gitcheck outdev"+file_list)print("file_list:%s"%file_list)#输入项目描述,并 提交到本地masterhttp://www.f-1.ccdesc=input(''请输入项目描述:'')os.system("git add-A")os.system("gitcommit-am''%s''"%desc)os.system("gitpu sh")print("git自动合并完成")input("按任意键退出")8.脚本完成了如下功能:编译:根据实际项目,这里用的ant。也可以maven动静分离发布:为了满足前端和后端的不同的发布需求,提高发布效率,采用了动静分离发布。纯静态文件直接同步到各服务器,只需几秒钟。动态文件发布则需编译,调用负载均衡,重启tomcat等,需1-2分钟。代码质量分析:发布完,sonar自动分析开发人员代码仓库的代码质量,作为后期改进。代码同步:采用rsyncssh模式进行代码同步到目标服务器调用负载均衡api:通过pythonsdk调用腾讯云负载均衡api,来上下线服务器。日志记录:每条命令的执行结果进行记录。定义代码配置中心:一套代码需要放在几个环境中运行,所以定义了不同的配置区分不同的环境,发布时拷贝相对应的配置文件到目标服务器,这样就达到了只需管理一套代码,运行在不同的环境。代码回滚:有时发布上去的代码有问题,这时可以紧急回滚,此处提供了按commitid来回滚和按文件回滚两种方式发布过程中会对网站状态进行判断,如果打开不是200,则不上线。9.消息通知:采用qqbot机器人自动发消息通知到群,让团队了解发布状态。qqbot采用smartqq协议,由于腾讯已下线,这里可以采用其他机器人插件(如酷Q),原理一样。 |
|
|
|
|
|
|
|
|
|
|