Git Hooks、GitLab CI持續集成以及使用Jenkins實現自動化任務


Git Hooks、GitLab CI持續集成以及使用Jenkins實現自動化任務

前言

在一個共享項目(或者說多人協同開發的項目)的開發過程中,為有效確保團隊成員編碼風格的統一,確保部署方式的統一,等等(git的用戶經常會涉及到此類場景),常常會使用類似 Git Flow 這種比較復雜的工作流開發模式。在較大型的項目中,雖然這種工作流模式比較成熟,但在分支處理方面,這種工作流就會造成較多的重復勞動。

因此,如果能借助某些工具來自動化處理這些重復性事務,比如自動合並分支,那么對於提升我們的工作效率,將會有很大的幫助。

本文將從以下三種方法對自動化任務處理做介紹,並對每一種方法的優缺點做個簡單的總結,以及在實際工作中我們該如何做出選擇。

三種實現方法:

  • 客戶端與服務端 Git hooks
  • GitLab-Runner 以及編寫 .gitlab-ci.yml 文件
  • GitLab Webhooks 與 Jenkins 的配合使用

Git 鈎子

Git hooks是基於事件的。當你執行特定的git指令時,該軟件會從git倉庫下的hooks目錄下檢查是否有相對應的腳本,如果有就執行。

有些腳本是在動作執行之前被執行的,這種“先行腳本”可用於實現代碼規范的統一、完整性檢查、環境搭建等功能。有些腳本則在事件之后被執行,這種“后行腳本”可用於實現代碼的部署、權限錯誤糾正(git在這方面的功能有點欠缺)等功能。

安裝一個鈎子

鈎子都被存儲在Git目錄下的hooks子目錄中。也即絕大部分項目中的.git/hooks。當你用git init初始化一個新版本庫時,Git 默認會在這個目錄中放置一些示例腳本。這些腳本除了本身可以被調用外,它們還暴露了被觸發時所傳入的參數。這些示例的名字都是以 .sample 結尾,如果想啟用它們,移除這個后綴即可。

把一個正確命名且可執行的文件放入 Git 目錄下的 hooks 子目錄中,即可激活該鈎子腳本。這樣一來,它就能 被 Git 調用。

客戶端和服務器端 Git hooks

git hooks 采用 事件機制, 在相應的操作(比如 git commit / git merge)下觸發, 分為 2 種:

  • 服務端 hooks, github 的 webhooks 就是在此基礎上建立起來的;

  • 客戶端 hooks, 每個 git 版本庫的 .git/hooks/ 文件夾下就有可以使用的例子。

注意: 客戶端 hooks 並不會同步到版本庫中

客戶端鈎子由諸如提交和合並這樣的操作所調用,而服務器端鈎子作用於諸如接收被推送的提交這樣的聯網操作。

客戶端鈎子位於項目根目錄 your_project/.git/hooks 文件夾下

服務端鈎子則位於 your_project.git 文件夾下的 hooks 和 custom_hooks

hooks與custom_hooks文件夾

可以看到GitLab為我們創建了一個軟連接連接到了GitLab自定義的鈎子目錄,這樣所有創建的項目都可以使用同一個腳本規則,減少了維護成本。

那我們如何結合GitLab定制自己的腳本呢?git會首先觸發GitLab的腳本,然后GitLab執行完自己的腳本文件后會再調用掉用戶放在custom_hooks下的腳本,所以我們只需要將我們定制好的腳本放在custom_hooks下即可,腳本名稱和之前一樣。例如:touch post-receive,這個腳本理論上可以使用任何腳本語言例如Perl、Python、Ruby等,不過執行這個腳本的用戶將是git,要注意git用戶對系統的操作權限,還要注意post-receive這個腳本需要能夠有執行權限。

客戶端與服務端鈎子圖示

(圖片來自於網絡)

示例

post-receive 推送代碼后自動部署

將目錄切換至 ../BRIDGE_REPO.git/hooks,用 cp post-receive.sample post-receive 復制並重命名文件后用 vim post-receive 修改。其內容大致如下:

#!/bin/sh

unset GIT_DIR

NowPath=`pwd`
DeployPath="../../www"

cd $DeployPath
git pull origin master

cd $NowPath
exit 0

使用 chmod +x post-receive 改變一下權限即可,服務器端的配置就基本完成了。

GitLab-CI與GitLab-Runner

持續集成(Continuous Integration)

