Git Hooks、GitLab CI持续集成以及使用Jenkins实现自动化任务

Git Hooks、GitLab CI持续集成以及使用Jenkins实现自动化任务

前言

在一个共享项目(或者说多人协同开发的项目)的开发过程当中,为有效确保团队成员编码风格的统一,确保部署方式的统一,等等(git的用户常常会涉及到此类场景),经常会使用相似 Git Flow 这种比较复杂的工做流开发模式。在较大型的项目中,虽然这种工做流模式比较成熟,但在分支处理方面,这种工做流就会形成较多的重复劳动。html

所以,若是能借助某些工具来自动化处理这些重复性事务,好比自动合并分支,那么对于提高咱们的工做效率,将会有很大的帮助。git

本文将从如下三种方法对自动化任务处理作介绍,并对每一种方法的优缺点作个简单的总结,以及在实际工做中咱们该如何作出选择。github

三种实现方法:

  • 客户端与服务端 Git hooks
  • GitLab-Runner 以及编写 .gitlab-ci.yml 文件
  • GitLab Webhooks 与 Jenkins 的配合使用

Git 钩子

Git hooks是基于事件的。当你执行特定的git指令时,该软件会从git仓库下的hooks目录下检查是否有相对应的脚本,若是有就执行。web

有些脚本是在动做执行以前被执行的,这种“先行脚本”可用于实现代码规范的统1、完整性检查、环境搭建等功能。有些脚本则在事件以后被执行,这种“后行脚本”可用于实现代码的部署、权限错误纠正(git在这方面的功能有点欠缺)等功能。docker

安装一个钩子

钩子都被存储在Git目录下的hooks子目录中。也即绝大部分项目中的.git/hooks。当你用git init初始化一个新版本库时,Git 默认会在这个目录中放置一些示例脚本。这些脚本除了自己能够被调用外,它们还暴露了被触发时所传入的参数。这些示例的名字都是以 .sample 结尾,若是想启用它们,移除这个后缀便可。shell

把一个正确命名且可执行的文件放入 Git 目录下的 hooks 子目录中,便可激活该钩子脚本。这样一来,它就能 被 Git 调用。vim

客户端和服务器端 Git hooks

git hooks 采用 事件机制, 在相应的操做(好比 git commit / git merge)下触发, 分为 2 种:segmentfault

  • 服务端 hooks, github 的 webhooks 就是在此基础上创建起来的;bash

  • 客户端 hooks, 每一个 git 版本库的 .git/hooks/ 文件夹下就有可使用的例子。服务器

注意: 客户端 hooks 并不会同步到版本库中

客户端钩子由诸如提交和合并这样的操做所调用,而服务器端钩子做用于诸如接收被推送的提交这样的联网操做。

客户端钩子位于项目根目录 your_project/.git/hooks 文件夹下

服务端钩子则位于 your_project.git 文件夹下的 hooks 和 custom_hooks

hooks与custom_hooks文件夹

能够看到GitLab为咱们建立了一个软链接链接到了GitLab自定义的钩子目录,这样全部建立的项目均可以使用同一个脚本规则,减小了维护成本。

那咱们如何结合GitLab定制本身的脚本呢?git会首先触发GitLab的脚本,而后GitLab执行完本身的脚本文件后会再调用掉用户放在custom_hooks下的脚本,因此咱们只须要将咱们定制好的脚本放在custom_hooks下便可,脚本名称和以前同样。例如:touch post-receive,这个脚本理论上可使用任何脚本语言例如Perl、Python、Ruby等,不过执行这个脚本的用户将是git,要注意git用户对系统的操做权限,还要注意post-receive这个脚本须要可以有执行权限。

客户端与服务端钩子图示

(图片来自于网络)

示例

post-receive 推送代码后自动部署

将目录切换至 ../BRIDGE_REPO.git/hooks,用 cp post-receive.sample post-receive 复制并重命名文件后用 vim post-receive 修改。其内容大体以下:

#!/bin/sh

unset GIT_DIR

NowPath=`pwd`
DeployPath="../../www"

cd $DeployPath
git pull origin master

cd $NowPath
exit 0

使用 chmod +x post-receive 改变一下权限便可,服务器端的配置就基本完成了。

GitLab-CI与GitLab-Runner

持续集成(Continuous Integration)

