架設Gerrit Server : 架設本地AOSP Gerrit Server完整指引 PART1

前言

本文引導入如何從無至有,建立一個專屬自己的Gerrit伺服器 (Gerrit Server)

本文是系列文的第一篇,本系列在介紹如何建立本地自有 (localhost) Gerrit Server並且將AOSP (Android Open Source Project)的原始碼完整導入此Gerrit Server。

文章分為三個部份,本文是第一部份,教導如何架設Gerrit Server,如果你已經很熟悉這個工作,可以直接跳至第二或第三部份。

第一部份:架設Gerrit Server (本文)
第二部份:移轉整個AOSP至本地Gerrit Server
第三部份:如何從本地Gerrit Server建立一個AOSP Branch

真正利用Gerrit來確保Code的品質並且保留企業內部技術。
進行此AOSP導入工作的主要目的在於本人專業工作上需要修改AOSP原始碼以符合客製化的需求,但AOSP本身龐大的原始碼及代碼庫(Repository)不適合再導入公司內部原有已存在的Gerrit Server。於是乎,將AOSP導入一個新建的Gerrit Server成為一個合理的選擇。另外更重要的原因是,自身內部專案的AOSP原始碼必須能夠提供以下功能:

  • 進行Code Review,確保穩定性及紀錄留存以保留技術知識。
  • 同步Merge Android官方原始碼,確保官方修正的問題可以同步合入自身專案。

在完成本文系統的三篇文章中所述的任務之後,你應該可以:

  • 建立基本Gerrit Server的能力
  • 抓取AOSP並導入自有Gerrit Server的能力
  • 同步AOSP並且合入官方修改的原始碼的能力
  • 建立自身AOSP Branch並且修改及進行Code Review

本文在Ubuntu 18.04進行,基本上我在Ubuntu 16.04也執行過同樣任務,所以差別不大,所以你的系統是在Ubuntu 16.04,應該完全可以適用。

所需軟體

  • Gerrit (version 2.16.4)
  • Git
  • Open JDK 8
  • MySQL (非必要)
  • Gerrit Delete Project Plug-in (非必要,但很好用)

安裝及設定

因為Gerrit是以Java開發,而且AOSP也需要Java 8做為Java Compilter,我們首先安裝Open JDK 8。

安裝OpenJDK 8

Ubuntu 18.04 預載OpenJDK 11,但為了之後編譯(BUILD)AOSP,所以我們把Java環境設為OpenJDK 8。使用apt-get進行安裝。如果是在Ubuntu 16.04安裝,只要直接安裝OpenJDK 8應該就沒問題了。

sudo apt-get install openjdk-8-jdk
sudo update-alternatives --config java
There are 3 choices for the alternative java (providing /usr/bin/java).

  Selection    Path                                            Priority   Status
------------------------------------------------------------
  0            /usr/lib/jvm/java-11-openjdk-amd64/bin/java      1101      auto mode
  1            /usr/lib/jvm/java-11-openjdk-amd64/bin/java      1101      manual mode
 *2            /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java   1081      manual mode
  3            /usr/lib/jvm/java-8-oracle/jre/bin/java          1081      manual mode

Press  to keep the current choice[*], or type selection number: 2




安裝完成後,執行指令update-alternatives --config java,以選擇openjdk-8做為預設Java。
執行java -version,確認java版本為openjdk 8
java -version
openjdk version "1.8.0_191"
OpenJDK Runtime Environment (build 1.8.0_191-8u191-b12-0ubuntu0.18.04.1-b12)
OpenJDK 64-Bit Server VM (build 25.191-b12, mixed mode)

安裝Git

很簡單就直接用apt-get安裝
 sudo apt-get install git-all

安裝Gerrit Server

  • 安裝MySQL (若選擇使用H2,或是已有MySQL Server,則可跳過)
sudo apt-get install mysql-client   
sudo apt-get install mysql-server
sudo mysql_secure_installation #初始MySQL root密碼
Securing the MySQL server deployment.

Connecting to MySQL using a blank password.

VALIDATE PASSWORD PLUGIN can be used to test passwords
and improve security. It checks the strength of password
and allows the users to set only those passwords which are
secure enough. Would you like to setup VALIDATE PASSWORD plugin?

Press y|Y for Yes, any other key for No: Y

There are three levels of password validation policy:

LOW    Length >= 8
MEDIUM Length >= 8, numeric, mixed case, and special characters
STRONG Length >= 8, numeric, mixed case, special characters and dictionary                  file