要了解GitLab-CI與GitLab Runner,我們得先了解持續集成是什么。

持續集成是一種軟件開發實踐,即團隊開發成員經常集成他們的工作,通常每個成員每天至少集成一次,也就意味着每天可能會發生多次集成。每次集成都通過自動化的構建(包括編譯,發布,自動化測試)來驗證,從而盡快地發現集成錯誤。許多團隊發現這個過程可以大大減少集成的問題,讓團隊能夠更快的開發內聚的軟件。

GitLab-CI

GitLab-CI就是一套配合GitLab使用的持續集成系統(當然,還有其它的持續集成系統,同樣可以配合GitLab使用,比如接下來要說的Jenkins)。

持續集成,我們通常使用CI來做一些自動化工作,比如程序的打包,單元測試,部署等,這種構建方式避免了打包環境差異引起的錯誤,提高了工作效率。Gitlab-CI是Gitlab官方提供的持續集成服務,我們可以在倉庫的根目錄下新建.gitlab-ci.yml文件,自己定義持續集成流程模板,並且在Gitlab中配置runner,在之后的每次提交或合並中將會觸發構建,並且可以通過Gitlab的hook, 在代碼提交的各個環節自動地完成一系列的構建工作,總之對於一些非復雜性的集成需求,都是可以滿足的。

實際上,GitLab-CI中有一個概念叫 Pipeline ,一次 Pipeline 其實相當於一次構建任務,里面可以包含多個流程,如安裝依賴、運行測試、編譯、部署測試服務器、部署生產服務器等流程。任何提交或者 Merge Request 的合並都可以觸發 Pipeline。

思考:
為什么不是 GitLab CI 來運行那些構建任務?

一般來說,構建任務都會占用很多的系統資源 (譬如編譯代碼),而 GitLab CI 又是 GitLab 的一部分,如果由 GitLab CI 來運行構建任務的話,在執行構建任務的時候,GitLab 的性能會大幅下降。

GitLab CI 最大的作用是管理各個項目的構建狀態,因此,運行構建任務這種浪費資源的事情就交給 GitLab Runner 來做了!

因為 GitLab Runner 可以安裝到不同的機器上,所以在構建任務運行期間並不會影響到 GitLab 的性能~

GitLab-Runner

GitLab-Runner是配合GitLab-CI進行使用的。一般地,GitLab里面的每一個工程都會定義一個屬於這個工程的軟件集成腳本,用來自動化地完成一些軟件集成工作。當這個工程的倉庫代碼發生變動時,比如有人push了代碼,GitLab就會將這個變動通知GitLab-CI。這時GitLab-CI會找出與這個工程相關聯的Runner,並通知這些Runner把代碼更新到本地並執行預定義好的執行腳本。

所以,GitLab-Runner就是一個用來執行軟件集成腳本的東西。你可以想象一下:Runner就像一個個的工人,而GitLab-CI就是這些工人的一個管理中心,所有工人都要在GitLab-CI里面登記注冊,並且表明自己是為哪個工程服務的。當相應的工程發生變化時,GitLab-CI就會通知相應的工人執行軟件集成腳本。

Runner一共有三種類型

  • 本地Runner
  • 普通的服務器上的Runner
  • 基於Docker的Runner

MAC環境安裝gitlab-ci-multi-runner

具體說下gitlab-runner register

Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/ci):
http://xxxxxx // 在這里輸入gitlab安裝的服務器ip/ci 即可

Please enter the gitlab-ci token for this runner:
xxxxxxxxxxxxxxxxxx // 這里的token可通過Gitlab上的項目Runners選項查看

Please enter the gitlab-ci description for this runner:[E5]:demo
// 這里填寫一個描述信息

Please enter the gitlab-ci tags for this runner (comma separated):
demo // 在這里填寫tag信息,多個tag可通過逗號,分割。
tag:一個項目可能有多個runner,是根據tag來區別runner的。

Registering runner... succeeded. runner=eaYyokc5

Please enter the executor: docker, docker-ssh, parallels, shell, ssh, virtualbox, docker+machine, docker-ssh+machine:
shell // 在這里需要輸入runner的執行方式,直接輸入shell

Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded! // 出現這樣信息表示服務端的配置就已經成功結束了。

如何編寫 .gitlab-ci.yml 文件

如果你在項目倉庫里面加入.gitlab-ci.yml文件,同時給項目配置了gitlab-runner, 那么每次提交代碼或者合並 mr , 都會觸發你的 CI Pipeline (持續集成管道)。

