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

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

前言

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

所以,若是能借助某些工具來自動化處理這些重複性事務,好比自動合併分支,那麼對於提高咱們的工做效率,將會有很大的幫助。git

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

三種實現方法:

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

Git 鉤子

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

有些腳本是在動做執行以前被執行的,這種「先行腳本」可用於實現代碼規範的統1、完整性檢查、環境搭建等功能。有些腳本則在事件以後被執行,這種「後行腳本」可用於實現代碼的部署、權限錯誤糾正(git在這方面的功能有點欠缺)等功能。docker

安裝一個鉤子

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

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

客戶端和服務器端 Git hooks

git hooks 採用 事件機制, 在相應的操做(好比 git commit / git merge)下觸發, 分爲 2 種:segmentfault

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

  • 客戶端 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

轉載請標註出處,謝謝!http://www.javashuo.com/article/p-oeilhptg-er.html

相關文章
相關標籤/搜索