gitlab pre-receive hook服務端配置限制提交代碼的備注長度


gitlab pre-receive hook服務端配置限制提交代碼的備注長度

前言

開發人員在使用git提交(commit)代碼的時候,需要添加備注信息,但是很多人偷懶不願意寫或者寫的很短。為了限制開發人員寫過短的備注信息,需要在gitlab服務器端進行配置(客戶端也可以,但這里配置的是服務端)

配置

服務端有兩種配置方式,一種是全局的配置,一種是各個項目獨立的配置。這里講各個項目獨立的配置:

  1. 選擇一個項目,比如叫testGit
  2. 在git所在服務器后台,切換到git項目源代碼存儲的目錄:如果使用的是docker鏡像啟動的gitlab, 源代碼庫目錄一般位於/var/opt/gitlab/git-data/repositories/<group>/<project>.git,假設group叫test, 則路徑就是/var/opt/gitlab/git-data/repositories/test/testGit.git目錄。
  3. 在testGit.git目錄創建一個新目錄custom_hooks
  4. 在custom_hooks目錄創建一個文件命名為pre-receive,並且可執行權限設置為777(或者設置其所在用戶組和擁有者為gitlab)
  5. 添加腳本內容到pre-receive, 保存腳本內容,不用重啟gitlab會立刻生效

腳本

下面是pre-receive文件的腳本內容,設置提交代碼時的備注長度至少為5個英文字符(如果是中文字符,一個中文字符相當於3個英文字符)

#!/bin/bash
#pre-receive script
#set -x #for debugging

