CI 持续集成系统环境 --Gitlab+Gerrit+Jenkins 完整对接

近年来,由于开源项目、社区的活跃热度大增,进而引来持续集成(CI)系统的诞生,也越发的听到更多的人在说协同开发、敏捷开发、迭代开发、持续集成和单元测试这些拉风的术语。然而,大都是仅仅听到在说而已,国内也很少有公司能有完整的 CI 体系流程。反之一些开源项目都有完整的 CI 体系,比如 openstack。
为了实现代码托管 -> 代码审核 -> 代码发布的一套自动化流程,我特意在 IDC 服务器上部署了 Gitlab+Gerrit+Jenkins 对接环境,以下记录了操作过程:

整体的架构图如下:

1)Gitlab 上进行代码托管
在 gitlab 上创建的项目设置成 Private,普通用户对这个项目就只有 pull 权限,不能直接进行 push,Git 自带 code review 功能。
强制 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 部署在两台机器上,这样 gitlab 既可以托管 gerrit 代码,也可以作为 gerrit 的备份。
因为 gitlab 和 gerrit 做了同步,gerrit 上的代码会同步到 gitlab 上。
这样即使 gerrit 部署机出现故障,它里面的代码也不会丢失,可以去 gitlab 上拿。
2)Gerrit 审核代码
Gerrit 是一款被 Android 开源项目广泛采用的 code review(代码审核) 系统。普通用户将 gitlab 里的项目 clone 到本地,修改代码后,虽不能直接 push 到代码中心 ,但是可以通过 git review 提交到 gerrit 上进行审核。gerrit 相关审核员看到 review 信息后,判断是否通过,通过即 commit 提交。然后,gerrit 代码会和 gitlab 完成同步。
grrit 的精髓在于不允许直接将本地修改同步到远程仓库。客户机必须先 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 环境完整记录
CI 持续集成系统环境 --- 部署 Gitlab 环境完整记录
CI 持续集成系统环境 --- 部署 Jenkins 完整记录

二、Gitlab+Gerrit+Jenkins 的对接

1)Gitlab 配置

gitlab 上的管理员账号是 gerrit,邮箱是 gerrit@xqshijie.cn
创建了一个普通账号 wangshibo,邮箱是 wangshibo@xqshijie.cn

[root@115]# su - gerrit  
[gerrit@115 ~]$ ssh-keygen -t rsa -C gerrit@xqshijie.cn         //产生公私钥  
[gerrit@115 ~]$ cat ~/.ssh/id_rsa.pub  

将上面 gerrit 账号的公钥内容更新到 Gitlab 上。
使用 gerrit 账号登陆 Gitlab,点击页面右上角的 Profile Settings - 点击左侧的 SSH Keys 小钥匙图标 - 点击 Add SSH Key。
在 Key 对应的输入框中输入上段落 $cat .ssh/id_rsa.pub 显示的公钥全文,点击 Title,应该会自动填充为 gerrit@xqshijie.cn。如下:

在 Gitlab 上创建 wangshibo 用户
然后在机器上生成 wangshibo 公钥(先提前在机器上创建 wangshibo 用户,跟上面一样操作),然后将公钥内容更新到 Gitlab 上(用 wangshibo 账号登陆 Gitlab)
用 gerrit 登陆 Gitlab,新建 group 组为 dev-group,然后创建新项目 test-project1(在 dev-group 组下,即项目的 Namespace 为 dev-group,将 wangshibo 用户添加到 dev-group 组内,权限为 Reporter),具体如下截图:

创建的项目设置成 Private 即私有的,这样普通用户这它就只有 pull 权限,没有 push 权限。

在 test-project1 工程里创建文件,创建过程此处省略......
文件创建后,如下:

在 linux 系统上登录 wangshibo 账号下,克隆工程 test-project1.git,测试权限

[root@115]# su - wangshibo  
[wangshibo@115 ~]$ git clone git@103.10.86.30:dev-group/test-project1.git  
Initialized empty Git repository in /home/wangshibo/test-project1/.git/  
remote: Counting objects: 15, done.  
remote: Compressing objects: 100% (9/9), done.  
remote: Total 15 (delta 0), reused 0 (delta 0)  
Receiving objects: 100% (15/15), done.  
[wangshibo@115 ~]$ cd ~/test-project1/  
[wangshibo@115 ~]$ git config --global user.name 'wangshibo'  
[wangshibo@115 ~]$ git config --global user.email 'wangshibo@xqshijie.cn'  
[wangshibo@115 ~]$ touch testfile  
[wangshibo@115 ~]$ git add testfile  
[wangshibo@115 ~]$ git commit -m 'wangshibo add testfile'  
[wangshibo@115 ~]$git push  
GitLab: You are not allowed to push code to this project.  
fatal: The remote end hung up unexpectedly

上面有报错,因为普通用户没有直接 push 的权限。需要先 review 到 gerrit 上进行审核并 commit 后,才能更新到代码中心仓库里。

2)Gerrit 配置

在 linux 服务器上切换到 gerrit 账号下生成公私钥

[gerrit@115]$ ssh-keygen -t rsa -C gerrit@xqshijie.cn

将 id_rsa.pub 公钥内容更新到 gerrit 上(管理员 gerrit 账号登陆)的 SSH Public Keys 里

