搭建安卓原始碼伺服器,repo+gerrit+git環境,程式碼稽核

weixin_33890499發表於2018-08-04

安裝ubuntu-14.04.5-server-amd64

我司使用的是Dell伺服器,做好啟動U盤,使用工具rufus-usb。
Dell伺服器的介面與普通PC不同,不過基本原理是一樣的,BIOS設定為UEFI。
開機時按F11,進入BootManager,選擇啟動項,其中有啟動U盤的啟動項,確認後即可開始安裝。
為方便使用,安裝的語言選擇為中文。
分割槽使用了整個磁碟,將原來的系統刪除。

安裝gitolite伺服器

Gitolite介紹

Gittolite是基於git搭建一箇中央程式碼伺服器,有以下特點:

  • 支援多個使用者,多個倉庫
  • 支援多個層次的許可權控制,支援到倉庫的branch和tag的許可權訪問
  • ssh安全訪問協議
  • 不需要http伺服器等其他依賴,更少的資源佔用
  • 簡單、靈活的管理

Gitolite安裝成功後會建立一個名為gitolite-admin的特殊倉庫,這個倉庫裡面管理著Gitolite的配置檔案,在這些配置檔案中可以新增刪除使用者、倉庫,也可以定義一些許可權控制規則。

認證與授權

Gitolite不做認證(authentication),只做授權(authorisation)。

  • 認證(authentication)。由ssh服務來認證訪問賬號的合法性。
  • 授權(authorisation)。授予某個賬號的訪問許可權。

Gitolite安裝和啟動

Gitolite是管理Git的倉庫,所以必須要安裝Git。

安裝Gitolite

  1. 切換到git使用者賬號:su – git
  2. 安裝SSH,一般來說伺服器上都已經安裝SSH了
  3. 獲取Gitolite程式碼,git clone git://github.com/sitaramc/gitolite
  4. 建立Gitolite安裝目錄。mkdir -p ~/bin
  5. 開始安裝。gitolite/install -to ~/bin
  6. 新增管理員公鑰。這個管理員公鑰就是對應著擁有管理程式碼倉庫的許可權,非常重要。把自己的公鑰admin.pub上傳到伺服器,新增到Gitolite中。gitolite setup -pk admin.pub

管理Gitolite

管理Gitolite也很簡單,它是通過一個Git倉庫來管理的。安裝好Gitolite後,會預設生成一個gitolite-admin的倉庫。管理員可以把這個倉庫clone到本地:

git clone git@host:gitolite-admin
git clone git@host:gitolite-admin
這個倉庫有兩個目錄:
keydir,存放使用者認證的公鑰檔案目錄
conf,存放Gitolite配置的檔案的目錄
gitolite.conf,gitolite配置檔案

使用者

新增使用者本質是把該使用者的公鑰檔案新增到gitolite-admin倉庫中。比如想新增一個使用者foo:
把foo的公鑰檔案重新命名為foo.pub
把foo.pub檔案放到gitolite-admin/keydir目錄中,並提交到遠端倉庫
刪除使用者也類似,只不過把該使用者的的公鑰檔案移出gitolite-admin倉庫。
有時候一個使用者有多個公鑰檔案。這種情況下,就需要把這些同名的公鑰檔案放到keydir不同的子目錄下。比如foo使用者的多個公鑰檔案如下放置:

keydir/home/foo.pub
keydir/laptop/foo.pub
keydir/desktop/foo.pub

只要這些公鑰都是命名為foo.pub,在不同的目錄下不衝突。

倉庫

新增倉庫
新增一個倉庫很簡單,編輯gitolite-admin倉庫裡面的gitolite-admin/conf/gitolite.conf即可。我們可以看下初始的gitolite.conf檔案內容:

repo gitolite-admin
    RW+     =   admin

repo testing
    RW+     =   @all

repo gitolite-admin
    RW+     =   admin
 
repo testing
    RW+     =   @all

repo name,就是定義一個名為name的倉庫。可以看到Gitolite裡面有兩個預設的倉庫,gitolite-admin和testing。

下面的RW+ = admin則便是這個倉庫的許可權控制規則,可以看到這個倉庫只允許admin可讀可寫可管理。