validate_ref()
{
    # --- Arguments
    oldrev=$(git rev-parse $1)
    newrev=$(git rev-parse $2)
    refname="$3"

    commitList=`git rev-list $oldrev..$newrev`
        #echo $commitList
    split=($commitList)
    for s in ${split[@]}
    do
        echo "@@@@@@@"
        echo "$s"
        msg=`git cat-file commit $s | sed '1,/^$/d'`
        echo $msg
        if [ ${#msg} -lt 5 ];then
            echo "!!! Commit message length less than 5"
            exit 1
        else
            echo "bigger than 5"
        fi
    done

}

fail=""

# Allow dual mode: run from the command line just like the update hook, or
# if no arguments are given then run as a hook script
if [ -n "$1" -a -n "$2" -a -n "$3" ]; then
    # Output to the terminal in command line mode - if someone wanted to
    # resend an email; they could redirect the output to sendmail
    # themselves
    PAGER= validate_ref $2 $3 $1
else
    while read oldrev newrev refname
    do
        validate_ref $oldrev $newrev $refname
    done
fi

if [ -n "$fail" ]; then
    exit $fail
fi

 

 

開發人員在push代碼(pull, commit的時候不會報錯)的時候如果備注長度小於5個英文字符,就會提示報錯:

 
image.png

改進

限制提交的comments備注必須為三行,第一行至少18個英文字符,第二行為空,第三行為30個英文字符

root@bob-k8s3:/srv/gitlab/data/git-data/repositories/root/pets.git/custom_hooks# cat pre-receive
#!/bin/bash
#pre-receive script
#set -x #for debugging

RED='\033[0;31m'
NC='\033[0m' # No Color

reverse() {
    # first argument is the array to reverse
    # second is the output array
    declare -n arr="$1" rev="$2"
    for i in "${arr[@]}"
    do
        rev=("$i" "${rev[@]}")
    done
}

regex_list=(
        '^test'
        '^fix '
        '^docs'
        '^task'
        '^refactor'
        '^revert'
        '^style'
        '^chore'
        '^Merge'
        '^merge'
        '^[ci skip]'
)

# Concatenate regex_list
separator="|"
regex="$( printf "${separator}%s" "${regex_list[@]}" )"
# remove leading separator
regex="${regex:${#separator}}"



validate_ref()
{
    # --- Arguments
    oldrev=$(git rev-parse $1)
    newrev=$(git rev-parse $2)
    refname="$3"

    #echo $oldrev
    #echo $newrev


    GITCMD="git"
    commitList=`git rev-list $oldrev..$newrev`
    split=($commitList)
    reverse split split2
    for s in ${split2[@]}
    do

        #echo "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
        echo "$s"
        currentrev=$s
        msg=`git cat-file commit $s | sed '1,/^$/d'`
        #echo $msg





        match=`echo $msg | grep -nE "(${regex})"`
        if [ "${match}" != "" ]; then
                #show all the changed files, between this push and last push, maybe one or more commits
                changedFiles=$($GITCMD diff --stat --name-only --diff-filter=ACMRT ${oldrev}..${currentrev})
                #echo $changedFiles

                #if it is bug fixing
                if [[ "${match}" =~ "fix" ]]; then
                        #check if there is unit testing commiting
                        if ! [[ $changedFiles =~ "src/test/" ]]; then
                                echo -e "${RED}Error: Need unit testing cases  ${NC}"
                                #exit 1
                        fi
                fi

                # if pom.xml changed, make sure it can not chang the code coverage threshold
                if [[ $changedFiles =~ "pom.xml" ]]; then
                        #check file contents, make sure no body change code coverage threshold
                        #codeCoverageKeyword=`git diff-tree -r -p --no-color --no-commit-id --diff-filter=d $s | grep -n "<minimum>"`
                        codeCoverageKeyword=`git  diff --unified=0 ${oldrev}..${currentrev} | grep -n "<minimum>"`
                        if [ "${codeCoverageKeyword}" != "" ]; then
                                echo -e "${RED}Error: you can not change code coverage rate  ${NC}"
                                #exit 1
                        fi
                fi


        else
                echo -e "Error:${RED} comments should be started wih test or fix or task... ${NC}"
        fi



       # validate the git comments
       if [[ $msg == *"Merge branch"* ]];
       then
           echo "Merge branch...skip the checking"
       else

        n=0
        while read -r line; do
          ((n++))

          # 1st line at least 18 english characters
          if [ $n -eq 1 ] && [ ${#line} -lt 3 ];then
            echo -e "Error:${RED} 1st line length should be bigger than 18${NC}: ${#line}"
            #exit 1
          fi

          # 2nd line must be empty
          if [ $n -eq 2 ] && [ ${#line} -gt 0 ];then
            echo -e "Error:${RED} 2nd line length should be 0${NC}: ${#line}"
            #exit 1
          fi

          # 3rd line at least 30 english characters
          if [ $n -eq 3 ] && [ ${#line} -lt 30 ];then
            echo -e "Error:${RED} 3rd line length should be bigger than 30${NC}: ${#line}"
            #exit 1
          fi
        done <<< "$msg"

        if [ $n -lt 3 ];then
            echo -e "Error:${RED} You should commit with 3 lines comments${NC}: $n"
#            exit 1
        fi

       fi

        #change the oldrev to show file list and file contents between 2 commits
        oldrev=$currentrev
    done

}

fail=""

# Allow dual mode: run from the command line just like the update hook, or
# if no arguments are given then run as a hook script
if [ -n "$1" -a -n "$2" -a -n "$3" ]; then
    # Output to the terminal in command line mode - if someone wanted to
    # resend an email; they could redirect the output to sendmail
    # themselves
    PAGER= validate_ref $2 $3 $1
else
    while read oldrev newrev refname
    do
        validate_ref $oldrev $newrev $refname
    done
fi

if [ -n "$fail" ]; then
    exit $fail
fi


第二行的空行是必須, 否則使用如下兩個命令時就會格式錯亂

$git log --oneline
$git shortlog

 

 

下圖中第一個是第二行添加了空行右邊會有三個點意思是可以點擊這三個點查看更多信息,第二個是只有一行時的效果:

 
image.png

備注

  1. pre-receive會響應以任何形式的代碼提交,比如命令行,比如通過gitlab網頁
  2. 如果在pre-receive里`touch testme.txt", 默認會在pre-receive腳本所在目錄的上一級目錄里生成。
  3. 也可以在pre-receive里使用curl調用REST接口,比如gitlab的各種restful api
  4. 在linux下面提交多行備注的方法很簡單,在備注內容中敲回車即可,但在windows中如果使用的是https://git-scm.com/, 方法就相對繁瑣一點,要使用多個 -m
     


免責聲明!

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



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