SVN Hooks的介紹及使用

閱讀此篇文章你可以:

  • 對SVN Hooks有一定的瞭解
  • 獲取兩個最常用的SVN Hooks案例

SVN hooks介紹

Hooks 鉤子,主要實現的功能就是在特定事件發生之前或者之後自動執行事先定義好的腳本代碼來實現某些功能,類似於JS中的監聽事件、MySQL中的觸發器、Django中的signals信號等

大多數開發語言都可以用來編寫hooks腳本,常用的如windows下的bat、vb,linux下的shell、python等

SVN中的hooks按照所在位置可以分爲兩類,客戶端hooks和服務端hooks,日常使用中服務端hooks使用更廣,我們也以服務端hooks介紹爲主

SVN服務端hooks主要有以下9種:

pre-lock:文件加鎖前執行,不常用

post-lock:文件加鎖後執行,通常用來發送鎖定事件通知,需要傳遞兩個參數給hooks腳本,按照順序依次爲:1.版本庫路徑,2.鎖定路徑的認證用戶名

per-unlock:文件解鎖前執行,不常用

post-unlock:文件解鎖後執行,通常用來發送解鎖事件通知,需要傳遞兩個參數給hooks腳本,按照順序依次爲:1.版本庫路徑,2.解鎖路徑的認證用戶名

start-commit:開始提交時執行,在pre-commit之前,通常用來確定用戶是否有提交權限

pre-commit:提交之前執行,在start-commit之後,通常用來對提交內容的檢查,例如我們後邊要介紹的利用pre-commit做提交log的合規性檢查,需要傳遞兩個參數給hooks腳本,按照順序依次爲:1.版本庫路徑,2.提交事務的名稱

post-commit:提交完成後執行,這應該是使用最廣的hooks之一,通常用來在提交之後發送提交通知,甚至是利用它來做自動化的CI/CD等操作,需要傳遞兩個參數給hooks腳本,按照順序依次爲:1.版本庫路徑,2.提交創建的修訂版本號

pre-revprop-change:在修改revision屬性之前執行,不常用

post-revprop-change:在修改revision屬性之後執行,不常用

SVN hooks應用

svn hooks位於svn版本庫的hooks文件夾下,例如svn目錄爲/home/svn/repos,倉庫名稱爲ops-coffee,那麼hooks就位於/home/svn/repos/ops-coffee/hooks/目錄下,文件夾下的.tmpl的文件爲hooks的模板文件,以shell腳本的方式展示了hooks該如何使用

注意這些hooks文件都要有可執行權限

如果我們要使用svn的hooks,那麼就在hooks文件夾下新建文件名爲hooks類型的文件(例如pre-commit,沒有後綴,名字也不能隨意改)併爲文件賦予可執行權限,或者直接複製模板文件去掉.tmpl後綴然後進行修改

接下來我們看兩個常用的例子來加深對hooks的理解

限制log提交規則

良好的svn log規範,有利於我們對項目的管理,尤其在多人協作開發的過程中,清晰、規範的log能大大降低溝通成本,提升開發效率。因此我們會制定相應的規則要求所有開發按照一定的規範提交log,這些規則通常依賴所有參與者的自覺,效果可能並不是很好,有麼有辦法強制參與者按照既定的規則提交log呢?

pre-commit這個hook就能很好的幫助我們實現這個需求,每一次代碼提交前都會觸發pre-commit腳本,那麼我們就可以在腳本中判斷log規則是否跟我們預先定義的一樣,不一樣則不允許提交

假如我們有如下log提交規範


代碼提交記錄以簡潔、表意清晰爲基本原則,建議每完成一個功能模塊都單獨提交一次代碼,每個提交記錄應包含以下信息:[功能模塊][任務類別]描述,例如:

  • [新聞][dev]新聞模塊添加搜索功能
  • [評論][bug]修復評論功能在IE瀏覽器下樣式錯亂的問題
  • [ops-coffee活動][misc]活動Q&A文案調整,添加“運維咖啡吧”公衆號二維碼

[功能模塊]

當前提交的功能模塊名字,不固定,例如:新聞、評論、ops-coffee活動等

[任務類別]

任務類別只包括dev、bug、misc幾種,不能自定義

  • dev:表示此次提交爲功能開發相關代碼
  • bug:表示此次提交爲代碼修復相關代碼
  • misc:表示此次提交爲完全非功能性變動及雜項變動代碼,例如文案微調、補充註釋等