我們可以用以下程式碼新增一個新的bar倉庫:

repo bar
    RW+     =   foo

repo bar
    RW+     =   foo

我們在gitolite.conf檔案中新增一個foo的倉庫,實際存放在伺服器上的倉庫目錄名是foo.git。這個新倉庫只允許foo使用者可讀可寫可管理。

你可以把兩個具有一樣的訪問許可權的倉庫定義成一行,如下:

repo a b c
    RW+     =   foo
    R       =   admin

repo a b c
    RW+     =   foo
    R       =   admin

這樣,a、b、c就是3個具有相同的訪問許可權的倉庫了,foo使用者可以讀可寫可管理,admin使用者只能可讀。

刪除、重名倉庫

刪除倉庫稍微麻煩一點:

  1. 從gitolite.conf刪除倉庫的定義
  2. 登陸到伺服器,刪除伺服器上對應的倉庫
    重新命名倉庫也是如此,修改gitolite.conf檔案,然後修改伺服器上對應倉庫的名字。

匯入現有倉庫

直接把一個倉庫放入Gitolite倉庫目錄是不行的,它有幾個要求:

  • 倉庫必須是bare倉庫
  • 倉庫目錄名必須以.git結尾
  • 倉庫裡面所有的檔案和目錄的歸屬(ownded)和可寫於Gitolite使用者賬號。
  • 執行gitolite setup

使用者組和倉庫組

你可以把使用者或者倉庫定義成一個組,對這個組賦予某種屬性,就是對組內所有的成員都賦予同樣的屬性。這對批量的處理某些問題很有幫助。
組名以@開頭,如下定義一個3個成員的組:

@developers = dilbert alice wally

也可以累積分別定義,效果跟上面一樣:


@developers = dilbert
@developers = alice
@developers = wally

你也可以把一個組放到另外一個組裡面:
@developers     =   dilbert alice
@interns        =   ashok
@staff          =   @interns @developers
@developers     =   wally

注意,後來新增到develpoers組的wally並不在staff組裡面。

如下是個使用組定義倉庫和它使用者的例子:

@developers     =   dilbert alice wally//三個使用者
@foss-repos     =   git gitolite//兩個倉庫

repo @foss-repos
    RW+         =   @developer

@developers     =   dilbert alice wally
@foss-repos     =   git gitolite
 
repo @foss-repos
    RW+         =   @developer

特殊組

@all表示所有的倉庫或者所有的使用者。

訪問許可權

緊跟著一個倉庫後面的就是這個倉庫的訪問許可權規則,有以下幾種許可權:
R,表示可讀許可權
RW,表示fast-forward push分支,建立新分支和tag許可權。不能迴轉、刪除分支
RW+,可以做任何事情
'-'表示拒絕訪問
以下面的配置為例子:

repo foo bar

    RW+                     =   alice @teamleads
    -   master              =   dilbert @devteam
    -   refs/tags/v[0-9]    =   dilbert @devteam
    RW+ dev/                =   dilbert @devteam
    RW                      =   dilbert @devteam
    R                       =   @managers
  • alice 和teamleads組可以做任何事情
  • dilbert @devteam許可權
    • 可以對/dev分支做任何事情,不能寫,刪除master
    • 可以fast-forward push分支,建立新分支和tag許可權
    • 除了以v開頭tag,可以建立其他tags
  • managers只能讀倉庫

你還可以建立一個倉庫組,在同一個倉庫組裡面的倉庫具有相同的許可權,如下:

repo @myrepos
    RW+     =   alice

@myrepos    =   foo
@myrepos    =   bar
@myrepos    =   zzq

這樣,有3個倉庫foo、bar、zzq都在myrepos同一個倉庫組裡面,具有相同的訪問許可權。

gitolite.conf

gitolite.conf有兩個重要的作用:定義倉庫名和定義倉庫的訪問許可權。

基本語法
所有的東西都是用空格分隔
可以使用#表示註釋
使用者名稱和倉庫名都是以字母開頭,可以包含.、_、-。使用者名稱還可以是電子郵件地址
組名類似使用者名稱,但不能是電子郵件地址
倉庫名可以包含/,用來表示目錄結構

