CI持续集成:Gitlab&&Gerrit&&Jenkins部署集成


引言:

  随着IT行业的不断发展,软件开发的复杂度也随着不断提高,软件的开发团队也越来越庞大,如何更好地协同整个团队进行高效准确的工作,确保软件开发的质量成为了开发过程中不可回避的问题。

  在软件开发中,不同的功能模块一般由不同的开发成员负责,同一功能模块的各层代码也可能是不同的开发成员编写,经验告诉我们,模块之间的问题是最难解决的,也是最耗费时间的。它需要多个开发人员相互协作找出问题,而协作过程中的沟通所消耗的时间成本是相当高的。而且还可能因为沟通的不足导致模块返工。

  事实上,在持续集成被提出来之前的传统开发方法中常常出现这种情况:由不同程序员开发的单个小模块可以单独工作,但把它们集成为一个大的系统则可能失败。而且集成失败往往是把集成放在开发周期后期,甚至是在项目快结束前单列的一个“总装阶段”。众所周知,问题发现的越晚,其修复的成本也就越高,耗时越长,而且经过新的修复工作后可能诞生新的错误,因此整个系统需要再次进行集成和测试,从而导致整个软件的生产周期漫长且不可预知。

  为了解决由传统开发方法带来的弊端,人们开始采用“早集成、常集成”的持续集成策略。从最初的分阶段集成,到后来的“每日构建” ,再发展到现在的持续集成(Continuous Integration,CI)。持续集成通过自动化构建、自动化测试以及自动化部署加上较高的集成频率保证了开发系统中的问题能迅速被发现和修复,降低了集成失败的风险,使得系统在开发中始终保持在一个稳定健康的集成状态。

  持续集成服务器是自动构建系统中关键的一部分。Jenkins是一个开源项目,它提供了一种易于使用的持续集成系统,使开发者从繁杂的集成中解脱出来,专注于更为重要的业务逻辑实现上。同时 Jenkins 能实施监控集成中存在的错误,提供详细的日志文件和提醒功能,还能用图表的形式形象地展示项目构建的趋势和稳定性。Jenkins还能通过自定义安装插件来实现多种多样的功能。持续集成服务器各系统实现功能如下:


1、Gitlab上进行代码托管

  在Gitlab上创建开发组,加入开发人员,新建开发项目项目并设置权限为Private,普通用户对该项目只有pull权限,不能直接进行push

  强制Review :在 Gitlab 上创建的项目,指定相关用户只有Reporter权限,这样用户没有权限使用git push功能,只能git review到Gerrit 系统上,Jenkins在监听Gerrit上的项目事件会触发构建任务来测试代码, Jenkins 把测试结果通过 ssh gerrit 给这个项目打上 Verified (信息校验)成功或失败标记,成功通知其它人员 Review(代码审核) 。

  Gitlab保护Master 分支:在 Gitlab 上创建的项目可以把 Master 分支保护起来,普通用户可以自己创建分支并提交代码到自己的分支上,没有权限直接提交到Master分支,用户最后提交申请把自己的分支 Merge 到 Master ,管理员收到 Merge 请求后, Review 后选择是否合并。

  因为Gitlab和Gerrit做了同步,Gerrit上的代码会同步到Gitlab上。