Please enter 0 = LOW, 1 = MEDIUM and 2 = STRONG: 0
Please set the password for root here.

New password: 

Re-enter new password:
sudo mysql
mysql> ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';

將MySQL Root密碼設為password
安裝MySQL完成後,加入Linux User--gerrit
  • 首先新增一個Linux使用者gerrit,以方便管理

sudo adduser --system --shell /bin/bash --gecos 'Gerrit server owner' --group --disabled-password --home /home/gerrit gerrit


  • 設定MySQL

mysql -u root -p
CREATE USER 'gerrit'@'localhost' IDENTIFIED BY 'Gerrit1234';
CREATE DATABASE reviewdb;
ALTER DATABASE reviewdb charset=latin1;
GRANT ALL ON reviewdb.* TO 'gerrit'@'localhost';
FLUSH PRIVILEGES;
quit
sudo su gerrit #切換至gerrit
cd #將目錄轉換至/home/gerrit
將gerrit加入MySQL,並初始database,完成後sudo su轉至gerrit user (gerrit@localhost的MySQL密碼為Gerrit1234,可自行替換) 修改MySQL sql_mode
sudoedit /etc/mysql/mysql.conf.d/mysqld.cnf

在mysqld.cnf中的[mysqld]下,加入
sql_mode = "ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
若少了本行,則Gerrit在初始化Database時會發生錯誤。

