使用gerrit作为代码评审工具

需求描述

其实作为项目代码的maintainer,一直习惯于mailing list + git的代码评审及管理,无奈公司主推敏捷+devops,老板让改用gerrit。硬着头皮切换到gerrit,在这里记录下安装配置的过程及踩过的许多坑,以便网友们以后配置gerrit留作参考。

需求其实很简单,我们项目一直使用公司内部一个类似于github的代码托管网站来托管项目代码,使用邮件列表来评审代码。代码通过评审通过后,我再将patch push到代码托管服务器上去。整个开发流程如下图所示:

目前开发流程

现在需要切换到gerrit来作为代码评审工具,以便于能够和jenkins集成,搭建一个集开发、构建、测试、部署为一体的devops系统,结构如下图所示。本文只关注gerrit的搭建。

CI

Gerrit简介

安装步骤

1 . 安装Java.

网上有很多安装java的博客和文章,因此在这里不再赘述,可以参考下面这篇文章:

Linux下安装java

2 . 给Gerrit单独创建一个账户

#useradd gerrit
#passwd gerrit
#su gerrit

3 . 下载gerrit

gerrit是在google上托管的项目,翻墙下载比较麻烦,可以在这里下载2.11版本的gerrit:

百度网盘下载Gerrit

将网盘中的两个文件gerrit-2.11.war以及bcpkix-jdk15on-151.jar下载到gerrit用户的家目录/home/gerrit下。

4 . 按下面的步骤安装gerrit,其中的问题大部分可以敲回车选择默认设置。


[gerrit@linux ~]$ java -jar ./gerrit-2.11.war init -d gerrit 
    
//-d指定gerrit的安装目录

Using secure store: com.google.gerrit.server.securestore.DefaultSecureStore

*** Gerrit Code Review 2.11
*** 

Create '/home/gerrit/gerrit'   [Y/n]? y

*** Git Repositories
*** 

Location of Git repositories   [git]:  

*** SQL Database
*** 

Database server type           [h2]: 

*** Index
*** 

Type                           [LUCENE/?]: 

*** User Authentication
*** 

Authentication method          [OPENID/?]: http    //为了不依赖于openid我们这里要设置成http
Get username from custom HTTP header [y/N]? y
Username HTTP header           [SM_USER]: 
SSO logout URL                 : 

*** Review Labels
*** 

Install Verified label         [y/N]? 

*** Email Delivery
*** 

SMTP server hostname           [localhost]: 
SMTP server port               [(default)]: 
SMTP encryption                [NONE/?]: 
SMTP username                  : 

*** Container Process
*** 

Run as                         [gerrit]: 
Java runtime                   [/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.45-38.b14.fc21.x86_64/jre]: 
Copy gerrit-2.11.war to /home/gerrit/gerrit/bin/gerrit.war [Y/n]? 
Copying gerrit-2.11.war to /home/gerrit/gerrit/bin/gerrit.war

*** SSH Daemon
*** 

Listen on address              [*]: 
Listen on port                 [29418]: 

Gerrit Code Review is not shipped with Bouncy Castle Crypto SSL v151
  If available, Gerrit can take advantage of features
  in the library, but will also function without it.
Download and install it now [Y/n]? n  //选择n,因为这个文件已经下载好了,安装完手动拷贝进去就行
Generating SSH host key ... rsa(simple)... done

*** HTTP Daemon
*** 