要了解GitLab-CI与GitLab Runner,咱们得先了解持续集成是什么。

持续集成是一种软件开发实践,即团队开发成员常常集成他们的工做,一般每一个成员天天至少集成一次,也就意味着天天可能会发生屡次集成。每次集成都经过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽快地发现集成错误。许多团队发现这个过程能够大大减小集成的问题,让团队可以更快的开发内聚的软件。

GitLab-CI

GitLab-CI就是一套配合GitLab使用的持续集成系统(固然,还有其它的持续集成系统,一样能够配合GitLab使用,好比接下来要说的Jenkins)。

持续集成,咱们一般使用CI来作一些自动化工做,好比程序的打包,单元测试,部署等,这种构建方式避免了打包环境差别引发的错误,提升了工做效率。Gitlab-CI是Gitlab官方提供的持续集成服务,咱们能够在仓库的根目录下新建.gitlab-ci.yml文件,本身定义持续集成流程模板,而且在Gitlab中配置runner,在以后的每次提交或合并中将会触发构建,而且能够经过Gitlab的hook, 在代码提交的各个环节自动地完成一系列的构建工做,总之对于一些非复杂性的集成需求,都是能够知足的。

实际上,GitLab-CI中有一个概念叫 Pipeline ,一次 Pipeline 其实至关于一次构建任务,里面能够包含多个流程,如安装依赖、运行测试、编译、部署测试服务器、部署生产服务器等流程。任何提交或者 Merge Request 的合并均可以触发 Pipeline。

思考:
为何不是 GitLab CI 来运行那些构建任务?

通常来讲,构建任务都会占用不少的系统资源 (譬如编译代码),而 GitLab CI 又是 GitLab 的一部分,若是由 GitLab CI 来运行构建任务的话,在执行构建任务的时候,GitLab 的性能会大幅降低。

GitLab CI 最大的做用是管理各个项目的构建状态,所以,运行构建任务这种浪费资源的事情就交给 GitLab Runner 来作了!

由于 GitLab Runner 能够安装到不一样的机器上,因此在构建任务运行期间并不会影响到 GitLab 的性能~

GitLab-Runner

GitLab-Runner是配合GitLab-CI进行使用的。通常地,GitLab里面的每个工程都会定义一个属于这个工程的软件集成脚本,用来自动化地完成一些软件集成工做。当这个工程的仓库代码发生变更时,好比有人push了代码,GitLab就会将这个变更通知GitLab-CI。这时GitLab-CI会找出与这个工程相关联的Runner,并通知这些Runner把代码更新到本地并执行预约义好的执行脚本。

因此,GitLab-Runner就是一个用来执行软件集成脚本的东西。你能够想象一下:Runner就像一个个的工人,而GitLab-CI就是这些工人的一个管理中心,全部工人都要在GitLab-CI里面登记注册,而且代表本身是为哪一个工程服务的。当相应的工程发生变化时,GitLab-CI就会通知相应的工人执行软件集成脚本。

Runner一共有三种类型

  • 本地Runner
  • 普通的服务器上的Runner
  • 基于Docker的Runner

MAC环境安装gitlab-ci-multi-runner

具体说下gitlab-runner register

Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/ci):
http://xxxxxx // 在这里输入gitlab安装的服务器ip/ci 便可

Please enter the gitlab-ci token for this runner:
xxxxxxxxxxxxxxxxxx // 这里的token可经过Gitlab上的项目Runners选项查看

Please enter the gitlab-ci description for this runner:[E5]:demo
// 这里填写一个描述信息

Please enter the gitlab-ci tags for this runner (comma separated):
demo // 在这里填写tag信息,多个tag可经过逗号,分割。
tag:一个项目可能有多个runner,是根据tag来区别runner的。

Registering runner... succeeded. runner=eaYyokc5

Please enter the executor: docker, docker-ssh, parallels, shell, ssh, virtualbox, docker+machine, docker-ssh+machine:
shell // 在这里须要输入runner的执行方式,直接输入shell

Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded! // 出现这样信息表示服务端的配置就已经成功结束了。

如何编写 .gitlab-ci.yml 文件

若是你在项目仓库里面加入.gitlab-ci.yml文件,同时给项目配置了gitlab-runner, 那么每次提交代码或者合并 mr , 都会触发你的 CI Pipeline (持续集成管道)。

stages:
  - deploy
