Gerrit 是一个免费、开源的 Code Review 软件,允许开发者通过 Web 界面审阅代码,使用 Git 作为底层的版本控制系统,支持私有化部署、权限控制,以及通过插件进行扩展。
它本身是为管理 Android 代码而出现,最早是用 Python2.7 + Django(fork of Rietveld) 编写,在 2.0 版本之后改用 Java 来写,目前的稳定版本是 3.6.1 版本(2022.06.28 Release),前端使用 Ploymer Web UI,兼容 Java 17 LTS。
快速上手
在本地开发环境通过源码编译搭建 gerrit 服务来熟悉功能,需要 Java 11 以上版本和 Bazel 构建工具。
代码仓库:gerrit.googlesource.com/gerrit | 国内镜像(下载加速)
# MacOS 通过 brew 安装依赖,其他系统按照对应方式安装即可
brew install bazel
brew install java11
# 获取源代码
# --recurse-submodules 下载所有依赖的子模块代码到本地
git clone --recurse-submodules https://gitee.com/mirrors/Gerrit
# 本地编译
cd gerrit && bazel build release
# 如果切换分支或者更新代码之后,运行下面的命令后再重新编译
git submodule update
git clean -ffd
编译成功后,在 ./bazel-bin 目录下可以看到二进制包 release.war , 在本地新建一个测试站点:
# 指定测试站点的目录位置
export GERRIT_SITE=~/gerrit_testsite
# 进行站点初始化
# --batch 默认的 gerrit 基础配置
# --dev 默认的 Auth 选项为 DEVELOPMENT_BECOME_ANY_ACCOUNT
$(bazel info output_base)/external/local_jdk/bin/java \
-jar bazel-bin/release.war init --batch --dev -d $GERRIT_SITE
# 或者不初始化站点,直接启动:
$(bazel info output_base)/external/local_jdk/bin/java \
-jar bazel-bin/release.war daemon -d $GERRIT_SITE \
--console-log
前端开发说明:https://gerrit.googlesource.com/gerrit/+/master/polygerrit-ui/README.md
生产环境部署(Linux Server)
首先要确定生产环境 JRE(1.8 or 11) 没问题,把下载或本地编译好的 war 包上传到服务器。
新建 gerrit 用户
sudo adduser gerrit && sudo su gerrit
部署并启动服务
# add to shell profile,比如:.bashrc or .zshrc
export GERRIT_SITE=/path/to/your/gerrit_application_directory
# 初始化站点到指定目录, 确保 gerrit 用户对该目录有正确的读写权限
java -jar gerrit.war init -d $GERRIT_SITE
站点初始化过程需要你提供一些基础的配置信息,存储在 $GERRIT_SITE/etc/gerrit.config, 示例:
# $GERRIT_SITE/etc/gerrit.config
[gerrit]
basePath = git
defaultBranch = refs/heads/main
canonicalWebUrl = https://code.phab.xyz
serverId = d9b542af-259c-4a49-ae81-852d0b62b7c4
[container]
javaOptions = "-Dflogger.backend_factory=com.google.common.flogger.backend.log4j.Log4jBackendFactory#getInstance"
javaOptions = "-Dflogger.logging_context=com.google.gerrit.server.logging.LoggingContext#getInstance"
user = gerrit
javaHome = /usr/local/btjdk/jdk17
[index]
type = lucene
[auth]
type = openid
[oauth]
allowRegisterNewEmail = true
allowEditFullName = true
[receive]
enableSignedPush = true
[sendemail]
smtpServer = smtpdm.aliyun.com
smtpServerPort = 465
smtpEncryption = SSL
smtpUser =
[sshd]
listenAddress = *:29418
[httpd]
listenUrl = proxy-https://127.0.0.1:8081
[cache]
directory = cache
如配置文件中所示,gerrit 会监听 8081 的端口(根据自己需求修改),在 WebServer 中配置反向代理:
# 以 Nginx 为示例:
server {
...
# HTTP反向代理相关配置开始 >>>
location ~ /purge(/.*) {
proxy_cache_purge cache_one 127.0.0.1$request_uri$is_args$args;
}
location / {
proxy_pass http://127.0.0.1:8081;
proxy_set_header Host 127.0.0.1:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header REMOTE-HOST $remote_addr;
add_header X-Cache $upstream_cache_status;
proxy_set_header X-Host $host:$server_port;
proxy_set_header X-Scheme $scheme;
proxy_connect_timeout 30s;
proxy_read_timeout 86400s;
proxy_send_timeout 30s;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
# HTTP反向代理相关配置结束 <<<
...
}
对服务进行管理
cd $GERRIT_SITE
./bin/gerrit.sh start # 启动
./bin/gerrit.sh stop # 停止
./bin/gerrit.sh status # 状态检查, etd.
将服务加入到系统自启动任务
vim $GERRIT_SITE/bin/gerrit.sh
# To get the service to restart correctly on reboot, uncomment below (3 lines):
# ========================
# chkconfig: 3 99 99
# description: Gerrit Code Review
# processname: gerrit
# ========================
sudo ln -snf $GERRIT_SITE/bin/gerrit.sh /etc/init.d/gerrit
sudo ln -snf /etc/init.d/gerrit /etc/rc3.d/S90gerrit
使用 Docker 镜像快速安装
Docker images of Gerrit are available on DockerHub
# To run a CentOS 8 based Gerrit image:
# Last released package of the version is installed if the release number is omitted.
docker run -p 8080:8080 gerritcodereview/gerrit[:version]-centos8
# To run a Ubuntu 20.04 based Gerrit image:
docker run -p 8080:8080 gerritcodereview/gerrit[:version]-ubuntu20
站点访问:http://{youer-server-ip}:8080
站点配置及个性化
配置文件的位置: $GERRIT_SITE/etc/gerrit.config , 下面是部分配置项说明:
[gerrit]
basePath = git # 所有 git 仓库存储的基础路径(相对路径)
defaultBranch = # 项目创建时的默认分支,默认是 refs/heads/master
canonicalWebUrl = # 自定义域名
cdnPath = # Path prefix for Gerrit's static resources if using a CDN.
[accounts]
visibility = ALL # 账号之间的可见权限控制,ALL | SMAE_GROUP | VISIABLE_GROUP | NONE
defaultDisplayName = FULL_NAME # FULL_NAME | USERNAME | FIRST_NAME
[auth]
type = HTTP # 账号的登录方式配置,比如可以增加 OAUTH、SSO、LDAP 的支持
[aouth]
allowRegisterNewEmail # additional email addresses can be registered
allowEditFullName = # the full name can be edited in the contact information.
[cache]
directory = cache # Gerrit 缓存目录配置(相对路径),持久化为 H2 databases 文件
h2CacheSize = 250m # in-memory cache for each opened H2 cache database
[capability]
administrateServer = group Fail Safe Admins # 管理员用户组配置
makeFirstUserAdmin = true # 是否将第一个用户设置为管理员,默认为 true
[change]
allowBlame = true # 是否在 diff 代码时,显示追责按钮
disablePrivateChanges # 是否允许创建私有 Change
enableAssignee = false # 是否允许在界面上进行 指派(Assign) 功能
[httpd] # 使用 Nginx or Apache Web Server 进行反向代理
listenUrl = proxy-http://127.0.0.1:8081
[container]
heapLimit = 512m # Maximum heap size of the Java process running Gerrit
javaHome = # Path of the JRE/JDK installation to run Gerrit with.
javaOptions = # Additional options to pass along to the Java runtime.
[sendemail] # SMTP 邮件发送配置
smtpServer =
smtpServerPort = 465
smtpEncryption = SSL
smtpUser =
更多配置:https://gerrit-documentation.storage.googleapis.com/Documentation/3.5.0.1/config-gerrit.html
重新加载配置文件或重启服务,运行下面的命令:
$GERRIT_SITE/bin/gerrit.sh reload config
$GERRIT_SITE/bin/gerrit.sh restart
网站样式定制
在 GERRIT_SITE 目录中创建或者修改定制 theme 文件,可以在登录页面生效:
- etc/GerritSiteHeader.html
- etc/GerritSiteFooter.html
- etc/GerritSite.css
- 静态资源位置:static/
例如,可以在 GerritSiteFooter.html 中增加 Google Analytics 站点统计代码:
<div>
<!-- standard analytics code -->
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
var pageTracker = _gat._getTracker("UA-nnnnnnn-n");
pageTracker._trackPageview();
</script>
be <!-- /standard analytics code -->
<script type="text/javascript">
window.onload = function() {
var p = window.location.pathname;
Gerrit.on('history', function (s) {
pageTracker._trackPageview(p + '/' + s)
});
};
</script>
</div>
参考资料