同样的,将 gerrit 的其他两个普通账号 wangshibo 和 jenkins 也在 linux 服务器上生产公私钥,邮箱分别是 wangshibo@xqshijie.cn 和 jenkins@xqshijie.cn
并将两者的公钥 id_rsa.pub 内容分别更新到各自登陆的 gerrit 的 SSH Public Keys 里

3)Jenkins 配置

Jenkins 系统已经创建了管理员账户 jenkins 并安装了 Gerrit Trigger 插件和 Git plugin 插件
在“系统管理”->“插件管理 "->”可选插件"-> 搜索上面两个插件进行安装
使用 jenkins 账号登陆 jenkins,进行 Jenkins 系统的 SMTP 设置 (根据具体情况配置)
“主页面 -> 系统管理 -> 系统设置”,具体设置如下:
首先管理员邮件地址设置成 jenkins@xqshijie.cn

设置 SMTP 的服务器地址,点击“高级”

jenkins@xqshijie.cn 的密码要确认填对,然后测试邮件发送功能,如果如下出现 successfully,就成功了! 点击“保存”

接下来设置 Gerrit Trigger

Add New Server : Check4Gerrit
勾选 Gerrit Server With Default Configurations

具体设置如下:
设置好之后,点击“Test Connection”,如果测试连接出现如下的 Success,即表示连接成功!
点击左下方的 Save 保存。

如果上一步在点击“Test Connection”测试的时候,出现下面报错:
解决办法:
管理员登录 gerrit
Projects->List->All-Projects
Projects->Access
Global Capabilities->Stream Events 点击 Non-Interactive Users
添加 Jenkins@zjc.com 用户到 ‘Non-Interactive Users’ 组

4)Gerrit 和 Jenkins 整合

让 Gerrit 支持 Jenkins
如果安装 Gerrit 时没有或者没有选择添加 Verified 标签功能 [‘lable Verified’],需要自己添加。
如下是手动添加 Verified 标签功能的设置(由于我在安装 Gerrit 的时候已经选择安装 Verified 标签功能了,所以下面橙色字体安装操作可省略)
[如果在安装 gerrit 的时候没有选择安装这个标签功能,就需要在此处手动安装下。具体可以登陆 gerrit,ProjectS->list->All-Projects->Access->Edit->Add Permission 看里面是否有 Verfied 的选项]

# su - gerrit  
$ git init cfg; cd cfg  
$ git config --global user.name 'gerrit'  
$ git config --global user.email 'gerrit@xqshijie.cn'  
$ git remote add origin ssh://gerrit@103.10.86.30:29418/All-Projects  
$ git pull origin refs/meta/config  
$ vim project.config  
[label "Verified"]  
    function = MaxWithBlock  
    value = -1 Fails  
    value = 0 No score  
    value = +1 Verified  
$ git commit -a -m 'Updated permissions'  
$ git push origin HEAD:refs/meta/config  
$ rm -rf cfg