本文使用的是v2.16.4,下載後的檔案為gerrit-2.16.4.war (可以直接下指令:wget https://gerrit-releases.storage.googleapis.com/gerrit-2.16.4.war 取得本文gerrit版本)

我們在gerrit的家目錄下建立兩個目錄,名稱任取(當然也可以把目錄建在其他gerrit user可以存取的任何目錄),一個目錄是Gerrit Server Site,另一個是存放Git Repository的地方。Git Repository導入AOSP後至少有100 Gbytes,所以要確保磁碟空間夠大
本文把Gerrit server目錄建立在/home/gerrit/aosp_review_site,把Git Respository建在/home/gerrit/aosp_git

mkdir aosp_review_site
mkdir aosp_git
  • 至此可以開始安裝Gerrit
java -jar gerrit-2.16.4.war init -d ~/aosp_review_site
...
Location of Git repositories   [git]: /home/gerrit/aosp_git
Database server type           [h2]: mysql
...
gerrit's password              : 
              confirm password :
...
Canonical URL                  [http://localhost:8080/]: http://10.50.100.56:8080/


安裝的過程有很多問答,大部份回預設值(直接按Enter),只有以上列出的部份根據本身的需求做改變。像是我自己安裝的Gerrit Server在10.50.100.56,這個值你是一定要改掉的。Location of Git repositories是指你的Git Repository的目錄,我指定在aosp_git目錄下。Database server type在本文使用MySQL而不是預設的h2。


  • 啟動Gerrit

進行第一次啟動,執行以下指令
~/aosp_review_site/bin/gerrit.sh start
Starting Gerrit Code Review: WARNING: Could not adjust Gerrit's process for the kernel's out-of-memory killer.

         This may be caused by /home/gerrit/aosp_review_site/bin/gerrit.sh not being run as root.

         Consider changing the OOM score adjustment manually for Gerrit's PID= with e.g.:

         echo '-1000' | sudo tee /proc//oom_score_adj
OK
在Gerrit Server安裝目錄下有個bin目錄,執行gerrit.sh start則啟動gerrit。啟動時的WARNING可以先無視。之後把gerrit的啟動交給root就可以解決了。
開啟Browser,輸入安裝的Server的位址及埠http://10.50.100.56:8080,若看到此畫面,則成功安裝Gerrit。
驗證Gerrit Service成功啟動
安裝成功後的Gerrit Web UI畫面(尚未登入)

右上角有個Sign in,點擊登入,在Gerrit Server的設計,第一位登入者即是管理員Administrator


  • 首次登入
本文是使用OpenID做為授權(Authentication)依據,所以之前我就在LaunchPad Net註冊一個帳號。
使用OpenID做為Gerrit Account授權認證
Gerrit登入畫面,本文使用Launchpad ID

按下Sign in with a Launchpad ID後,登入,成為管理員 如果還沒有LaunchPad帳號,去https://launchpad.net/註冊一個,快速,簡單!

登入成功後,首先是先把自己的username加入。因為我們用OpenID登入,一開始是沒有username。這會造成後續的command line: ssh -p29418 xxx@host gerrit之類型式的命令無法使用,所以必須先設好username。設定好之後就不能改了,所以必須考慮清楚。
設定username的地方先點擊在右上角的齒輪icon(就是Settings),然後在username輸入,在本例中,輸入的是jeremychen。
你可以看出,輸入後就不能改了。

設定Gerrit帳號名稱
設定使用者帳號,設定後不能再改!

再來就是加入SSH Key
此時我們登入另一個PC做為Gerrit Client,由該PC經由網路連結至Gerrit Server。(如果沒有另一台Linux可試就直接在localhost建立一個帳號來試) 首先檢查你的家目錄~/.ssh目錄下是否已有SSH public key,如果沒有就必須以下列命令產生。

ssh-keygen -t rsa -C "yourname@yourmail.com"
Generating public/private rsa key pair.
Enter file in which to save the key (/home/jeremychen/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/jeremychen/.ssh/id_rsa.
Your public key has been saved in /home/jeremychen/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:+/NFKhFBTmgNj4FQgBllFYCbA4hjIlMYdK8OeXuvxNU yourname@yourmail.com
The key's randomart image is:
+---[RSA 2048]----+
|==oB**+oo=+      |
|X.=.. . o*..     |
|++ o . .. +      |
|  = .   .  .     |
| o +   .SE.   .  |
|  + o .  . . o   |
|   o +  . . . .  |
|    o .  ... .   |
|     ...  .o.    |
+----[SHA256]-----+

cat ~/.ssh/id_rsa.pub 
ssh-rsa 2EAAAADAQABAAABAQD53E9s9sSKaZ2RRok9i/UmYCBkTBENM73emUHxNOdPcHKQNUMtvVVq2J2IWfyUrc+vyFemu
...CITPjYRbWJZAyVfsY0q9hQvNTjVxYSrSyKif yourname@yourmail.com

注意:email的前綴名稱最好和你的gerrit account相同,例如你的gerrit account名稱是foo,那email最好是foo@...,在gerrit上並沒有這樣的要求,但往後會用到的repo命令,在這一點上是有要求的。

在Gerrit Web上將cat出的id_rsa.pub內容複製貼上至Settings(右上角齒輪)->SSH Keys,貼至“New SSH key”欄位中
將SSH Key加入Gerrit 帳號
在Gerrit Server中,加入SSH Key

最後按下 “ADD NEW SSH KEY” 後,即完成加入SSH Key。
完成後利用命令列進行測試。

ssh -p 29418 jeremychen@10.50.100.56
The authenticity of host '[10.50.100.56]:29418 ([10.50.100.56]:29418)' can't be established.
ECDSA key fingerprint is SHA256:FBtsyexuskBOcPsRkjUq9STYXd7a2q9SVQbDii8Q2WI.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '[10.50.100.56]:29418' (ECDSA) to the list of known hosts.

  ****    Welcome to Gerrit Code Review    ****

  Hi Jeremy Chen, you have successfully connected over SSH.

  Unfortunately, interactive shells are disabled.
  To clone a hosted Git repository, use:

  git clone ssh://jeremychen@10.50.100.56:29418/REPOSITORY_NAME.git

有Welcome的訊息就代表SSH key加入成功,可以遠端直接下命令。若失敗則會有Connection refused的錯誤訊息。此時可能是email不合或其他連線原因。

在推送整個AOSP之前,我們先初始建立一個Project,測試是否可以成功建立並進行Code Review。
  • 建立第一個Project
其實在Gerrit 2.16版之後在UI上已經沒有 『Project』 這個名詞了,而是一律使用Repository來表示一個代碼庫的概念。不過Project仍是對大多數有用過Gerrit code review的人而言,對“Project”這個名詞仍是比較熟悉的,而且在gerrit命令集也是用gerrit create-project之類的方式來稱呼。所以本文仍用建立Project來描述這個工作。
在Browser->Repository下,可以在右上角看見“CREATE NEW"。點擊!
新增Gerrit Repository (Project)
建立第一個Repository (或稱Project)

Project名稱是test-project,Owner是目前唯一個用戶,就是管理者jeremychen,按CREATE後第一個Project完成建立。
  • 第一個Code Review
在Gerrit Client中的test-project,建立並推送push第一個檔案main.cpp至Gerrit Server進行Review。首先從Gerrit Server取出Project (此時為空Project,只含一個.git目錄)。流程都是按照官方指令
https://gerrit-review.googlesource.com/Documentation/intro-gerrit-walkthrough.html

git clone ssh://jeremychen@10.50.100.56:29418/test-project
Cloning into 'test-project'...
remote: Counting objects: 2, done
remote: Finding sources: 100% (2/2)
remote: Total 2 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (2/2), done.
cd test-project
scp -p -P29418 jeremychen@10.50.100.56:hooks/commit-msg .git/hooks/
chmod u+x .git/hooks/commit-msg
commit-msg                                                                                        100% 1392     1.4MB/s   00:00    
git remote -v
origin ssh://jeremychen@10.50.100.56:29418/test-project (fetch)
origin ssh://jeremychen@10.50.100.56:29418/test-project (push)

建立第一個檔案main.cpp,並推送至Gerrit Server

touch main.cpp #建立第一個檔案
echo -e "#include \n\nint main(int argc, char**argv){\n\treturn 0;\n};\n" > main.cpp #加入原始碼
git status 
On branch master
Your branch is up to date with 'origin/master'.

Untracked files:
  (use "git add ..." to include in what will be committed)

 main.cpp

git add main.cpp
git commit -m"Test: first code review" main.cpp
[master 1b12406] Test: first code review
 1 file changed, 6 insertions(+)
 create mode 100644 main.cpp
git push origin HEAD:refs/for/master#上傳至Gerrit Server進行Code Review
Counting objects: 3, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 326 bytes | 326.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
remote: Processing changes: refs: 1, new: 1, done    
remote: 
remote: SUCCESS
remote: 
remote: New Changes: 

在Gerrit Website中,點選Changes->Open即可看到第一個Code Review!
測試Gerrit Code Review
第一個Code Review代碼審視
點擊進入後,就可以將Code推入Git Repository (當然你也可以Abandon它!)

安裝delete-project Plug-in

在前期測試時delete-project的Gerrit Plug-in是很重要的,尤其是下一篇會導入整個AOSP的時候,一有差錯則可能需要手動把不小心導入的數百個Projects慢慢刪掉。所以我們需要一個可以方便刪除Project的工具,而測試Gerrit Server時建立的的第一個Project,test-project,當然是會刪除的標的!
自行Build出Plug-in是滿麻煩的,直接拿Prebuilt的JAR檔來安裝即可,除非你是要去修改功能或要開發新的Plug-in,否則實在不需要從原始代碼開始Build起。
Prebuilt版本的下載處:https://gerrit-ci.gerritforge.com/job/plugin-delete-project-bazel-stable-2.16/
複製 delete-project.jar的連結位址後

ssh -p 29418 jeremychen@10.50.100.56 gerrit plugin install -n delete-project.jar https://gerrit-ci.gerritforge.com/job/plugin-delete-project-bazel-stable-2.16/lastSuccessfulBuild/artifact/bazel-genfiles/plugins/delete-project/delete-project.jar

如果發生錯誤訊息:fatal: remote plugin administration is disabled 表示你由遠端安裝Plug-in,此時有兩個方法(1)回到Gerrit Server本地安裝 (2)在gerrit.conf中加入新的Section
[plugins]
    allowRemoteAdmin = true
加入要重新啟動Gerrit Server,在Gerrit Server下: /home/gerrit/aosp_review_site/bin/gerrit.sh restart
完成重啟後再把上述安裝Plug-in的命令執行一次即可。
回到Gerrit Website,在Browse->Repository下選test-project。在左側點選Command,即可看到命令列中多出一個DELETE PROJECT的命令。(如果沒看到有可能是Browser Cache,按F5重刷一次!)
Gerrit Delete Project插件
Gerrit Delete Project插件

執行Delete Project時務必小心,因為一不小心之前累積的Knowledge就付諸流水了。我想這也是Gerrit沒有把Delete Project這麼平常不過的功能實作出來的主因吧!如果Gerrit Server正式上線後,我也是建議把此功能先Disable掉,否則悲劇隨時可能發生!
按下「 DELETE PROJECT」之後會再確認一次,按下Delete把Project刪除!

如此我們就有一個乾淨的Gerrit Server來進入第二個部份:PART2 移轉整個AOSP至本地Gerrit Server

留言

  1. 請問能分享 delete-project-v2.16版的jar嗎? 目前都抓不到了 而且自己build一值fail
    感謝

    回覆刪除
    回覆
    1. 找到替代網站了 感謝
      https://archiva.wikimedia.org/repository/releases/com/googlesource/gerrit/plugins/delete-project/2.16.16/

      刪除

張貼留言

這個網誌中的熱門文章

完整指引如何編譯AOSP (Build Android P),整合GMS及刷機 (Pixel 2)

將AOSP加入Gerrit Server : 架設本地AOSP Gerrit Server完整指引 PART2