描述

  • 描述內容務必簡單明瞭
  • 如果一次提交包括多個內容,使用“1. abc; 2. def” 分別說明

接下來我們利用pre-commit每次提交前檢查是否符合上邊定義的規範,具體配置如下

  1. 我們先創建pre-commit的hook腳本,內容如下
#!/bin/bash
REPOS="$1"
TXN="$2"

SVNLOOK=/usr/bin/svnlook  
LOGMSG=$($SVNLOOK log -t "$TXN" "$REPOS")
LOGFORMAT="\[(.+)\]\[(dev|bug|misc)\](.+)$"

# 判斷提交log與預設的規則是否匹配
[[ ${LOGMSG} =~ ${LOGFORMAT} ]] || exit 1

exit 0

LOGFORMAT爲我們根據規範寫的正則表達式,符合[xxx][(dev|bug|misc)]xxx這樣的規則即可

通過svnlook命令拿到本次提交的log記錄,然後與預設的正則進行匹配,通過則繼續往下走,不通過則直接退出狀態1

最終exit退出狀態爲0時則表示全部規則驗證通過,進行後續的代碼提交操作,非0時表示驗證失敗

可以在hook腳本中寫多條不同的驗證規則,每條規則不通過時返回不同的狀態碼,這樣後續不通過就知道哪裏驗證失敗了,例如檢測提交的文件名不能包含有空格,不然就exit 2等

  1. 別忘了給hook腳本加上可執行權限
# chmod +x /home/svn/repos/ops-coffee/hooks/pre-commit

這樣就ok了,很簡單,再提交log時就會按照定義的規則來判斷,如果判斷不通過則直接報錯’Commit blocked by pre-commit hook’讓你重新寫log

提交成功發送郵件通知

看了上邊強制log提交規則的示例,想必對SVN hooks有了一定的瞭解,那麼我們趁熱打鐵再來看一個提交成功發送郵件的例子

假如我們有一個賬號叫merge,專門用來合併上線代碼,經過這個賬號合併的代碼自動觸發發佈API更新代碼到生產環境,其他賬號合併的代碼發送郵件通知給[email protected]的郵箱,那麼該如何實現呢?

  1. 首先是代碼提交(合併)之後觸發,那麼就需要用到post-commit這個hook,具體內容如下
# cat /home/svn/repos/ops-coffee/hooks/post-commit
#!/bin/bash
REPOS="$1"
REV="$2"

export LANG=zh_CN

# svn info
AUTHOR=$(svnlook author -r $REV $REPOS)
MESSAGE=$(svnlook log -r $REV $REPOS)
CHANGED=$(svnlook changed -r $REV $REPOS)
REPERTORY=$(echo $REPOS | awk -F'/' '{print $NF}')

LOGFILE="/tmp/.svn_hooks_post_commit.log"
echo "$AUTHOR

版本庫:
$REPERTORY - $REV

更新LOG:
$MESSAGE

更新內容:
$CHANGED
" > $LOGFILE


if [ $AUTHOR == merge ];then
    curl -H "Authorization:Token 3w2290j02baa1xb8cemec35k8b" "https://ops-coffee.cn/api/deploy?p=${REPERTORY}&v=${REV}"
else
    mail -s "SVN 更新通知:系統版本號【$REV】" [email protected] < $LOGFILE
fi

通過svnlook命令獲取到提交者、LOG、更新內容的數據,然後將數據拼裝成郵件的正文,以便下邊發送郵件

然後if判斷提交者是不是merge,如果是則通過curl命令調用deploy的API,API會根據所傳的兩個參數v:倉庫名和p:版本號將代碼發佈到對應項目的生產環境上,如果不是則發送郵件通知

以上爲演示代碼,生產環境的發佈各位根據自己實際情況調整

  1. 同樣不要忘了給腳本添加可執行權限
# chmod +x /home/svn/repos/ops-coffee/hooks/post-commit

這樣就ok了,每次代碼提交(合併)之後就會判斷是哪個賬號的提交,確定是發送郵件通知還是直接部署上線


長按關注公衆號查看更多原創文章

如果你覺得文章對你有幫助,請轉發分享給更多的人。如果你覺得讀的不盡興,推薦閱讀以下文章:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章