基于Gitlab+Jenkins的代码自动化发布

这里所讲的自动化发布是指代码从提交到仓库,到发布到目标服务器的整个过程。

主要涉及到两个工具Gitlab,Jenkins,要完成自动化还需要rsync,qqbot,log,ant、shell脚本,python等。

Gitlab:我们主要用它来做代码的仓库

Jenkins:用来执行任务的持续集成,构建等。
一、大体的自动化思路:

开发人员push代码到gitlab,触发webhook,调用jenkins job。 jenkins job 执行拉取代码,编译,调用loadblance,下架部分服务器更新代码,验证更新后的可用性,上线;再下架另一部分服务器,更新代码,再上线。 更新完后,将本次发布的状态信息推送给项目组。

二、实际工作中,我们遇到的比以上要复杂。

服务器环境包括:测试环境,开发环境,预发布环境,生产环境等。 代码仓库又分为多个分支:master分支,开发分支,项目分支,本地分支等。

因此要完成整个过程自动化,还需要整合多分支,多环境的情况。

三、测试环境的自动化思路:

1.建一个dev分支用来专门发布测试环境,此分支只允许开发人员合并代码和push,不能直接在上面改代码。 2.开发人员开发一个功能,先在本地建一个本地分支,写完后合并到dev,然后push到gitlab,gitlab触发钩子事件,调用jenkins完成项目的自动化部署。

以上2点看似已经实现了自动化发布,但实践发现,开发人员仍需花不少时间在代码的提交 ,切换分支,合并分支,push代码等重复而繁琐的工作上。于是这里我做了对GIT操作的自动化,将提交、切换、合并、push整合整合起来成工具,后面会列出工具代码。

四、预发布环境的自动化思路:

1.预发布的自动化采用和测试环境一样的思路,只是dev分支换成了master分支。 2.master分支:我们用它来发布预发布和生产环境,对没错两套环境用同一分支,此分支只有项目经理有权限push,普通开发没权限操作。

以上2点看似也实现了代码的自动化发布,但实际工作中项目经理同样也要花不少时间在代码的提交 ,切换分支,合并分支,push代码等重复繁琐的工作,因此这里也要解决项目经理Git操作的自动化,后面列出工具。

五、生产环境的自动化发布:

生产环境的发布其实只是取消了webhook的自动触发jenkins job,改为手动点击发布,主要是为发布安全考虑。

六、实操:

1.设置webhook,对测试环境job和预发布环境job设置相应的钩子事件:

2.在jenkins中配置git插件

3.配置jenkins job,这里我用shell脚本做一系列的job,不需要像网上安装各种繁琐的插件。

#!/bin/bash
#本案例中WORKSPACE=/root/.jenkins/workspace/dev_test

#源目录
src="$WORKSPACE/WebRoot/"

#发布的目标目录
dest="/usr/local/apache-tomcat-6.0.39/webapps/xiangmu/"

#目标主机用户
user="root"

#目标主机,测试机1、测试机2
host1="10.111.111.1"
host2="10.111.111.2"

# 需要发布的文件列表
cd $WORKSPACE
change_file_list=`git diff --name-only HEAD~ HEAD`
echo "需要发布的文件列表:$change_file_list"

#定义机器人发布消息功能函数
function qqbot_deploy(){
proj_name=`git show $commitid --pretty=format:"%s" |sed -n 1p`

author=`git show $commitid --pretty=format:"%an" |sed -n 1p`

now_time=`date "+%Y-%m-%d %H:%M:%S"`

qq send group IT群 "
QQ消息机器人:
【测试环境】 发布时间:$now_time 自动化发布完成
项目:$proj_name 状态:$status $solution
发布的文件列表:$change_file_list
发布人:$author" &
} 

# 定义执行命令成功或失败日志记录功能函数
function log(){
  if [ $? -eq 0 ];then
      echo "执行‘$arg‘成功"
  else
      echo "执行‘$arg‘失败"
      status="发布失败"
      qqbot_deploy
      exit 1
  fi
}