用 gerrit 管理员账号登录 Gerrit
现在提交的 Review 请求只有 Code Rivew 审核,我们要求的是需要 Jenkins 的 Verified 和 Code Review 双重保障,在 Projects 的 Access 栏里,针对 Reference: refs/heads/ 项添加 Verified 功能,如下如下:
Projects -> List -> All-Projects
Projects -> Access -> Edit -> 找到 Reference: refs/heads/* 项 -> Add Permission -> Label Verified -> Group Name 里输入 Non-Interactive Users -> 回车 或者 点击 Add 按钮 -> 在最下面点击 Save Changes 保存更改。
( 注意:提前把 jenkins 用户添加到 Non-Interactive Users 组内)
权限修改结果如下:

截图如下:

添加 Verified 后的权限如下

Gitlab 上设置 test-project1 工程
前面我们在 Gitlab 上搭建了一个 test-project1 的工程,普通用户是没有办法去 push 的,只能使用 git review 命令提交. 而 git review 命令需要 .gitreview 文件存在于项目目录里。
用 gerrit 用户添加.gitreview 文件

[root@115]# su - gerrit  
[gerrit@115]$ git clone git@103.10.86.30:dev-group/test-project1.git  
[gerrit@115]$ cd test-project1  
[gerrit@115]$ vim .gitreview
[gerrit]
host=103.10.86.30
port=29418
project=test -project1.git

添加.gitreview 到版本库

[gerrit@115]$git add .gitreview  
[gerrit@115]$git config --global user.name 'gerrit'  
[gerrit@115]$git config --global user.email 'gerrit@xqshijie.cn'  
[gerrit@115]$git commit .gitreview -m 'add .gitreview file by gerrit.'  
[gerrit@115]$git push origin master

用 gerrit 用户添加.testr.conf 文件
Python 代码我使用了 testr,需要先安装 testr 命令

[root@115]# easy_install pip  
[root@115]# pip install testrepository

在 test-project1 这个项目中添加 .testr.conf 文件

[root@115]#su - gerrit  
[gerrit@115]$cd test-project1  
[gerrit@115]$vim .testr.conf
[DEFAULT]
test_command=OS_STDOUT_CAPTURE=1
OS_STDERR_CAPTURE=1
OS_TEST_TIMEOUT=60
${PYTHON:-python} -m subunit.run discover -t ./ ./ $LISTOPT $IDOPTION
test_id_option=--load-list $IDFILE
test_list_option=-list

提交到版本库中

[gerrit@115]$git add .testr.conf  
[gerrit@115]$git commit .testr.conf -m 'add .testr.conf file by gerrit'  
[gerrit@115]$git push origin master

Gerrit 上设置 test-project1 工程
在 Gerrit 上创建 test-project1 项目
要知道 review 是在 gerrit 上,而 gerrit 上现在是没有项目的,想让 gitlab 上的项目能在 gerrit 上 review 的话,必须在 gerrit 上创建相同的项目,并有相同的仓库文件.
用 gerrit 用户在 Gerrit 上创建 test-project1 项目

[root@115]# su - gerrit  
[gerrit@115]$ ssh-gerrit gerrit create-project test-project1 (gerrit环境部署篇里已经设置好的别名,方便连接gerrit)  

登陆 gerrit 界面,发现 test-project1 工程已经创建了。(这种方式创建的项目是空的)

clone --bare Gitlab 上的仓库到 Gerrit (gerrit 上的项目最好是从 gitlab 上 git clone --bare 过来,并且项目不要为空)
因为 gerrit 用户无访问 gitlab 的权限。所以要先看是否 gerrit 用户下已经存在了 id_rsa 密钥,如果没有则创建,然后把公钥加入到 gitlab 的管理员账户上(因为后面 Gerrit 系统还会有个复制 git 库到 Gitlab 的功能需要管理员权限)(这个测试环境,gitlab 和 gerrit 的管理员我用的都是 gerrit,所以秘钥也是共用)

[gerrit@115]$ cd /home/gerrit/gerrit_site/git/            //即登陆到gerrit安装目录的git下  
[gerrit@115 git]$ rm -fr test-project1.git  
[gerrit@115 git]$ git clone --bare git@103.10.86.30:dev-group/test-project1.git             //创建并将远程gitlab上的这个项目内容发布到gerrit上  
[gerrit@115 git]$ ls  
All-Projects.git test-project1.git  
[gerrit@115 git]$ cd test-project1.git/  
[gerrit@115 git]$ ls                                 //即test-project1工程和gerrit里默认的All-Projects.git工程结构是一样的了  
branches config description HEAD hooks info objects packed-refs refs

同步 Gerrit 的 test-project1 项目到 Gitlab 上的 test-project1 项目目录中
当用户 git review 后,代码通过 jenkins 测试、人工 review 后,代码只是 merge 到了 Gerrit 的 test-project1 项目中,并没有 merge 到 Gitlab 的 test-project1 项目中,所以需要当 Gerrit test-project1 项目仓库有变化时自动同步到 Gitlab 的 test-project1 项目仓库中。
Gerrit 自带一个 Replication 功能,同时我们在安装 Gerrit 时候默认安装了这个 Plugin。

现在只需要添加一个 replication.config 给 Gerrit

[gerrit@115]$ cd /home/gerrit/gerrit_site/etc/  
[gerrit@115]$ vim replication.config
[remote "test-project1"]
projects = test-project1
url = git@103.10.86.30:dev-group/test-project1.git
push = +refs/heads/*:refs/heads/*
push = +refs/tags/*:refs/tags/*
push = +refs/changes/*:refs/changes/*
threads = 3

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

[gerrit@115]$ vim /home/gerrit/.ssh/config
Host 103.10.86.30:
IdentityFile ~/.ssh/id_rsa
PreferredAuthentications publickey

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

[gerrit@115]$ sh -c "ssh-keyscan -t rsa 103.10.86.30 >> /home/gerrit/.ssh/known_hosts"  
[gerrit@115]$ sh -c "ssh-keygen -H -f /home/gerrit/.ssh/known_hosts"  

上面设置的 ~/.ssh/config 文件的权限已定要设置成 600
不然会报错:“Bad owner or permissions on .ssh/config“

重新启动 Gerrit 服务

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

Gerrit 的复制功能配置完毕
在 gerrit 文档中有一个 ${name} 变量用来复制 Gerrit 的所有项目,这里并不需要。如果有多个项目需要复制,则在 replication.config 中添加多个 [remote ….] 字段即可。务必按照上面步骤配置复制功能。

在 Jenkins 上对 test-project1 项目创建构建任务
Jenkins 上首先安装 git 插件:Git Plugin
登陆 jenkins,“系统管理”->“管理插件”->“可选插件”-> 选择 Git Pluin 插件进行安装

Jenkins 上创建项目
添加 test-project1 工程

下面添加 url:http://103.10.86.30:8080/p/test-project1.git
添加分支:origin/$GERRIT_BRANCH

如下:

构建 Excute Shell,添加如下脚本

cd $WORKSPACE  
[ ! -e .testrepository ] && testr init 

testr run

测试
linux 系统上用 wangshibo 账号提交一个更改
用 wangshibo 登录
删除目录 test-project1
克隆 test-project1 工程
进入 test-project1 目录
添加文件、提交
git review 增加 review 到 Gerrit

[root@115]# su - wangshibo  
[wangshibo@115]$ rm -rf test-project1/  
[wangshibo@115]$ git clone git@103.10.86.30:dev-group/test-project1.git  
[wangshibo@115]$ cd test-project1/  
[wangshibo@115]$ touch testfile  
[wangshibo@115]$ git add testfile  
[wangshibo@115]$ git commit -m "wangshibo add this testfile"

[wangshibo@115]$ **git review**                        //提交review代码审核请求  
The authenticity of host '[103.10.86.30]:29418 ([103.10.86.30]:29418)' can't be established.  
RSA key fingerprint is 83:ff:31:e8:68:66:6d:49:29:08:91:aa:ef:36:77:3e.  
Are you sure you want to continue connecting (yes/no)? yes  
Creating a git remote called "gerrit" that maps to:  
ssh://wangshibo@103.10.86.30:29418/test-project1.git  
Your change was committed before the commit hook was installed  
Amending the commit to add a gerrit change id  
remote: Resolving deltas: 100% (1/1)  
remote: Processing changes: new: 1, refs: 1, done  
To ssh://wangshibo@103.10.86.30:29418/test-project1.git  
* [new branch] HEAD -> refs/publish/master  

安装 git-review

[root@115]# git clone git://github.com/facebook/git-review.git  
[root@115]# cd git-review  
[root@115]# python setup.py install  
[root@115]# pip install git-review==1.21  
[root@115]# yum install readline-devel  

代码审核处理
用 gerrit 管理员账号登录 Gerrit ,点击 "All“->”Open“-> 打开提交的 review
打开后就能看见 jenkins 用户已经 Verified【原因下面会提到】。
然后点击 Review 进行审核

由于上面已经配置了 gerrit 跟 jenkins 的对接工作,所以当 git review 命令一执行,jenkins 上的 test-project1 工程的测试任务就会自动触发
如下:如果任务自动执行成功了,就说明 jenkins 测试通过,然后 jenkins 会利用 ssh 连接 gerrit 并给提交的 subject 打上 verified 信息校验结果,然后审核人员再进行 review。

所以用 gerrit 管理员登陆后发现,jenkins 已经通过了 Verified。然后进入 subject,先查看代码 / 文件变更,然后点击 Reply, 写一点 review 后的意见之类的,然后评分(+2 通过,-2 拒绝,+1 投赞成票,-1 投反对票),然后点击 post。

注意:
等到 jenkins 上 Verified 通过后,即看到下图右下角出现“Verified +1 jenkins" 后
才能点击 "Code-Review+2", 如下:

然后点击“Submit",提交审核过的代码

再次查看,review 请求已被审核处理,并且已经 Merged 合并了!

最后登录 Gitlab 查看 test-project1 工程,可以看到新增加文件操作已经同步过来了

注意:在审核人员进行 review 和 submit 操作前,要先等到 jenkins 测试并通过 ssh 方式连上 gerrit 给相应提交审核的 subjects 带上 Verified 通过后才能进行。(gitlab+gerrit+jenkins 环境配置后,提交到 gerrit 上审核的 subjects 的 review 人员中会默认第一个是 jenkins,jenkins 有结果并 verified 后,其他人员才能 veriew 和 submit。也就是说当开发人员使用 git review 上报 gerrit 进行 code review 后,jenkins 会自动触发测试任务,通过后会在 gerrit 的 subject 审核界面显示 verified 结果,当显示的结果是“verified +1 jenkins“后就可以进行 Review 和 submit 了,最后同步到 gitlab 中心仓库。)

查看同步日志:
可以在 gerrit 服务器上查看 replication 日志:

[gerrit@115 logs]$ pwd  
/home/gerrit/gerrit_site/logs  
[gerrit@115 logs]$ cat replication_log  
.........................  
[2016-07-14 15:30:13,043] [237da7bf] Replication to git@103.10.86.30:dev-group/test-project1.git completed in 1288 ms  
[2016-07-14 15:32:29,358] [] scheduling replication test-project1:refs/heads/master => git@103.10.86.30:dev-group/test-project1.git  
[2016-07-14 15:32:29,360] [] scheduled test-project1:refs/heads/master => [03b983c0] push git@103.10.86.30:dev-group/test-project1.git to run after 15s  
[2016-07-14 15:32:44,360] [03b983c0] Replication to git@103.10.86.30:dev-group/test-project1.git started...  
[2016-07-14 15:32:44,363] [03b983c0] Push to git@103.10.86.30:dev-group/test-project1.git references: [RemoteRefUpdate[remoteName=refs/heads/master, NOT_ATTEMPTED, (null)...dda55b52b5e5f78e2332ea2ffcb7317120347baa, srcRef=refs/heads/master, forceUpdate, message=null]]  
[2016-07-14 15:32:48,019] [03b983c0] Replication to git@103.10.86.30:dev-group/test-project1.git completed in 3658 ms

关于 jenkins 上的结果:
如上,在服务器上 wangshibo 账号下
git review 命令一执行,即代码审核只要一提出,Jenkins 就会自动获取提交信息并判断是否 verified
如下,当 jenkins 上之前创建的工程 test-project1 执行成功后,那么 jenkins 对提交到 gerrit 上的 review 请求
就会自动执行 Verified(如上)

有个发现:
jenkins 上测试并返回给 gerrit 上提交的 subject 打上 Verified 信息核实通过的标签后,会将代码拿到自己本地相应工程的 workspace 目录下
这里的 jenkins 代码路径是:/usr/local/tomcat7/webapps/jenkins/workspace/test-project1

不过值得注意的是,jenkins 拿过来的代码只是每次 git review 修改前的代码状态
可以把这个当做每次代码修改提交前的备份状态
即:代码修改后,在 gerrit 里面审核,commit 后同步到 gitlab,修改前的代码状态存放在 jenkins 里面

手动安装 gerrit 插件

[gerrit@115r ~]$ pwd  
/home/gerrit  
[gerrit@115r ~]$ ls  
gerrit-2.11.3.war gerrit_site

进行插件安装,下面安装了四个插件

[gerrit@115r ~]$ java -jar gerrit-2.11.3.war init -d gerrit_site --batch --install-plugin replication  
Initialized /home/gerrit/gerrit_site  
[gerrit@115r ~]$ java -jar gerrit-2.11.3.war init -d gerrit_site --batch --install-plugin reviewnotes  
Initialized /home/gerrit/gerrit_site  
[gerrit@115r ~]$ java -jar gerrit-2.11.3.war init -d gerrit_site --batch --install-plugin commit-message-length-validator  
Initialized /home/gerrit/gerrit_site  
[gerrit@115r ~]$ java -jar gerrit-2.11.3.war init -d gerrit_site --batch --install-plugin download-commands  
Initialized /home/gerrit/gerrit_site

查看 plugins 目录,发现已经有插件了

[gerrit@115r ~]$ cd gerrit_site/plugins/  
[gerrit@115r ~]$ ls  
commit-message-length-validator.jar download-commands.jar replication.jar reviewnotes.jar

查看安装了哪些插件

[gerrit@115r ~]$ ssh-gerrit gerrit plugin ls

Name                                    Version                Status                 File  
-------------------------------------------------------------------------------  
commit-message-length-validator v2.11.3 ENABLED commit-message-length-validator.jar  
download-commands v2.11.3 ENABLED download-commands.jar  
replication v2.11.3 ENABLED replication.jar  
reviewnotes v2.11.3 ENABLED reviewnotes.jar

或者登陆 gerrit 也可查看

gerrit 手动同步代码到 gitlab 中心仓库上

[gerrit@115r ~]$ ssh-gerrit gerrit --help          //查看帮助,发现gerrit COMMAND --help可查找命令帮忙  
[gerrit@115r ~]$ ssh-gerrit replication start --help          //查看replication同步命令的用法

replication start [PATTERN ...] [--] [--all] [--help (-h)] [--url PATTERN] [--wait]

PATTERN : project name pattern  
-- : end of options  
--all : push all known projects  
--help (-h) : display this help text  
--url PATTERN : pattern to match URL on  
--wait : wait for replication to finish before exiting

  
[gerrit@115r ~]$ ssh-gerrit replication start --all                    //同步所有工程  

重载 replication 的同步服务

[gerrit@115r ~]$ ssh-gerrit gerrit plugin reload replication 

如果报错:fatal: remote plugin administration is disabled

解决办法:
在 /home/gerrit/gerrit_site/etc/gerrit.config 文件里添加下面内容:

[plugins]  
allowRemoteAdmin = true

然后重启 gerrit 服务即可:

[gerrit@115r ~]$ /home/gerrit/gerrit_site/bin/gerrit.sh restart  
Stopping Gerrit Code Review: OK  
Starting Gerrit Code Review: OK

ssh-gerrit 是别名

[gerrit@115r ~]$ cat ~/.bashrc  
# .bashrc

# Source global definitions  
if [ -f /etc/bashrc ]; then  
. /etc/bashrc  
fi  
alias ssh-gerrit='ssh -p 29418 -i ~/.ssh/id_rsa 103.10.86.30 -l gerrit'  
# User specific aliases and functions  

多个工程在 Gitlab 上可以放在不同的 group 下进行管理
如下面两个工程(多个工程,就在后面追加配置就行)

dev-group /test-project1  
app/xqsj_android

多个工程的 replication

[gerrit@Zabbix-server etc]$ cat replication.config

[remote "test-project1"]

projects = test-project1

url = git@103.10.86.30:dev-group/test-project1.git

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

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

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

threads = 3

[remote "xqsj_android"]

projects = xqsj_android

url = git@103.10.86.30:app/xqsj_android.git

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

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

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

threads = 3

然后在每个代码库里添加.gitreview 和.testr.conf 文件,
注意.gitreview 文件里的项目名称

按照上面同步配置后,Gerrit 里面的代码就会自动同步到 Gitlab 上,包括 master 分支和其他分支都会自动同步的。
如果,自动同步失效或者有问题的话,可以尝试手动同步(下面有提到)

另外:为了减少错误,建议在配置的时候,gitlab 和 gerrit 里的账号设置成一样的,共用账号 / 邮箱 / 公钥
gerrit 默认的两个 project:All-Project 和 All-Users 绝不能删除!!

去掉 jenkins 测试的方式

如果 gerrit 不跟 jenkins 结合,不通过 jenkins 测试并返回 verified 核实的方式,可以采用下面的代码审核流程(必须先对提交的审核信息进行 verified 核实,然后再进行代码的 review 审核,最后 submit 提交):
[去掉上面 gerrit 和 jenkins 对接设置,即关闭 jenkins 服务(关停对应的 tomcat 应用),gerrit 的 access 授权项 verified 里删除“Group Non-Interactive Users”(在这个组内踢出 jenkins 用户),并删除 gerrit 上的 jenkins 用户]

1)上传代码者(自己先 verified 核实,然后通知审核者审核)
修改代码,验证后提交到 Gerrit 上。
代码提交后登陆 Gerrit,自己检查代码(重点看缩进格式跟原文件是否一致;去掉红色空格部分;修改内容是否正确;命名是否有意义;注释内容是否符合要求等)。
自己检查没问题后,点 “Reply”按钮,在“Verified”中 +1,在“Code Review”中 +1,并点“Post“
在”Reviewer”栏中,点击”Add" 添加审核者 [如果不添加审核者,上传者自己也可以审核并完成提交。注意:只有 Review 是+2 的时候,才能出现 submit 的提交按钮]
如果代码审核没有通过,请重复步骤 1,2,3。

流程截图:
代码提交后,上传者自行登陆 gerrit,找到提交的 subject,点击 "Reply"

2)审核者
收到邮件通知后登陆 Gerrit,审核代码。
如果审核通过,点 “Reply”按钮,在“Verified”中 +1,在“Code Review”中 +2,并点“Post”,最后点击“Submit“提交!
如果代码审核没有通过,点 “Review”按钮,在“Code Review”中 -2,写好评论后,点“Post”。

流程截图:
如上,subject 的 owner 添加审核者后,审核者登陆 gerrit 进行 review
点击“Reply"

这样,就完成了一个代码的审核全部过程!
登陆 gitlab,就会发现 gerrit 上审核通过并提交后的代码已经同步过来了!

注意:
如上的设置,在 gerrit 里授权的时候:
Revified 权限列表里添加“Project Owners“(-1 和 +1)和审核者组(-1 和+1)
Review 权限列表里添加“Project Owners“和审核者组(都要设置-2 和+2)

附授权截图:

让非管理员用户也有 gitweb 访问权限

发现在 gerrit 与 gitweb 集成后,默认情况下,只有 gerrit 的管理员才有 gitweb 的访问权限,普通用户点击 gitweb 链接显示 404 错误。
最后发现使用 gitweb 需要有【refs/】下所有的 read 权限和【refs/meta/config】的 read 权限!
默认情况下:
【refs/
】下的 read 权限授予对象是:Administrators 和 Anonymous Users(所有用户都是匿名用户,这个范围很大,已默认包括所有用户)

【refs/meta/config】的 read 权限授予对象是:Administrators 和 Project Owners
如想要比如上面的 xqsh-app 组内的用户能正常访问 gitweb,那么就在【refs/meta/config】分支下授予这个组的 Allow 权限即可!!
截图如下:

使用普通用户 wangshibo(在 xqsj-app 组内)登陆 gerrit,发现能打开 xqsj_android 项目的 gitweb 超链接访问了

后续应开发人员的要求:Gitlab+gerrit+jenkins 环境下,gerrit 有几个细节,都是需要设置好的:
1)项目 A 的开发人员对于除 A 以外的项目没有访问权限;
2)每个开发人员应该有 +2 和 submit,以及创建分支的权限;
3)给 teamleader 配置 force push 的权限;

设置方案:
第 1 个要求:
在 gerrit 里面设置 read 权限,即 "refs/*" 下的 "Read" 权限。
先保持将 All-Projects 默认权限不变!
然后重新 Edit 项目 A 的权限去覆盖掉 All-Projects 继承过来的这个权限(下面会提到)
如下截图(前面的 Exclusive 一定要打勾,覆盖效果才能生效)

其实,开发人员是没有必要开通 gitlab 账号!只要 gerrit 提前和 gitlab 做好同步对接工作,那么直接设置好 gerrit 权限,开发人员可直接通过 ssh 方式登陆 gerrit 进行代码操作(git clone 代码,然后修改,提交审核,自动同步等)所以,只需要给开发人员开通 gerrit 账号即可!
< 如下,通过 ssh 方式连接 gerrit 上的项目,进行 git clone 代码或 git pull 操作等 >
如下:
按照 gerrit 上的 ssh 连接方式 clone 项目代码(前提是把本地服务器的公钥上传到 gerrit 上)
可以复制下图中的 clone 或 clone with commit-msg hook 地址在本地进行代码 clone

第 2 个要求:
a)在 gerrit 里面设置,创建组比如 xqsj-app,然后把这个组添加到 gerrit 界面相对应项目的”access“授权里的“refs/heads/*”->Label Code-Review 内,以及 Submit 内,这样就保证每个开发人员有+2 和 submit 权限
b)将上面创建的 xqsh-app 组添加到 gerrit 界面相对应项目的”access“授权里的“refs/heads/*”->“Create Reference”内,这样就能保证每个开发人员有创建分支的权限了。

第 3 个要求:
创建 teamleader 组,比如 xqsj-app-teamleader,将这个组添加到 A 项目编辑的下面两个权限里,去覆盖从 All-Projects 继承过来的权限!
“refs/heads/*”->"Push"
“refs/meta/config”->“Push”
这两个地方地 Push 权限最好只赋给 Administrators 管理员和 teamleader 组,这样就保证了每个 teamleader 有 force push 的权限了。
(注意,勾上在后面的“force push”前的小框,如下截图)
这样,xqsj-app-teamleader 组内的用户通过 ssh 方式连接 gerrit,git clone 下载代码,修改后可直接 git push 了(不需要 review 审核)

在这里还讲一下下面 /refs/for/refs/* 的两个 Push 权限,这个 All-Projects 里默认是赋予 Registered Users 注册用户的
那么,在给项目新编辑权限去覆盖的时候,最好把权限赋予对象改成项目所在的组!
(如上面所说的,修改代码 push 的中心仓库的权限就只关联到上面两个权限,跟这个无关)

如下:
将 wangshibo 用户拉到 xqsj-app-teamleader 组内,上面已经设置了“Force Push”权限,所以 wangshibo 用户连接 gerrit
修改后的代码可直接 push 了!然后同步到 gitlab!

[wangshibo@115 ~]$ git clone ssh://wangshibo@103.10.86.30:29418/xqsj_android  
Initialized empty Git repository in /home/wangshibo/www/xqsj_android/.git/  
remote: Counting objects: 653, done  
remote: Finding sources: 100% (653/653)  
remote: Total 653 (delta 180), reused 653 (delta 180)  
Receiving objects: 100% (653/653), 2.86 MiB, done.  
Resolving deltas: 100% (180/180), done.  
[wangshibo@Zabbix-server www]$ ls  
xqsj_android  
[wangshibo@115 ~]$ cd xqsj_android/  
[wangshibo@115 ~]$ vim testfile                  //修改代码  
[wangshibo@115 ~]$ git add testfile  
[wangshibo@115 ~]$ git commit -m "222"  
[master 87a02b7] 222  
1 files changed, 1 insertions(+), 0 deletions(-)  
[wangshibo@115 ~]$ git push             //直接push即可!如果wangshibo不在teamleader组内,就不能直接push了,就只能git review审核了!  
Counting objects: 5, done.  
Delta compression using up to 32 threads.  
Compressing objects: 100% (2/2), done.  
Writing objects: 100% (3/3), 261 bytes, done.  
Total 3 (delta 1), reused 0 (delta 0)  
remote: Resolving deltas: 100% (1/1)  
remote: Processing changes: refs: 1, done  
To ssh://wangshibo@103.10.86.30:29418/xqsj_android  
1840a0c..87a02b7 master -> master

这样,一个项目的开发人员在修改代码并提交 gerrit 后,就可以指定有相应权限的人员进行 review 和 submit 了。
另外注意:
修改 gerrit 上创建的 group 组名或增删等操作,可以直接在服务器上的 mysql 里面操作。

如果要想让新建立的项目不继承或不完全继承 All-Project 项目权限,可以自己重新修改或添加权限,以便去覆盖掉不想继承的权限!
这里以我测试环境的一个项目 xqsj_android 做个例子说明:

首先在 gerrit 上创建一个组 xqsj_android,将 wangshibo 普通用户放到这个组内!
1)想要 wangshibo 登陆 gerrit 后,只能访问它所在的项目 xqsj_android
设置方法:
上面已讲到,即将 All-Projects 的 access 里的 "refs/*"-"Read" 权限只给 Administors(就只保留管理员的这个 read 权限),这样,project 工程就只有管理员权限才能访问到了!
< 因为其他新建的项目默认都是继承 All-Projects 权限的,设置上面的 Read 权限只保留 Administors 后,其他的项目如果不 Edit 自己的权限去覆盖继承过来的权限,那么这些项目内的用户登陆后,都访问不了这些项目的 >

然后再在 xqsj_android 项目上创建 Reference 权限,去覆盖继承过来的 All-Project 权限!
特别注意下面的“Exclusive”,这个一定要勾上!!勾上了才能生效,才能覆盖 All-Project 项目的权限。
截图如下:

如上截图,发现“refs/*”的“Read”权限除给了管理员 Administrators,也添加了 xqsj_android 组,由于 wangshibo 在这个组内,
所以 wangshibo 登陆 gerrit 后,有访问 xqsj_android 项目的权限。

注意:
All-Projects 默认的权限最好都保持不变,不要动!
新建项目有的权限可以自行 Edit 编辑,然后去覆盖 All-Projects 继承过来的权限(新建的 Reference 时,后面的 Exclusive 一定要在前面的小方框内打上勾,这样覆盖才能生效!)

下面贴一下本人线上的 gerrit 项目修改后的权限:

git clone 下载代码,可以根据 gitlab 上的 ssh 方式克隆,也可以根据 gerrit 上的 ssh 方式克隆代码。
具体采用哪种,根据自己的需要判断。

注意:当审核未通过打回时,我们再修改完成之后,执行:

git add 文件名  
git commit --amend ##注意会保留上次的 change-id ,不会生成新的评审任务编号,重用原有的任务编号,将该提交转换为老评审任务的新补丁集  
git review  

如果想让某个用户只有读权限,没有写权限。即登陆 gerrit 后只能查看,不能进行下载,上传提交等操作
解决:
1)创建一个 read 的用户组,然后将这个只读用户拉到这个 read 组内

2)在相应项目的 access 授权里添加这个用户组,如下,只需添加下面两个地方的 Read 部分即可:
其中,“refs/meta/config”里的 Read 授权,可以让用户查看到 gitlab

添加 tag 权限
如上,已经给 teamleader 用户组内的用户授权直接 push 了,但是后面发现 teamleader 里的用户只能直接 push 推送代码到 gerrit 里,
而不能直接 push 推送 tag 标签到 gerrit 里!
这是因为上面的 push 权限是针对“refs/heads/”和“refs/meta/config”设置的
而 push tag 需要针对“refs/tags/
”进行设置
所以,需要添加 refs/tags/* 部分的设置,并给与 push 权限,如下:

gerrit 完整迁移
将远程 gerrit 上的代码迁移到本地新的 gerrit 上
要求:
远程 gerrit 里的代码分支和提交记录都要迁移过来,【即 Git 仓库迁移而不丢失 log】(push 的时候使用 --mirrot 镜像方式即可)
流程:
1)将远程 gerrit 的项目比如 A 进行 git clone –bare 克隆裸版本库到本地
2)在本地新的 gerrit 上创建同名项目 A(创建空仓库)
3)然后将克隆过来的 A 项目内容 git push --mirror 到本地新 gerrit 上的项目 A 内
git push --mirror git@gitcafe.com/username/newproject.git (新 gerrit 上项目 A 的访问地址)
这种方式就能保证分支和提交记录都能完整迁移过来了!!!

后续对项目代码进行操作,在登陆 gerrit 审核后,查看代码(对比代码提交前后的内容)时候出现了一个错误,具体如下:
其实代码 review 通过并 submit 后,查看代码有两种方式:
1)通过项目的 gitweb 查看。当然,这种方法查看也比较繁琐,没有下面的第(2)种方法查看起来方便

2)通过 submit 提交后的界面(也就是 merged 合并后的界面),如下点击红色方框内的审核代码进行查看:

但是点击上面红色方框内的审核代码进行查看,出现如下报错:

经过排查,发现造成这个报错的原因是由于 nginx 的反代配置有误造成的,如下:
proxy_pass http://103.10.86.30:8080/;
需要将上面的反向代理改为:
proxy_pass http://103.10.86.30:8080;
也就是说代理后的 url 后面不能加 "/",这个细节在前期配置的时候没有注意啊!!

gerrit.conf 最后完整配置如下:

[root@localhost vhosts]# pwd

/usr/local/nginx/conf/vhosts

[root@localhost vhosts]# cat gerrit.conf

server {

listen 80;

server_name localhost;

 

#charset koi8-r;

    #access_log  /var/log/nginx/log/host.access.log  main;

location / {

          auth_basic "Gerrit Code Review";

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

          proxy_pass              http://103.10.86.30:8080;

          proxy_set_header        X-Forwarded-For $remote_addr;

          proxy_set_header        Host $host;

    }

}

[root@localhost vhosts]# /usr/local/nginx/sbin/nginx -s reload

对比代码在 review 前后的状态:修改了哪些内容(右边部分是 review 修改后的代码状态。点击右边 "Patch Set 1" 后面的图标,可以下载或修改代码)

以上部署环境中,有一个不安全的地方,就是用户提交代码后,自己对代码都有 review 最终审核权限,即 "用户自己 review 提交审核 - 自己 +1/+2 审核 - 自己 submit",这样设计不是很合理!
现在做下调整:
用户自己 review 提交代码后,自己只有 Code-Review +2 的权限和 Submit,Verfied +1 的权限统一交由专门的审核人员去处理,比如 teamleader 组。
这样,代码审核的过程:
1)用户自己 review 提交代码审核
2)teamleader 组内人员收到审核后,通过 Verfied +1 审核
3) 用户自己通过 Code-Review +2 审核
4)用户自己 Submit 提交,Merged 合并处理。
具体的权限设置调整如下:

有一个问题:
如果给某个账号开了 push 权限,他在代码 commit 提交后,就可以直接 git push 上传到 gerrit 里面,可以不经过 git review 审核提交的代码。如下授权截图:

但是这样直接 git push 的话,在 gerrit 界面的 Merged 处就追踪不到这个账号提交代码的记录了,也就是说,只有经过 review 审核提交的代码记录才能在 gerrit 界面的 Merged 下追踪到! 如下:

如上所说,那么直接 push 提交代码的记录该怎么追踪到呢?
莫慌!
其实不管是 push 直接提交代码的记录,还是经过 review 审核提交的代码记录,都可以在 gitweb 的 log 里追踪到的!

虽然授权了 push 权限,但是也还是可以使用 git review 命令进行审核的,这样在 gerrit 界面的 Merged 里也能追踪到提交记录了。
如果是直接 git push 的,那么提交代码的时候就会直接绕过 review 审核了,这样当然不会在 gerrit 的 Merged 里留有记录。

到此!
gerrit 环境部署及其中遇到的一些问题,权限设置等已经收录完成,希望对有用到 gerrit 的朋友们有所帮助!!