Behind reverse proxy           [y/N]? y  //需要配置反向代理来满足http认证
Proxy uses SSL (https://)      [y/N]? N
Subdirectory on proxy server   [/]: 
Listen on address              [*]: 
Listen on port                 [8081]: 
Canonical URL                  [http://null/]: 

*** Plugins
*** 

Installing plugins.
Install plugin download-commands version v2.11 [y/N]? 
Install plugin reviewnotes version v2.11 [y/N]? 
Install plugin singleusergroup version v2.11 [y/N]? 
Install plugin replication version v2.11 [y/N]? 
Install plugin commit-message-length-validator version v2.11 [y/N]? 
Initializing plugins.
No plugins found with init steps.

Initialized /home/gerrit/gerrit
Executing /home/gerrit/gerrit/bin/gerrit.sh start
Starting Gerrit Code Review: OK

安装完成后需要将下载好的bcpkix-jdk15on-151.jar文件拷贝到安装目录中去:

cp bcpkix-jdk15on-151.jar /home/gerrit/gerrit/lib/bcpkix-jdk15on-151.jar

5 . 配置Apache反向代理

修改httpd的配置文件,在其末尾加入:

<VirtualHost *>
  ServerName gerrit.example.com

  ProxyRequests Off
  ProxyVia Off
  ProxyPreserveHost On

  <Proxy *>
    Order deny,allow
    Allow from all
  </Proxy>
  <Location /login/>
    AuthType Basic
    AuthName "Gerrit Code Review"
    AuthBasicProvider file
    AuthUserFile /home/gerrit/gerrit/etc/passwords
    Require valid-user
  </Location>
  ProxyPass / http://9.181.129.109:8081/
</VirtualHost>

需要将IP地址替换成你自己的IP.修改/etc/hosts,加入gerrit.example.com的解析:

9.181.129.109	gerrit.example.com

这里也需要替换IP地址。

6 . 创建管理员账户,Gerrit把第一个被创建的用户当做是管理员账户:

$htpassword /home/gerrit/gerrit/etc/passwords $username

$username替换成你要设置的用户名。

7 . 重启服务

$./gerrit/bin/gerrit.sh restart
$sudo service httpd restart

问题总结

1 . Could not open password file.

症状:web浏览器提示服务器端错误,查看httpd日志文件/var/log/httpd/error_log,发现如下错误信息:

Permission denied:......Could not open password file: /home/gerrit/gerrit/etc/passwords

原因:该问题是由于passwords文件的路径上权限设置阻挡了httpd的访问。 解决方法:将/home/gerrit目录及passwords文件的权限设置为755

$chmod 755 /home/gerrit
$chmod 755 /home/gerrit/gerrit/etc/passwords

2 . Proxy Error

症状:输入用户名和密码登陆后,web浏览器提示代理错误。

Proxy Error

The proxy server received an invalid response from an upstream server.
The proxy server could not handle the request GET /login/.

Reason: DNS lookup failure for: 9.181.129.109:8081login

原因:最后发现是httpd的配置文件中在ProxyPass一行的IP地址后少写了一个/

ProxyPass / http://9.181.129.109:8081
--->
ProxyPass / http://9.181.129.109:8081/

参考文献

1 . Gerrit官方文档 2 . Gerrit简易安装入门

基于Jenkins和Koji的代码管理及构建系统

<h1>Summary</h1>

Currently, we KVM team are maintaining the code repository of the virtualization software(such as QEMU, Libvirt, Kimchi, Linux, etc.) for PowerKVM development team and delivering corresponding RPM packages. We collect patches from mailing list and build update RPM packages every workday. The work load is extremely heavy if we manually download the patches from mailing list, apply them to the repository, and build RPM packages covering all the supported platforms.

This environment, based on Jenkins and Koji, can automatically manage the code(apply the patches from mailing lists to the appropriate repository and branch) and build the required RPM packages covering all supported platforms nightly or triggered manually. By using this automation environment, developers can easily get the updated RPM packages just by sending the patches to the given e-mail address or mailing list. Furthermore, the time cost for daily routine work is dramatically reduced and the quality of the packages will be improved by eliminating human errors. This environment also can be used to other projects by making few changes to configure files.

<h1>Challenges</h1>

In PowerKVM development, we have to ship all the significant bug fixes frequently, usually a couple days. All the fix patches of QEMU, Libvirt, Linux, Kimchi will be sent to a certain mailing list. After the code cut-off day, we download all the patches from the mailing list and manually apply them to different git repositories accordingly. Then copy all the git repositories to different platform(RHEL,Fedora,etc) and do build. Last step, copy all the output RPM packages to different RPM repositories accordingly. Sometimes, we can not deliver the packages on time because the workload is extremely heavy. Furthermore, errors occur frequently such as some patches may get lost during the process due to lack of time. In order to solve these problems, we decided to make use of Jenkins and Koji to establish the CI environment.

During the construction of this environment, we have to resolve the following problems:

  • Define the rules of sending patches for developers in order to make the CI know where the patches should go.
  • Define the regular expression to distinguish patches from other e-mails.
  • How to handle exceptions.

<h1>Experience</h1>

<1>. Tools and Framework Overview

In order to implement this automation environment, several tools are needed:

  • Jenkins: Jenkins is a software that monitors executions of repeated jobs. This automation environment use Jenkins as the user interface and the manager of all the underlying jobs.
  • Koji: Koji can build RPMs packages for multiple platforms. This automation environment make use of Koji to build RPMs for all supported platform.
  • Python scripts: implement the function that collect patches from mailing list, organize and archive these patches.
  • Shell scripts: Apply the patches to the appropriate git repositories, process build and release the output RPM packages via web server.
  • Apache HTTP server: Release the RPMs via web page. Below is the chart about the framework overview of this automation environment and the relationship among these tools.

Framework

<2>. User Interface

The automation environment runs nightly. However, if the developer want to get the RPM packages immediately, he or she can simply click the start button of Jenkins. See below chart.

User Interface

<3>. Execution flow

After the developers click the first run button, jenkins will call python scripts to collect emails matching certain regular expression(We advise developers send patches to mailing list in fixed forms, such as [branch_name PATCH repo_name]xxx) and archive all the patches by date. Then, Jenkins will call shell scripts to apply these patches to the appropriate git repositories. After that, Koji will be noticed to build the RPM packages of all the supported platforms. Finally, Jenkins will call the shell scripts to copy all the RPM packages to certain directory of Apache web server.

<4>. Handle exception

The automation environment will send report containing how many patches received and where the RPM packages are published to the mailing list if all the jobs are successfully executed. If a certain job failed, it also sends report to the mailing list or email boxes configured in the configuration file. Different job has different error report message. For example, when the job who collects patches from mailing list fails, it will send out the failed patches’ name, but when the job who builds RPM packages fails, it will send out the build log.

<h1>Benefit</h1>

For the repositories maintainers, this automation environment can save much time costs for their daily routing work. What they need to do is just check reports via email clients if this automation environment start to work. The time costs dramatically reduce from several hours to a few minutes.

For the developers, they can get the RPM packages by themselves whenever they want to build one, instead of asking the maintainers spend much time to build for them. What they need to do is simply click a button.

Furthermore, the quality of the RPM packages will be improved because this automation environment can eliminate human errors effectively.

<h1>Next Steps and Recommendations</h1>

Currently, this automation environment is just used for code management and RPM packages build. Since it can save much time cost for developers and repository maintainers, we are planing to involve test cases. We can make use of automation test technology and integrate the test cases into this automation environment. After that, test engineers will be set free from burdensome test work.