# 定义java编译功能函数
function ant_shell(){
  #jdk需要基于1.7,ant低于1.9编译
  cd $WORKSPACE
  arg="编译"
  #ant >/dev/null 2>&1
  ant
  log

  # 一套代码,定义配置文件中心,拷贝不同的配置文件到不同的环境。这里拷贝测试环境配置文件到测试环境
  \cp -rf conf/xiangmu/dev/system_dev.properties WebRoot/WEB-INF/classes/system.properties

  \cp -rf conf/xiangmu/dev/ApplicationContext_dev.xml WebRoot/WEB-INF/classes/spring/ApplicationContext.xml

  \cp -rf conf/xiangmu/dev//ApplicationContext-service_dev.xml WebRoot/WEB-INF/classes/spring/ApplicationContext-service.xml
}

# 定义java发布功能函数
function deploy_java(){
    #1.编译
    ant_shell

    #2.对e互助测试1的操作
    #2.1修改测试机1的负载均衡的值为0
    arg="修改负载均衡的值"
    python ModifyLoadBalancerBackends_test1_value0.py
    log
    sleep 3

    #2.2发布测试机1的代码,rsync安静模式同步
    arg="发布$host1代码"
    rsync -e ‘ssh -o stricthostkeychecking=no -p22‘ -qapgolr --progress --delete $src [email protected]$host1:$dest
    log

   #2.3重启测试机1的tomcat
    ssh $host1 /home/tomcat/ver/restart_tomcat.sh&
    sleep 18
    status_code1=`curl -I -m 10 -o /dev/null -s -w %{http_code} http://$host1/planweb/index.do`

    if [ $status_code1 -eq 200 ]
    then
        echo "http://$host1/planweb/index.do 打开正常"
    else
        echo "http://$host1/planweb/index.do 打开失败"

        #发布失败通知消息到qq群
        solution="原因和方案:可能tomcat启动时间过长的误报,延长sleep时间,重新发布一次"
        status="发布失败"
        qqbot_deploy
        exit 1
    fi      

    #3.上线测试机1,并下线测试机2,修改测试机1的负载均衡值为10,修改测试机2的值为0
    arg="修改负载均衡的值"
    python ModifyLoadBalancerBackends_test1_value10.py
    log

#4.对测试机2的操作
    #4.1发布代码到测试机2
    arg="发布$host2代码"
    rsync -e ‘ssh -o stricthostkeychecking=no -p22‘ -aqpgolr --progress --delete $src [email protected]$host2:$dest
    log

    #4.2重启测试机2的tomcat
    ssh $host2 /home/tomcat/ver/restart_tomcat.sh&
    sleep 22
    status_code2=`curl -I -m 10 -o /dev/null -s -w %{http_code} http://$host2/planweb/index.do`

    if [ $status_code2 -eq 200 ]

    then
        echo "http://test.xiangmu.com 打开正常"
            #4.3上线测试机2,修改测试1的值为10,全部上线
            arg="修改负载均衡的值"
            python ModifyLoadBalancerBackends_test2_value10.py
            log

            echo "测试机$host1,$host2上线java代码完成"
            #动态文件,发布成功消息通知到qq群
            status="发布成功"
            qqbot_deploy

            #退出循环
            exit 0
    else
        echo "http://test.xiangmu.com打开失败"
        #发布失败通知消息到qq群
        status="发布失败"
        solution="原因和方案:可能tomcat启动时间过长,重置clb,查看tomcat启动log"
        qqbot_deploy
        exit 1
    fi
}

# 定义静态文件发布功能函数,无需重启tomcat
function deploy_static(){
    arg="发布$host1的静态代码"
    rsync -e ‘ssh -o stricthostkeychecking=no -p22‘ -qapgolr --progress --delete $src [email protected]$host1:$dest
    log

    arg="发布$host2的静态代码"
    rsync -e ‘ssh -o stricthostkeychecking=no -p22‘ -qapgolr --progress --delete $src [email protected]$host2:$dest
    log
}

#异步执行:代码质量分析。
function code_quality_analysis(){
    if [ ! -f "sonar-project.properties" ];then
        echo -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
    fi

    BUILD_ID=
    /usr/local/sonar-scanner/bin/sonar-scanner &
    echo "开始异步运行代码质量分析"
}