2、Gerrit审核代码

  普通用户将Gitlab里的项目clone到本地,修改代码后,虽不能直接push到代码中心 ,但是可以通过git review提交到Gerrit上进行审核。Gerrit相关审核员看到review信息后,判断是否通过,通过即commit提交。然后,Gerrit代码会和Gitlab完成同步。

  Gerrit的精髓在于不允许直接将本地修改同步到远程仓库。客户机必须先push到远程仓库的refs/for/*分支上,等待审核。

  Gerrit上也可以对比代码审核提交前后的内容状态。

3、Jenkins代码发布

  当用户git review后,代码通过Jenkins自动测试(verified)、人工review 后,代码只是merge到了Gerrit的项目中,并没有merge到 Gitlab的项目中,所以需要当 Gerrit 项目仓库有变化时自动同步到Gitlab的项目仓库中。Gerrit 自带一个 Replication 功能,同时我们在安装 Gerrit 时候默认安装了这个 Plugin,通过添加replication.config 给 Gerrit即可。


CI持续集成系统安装部署流程描述如下:

Gerrit部署配置

1、 安装JDK

[root@Ubuntu]#sudo add-apt-repository ppa:webupd8team/java

[root@Ubuntu]#sudo apt-get update

[root@Ubuntu]#sudo apt-get install oracle-java8-installer

2、 安装mysql

[root@Ubuntu]#sudo apt-get install mysql-server mysql-client #中途会让你输入一次root用户密码(密码:root)

3、 创建gerrit数据库

[root@Ubuntu]#mysql –uroot –p 进入mysql创建gerrit数据库gerritdb

mysql>create database gerritdb CHARACTER SET utf8 COLLATE utf8_general_ci;

mysql>grant all on gerritdb.* to 'gerrit'@'localhost' identified by '123456';

mysql>flush privileges;

4、 安装配置并启动nginx(反向代理端口设为9095)

[root@Ubuntu]#sudo apt-get install nginx

[root@Ubuntu]#cd /etc/nginx/conf.d

[root@Ubuntu]#vim gerrit.conf
server {

 listen 9095;

 server_name localhost;

 allow all;

 deny all;

 auth_basic "Welcomme to Gerrit Code Review Site!";

 auth_basic_user_file /home/gerrit/gerrit_site/etc/passwords;

 location / {

 proxy_pass http://10.0.2.15:9091;

 }

 }
[root@Ubuntu]#sudo /etc/init.d/nginx start

5、 安装git

[root@Ubuntu]#  sudo apt-get install git

6、 安装git-review

[root@Ubuntu]#sudo apt-get install git-review

7、 安装gerrit

[root@Ubuntu]#useradd –m gerrit

切换用户gerrit

[root@Ubuntu]#su – gerrit

将gerrit安装包gerrit-2.11.3.war放在相应目录下,执行:

[gerrit@Ubuntu]$java -jar gerrit-2.11.3.war init -d ~/gerrit_site

安装gerrit

安装过程提示的配置项可在gerrit安装完成后在gerrit配置文件中进行配置。

8、 配置gerrit

[gerrit@Ubuntu]$cd /home/gerrit/gerrit_site/etc

[gerrit@Ubuntu]$vi gerrit.config

配置文件内容:

[gerrit]

 basePath = git

 canonicalWebUrl = http://10.0.2.15:9091/

[database]

 type = mysql

 hostname = localhost

 database = gerritdb

 username = gerrit

[index]

 type = LUCENE

[auth]

 type = HTTP

[sendemail]

 smtpServer = smtp.qq.com

 smtpServerPort = 465

 smtpEncryption = ssl

 smtpUser = xxx@qq.com

 smtpPass = xxxxxxxxxxxx

 sslVerify = false

 from = CodeReview<xxx@qq.com>

[container]

 user = gerrit

 javaHome = /usr/lib/jvm/java-8-oracle/jre

[sshd]

 listenAddress = *:29418

[httpd]

 listenUrl = proxy-http://10.0.2.15:9091

[cache]

 directory = cache

9、 启动gerrit

[gerrit@Ubuntu]$/home/gerrit/gerrit_site/bin/./gerrit.sh restart

10、 浏览器地址栏输入http://10.0.2.15:9095访问gerrit,弹出登录对话框

浏览器访问Gerrit

Gerrit搭建成功!

11、 gerrit添加用户

注意:第一次加-c参数是为了创建密码文件,默认第一个用户是系统管理员

[root@Ubuntu]#  htpasswd -c /home/gerrit/gerrit_site/etc/passwords gerrit

New password:

Re-type new password:

[root@Ubuntu]#htpasswd /home/gerrit/gerrit_site/etc/password jenkins5062

New password:

Re-type new password:

[root@Ubuntu]#htpasswd /home/gerrit/gerrit_site/etc/password jenkins

New password:

Re-type new password:

12、 登录gerrit并注册用户邮箱

1) 输入用户名密码,进入gerrit页面

输入用户名密码,进入gerrit页面

2) 打开My->Groups->Contact Information页面进行邮箱注册

用户邮箱注册

3)单击Register New Email按钮,在提示框内输入邮箱地址,进行注册

用户邮箱注册

3) 打开邮箱,查看验证邮件,打开验证链接,用户邮箱注册成功

用户邮箱注册成功

13、 生成用户公私钥并进行配置

1)切换到需要配置公私钥的用户,执行生成公私钥操作

[gerrit@Ubuntu]$ su - gerrit

[gerrit@Ubuntu]$ ssh-keygen -t rsa -C gerrit5062@163.com         //产生公私钥

 [gerrit@Ubuntu]$cat ~/.ssh/id_rsa.pub
获取用户公钥

2)使用用户账号登录gerrit系统,将公钥添加到用户的SSH Public keys

Gerrit添加用户SSH Public keys

一、Gitlab部署配置

1、 安装Gitlab

[root@Ubuntu] #sudo apt-get install -y curl openssh-server ca-certificates

[root@Ubuntu] #sudo apt-get install -y postfix

[root@Ubuntu]#curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ee/script.deb.sh | sudo bash

[root@Ubuntu] #sudo apt-get install gitlab-ee

[root@Ubuntu] #sudo gitlab-ctl reconfigure

2、 Gitlab配置

Gitlab配置信息位于/etc/gitlab/目录下的gitlab.rb文件,

[root@Ubuntu] #cd /etc/gitlab/

[root@Ubuntu] #vim gitlab.rb配置gitlab,相关配置如下:
Gitlab配置文件信息
Gitlab配置文件信息
Gitlab配置文件信息
Gitlab配置文件信息

配置完成后,重新启动gitlab

[root@Ubuntu] #sudo gitlab-ctl configure

3、 配置root用户密码,登录gitlab

1)终端执行

  [root@Ubuntu] #gitlab-rails console production

irb(main):001:0>u=User.where(id:1).first

u.password = 'secret_pass'

 >u.password_confirmation = 'secret_pass'

>u.save!

2)root登录gitlab

登录gitlab
登录gitlab

4) 添加用户,此处新增gerrit用户为管理员

新增gerrit用户为管理员

5) gerrit用户登录gitlab,添加SSH Public Keys

Gitlab添加用户gerrit SSH Public Keys

二、Jenkins部署配置

1、安装jenkins

[root@Ubuntu] #wget -q -O - https://pkg.jenkins.io/debian/jenkins-ci.org.key | sudo apt-key add -

[root@Ubuntu] #sudo sh -c 'echo deb http://pkg.jenkins.io/debian-stable binary/ > /etc/apt/sources.list.d/jenkins.list'

[root@Ubuntu] #sudo apt-get update

[root@Ubuntu] #sudo apt-get install Jenkins

2、jenkins默认端口为8080,为防止端口冲突,重新配置端口号为8082

[root@Ubuntu] #cd /etc/default

[root@Ubuntu] #vim Jenkins
修改Jenkins配置文件

4、 启动jenkins

[root@Ubuntu] #/etc/init.d/Jenkins start

5、 登录jenkins

1) 初始默认密码在/var/lib/Jenkins/secrets目录下的initialAdminPassword文件中

cat /var/lib/Jenkins/secrets/initialAdminPassword

登录后重新配置jenkins账号密码,默认管理员用户为jenkins。

2) 登录jenkins

Jenkins登陆页面
Jenkins首页

Jenkins搭建完成。

6、 jenkins系统配置

1) 进入Jenkins系统配置界面

Jenkins系统配置界面

Jenkins Location配置:

Jenkins Location配置

Email-Notification配置:

Email-Notification配置

2) 进入Jenkins插件管理界面

Jenkins插件管理

搜索选择(Available)需要安装的插件,(构建工具gradle,Gerrit事件触发器gerrit_trigger, 版本控制工具Git plugin)

Available可安装插件

构建工具(Gradle)实现项目的自动构建、自动测试、自动部署等功能。Gerrit事件触发器Gerrit_trigger监听Gerrit系统事件。版本控制工具(Git plugin)保证项目源码处于有序的管理中,方便开发人员随时获取和提交变更。

三、Gitlab与Gerrit集成

1、Gitlab项目设置

管理员用户在Gitlab系统新建开发组dev-group,新建项目user,将开发人员加入开发组并配置为reporter权限,reporter用户没有push权限,只能使用 git review 命令提交,而 git review 命令需要 .gitreview 文件存在于项目目录里。管理员gerrit用户添加.gitreview 文件

[root@Ubuntu] #su – gerrit

[gerrit@Ubuntu]$git clone [git@10.0.2.15:dev-group/user.git](mailto:git@10.0.2.15:dev-group/user.git)

[gerrit@Ubuntu]$cd user

[gerrit@Ubuntu]$ vim .gitreview
编辑.gitreview文件
编辑.gitreview文件

添加.gitreview到版本库

[gerrit@Ubuntu]$ git add .gitreview

[gerrit@Ubuntu]$ git config --global user.name 'gerrit'

[gerrit@Ubuntu]$git config --global user.email 'gerrit5062@163.com'

[gerrit@Ubuntu]$ git commit .gitreview -m 'add .gitreview file by gerrit.'

[gerrit@Ubuntu]$ git push origin master

项目目录下缺少.gitreview文件,开发人员git review时会报错:

No '.gitreview' file found in this repository. We don't know where

your gerrit is. Please manually create a remote named "gerrit" and try

again.

2、Gerrit设置项目

gitlab上的项目能在gerrit上review的话,必须在gerrit上创建相同的项目,并有相同的仓库文件,所以gerrit上的项目最好是从gitlab上git clone --bare过来,并且项目不要为空

1)clone --bare Gitlab上的仓库到 Gerrit

[gerrit@Ubuntu]$ cd /home/gerrit/gerrit_site/git/       

[gerrit@Ubuntu]$ git clone --bare git@10.0.2.15:dev-group/user.git  

2)同步 Gerrit的user项目到 Gitlab 上的user项目目录中

当用户git review后,代码通过 jenkins 测试、人工 review 后,代码只是 merge 到了 Gerrit 的user项目中,并没有 merge 到 Gitlab 的user项目中,所以需要当 Gerrit user项目仓库有变化时自动同步到 Gitlab 的 user项目仓库中。

Gerrit 自带一个 Replication 功能,同时我们在安装 Gerrit 时候默认安装了这个 Plugin。添加一个 replication.config 给 Gerrit

[gerrit@Ubuntu]$ cd /home/gerrit/gerrit_site/etc/

[gerrit@Ubuntu]$vim replication.config

[remote "user"]

projects =user

url = git@10.0.2.15:dev-group/user.git

push = +refs/heads/*:refs/heads/*

push = +refs/tags/*:refs/tags/*

push = +refs/changes/*:refs/changes/*

threads = 3
添加replication.config配置文件
添加replication.config配置文件

设置gerrit用户的 ~/.ssh/config

[gerrit@Ubuntu]$vim /home/gerrit/.ssh/config
 Host 10.0.2.15:

 IdentityFile ~/.ssh/id_rsa

 PreferredAuthentications publickey
添加配置用户config文件

在gerrit用户的~/.ssh/known_hosts 中,给10.0.2.15 添加 rsa 密钥

[gerrit@Ubuntu]$sh -c "ssh-keyscan -t rsa 10.0.2.15>> /home/gerrit/.ssh/known_hosts"

[gerrit@Ubuntu]$sh -c "ssh-keygen -H -f /home/gerrit/.ssh/known_hosts"

重新启动 Gerrit 服务 [gerrit@Ubuntu]$/home/gerrit/gerrit_site/bin/gerrit.sh restart

五、Gerrit与Jenkins集成

1、Gerrit配置时已经将jenkins配置为Gerrit用户,将jenkins用户的密钥添加到Gerrit

 [root@Ubuntu] #su – Jenkins

[jenkins@Ubuntu]$cat .ssh/id_rsa.pub
获取jenkins用户的公钥
获取jenkins用户的公钥

2、Jenkins项目设置

1)Jenkins新建项目user并完成相关配置

Jenkins新建项目user
配置user项目信息

配置jenkins连接Gerrit仓库

jenkins连接Gerrit仓库

选择监听Gerrit event

监听Gerrit event
监听Gerrit event

选择gradle构建项目

gradle构建
gradle构建

2、配置Gerrit_trigger plugin

1) Manage Jenkins->Gerrit Trigger进入配置界面

Gerrit Trigger配置

2)Add New Server

Add New Server

2) 填写配置信息并测试,Test Conection success,配置成功

Test Conection success

3、配置Gradle插件

1)Manage Jenkins->Global Tool Configuration,完成Gradle配置

配置Gradle插件
配置Gradle插件

六、测试(操作手册)

1、普通用户jenkins5062 从Gitlab或Gerrit系统将项目clone到本地进行编辑,修改代码后,不能直接push到代码中心 ,可以通过git review提交到gerrit上进行审核。gerrit相关审核员看到review信息后,判断是否通过,通过即Submit提交。

Gitlab代码库clone代码到本地进行编辑

[jenkins5062@Ubuntu]$ git clone [git@10.0.2.15:dev-group/user.git](mailto:git@10.0.2.15:dev-group/user.git)
Gitlab代码库clone代码到本地进行编辑

或者在Gerrit代码库clone代码到本地进行编辑,用户登录Gerrit->Project->General, 选中clone with commit-msg hook,选择SSH或HTTP,复制clone命令

Gitlab代码库clone代码到本地进行编辑
Gitlab代码库clone代码到本地进行编辑

2、项目编辑完成后提交审核

git add test

git commit –m “jenkins5062 change test”

git review
提交审核

如果开发者需要在Gerrit里保存一些需要较长时间完成的工作,可以使用

git review –D

命令进行提交,提交的代码将被Gerrit标记为Draft状态,Draft状态下的change只有提交者自己和被开发者添加的reviewer及项目管理员可以看到。处于draft状态的change一样可以添加reviewer。

如果开发者git review后需要在当前版本下继续修改,可在再次编辑文件后git commit时添加--amend参数,重新git review。

3、Gerrit进行代码审核

1)用户git review后,jenkins监听Gerrit events,对提交的代码进行构建

jenkins监听Gerrit events,对提交的代码进行构建
jenkins监听Gerrit events,对提交的代码进行构建

2)普通用户登录Gerrit进行审核,All->Open->Subject列表下列出提交的项目代码,代码已经过Jenkins自动测试(Verified +1)

普通用户登录Gerrit进行审核
普通用户登录Gerrit进行审核

Files->File Path->user/test查看代码变更的详细信息

查看代码变更的详细信息

3) 管理员登录Gerrit系统审核All->Open->Subject列表

管理员登录Gerrit系统审核
管理员登录Gerrit系统审核
管理员登录Gerrit系统审核

审核通过后Submit提交Gitlab并合并到主分支。当用户git review后,代码通过jenkins自动测试(verified)、人工review 后,代码只是merge到了Gerrit的项目中,并没有merge到 Gitlab的项目中,所以需要配置replication插件,当 Gerrit 项目仓库有变化时自动同步到Gitlab的项目仓库中。

管理员登录Gerrit系统审核

系统发送邮件,提醒jenkins5062用户代码已Submit并合并到Gitlab代码仓库

系统发送邮件,提醒jenkins5062用户代码已Submit并合并到Gitlab代码仓库

如果审核不通过

Reply...标记-2 ->Post

审核不通过
审核不通过

jenkins5062收到邮件提醒,代码未通过审核

jenkins5062收到邮件提醒,代码未通过审核
jenkins5062收到邮件提醒,代码未通过审核

4、登录Gitlab查看项目更新

登录Gitlab查看项目更新
登录Gitlab查看项目更新

Gitlab代码仓库已完成代码更新!

七、部署集成部分问题整理总结

1、找不到适配Ubuntu 32位版本的gitlab安装源,重装64位Ubuntu系统后,

gitlab正常安装

2、gitlab安装完成后,执行sudo gitlab-ctl reconfigure启动命令,

报错:


 Error executing action 'run' on resource 'bash[migrate

 gitlab-rails database]'

 LoadError:/opt/gitlab/embedded/lib/libre2.so.0: symbol _ZTVNSt7__

 cxx1119basic_sotringstreamIcSt11char_traitsIcESaIcEEE,version

 GLIBCXX_3.4.21 not defined in file libstdc++.so.6 with link time

 reference

原因:GCC版本太低,升级Ubuntu至 16.04LTS版本后完成部署

3、执行:ssh -p 29418 -i ~/.ssh/id_rsa 10.0.2.15 -l gerrit

报错:

Unable to negotiate with 192.168.1.101 port 29418: no matching key exchange method found. Their offer: diffie-hellman-group1-sha1

解决:修改~/.ssh/config,加入

Host *

 KexAlgorithms +diffie-hellman-group1-sha1

4、添加jenkins用户登录gerrit时报

500 Internal Server Error
nginx/1.10.3 (Ubuntu)错误,

执行 chmod 777 passswords修改/home/gerrit/gerrit_site/etc/passwords的权限,修改文件权限后gerrit恢复正常访问

5、用户从gerrit上将代码clone到本地时报错

Unable to negotiate with 10.0.2.15 port 29418: no matching key exchange method found. Their offer: diffie-hellman-group1-sha1

在.ssh/config文件中添加语句:

Host *

 KexAlgorithms +diffie-hellman-group1-sha1

6、gerrit安装报错:

Exception in thread "main" com.google.gwtorm.server.OrmException: Cannot apply SQL

ALTER TABLE changes ADD submission_id VARCHAR(255) BINARY

修改数据库设置,执行数据库设置语句:

set global explicit_defaults_for_timestamp=1;

7、nginx 报403 Forbidden错误

反向代理nginx /etc/nginx/conf.d/gerrit.conf 中 auth_basic_user_file /home/gerrit/gerrit_site/passwords;

路径错误,改为auth_basic_user_file /home/gerrit/gerrit_site/etc/passwords;

注意:IP配置问题,文件权限问题

8、gerrit用户注册邮箱发送验证连接失败

原因:

1). /etc/secure.config文件内没有配置的发送邮箱密码和gerrit.config中的密码不一致

解决方法:配置/etc/secure.config smtpPass同gerrit.config中的smtpPass的配置保持一致。

2). 网易smtp.163.com服务器问题,DT:SPM 发送的邮件内容包含了未被许可的信息,或被系统识别为垃圾邮件。

请检查是否有用户发送病毒或者垃圾邮件;发件邮箱更换为qq邮箱

9、1.git review 提交代码请求 可触发jenkins自动测试,自动测试通过代码被标记 Verified +1 后被提交gerrit进行审核,审核人员审核后通过后Review +2,Submit,修改后的代码未同步到gitlab。

解决:Gerrit安装配置replication 插件

10、jenkins build failure 构建错误,使用jenkins安装的gradle插件进行项目构建。