deploy:
    stage: deploy
    script:
      - echo "start deploy....."
      - deploy
    only:
      - master
    tags:
      - shell

其中deploy是编写的shell脚本,能够实现将要发布的内容自动部署到发布目录下:

#!/bin/bash
deploy_path="xxx"
project_path="xxx;
judge_path = "$deploy_path/$project_path"
if [ ! -d "$judge_path" ]
then
   project_url="xxx.git"
   git clone $project_path $deploy_path
else
   cd $deploy_path
   git pull
fi

.gitlab-ci.yml配置详解请参考:

gitlab ci/cd .gitlab-ci.yml配置详解

官方GitLab文档

官方GitLab文档翻译

Gitlab Webhooks

Webhooks 容许第三方应用监听 GitLab 上的特定事件,在这些事件发生时经过 HTTP POST 方式通知( 超时5秒) 到第三方应用指定的 Web URL。 例如项目有新的内容 Push,或是 Merge Request 有更新等。 WebHooks 可方便用户实现自动部署,自动测试,自动打包,监控项目变化等。

webhooks, 能够在 pull request / merge master 等几个场景下, 设置异步回调通知(http 请求)。这个背后就是 git hooks 在起做用。

所以,利用 WebHooks 的特性,可配合 Jenkins 实现一系列的自动化任务。

Jenkins

Jenkins是一个用Java编写的开源的持续集成工具,能够与Git打通,监听Git的merge, push事件,触发执行Jenkins的指定任务(job)。例如发布的任何一个环节均可自动完成,无需太多的人工干预,有利于减小重复过程以节省时间和工做量等。

实例:Jenkins、Gitlab webhooks实现开发分支自动合并

步骤梳理

  1. GitLab上准备一个web工程;
  2. GitLab上配置Jenkins的webhook地址;
  3. Jenkins安装GitLab Plugin插件;
  4. Jenkins配置GitLab访问权限;
  5. Jenkins上建立一个构建项目,对应的源码是步骤1中的web工程;
  6. 修改web工程的源码,并提交到GitLab上;
  7. 检查Jenkins的构建项目是否会触发自动任务脚本。
(Jenkins Job 和 GitLab 的关联,在网上已经有许多完善的文档了,在这里就不赘述了)
如下为开发分支develop自动合并master分支的脚本示例,仅供参考:
#!/bin/sh
echo *****************Start*****************
date
# 获取最近一次提交的 commit id
sha1=`git rev-parse HEAD`
# 获取姓名及邮箱,来配置git提交者信息
name=`git show $sha1 | grep 'Author:' | cut -d' ' -f2`
email=`git show $sha1 | grep 'Author:' | cut -d' ' -f3 | sed -e 's/<//g' | sed -e 's/>//g'`
echo '当前提交人信息:'
echo $name 
echo $email 
git config --global user.name $name
git config --global user.email $email
echo '***************** git checkout develop & git pull:'
git checkout develop
git pull
# develop合并master
echo '***************** git merge origin/master:'
conflict=`git merge origin/master`
echo $conflict | grep 'CONFLICT'
if [ $? -ne 0 ]; then
    echo '***************** git push origin HEAD:'
    git push origin HEAD
    echo '***************** git status:'
    git status
else
    git status
    echo 'Automatic merge failed...'
    echo 'Please fix conflicts and then commit the result...'
    exit 1
fi
echo *****************End*****************

三种实现方法的优缺点对比:

  • 客户端与服务端 Git hooks :若是仅涉及客户端钩子,用这种方法比较好,好比 husky 这个插件;但若是是服务端钩子,就必须在服务端配置才可以使用,好比 post-receive 钩子;
  • GitLab-Runner 以及编写 .gitlab-ci.yml 文件:需服务端安装 gitlab-runner 来支持自动化脚本的执行;
  • GitLab Webhooks 与 Jenkins 的配合使用:Jenkins是比较成熟的第三方持续集成系统,可与GitLab完美的结合使用,但配置过程还是稍显复杂,但在自动化任务处理方面,Jenkins无疑是个较好的选择。

参考资料

Pro Git

GitLab 官方文档

Git Hooks

GitLab-CI 与 GitLab-Runner

转载请标注出处,谢谢!http://www.javashuo.com/article/p-oeilhptg-er.html

相关文章
相关标签/搜索