include其他配置

Gitolite允許你把配置放在另外的.conf檔案裡,然後在gitolite.conf把這些配置檔案include進來就可以了。比如include “foo.conf”,就把foo.conf檔案裡面的配置包括進來了。

gitolite配置參考連結

完成和驗證

到列印出如下結果gitolite安裝完成。

初始化空的 Git 倉庫於 /home/gitolite/repositories/gitolite-admin.git/
初始化空的 Git 倉庫於 /home/gitolite/repositories/testing.git

這是建立了兩個倉庫,一個是管理倉庫gitolite-admin.git,另一個是測試使用的testings.git.
現在要做的是要從gitolite伺服器中把gitolite-admin.git拉取下來進行project和許可權的管理

遇到的問題及其說明

建立新使用者並同時建立主目錄--useradd -m xxxname
設定密碼--passwd xxxname,然後再輸入密碼

gitolite 不在 sudoers 檔案中。此事將被報告

sudo命令可以讓你以root身份執行命令,來完成一些我們這個帳號完成不了的任務。
其實並非所有使用者都能夠執行sudo,因為有許可權的使用者都在/etc/sudoers中呢。
我們可以通過編輯器來開啟/etc/sudoers,或者直接使用命令visudo來搞定這件事情。
開啟sudoers後,像如下那樣加上自己的帳號儲存後就可以了。

# User privilege specification
root    ALL=(ALL:ALL) ALL
gitolite ALL=(ALL:ALL) ALL

sudoers的許可權是0440,即只有root才能讀。在你用root或sudo後強行儲存(wq!)即可.
測試通過後開始下面的安裝

repo環境配置

概要

repo是Android為了方便管理多個git庫而開發的Python指令碼。repo的出現,並非為了取代git,而是為了讓Android開發者更為有效的利用git。
Android原始碼包含數百個git庫,僅僅是下載這麼多git庫就是一項繁重的任務,所以在下載原始碼時,Android就引入了repo。 Android官方推薦下載repo的方法是通過Linux curl命令,下載完後,為repo指令碼新增可執行許可權:

$ git clone https://gerrit-googlesource.lug.ustc.edu.cn/git-repo  > ~/bin/repo
$ chmod a+x ~/bin/repo
$ cp repo/repo .    //在~bin目錄下
再將~/bin新增到環境變數,這樣就可以使用repo命令了

工作原理

repo需要關注當前git庫的數量、名稱、路徑等,有了這些基本資訊,才能對這些git庫進行操作。通過集中維護所有git庫的清單,repo可以方便的從清單中獲取git庫的資訊。 這份清單會隨著版本演進升級而產生變化,同時也有一些本地的修改定製需求,所以,repo是通過一個git庫來管理專案的清單檔案的,這個git庫名字叫manifest。

當開啟repo這個可執行的python指令碼後,發現程式碼量並不大(不超過1000行),難道僅這一個指令碼就完成了AOSP數百個git庫的管理嗎?並非如此。 repo是一系列指令碼的集合,這些指令碼也是通過git庫來維護的,這個git庫名字叫repo

在客戶端使用repo初始化一個專案時,就會從遠端把manifests和repo這兩個git庫拷貝到本地,但這對於Android開發人員來說,又是近乎無形的(一般通過檔案管理器,是無法看到這兩個git庫的)。 repo將自動化的管理資訊都隱藏根目錄的.repo子目錄中。

專案清單庫(.repo/manifests)

<?xml version="1.0" encoding="UTF-8"?>
<manifest>
<remote  name="origin" fetch=".." review="https://android-review.googlesource.com/" />
<default revision="master" remote="origin"/>
<project path="repo-test1" name="platform/repo-test1"/>
<project path="repo-test2" name="platform/repo-test2"/>
</manifest>

注意project的path和name後面不要有/

  • <remote>:描述了遠端倉庫的基本資訊。name描述的是一個遠端倉庫的名稱,通常我們看到的命名是origin;fetch用作專案名稱的前緣,在構造專案倉庫遠端地址時使用到;review描述的是用作code review的server地址

  • <default>:default標籤的定義的屬性,將作為<project>標籤的預設屬性,在<project>標籤中,也可以重寫這些屬性。屬性revision表示當前的版本,也就是我們俗稱的分支;屬性remote描述的是預設使用的遠端倉庫名稱,即<remote>標籤中name的屬性值;屬性sync-j表示在同步遠端程式碼時,併發的任務數量,配置高的機器可以將這個值調大

  • <project>:每一個repo管理的git庫,就是對應到一個<project>標籤,path描述的是專案相對於遠端倉庫URL的路徑,同時將作為對應的git庫在原生程式碼的路徑; name用於定義專案名稱,命名方式採用的是整個專案URL的相對地址。 譬如,AOSP專案的URL為https://android.googlesource.com/,命名為platform/build的git庫,訪問的URL就是https://android.googlesource.com/platform/build
    如果需要新增或替換一些git庫,可以通過修改default.xml來實現,repo會根據配置資訊,自動化管理。但直接對default.xml的定製,可能會導致下一次更新專案清單時,與遠端default.xml發生衝突。 因此,repo提供了一個種更為靈活的定製方式local_manifests:所有的定製是遵循default.xml規範的,檔名可以自定義,譬如local_manifest.xml, another_local_manifest.xml等, 將定製的XML放在新建的.repo/local_manifests子目錄即可。repo會遍歷.repo/local_manifests目錄下的所有*.xml檔案,最終與default.xml合併成一個總的專案清單檔案manifest.xml。
    問題的疑難點在於manifest中的配置,manifest.git相對於它管理的倉庫的路徑關係在remote節點配置的

在伺服器建立倉庫

在建立好default.xml後,提交到伺服器。
然後在伺服器端,利用default.xml生成src.txt,再寫個指令碼自動建立所有的git倉庫。
生成src.txt

cat default.xml | cut -d '"'   -f 2 > src.txt
命令解釋:
cat default.xml是輸出檔案內容
| 是管道,檔案內容被定向輸出到管道
cut 是針對行擷取,-d是自定義分隔符為 "
-f 2顯示之前分隔開的第二個區域,比如行
   <project name="platform/build" path="build/" />
按"擷取後為 project  name=  platform/build   path=  build/
下標從0開始,第二個區域為platform/build.
>src.txt定向輸出到檔案src.txt

cut詳細引數:
-b :以位元組為單位進行分割。這些位元組位置將忽略多位元組字元邊界,除非也指定了 -n 標誌。
-c :以字元為單位進行分割。
-d :自定義分隔符,預設為製表符。
-f :與-d一起使用,指定顯示哪個區域。
-n :取消分割多位元組字元。僅和 -b 標誌一起使用。如果字元的最後一個位元組落在由 -b 標誌的 List 引數指示的<br />範圍之內,該字元將被寫出;否則,該字元將被排除。
cut詳細用法
生成src.txt後,去掉不必要的行,檔案首尾有一些不需要的行。
生成src.sh檔案如下:

#/bin/bash
set -x
set -e
pwd=${PWD}

cd /home/gitolite/repositories#此處要根據實際的repositories路徑修改
while read line; do
    if [ -z "$line" ]; then
        echo $work_dir not exist !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 1>&2
        continue
    fi
        git init --bare $line.git    
#初始化裸倉庫,使用--bare選項時,不再生成.git目錄,而是隻生成.git目錄下面的版本歷史記錄檔案,這些版本歷史記錄檔案也不再存放在.git目錄下面,而是直接存放在版本庫的根目錄下面
        echo ==== $line
        pwd
done

執行此指令碼,會在/home/gitolite/repositoires下面生成相關倉庫
如下:

abi.git       build.git    developers.git   external.git    hardware.git         ndk.git    sdk.git       u-boot.git
art.git       chipram.git  development.git  flyscale.git    kernel.git           packages   system.git    vendor.git
bionic.git    cts.git      device.git       frameworks.git  libcore.git          pdk.git    tools.git
bootable.git  dalvik.git   docs.git         gen.git         libnativehelper.git  prebuilts  u-boot64.git

但是有一個問題,這樣雖然初始化了裸倉庫,但是由於沒有在gitolite中進行新增和配置,客戶端是不能提交成功能,所以所有的這些倉庫必須都被 gitolite管理起來才可以。那如上方法就不可取了。

使用指令碼生成gitolite.conf

因為要建立上百個倉庫,不可能全部手動進行配置,我們需要使用指令碼來生成gitolite.conf。
指令碼很簡單:

#/bin/bash

set -x #追蹤程式碼執行情況
set -e #當指令碼執行出現意料之外的情況時,立即退出,避免錯誤被忽略,導致最終結果不正確

work_dir=$1 #傳入的第一個引數

pwd=${PWD}
echo $pwd start create gitrepo...
while read line; do
        echo repo $line >> gitolite.conf  #倉庫名稱
        echo     RW+     =   @user >> gitolite.conf  #許可權配置
done

同樣利用到了src.txt,執行命令cat src.txt | ./con-tools.sh
這樣就配置好了,再執行如下命令提交gitolite-admin

git add -all
git commit -m "更新gitolite.conf"
git push origin master

執行完之後 在/home/gitolite/repositories下面就生成了對應的所有倉庫。

客戶端上傳原始碼

首先要準備一份沒有建立git的原始碼。根據default.xml生成des.txt,生成的命令如下

cat default.xml | cut -d ‘”’ -f 4 > des.txt
//關於該命令的含義前面已經說過,

使用如下指令碼進行倉庫的批量初始化和提交

#/bin/bash

set -x #追蹤程式碼執行情況
set -e #當指令碼執行出現意料之外的情況時,立即退出,避免錯誤被忽略,導致最終結果不正確

para1=
work_dir=$1 #傳入的第一個引數

pwd=${PWD}
echo $pwd start create gitrepo...
while read line; do
    echo readline
    line1=${line%%/*}
    if [ -z "$line" ]; then
        echo $work_dir not exist !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 1>&2
        continue
    fi
    if [ $(ls -A $pwd/$line | wc -l) -eq 0 ]; then
        echo $work_dir empty !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 1>&2
        continue
    fi
    workdir=$pwd/$line
    echo ==== $workdir
    cd $workdir  #以下是提交流程
        rm -rf .git
        git init .  1>&2
        git add . -f 1>&2
        git commit -m "Initial commit" 1>&2
        git push --set-upstream gitolite@192.168.1.104:/platform/$line.git master --force
done

執行如下命令進行批量提交:
cat des.txt | ./des.sh

客戶端下載程式碼

  1. 客戶端需要首先下載git-repo倉庫,並配置環境變數,這樣才能使用repo命令
    git clone gitolite@192.168.1.104:git-repo.git
    然後把repo配置到環境變數中。
  2. repo init -u gitolite@192.168.1.104:/platform/manifest.git
  3. repo sync

repo upload

set -x
set -e
Shell指令碼$的含義

錯誤處理

  1. 執行repo init報錯
    rror: manifest missing or unreadable -- please run init
  2. repo: no branches ready for upload
    https://blog.csdn.net/armwind/article/details/52488961

參考連結:
repo工作原理
default.xml檔案配置詳解
repo客戶端安裝
修改/etc/profile出錯後恢復

搭建Gerrit程式碼稽核伺服器

參考連結
參考連結
下載wget http://gerrit-releases.storage.googleapis.com/gerrit-2.8.1.war
下載路徑/usr/local/

安裝apache2報依賴錯誤的問題,只需要把依賴包安裝指定版本的即可。
解決依賴錯誤

apache2啟動失敗,參考Log:/var/log/apache2/error.log

登入mysql並修改使用者

啟動gerrit服務
./gerrit.sh start

登入mysql資料庫
格式:mysql -u[使用者名稱] -p
示例,使用者名稱root:
mysql -uroot -p
show databases;//檢視所有資料庫

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| reviewdb           |
+--------------------+
4 rows in set (0.02 sec)

information_schema資料庫是MySQL自帶的,它提供了訪問資料庫後設資料的方式。詳細information_schema
reviewdb是gerrit使用的資料庫
use reviewdb;//使用reviewd資料庫
//確認使用的資料庫

mysql> select database();
+------------+
| database() |
+------------+
| reviewdb   |
+------------+
1 row in set (0.00 sec)

//檢視reviewdb中的所有表

mysql> show tables;
+-----------------------------+
| Tables_in_reviewdb          |
+-----------------------------+
| account_group_by_id         |
| account_group_by_id_aud     |
| account_group_id            |
| account_group_members       |
| account_group_members_audit |
| account_group_names         |
| account_groups              |
| account_id                  |
| change_id                   |
| change_messages             |
| changes                     |
| patch_comments              |
| patch_set_approvals         |
| patch_sets                  |
| schema_version              |
| system_config               |
+-----------------------------+
16 rows in set (0.01 sec)

修改gerrit認證方式

gerrit有多種身份驗證方法,身份驗證方法決定了如何登入Gerrit。

  1. OPENID,如果你想掛入某個現有的身份驗證提供方(例如GoogleAccounts),那麼可以使用OpenID。
  2. development_become_any_account,如果是用於測試和學習,可以選擇最簡單的development_become_any_account。
  3. HTTP認證也是可選的認證方式,此認證方式下需要配置Apache的反向代理,並在Apache中配置Web站點的口令認證,通過口令認證後gerrit在建立賬號的過程中會詢問使用者的郵件地址併傳送確認郵件。
  4. LDAP, LDAP全稱Lightweight Directory Access Protocol,輕量目錄訪問協議。使用使用者名稱和密碼。
    在etc/gerrit.config下的
[auth]
        type = LDAP

使用HTTP認證需要使用反向代理

我司使用的HTTP進行認證。
反向代理:反向代理(Reverse Proxy)方式是指以代理伺服器來接受internet上的連線請求,然後將請求轉發給內部網路上的伺服器,並將從伺服器上得到的結果返回給internet上請求連線的客戶端,此時代理伺服器對外就表現為一個反向代理伺服器。

配置說明

下面是我的配置,伺服器地址192.168.1.104,代理埠9999,被代理埠10000。本機迴環IP127.0.1.1

  1. 在/etc/apache2/下建立httpd.conf
#add gerrit reverse proxy --bianjb
<VirtualHost *:9999>    #代理埠9999
    ServerName 192.168.1.104
    ProxyPreserveHost On    #開啟反向代理
    ProxyRequests Off
    <Proxy *>    #訪問許可權規則
        Order deny,allow  
        Allow from all  
    </Proxy>
    <Location /login/>  #登入成功轉到登入介面
      AuthType Basic
      AuthName "Welcomme to Gerrit Code Review Site!"
      Require valid-user
      AuthBasicProvider file
      AuthUserFile /home/gerrit/review_site/etc/passwd    #使用者驗證使用的檔案,需要自行建立
    </Location>
    ProxyPass / http://127.0.1.1:10000/    #被代理地下
</VirtualHost>

AuthUserFile /home/gerrit/review_site/etc/passwd,我放在了這個目錄下,可以自行指定,建立方法如下:

sudo touch /home/gerrit/review_site/etc/passwd  //建立檔案
sudo htpasswd -b home/gerrit/review_site/etc/passwd  username passwd
//使用htpasswd幫助資訊
htpasswd -h

後面登入的時候就可以使用useranme+passwd進行登入 了。

  1. 在/etc/apache2/apache2.conf中引入我們新建的httpd.conf
Include httpd.conf
  1. 配置/etc/apache2/ports.conf
Listen 80    #apache2預設監聽的埠
Listen 9999  #新新增監聽9999埠作為代理
  1. 重啟apache2服務
sudo service apache2 restart

現在就可以訪問伺服器了,如下圖:


4123353-344bd527d6a17e8a.png
image.png

登入成功後如圖:


4123353-bcb6daf74746aa0a.png
image.png

配置Gerrit開機啟動

  1. 安裝gerrit的時候,會有一個安裝目錄,在它的下面有個 bin/gerrit.sh檔案,把這個檔案拷貝到/etc/init.d下 改名叫做 gerrit
  2. 然後用sysv-rc-conf工具,這個沒有可以直接apt-get install進行安裝
  3. 執行sysv-rc-conf
    4123353-23e7d70399869e25.png
    image.png

    找到gerrit的那一行,把2~5都X上。

搭建起來還是挺費勁的,歡迎各位交流指正!

相關文章