#定义代码发布功能函数
function deploy(){
    #标记静态文件出现的次数,解决遇到静态文件重复同步多次的问题
    count=0

    #遍历发布的文件列表
    for i in $change_file_list;
    do
        # 遇到有java等后缀需要编译的文件,则编译发布。
        if [ "${i##*.}"x = "java"x ] || [ "${i##*.}"x = "xml"x ] || [ "${i##*.}"x = "properties"x ];then

            #发布编译的代码
            deploy_java

        # 如果是前端静态文件,则无需编译直接发布。第一次遇到静态发布一次,再遇到静态则不发布。
        elif [ ! "${i##*.}"x = "java"x ] || [ ! "${i##*.}"x = "xml"x ] || [ ! "${i##*.}"x = "properties"x ] && [ $count -eq 0 ];then

            #发布静态文件
            deploy_static

            #标记为1,记已同步一次代码
            count+=1
        fi
     done

    #全静态文件,发送消息通知到qq群
    status="发布成功"
    echo "全静态文件发布完成"
    qqbot_deploy
  }

#紧急回滚措施,只是发布回滚,实际git上面没回滚,事后得修改原先bug重新提交发布。
function rollback(){
    cd ${WORKSPACE}
    echo "commitid:$commitid"
    if [ ! $commitid ] && [ ! $file ];then
        echo "commitid和file至少填一个"
        exit 1
    elif [ ! $commitid ] && [ $file ];then
        #回滚某个文件到上一次的更改
        num=2
        commitid=`git log -n $num --pretty=format:"%H" $file |sed -n ${num}p`

        git checkout $commitid $file
        deploy
    else
        arg="回滚"
        # 回滚到指定的commit版本,或者回滚指定版本的某个文件
        # git log WebRoot/campaign/daily/share.js 可以查看share.js最近修改的记录

        git checkout $commitid $file
        log

        #发布回滚的版本
        deploy
    fi
}

case $select in
    Deploy)
        echo "select:$select"
        commitid=`git rev-parse remotes/origin/dev`
        #发布
        deploy
        ;;
    Rollback)
        echo "select:$select"
        #回滚
        rollback
        ;;
    *)
        echo "*select:$select"
        commitid=`git rev-parse remotes/origin/dev`
        deploy
        ;;
esac

4.实际效果

开发人员自动化git工具

#coding:utf-8
#author:laocao
#date: 20181225
#测试环境运行在python3.6 windows上

import os
from time import sleep

code_dir = "D:\\proj\\xiangmu"
#code_dir = "D:\git\xiangmu-git"
print("------------提×××并本地分支的代码到dev----------")
print("注意:本程序运行的的前提,代码必须在D:\proj\xiangmu中")
print("")
print("")

os.chdir(code_dir)
print("当前工作目录:" + os.getcwd())

#输入分支名称,拉取远端dev最新代码到本地
my_branch=input(‘请输入您本地的分支名称:‘)
os.system("git checkout %s" % my_branch)
os.system("git pull origin dev")

#输入项目描述,并提交到本地
desc=input(‘请输入项目描述:‘)
os.system("git add -A")
os.system("git commit -am ‘%s‘" % desc)

# 切换到dev分支,拉取dev最新代码
os.system("git checkout dev")
os.system("git pull")

#合并本地分支到dev,并推送
os.system("git merge %s" % my_branch)
os.system("git push")

#返回本地分支
os.system("git checkout %s" % my_branch)
print("提交成功,返回本地分支%s" % my_branch)
input("按任意键退出")

6.项目经理自动化git工具,根据commitid合并


#coding:utf-8
#author:jorden
#date: 20181225
#测试环境运行在python3.6 windows上
import os
from time  import sleep

code_dir = "D:\\proj\\xiangmu"
#code_dir = "D:\git\xiangmu-git"

print("------------合并dev的代码到master----------")
print("注意:本程序运行的的前提,代码必须在D:\proj\xiangmu中")
print("")
print("")