stages:
  - deploy
deploy:
    stage: deploy
    script:
      - echo "start deploy....."
      - deploy
    only:
      - master
    tags:
      - shell

其中deploy是編寫的shell腳本,可以實現將要發布的內容自動部署到發布目錄下:

#!/bin/bash
deploy_path="xxx"
project_path="xxx;
judge_path = "$deploy_path/$project_path"
if [ ! -d "$judge_path" ]
then
   project_url="xxx.git"
   git clone $project_path $deploy_path
else
   cd $deploy_path
   git pull
fi

.gitlab-ci.yml配置詳解請參考:

gitlab ci/cd .gitlab-ci.yml配置詳解

官方GitLab文檔

官方GitLab文檔翻譯

Gitlab Webhooks

Webhooks 允許第三方應用監聽 GitLab 上的特定事件,在這些事件發生時通過 HTTP POST 方式通知( 超時5秒) 到第三方應用指定的 Web URL。 例如項目有新的內容 Push,或是 Merge Request 有更新等。 WebHooks 可方便用戶實現自動部署,自動測試,自動打包,監控項目變化等。

webhooks, 可以在 pull request / merge master 等幾個場景下, 設置異步回調通知(http 請求)。這個背后就是 git hooks 在起作用。

因此,利用 WebHooks 的特性,可配合 Jenkins 實現一系列的自動化任務。

Jenkins

Jenkins是一個用Java編寫的開源的持續集成工具,可以與Git打通,監聽Git的merge, push事件,觸發執行Jenkins的指定任務(job)。例如發布的任何一個環節都可自動完成,無需太多的人工干預,有利於減少重復過程以節省時間和工作量等。

實例:Jenkins、Gitlab webhooks實現開發分支自動合並

步驟梳理

  1. GitLab上准備一個web工程;
  2. GitLab上配置Jenkins的webhook地址;
  3. Jenkins安裝GitLab Plugin插件;
  4. Jenkins配置GitLab訪問權限;
  5. Jenkins上創建一個構建項目,對應的源碼是步驟1中的web工程;
  6. 修改web工程的源碼,並提交到GitLab上;
  7. 檢查Jenkins的構建項目是否會觸發自動任務腳本。
(Jenkins Job 和 GitLab 的關聯,在網上已經有許多完善的文檔了,在這里就不贅述了)
以下為開發分支develop自動合並master分支的腳本示例,僅供參考:
#!/bin/sh
echo *****************Start*****************
date
# 獲取最近一次提交的 commit id
sha1=`git rev-parse HEAD`
# 獲取姓名及郵箱,來配置git提交者信息
name=`git show $sha1 | grep 'Author:' | cut -d' ' -f2`
email=`git show $sha1 | grep 'Author:' | cut -d' ' -f3 | sed -e 's/<//g' | sed -e 's/>//g'`
echo '當前提交人信息:'
echo $name 
echo $email 
git config --global user.name $name
git config --global user.email $email
echo '***************** git checkout develop & git pull:'
git checkout develop
git pull
# develop合並master
echo '***************** git merge origin/master:'
conflict=`git merge origin/master`
echo $conflict | grep 'CONFLICT'
if [ $? -ne 0 ]; then
    echo '***************** git push origin HEAD:'
    git push origin HEAD
    echo '***************** git status:'
    git status
else
    git status
    echo 'Automatic merge failed...'
    echo 'Please fix conflicts and then commit the result...'
    exit 1
fi
echo *****************End*****************

三種實現方法的優缺點對比:

  • 客戶端與服務端 Git hooks :如果僅涉及客戶端鈎子,用這種方法比較好,比如 husky 這個插件;但如果是服務端鈎子,就必須在服務端配置才可使用,比如 post-receive 鈎子;
  • GitLab-Runner 以及編寫 .gitlab-ci.yml 文件:需服務端安裝 gitlab-runner 來支持自動化腳本的執行;
  • GitLab Webhooks 與 Jenkins 的配合使用:Jenkins是比較成熟的第三方持續集成系統,可與GitLab完美的結合使用,但配置過程仍是稍顯復雜,但在自動化任務處理方面,Jenkins無疑是個較好的選擇。

參考資料

Pro Git

GitLab 官方文檔

Git Hooks

GitLab-CI 與 GitLab-Runner

轉載請標注出處,謝謝!https://www.cnblogs.com/mycognos/p/10155978.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM