引言:
??隨著IT行業的不斷發展,軟件開發的復雜度也隨著不斷提高,軟件的開發團隊也越來越龐大,如何更好地協同整個團隊進行高效準確的工作,確保軟件開發的質量成為了開發過程中不可回避的問題。
??在軟件開發中,不同的功能模塊一般由不同的開發成員負責,同一功能模塊的各層代碼也可能是不同的開發成員編寫,經驗告訴我們,模塊之間的問題是最難解決的,也是最耗費時間的。它需要多個開發人員相互協作找出問題,而協作過程中的溝通所消耗的時間成本是相當高的。而且還可能因為溝通的不足導致模塊返工。
??事實上,在持續集成被提出來之前的傳統開發方法中常常出現這種情況:由不同程序員開發的單個小模塊可以單獨工作,但把它們集成為一個大的系統則可能失敗。而且集成失敗往往是把集成放在開發周期后期,甚至是在項目快結束前單列的一個“總裝階段”。眾所周知,問題發現的越晚,其修復的成本也就越高,耗時越長,而且經過新的修復工作后可能誕生新的錯誤,因此整個系統需要再次進行集成和測試,從而導致整個軟件的生產周期漫長且不可預知。
??為了解決由傳統開發方法帶來的弊端,人們開始采用“早集成、常集成”的持續集成策略。從最初的分階段集成,到后來的“每日構建” ,再發展到現在的持續集成(Continuous Integration,CI)。持續集成通過自動化構建、自動化測試以及自動化部署加上較高的集成頻率保證了開發系統中的問題能迅速被發現和修復,降低了集成失敗的風險,使得系統在開發中始終保持在一個穩定健康的集成狀態。
??持續集成服務器是自動構建系統中關鍵的一部分。Jenkins是一個開源項目,它提供了一種易于使用的持續集成系統,使開發者從繁雜的集成中解脫出來,專注于更為重要的業務邏輯實現上。同時 Jenkins 能實施監控集成中存在的錯誤,提供詳細的日志文件和提醒功能,還能用圖表的形式形象地展示項目構建的趨勢和穩定性。Jenkins還能通過自定義安裝插件來實現多種多樣的功能。持續集成服務器各系統實現功能如下:
1、Gitlab上進行代碼托管
??在Gitlab上創建開發組,加入開發人員,新建開發項目項目并設置權限為Private,普通用戶對該項目只有pull權限,不能直接進行push
??強制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做了同步,Gerrit上的代碼會同步到Gitlab上。
2、Gerrit審核代碼
??普通用戶將Gitlab里的項目clone到本地,修改代碼后,雖不能直接push到代碼中心 ,但是可以通過git review提交到Gerrit上進行審核。Gerrit相關審核員看到review信息后,判斷是否通過,通過即commit提交。然后,Gerrit代碼會和Gitlab完成同步。
??Gerrit的精髓在于不允許直接將本地修改同步到遠程倉庫。客戶機必須先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部署配置
1、 安裝JDK
[root@Ubuntu]#sudo add-apt-repository ppa:webupd8team/java
[root@Ubuntu]#sudo apt-get update
[root@Ubuntu]#sudo apt-get install oracle-java8-installer
2、 安裝mysql
[root@Ubuntu]#sudo apt-get install mysql-server mysql-client #中途會讓你輸入一次root用戶密碼(密碼:root)
3、 創建gerrit數據庫
[root@Ubuntu]#mysql –uroot –p 進入mysql創建gerrit數據庫gerritdb
mysql>create database gerritdb CHARACTER SET utf8 COLLATE utf8_general_ci;
mysql>grant all on gerritdb.* to 'gerrit'@'localhost' identified by '123456';
mysql>flush privileges;
4、 安裝配置并啟動nginx(反向代理端口設為9095)
[root@Ubuntu]#sudo apt-get install nginx
[root@Ubuntu]#cd /etc/nginx/conf.d
[root@Ubuntu]#vim gerrit.conf
server {
listen 9095;
server_name localhost;
allow all;
deny all;
auth_basic "Welcomme to Gerrit Code Review Site!";
auth_basic_user_file /home/gerrit/gerrit_site/etc/passwords;
location / {
proxy_pass http://10.0.2.15:9091;
}
}
[root@Ubuntu]#sudo /etc/init.d/nginx start
5、 安裝git
[root@Ubuntu]# sudo apt-get install git
6、 安裝git-review
[root@Ubuntu]#sudo apt-get install git-review
7、 安裝gerrit
[root@Ubuntu]#useradd –m gerrit
切換用戶gerrit
[root@Ubuntu]#su – gerrit
將gerrit安裝包gerrit-2.11.3.war放在相應目錄下,執行:
[gerrit@Ubuntu]$java -jar gerrit-2.11.3.war init -d ~/gerrit_site
安裝gerrit
安裝過程提示的配置項可在gerrit安裝完成后在gerrit配置文件中進行配置。
8、 配置gerrit
[gerrit@Ubuntu]$cd /home/gerrit/gerrit_site/etc
[gerrit@Ubuntu]$vi gerrit.config
配置文件內容:
[gerrit]
basePath = git
canonicalWebUrl = http://10.0.2.15:9091/
[database]
type = mysql
hostname = localhost
database = gerritdb
username = gerrit
[index]
type = LUCENE
[auth]
type = HTTP
[sendemail]
smtpServer = smtp.qq.com
smtpServerPort = 465
smtpEncryption = ssl
smtpUser = xxx@qq.com
smtpPass = xxxxxxxxxxxx
sslVerify = false
from = CodeReview<xxx@qq.com>
[container]
user = gerrit
javaHome = /usr/lib/jvm/java-8-oracle/jre
[sshd]
listenAddress = *:29418
[httpd]
listenUrl = proxy-http://10.0.2.15:9091
[cache]
directory = cache
9、 啟動gerrit
[gerrit@Ubuntu]$/home/gerrit/gerrit_site/bin/./gerrit.sh restart
10、 瀏覽器地址欄輸入http://10.0.2.15:9095訪問gerrit,彈出登錄對話框
Gerrit搭建成功!
11、 gerrit添加用戶
注意:第一次加-c參數是為了創建密碼文件,默認第一個用戶是系統管理員
[root@Ubuntu]# htpasswd -c /home/gerrit/gerrit_site/etc/passwords gerrit
New password:
Re-type new password:
[root@Ubuntu]#htpasswd /home/gerrit/gerrit_site/etc/password jenkins5062
New password:
Re-type new password:
[root@Ubuntu]#htpasswd /home/gerrit/gerrit_site/etc/password jenkins
New password:
Re-type new password:
12、 登錄gerrit并注冊用戶郵箱
1) 輸入用戶名密碼,進入gerrit頁面
2) 打開My->Groups->Contact Information頁面進行郵箱注冊
3)單擊Register New Email按鈕,在提示框內輸入郵箱地址,進行注冊
3) 打開郵箱,查看驗證郵件,打開驗證鏈接,用戶郵箱注冊成功
13、 生成用戶公私鑰并進行配置
1)切換到需要配置公私鑰的用戶,執行生成公私鑰操作
[gerrit@Ubuntu]$ su - gerrit
[gerrit@Ubuntu]$ ssh-keygen -t rsa -C gerrit5062@163.com //產生公私鑰
[gerrit@Ubuntu]$cat ~/.ssh/id_rsa.pub
2)使用用戶賬號登錄gerrit系統,將公鑰添加到用戶的SSH Public keys
一、Gitlab部署配置
1、 安裝Gitlab
[root@Ubuntu] #sudo apt-get install -y curl openssh-server ca-certificates
[root@Ubuntu] #sudo apt-get install -y postfix
[root@Ubuntu]#curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ee/script.deb.sh | sudo bash
[root@Ubuntu] #sudo apt-get install gitlab-ee
[root@Ubuntu] #sudo gitlab-ctl reconfigure
2、 Gitlab配置
Gitlab配置信息位于/etc/gitlab/目錄下的gitlab.rb文件,
[root@Ubuntu] #cd /etc/gitlab/
[root@Ubuntu] #vim gitlab.rb配置gitlab,相關配置如下:
配置完成后,重新啟動gitlab
[root@Ubuntu] #sudo gitlab-ctl configure
3、 配置root用戶密碼,登錄gitlab
1)終端執行
[root@Ubuntu] #gitlab-rails console production
irb(main):001:0>u=User.where(id:1).first
u.password = 'secret_pass'
>u.password_confirmation = 'secret_pass'
>u.save!
2)root登錄gitlab
4) 添加用戶,此處新增gerrit用戶為管理員
5) gerrit用戶登錄gitlab,添加SSH Public Keys
二、Jenkins部署配置
1、安裝jenkins
[root@Ubuntu] #wget -q -O - https://pkg.jenkins.io/debian/jenkins-ci.org.key | sudo apt-key add -
[root@Ubuntu] #sudo sh -c 'echo deb http://pkg.jenkins.io/debian-stable binary/ > /etc/apt/sources.list.d/jenkins.list'
[root@Ubuntu] #sudo apt-get update
[root@Ubuntu] #sudo apt-get install Jenkins
2、jenkins默認端口為8080,為防止端口沖突,重新配置端口號為8082
[root@Ubuntu] #cd /etc/default
[root@Ubuntu] #vim Jenkins
4、 啟動jenkins
[root@Ubuntu] #/etc/init.d/Jenkins start
5、 登錄jenkins
1) 初始默認密碼在/var/lib/Jenkins/secrets目錄下的initialAdminPassword文件中
cat /var/lib/Jenkins/secrets/initialAdminPassword
登錄后重新配置jenkins賬號密碼,默認管理員用戶為jenkins。
2) 登錄jenkins
Jenkins搭建完成。
6、 jenkins系統配置
1) 進入Jenkins系統配置界面
Jenkins Location配置:
Email-Notification配置:
2) 進入Jenkins插件管理界面
搜索選擇(Available)需要安裝的插件,(構建工具gradle,Gerrit事件觸發器gerrit_trigger, 版本控制工具Git plugin)
構建工具(Gradle)實現項目的自動構建、自動測試、自動部署等功能。Gerrit事件觸發器Gerrit_trigger監聽Gerrit系統事件。版本控制工具(Git plugin)保證項目源碼處于有序的管理中,方便開發人員隨時獲取和提交變更。
三、Gitlab與Gerrit集成
1、Gitlab項目設置
管理員用戶在Gitlab系統新建開發組dev-group,新建項目user,將開發人員加入開發組并配置為reporter權限,reporter用戶沒有push權限,只能使用 git review 命令提交,而 git review 命令需要 .gitreview 文件存在于項目目錄里。管理員gerrit用戶添加.gitreview 文件
[root@Ubuntu] #su – gerrit
[gerrit@Ubuntu]$git clone [git@10.0.2.15:dev-group/user.git](mailto:git@10.0.2.15:dev-group/user.git)
[gerrit@Ubuntu]$cd user
[gerrit@Ubuntu]$ vim .gitreview
添加.gitreview到版本庫
[gerrit@Ubuntu]$ git add .gitreview
[gerrit@Ubuntu]$ git config --global user.name 'gerrit'
[gerrit@Ubuntu]$git config --global user.email 'gerrit5062@163.com'
[gerrit@Ubuntu]$ git commit .gitreview -m 'add .gitreview file by gerrit.'
[gerrit@Ubuntu]$ git push origin master
項目目錄下缺少.gitreview文件,開發人員git review時會報錯:
No '.gitreview' file found in this repository. We don't know where
your gerrit is. Please manually create a remote named "gerrit" and try
again.
2、Gerrit設置項目
gitlab上的項目能在gerrit上review的話,必須在gerrit上創建相同的項目,并有相同的倉庫文件,所以gerrit上的項目最好是從gitlab上git clone --bare過來,并且項目不要為空
1)clone --bare Gitlab上的倉庫到 Gerrit
[gerrit@Ubuntu]$ cd /home/gerrit/gerrit_site/git/
[gerrit@Ubuntu]$ git clone --bare git@10.0.2.15:dev-group/user.git
2)同步 Gerrit的user項目到 Gitlab 上的user項目目錄中
當用戶git review后,代碼通過 jenkins 測試、人工 review 后,代碼只是 merge 到了 Gerrit 的user項目中,并沒有 merge 到 Gitlab 的user項目中,所以需要當 Gerrit user項目倉庫有變化時自動同步到 Gitlab 的 user項目倉庫中。
Gerrit 自帶一個 Replication 功能,同時我們在安裝 Gerrit 時候默認安裝了這個 Plugin。添加一個 replication.config 給 Gerrit
[gerrit@Ubuntu]$ cd /home/gerrit/gerrit_site/etc/
[gerrit@Ubuntu]$vim replication.config
[remote "user"]
projects =user
url = git@10.0.2.15:dev-group/user.git
push = +refs/heads/*:refs/heads/*
push = +refs/tags/*:refs/tags/*
push = +refs/changes/*:refs/changes/*
threads = 3
設置gerrit用戶的 ~/.ssh/config
[gerrit@Ubuntu]$vim /home/gerrit/.ssh/config
Host 10.0.2.15:
IdentityFile ~/.ssh/id_rsa
PreferredAuthentications publickey
在gerrit用戶的~/.ssh/known_hosts 中,給10.0.2.15 添加 rsa 密鑰
[gerrit@Ubuntu]$sh -c "ssh-keyscan -t rsa 10.0.2.15>> /home/gerrit/.ssh/known_hosts"
[gerrit@Ubuntu]$sh -c "ssh-keygen -H -f /home/gerrit/.ssh/known_hosts"
重新啟動 Gerrit 服務 [gerrit@Ubuntu]$/home/gerrit/gerrit_site/bin/gerrit.sh restart
五、Gerrit與Jenkins集成
1、Gerrit配置時已經將jenkins配置為Gerrit用戶,將jenkins用戶的密鑰添加到Gerrit
[root@Ubuntu] #su – Jenkins
[jenkins@Ubuntu]$cat .ssh/id_rsa.pub
2、Jenkins項目設置
1)Jenkins新建項目user并完成相關配置
配置jenkins連接Gerrit倉庫
選擇監聽Gerrit event
選擇gradle構建項目
2、配置Gerrit_trigger plugin
1) Manage Jenkins->Gerrit Trigger進入配置界面
2)Add New Server
2) 填寫配置信息并測試,Test Conection success,配置成功
3、配置Gradle插件
1)Manage Jenkins->Global Tool Configuration,完成Gradle配置
六、測試(操作手冊)
1、普通用戶jenkins5062 從Gitlab或Gerrit系統將項目clone到本地進行編輯,修改代碼后,不能直接push到代碼中心 ,可以通過git review提交到gerrit上進行審核。gerrit相關審核員看到review信息后,判斷是否通過,通過即Submit提交。
Gitlab代碼庫clone代碼到本地進行編輯
[jenkins5062@Ubuntu]$ git clone [git@10.0.2.15:dev-group/user.git](mailto:git@10.0.2.15:dev-group/user.git)
或者在Gerrit代碼庫clone代碼到本地進行編輯,用戶登錄Gerrit->Project->General, 選中clone with commit-msg hook,選擇SSH或HTTP,復制clone命令
2、項目編輯完成后提交審核
git add test
git commit –m “jenkins5062 change test”
git review
如果開發者需要在Gerrit里保存一些需要較長時間完成的工作,可以使用
git review –D
命令進行提交,提交的代碼將被Gerrit標記為Draft狀態,Draft狀態下的change只有提交者自己和被開發者添加的reviewer及項目管理員可以看到。處于draft狀態的change一樣可以添加reviewer。
如果開發者git review后需要在當前版本下繼續修改,可在再次編輯文件后git commit時添加--amend參數,重新git review。
3、Gerrit進行代碼審核
1)用戶git review后,jenkins監聽Gerrit events,對提交的代碼進行構建
2)普通用戶登錄Gerrit進行審核,All->Open->Subject列表下列出提交的項目代碼,代碼已經過Jenkins自動測試(Verified +1)
Files->File Path->user/test查看代碼變更的詳細信息
3) 管理員登錄Gerrit系統審核All->Open->Subject列表
審核通過后Submit提交Gitlab并合并到主分支。當用戶git review后,代碼通過jenkins自動測試(verified)、人工review 后,代碼只是merge到了Gerrit的項目中,并沒有merge到 Gitlab的項目中,所以需要配置replication插件,當 Gerrit 項目倉庫有變化時自動同步到Gitlab的項目倉庫中。
系統發送郵件,提醒jenkins5062用戶代碼已Submit并合并到Gitlab代碼倉庫
如果審核不通過
Reply...標記-2 ->Post
jenkins5062收到郵件提醒,代碼未通過審核
4、登錄Gitlab查看項目更新
Gitlab代碼倉庫已完成代碼更新!
七、部署集成部分問題整理總結
1、找不到適配Ubuntu 32位版本的gitlab安裝源,重裝64位Ubuntu系統后,
gitlab正常安裝
2、gitlab安裝完成后,執行sudo gitlab-ctl reconfigure啟動命令,
報錯:
Error executing action 'run' on resource 'bash[migrate
gitlab-rails database]'
LoadError:/opt/gitlab/embedded/lib/libre2.so.0: symbol _ZTVNSt7__
cxx1119basic_sotringstreamIcSt11char_traitsIcESaIcEEE,version
GLIBCXX_3.4.21 not defined in file libstdc++.so.6 with link time
reference
原因:GCC版本太低,升級Ubuntu至 16.04LTS版本后完成部署
3、執行:ssh -p 29418 -i ~/.ssh/id_rsa 10.0.2.15 -l gerrit
報錯:
Unable to negotiate with 192.168.1.101 port 29418: no matching key exchange method found. Their offer: diffie-hellman-group1-sha1
解決:修改~/.ssh/config,加入
Host *
KexAlgorithms +diffie-hellman-group1-sha1
4、添加jenkins用戶登錄gerrit時報
500 Internal Server Error
nginx/1.10.3 (Ubuntu)錯誤,
執行 chmod 777 passswords修改/home/gerrit/gerrit_site/etc/passwords的權限,修改文件權限后gerrit恢復正常訪問
5、用戶從gerrit上將代碼clone到本地時報錯
Unable to negotiate with 10.0.2.15 port 29418: no matching key exchange method found. Their offer: diffie-hellman-group1-sha1
在.ssh/config文件中添加語句:
Host *
KexAlgorithms +diffie-hellman-group1-sha1
6、gerrit安裝報錯:
Exception in thread "main" com.google.gwtorm.server.OrmException: Cannot apply SQL
ALTER TABLE changes ADD submission_id VARCHAR(255) BINARY
修改數據庫設置,執行數據庫設置語句:
set global explicit_defaults_for_timestamp=1;
7、nginx 報403 Forbidden錯誤
反向代理nginx /etc/nginx/conf.d/gerrit.conf 中 auth_basic_user_file /home/gerrit/gerrit_site/passwords;
路徑錯誤,改為auth_basic_user_file /home/gerrit/gerrit_site/etc/passwords;
注意:IP配置問題,文件權限問題
8、gerrit用戶注冊郵箱發送驗證連接失敗
原因:
1). /etc/secure.config文件內沒有配置的發送郵箱密碼和gerrit.config中的密碼不一致
解決方法:配置/etc/secure.config smtpPass同gerrit.config中的smtpPass的配置保持一致。
2). 網易smtp.163.com服務器問題,DT:SPM 發送的郵件內容包含了未被許可的信息,或被系統識別為垃圾郵件。
請檢查是否有用戶發送病毒或者垃圾郵件;發件郵箱更換為qq郵箱
9、1.git review 提交代碼請求 可觸發jenkins自動測試,自動測試通過代碼被標記 Verified +1 后被提交gerrit進行審核,審核人員審核后通過后Review +2,Submit,修改后的代碼未同步到gitlab。
解決:Gerrit安裝配置replication 插件
10、jenkins build failure 構建錯誤,使用jenkins安裝的gradle插件進行項目構建。