os.chdir(code_dir)
print("当前工作目录:" + os.getcwd())

# 切换到dev分支,拉取dev最新代码
os.system("git checkout dev")
os.system("git pull")

# 切换到master分支,拉取master最新代码
os.system("git checkout master")
os.system("git pull")

dev_commitid=input(‘请输入dev中需要合并的commitid:‘)
print(dev_commitid)
os.system("git cherry-pick " + dev_commitid)
print("dev_commitid: %s" % dev_commitid)
os.system("git push")
print("git自动合并完成")
input("按任意键退出")

7.项目经理自动化工具,根据文件合并版本。


#coding:utf-8
#author:laocao
#date: 20181225
#测试环境运行在python3.6 windows上

import os
from time  import sleep

code_dir = "D:\\proj\\xiangmu"
#code_dir = "D:\git\xiangmu-git"

print("------------合并dev的代码到master,按文件合并----------")
print("注意:本程序运行的的前提,代码必须在D:\proj\xiangmu中")
print("")
print("")

os.chdir(code_dir)
print("当前工作目录:" + os.getcwd())

# 切换到dev分支,拉取dev最新代码
os.system("git checkout dev")
os.system("git pull")

# 切换到master分支,拉取master最新代码
os.system("git checkout master")
os.system("git pull")

#dev_commitid=input(‘请输入dev中需要合并的commitid:‘)
file_list = input(‘请输入dev中需要合并的文件列表:‘)
os.system("git checkout dev " + file_list)
print("file_list: %s" % file_list)

#输入项目描述,并提交到本地master
desc=input(‘请输入项目描述:‘)
os.system("git add -A")
os.system("git commit -am ‘%s‘" % desc)
os.system("git push")
print("git自动合并完成")
input("按任意键退出")

8.脚本完成了如下功能:

编译:根据实际项目,这里用的ant。也可以maven

动静分离发布:为了满足前端和后端的不同的发布需求,提高发布效率,采用了动静分离发布。纯静态文件直接同步到各服务器,只需几秒钟。动态文件发布则需编译,调用负载均衡,重启tomca等,需1-2分钟。

代码质量分析: 发布完,sonar自动分析开发人员代码仓库的代码质量,作为后期改进。

代码同步:采用rsync ssh模式进行代码同步到目标服务器

调用负载均衡api:通过python sdk调用腾讯云负载均衡api,来上下线服务器。

日志记录: 每条命令的执行结果进行记录。

定义代码配置中心:一套代码需要放在几个环境中运行,所以定义了不同的配置区分不同的环境, 发布时拷贝相对应的配置文件到目标服务器,这样就达到了只需管理一套代码,运行在不同的环境。

代码回滚:有时发布上去的代码有问题,这时可以紧急回滚,此处提供了按commitid来回滚和按文件回滚两种方式

发布过程中会对网站状态进行判断,如果打开不是200,则不上线。
9.消息通知:采用qqbot机器人自动发消息通知到群,让团队了解发布状态。qqbot采用smartqq协议,由于腾讯已下线,这里可以采用其他机器人插件(如酷Q),原理一样。

原文地址:http://blog.51cto.com/jin544642965/2340038

时间: 2024-08-11 14:18:08

基于Gitlab+Jenkins的代码自动化发布的相关文章

gitlab+jenkins+hook代码自动构建发布上线

Gitlab+Jenkins+Hook 1.gitlab和jenkins的安装见: http://www.cnblogs.com/cuishuai/p/7544663.html http://www.cnblogs.com/cuishuai/p/7544775.html 2.gitlab配置 1)创建一个project,并创建一个monkey的分支. 2)对分支进行设置: 点击project->settings->integrations: 1. 2. 3 Webhook,点击test,返回如

基于GitLab+Jenkins的DevOps赋能实践

随着微服务.中台架构的兴起,DevOps也变得非常关键,毕竟是一些基础设施层面的建设,如果搞好了对后面的研发工作会有很大的效率提升.关于DevOps本身的概念,网上已经非常多了,在园子里随便搜索一些都一堆概念,我就不再重复介绍了.下面直接进入正题,怎么使用GitLab+Jenkins来完成DevOps的建设. 在开始实战演练之前,首先用一张图来展示一下这次实践所要完成的功能: 在这个流程中,分为3个环境,分别是预览环境.预发环境和生产环境,普通开发者接受到任务以后,在GitLab中基于featu

Jenkins环境搭建部署实现代码自动化发布

一.jenkins代码自动部署 1.配置免密钥通信 实现自动化部署首先要解决的是免密码传输,配置jenkins至测试服务器之间免密钥ssh登录 测试免密钥ssh登录 在测试服务器上编写一个测试脚本,检测是否可以执行成功,正式环境可以写一个自动化部署的脚本 2.jenkins新建部署代码项目 在构建这里选择执行shell命令 点击立即构建 控制台输出日志:成功 这样就实现了使用jenkins代码的自动化部署 实际情况中我们通常使用版本控制系统管理代码,svn 或者 git 二.gitlab利用we

gitlab+jenkins+ansible集成持续发布

1.Gitlab安装 gitlab 10.0.1安装使用 内存最少2G否则系统安装完会502报错 安装 如想使用Postfix来发送邮件,在安装期间请选择'Internet Site'. 您也可以用sendmai或者 配置SMTP服务 并 使用SMTP发送邮件. 在 Centos 6 系统上, 下面的命令将在系统防火墙里面开放HTTP和SSH端口. sudo yum install curl openssh-server openssh-clients postfix cronie policy

Jenkins CICD代码构建发布流程

一.发布环境 发布脚本 #!/bin/bash #node group1="172.16.8.11 172.16.8.12" group2="172.16.8.13 172.16.8.14" #deloy tomcat1_dir=/app/tomcat1 tomcat2_dir=/app/tomcat2 tomcat3_dir=/app/tomcat3 tomcat4_dir=/app/tomcat4 #BACKUP backup_dir1=/app/backup1

Linux-GitLab+Jenkins持续集成+自动化部署

GitLab+Jenkins持续集成+自动化部署 什么是持续集成? (1)Continuous integration (CI) 持续集成是一种软件开发实践,即团队开发成员经常集成他们的工作,通常每个成员至少集成一次,也就意味着每天可能会发生多次集成.每次集成都通过自动化的构建(包括编译.发布.自动化测试)来验证,从而尽快地发现集成错误.许多团队发现这个过程可以大大减少集成的问题,让团队能够更快的开发内聚的软件. (2)没有持续集成 项目做模块集成的时候,发现很多接口都不通==>浪费大量时间 需

docker搭建gitlab+Jenkins持续集成环境

安装docker 此处省略一.使用docker安装gitlab docker pull gitlab/gitlab-ce:latest下载完成之后使用docker生成容器docker run -dit \-p 8443:443 \-p 8080:80 \-p 2222:22 \-p 9090:9090 \--name gitlab \--restart always \-v /home/gitlab/config:/etc/gitlab \-v /home/gitlab/logs:/var/lo

gitlab+jenkins自动化部署

基于gitlab和jenkins的自动化部署 Gitlab基于Jenkins自动化部署教程: https://blog.csdn.net/aaaaaab_/article/details/82012044 https://www.cnblogs.com/dengbingbing/p/10448185.html GitLab是一个代码仓库,用来管理代码. Jenkins是一个自动化服务器,可以运行各种自动化构建.测试或部署任务.所以这两者结合起来,就可以实现开发者提交代码到GitLab,Jenki

从0到1体验Jenkins+Docker+Git+Registry实现CI自动化发布

一.前言 Jenkins是一款开源 CI&CD 软件,用于自动化各种任务,包括构建.测试和部署软件.Jenkins 支持各种运行方式,可通过系统包.Docker 或者通过一个独立的 Java 程序.Jenkins是一个广泛用于持续构建的可视化Web工具,持续构建就是将项目自动化编译.打包.部署.通过规范化来完成,简单,繁琐,浪费时间的重复工作. Jenkins名言:构建伟大,无所不能! Jenkins用户手册传送门:https://jenkins.io/zh/doc/ 二.发布流程 工作详细流程