專案commit前使用阿里規範做強制提交校驗
最近幾天一直在瞭解git 如何提交前做git強制校驗。因為專案使用的是coding,之前的gitlab 是有hook的設定的。可以在push時候做校驗,但是coding 我看了他們 的官網,沒找到設定hook的地方。於是決定換一種方式:在本地commit前做強制校驗。
思路是這樣的:本地專案的.git/hook目錄下面是預設的提交前校驗,裡面有pre-commit.example、pre-commit-msg.example等shell指令碼檔案。帶example預設是不執行的,去掉字尾example就會做對應的校驗。那麼 是不是可以利用這點,在本地commit前來做校驗呢?
好的 ,思路有了。首先是去掉pre-commit.example的字尾,隨便寫點shell指令碼,發現git commit 前 是可以執行的(簡單的加上一句echo 什麼內容都不要)。但是如何在commit前讓本地走阿里規範呢?
帶著這個問題,繼續去思考。阿里規範本身是一套p3c的標準,在網上看到別人已經有寫好的現成的方案。於是藉助現成的方案:(參考 https://www.jianshu.com/p/b87ca8615c9c、https://www.jianshu.com/p/048627b20860 感謝作者)就是把阿里規範的原始碼 通過maven達成了jar包,然後使用 java jar的命令 來實現的。再然後把這行命令寫在本地的pre-commit腳本里面,這樣就可以實現commit 前校驗程式碼是否走阿里規範了。
具體操作就是:去gitlab上下載 cp3的原始碼(地址:https://github.com/alibaba/p3c)下載到本地,通過maven命令達成jar包:如下
mvn clean package -Dmaven.test.skip=true
打的jar包有好幾個,主要是使用 p3c-pmd-2.1.1-jar-with-dependencies.jar 。使用命令列:
java -Dpmd.language=en -cp /d/p3c-pmd-2.1.1-jar-with-dependencies.jar net.sourceforge.pmd.PMD -d /d/workspace/community -R rulesets/ali-p3c.xml -f text -shortnames
引數解釋:
- -d 原始碼目錄,多個檔案或者目錄以,號分開
- -R 指定規則,多個規則以,號分開。阿里規則路徑在包中rulesets/java/ali-*.xml
- -f 報告格式,text html xml等。
#!/bin/sh #本地提交前自動觸發阿里巴巴p3c規範指令碼 EJECT=0 #REJECT變數,初始化為0 GIT_ROOT=$(cd $(dirname ${BASH_SOURCE[0]}); pwd) # 獲取.git/hooks/根目錄 HOOKS_DIR="$GIT_ROOT/.git/hooks" # 沒有時建立該目錄 if [ ! -d "$HOOKS_DIR" ]; then mkdir "$HOOKS_DIR" fi # 所有需要hook的git hooks檔名 hook_names=( pre-commit ) # 在.git/hooks/下生成這些執行檔案 for hook_name in ${hook_names[@]} do # 生成hook檔案 REAL_HOOK_FILE=$HOOKS_DIR/$hook_name # 將模板檔案內容copy進去 cp $GIT_ROOT/check.sh $REAL_HOOK_FILE # 替換模板檔案中的hook-tmp為正確的hook檔名 #sed -i "" "s/check.sh/$hook_name/g" $REAL_HOOK_FILE # 修改hook檔案許可權 chmod a+x $REAL_HOOK_FILE done
#!/bin/sh # # An example hook script to make use of push options. # The example simply echoes all push options that start with 'echoback=' # and rejects all pushes when the "reject" push option is used. # # To enable this hook, rename this file to "pre-receive". EJECT=0 #REJECT變數,初始化為0 BASE_PATH=$(cd `dirname $0`; pwd) #BASE_PATH變數中為當前指令碼存放的路徑,比如當前指令碼路徑為/usr/local/script/shell.sh,則BASE_PATH=/usr/local/script/ PROJECT_ROOT=$(cd $(dirname ${BASH_SOURCE[0]})/../..; pwd) java -Dpmd.language=en -cp $PROJECT_ROOT/p3c-pmd-2.1.1-jar-with-dependencies.jar net.sourceforge.pmd.PMD -d $PROJECT_ROOT -R rulesets/java/ali-comment.xml,rulesets/java/ali-concurrent.xml,rulesets/java/ali-constant.xml,rulesets/java/ali-exception.xml,rulesets/java/ali-flowcontrol.xml,rulesets/java/ali-naming.xml,rulesets/java/ali-oop.xml,rulesets/java/ali-orm.xml,rulesets/java/ali-other.xml,rulesets/java/ali-set.xml -f text #執行校驗 REJECT=$? #REJECT變數接收上面的java命令執行的結果返回值 if test $[REJECT] -eq 0 then echo -e "\033[36m commit success!!! \033[1m" #藍色列印提交成功 else echo -e "\033[31m 程式碼提交未通過阿里規範,不允許提交!!! \033[1m" #紅色列印未通過 fi exit $REJECT
這樣就可以了,因為是本地commit,如果想要跳過本地commit,直接在git base 後面 加上 git commit -m "註釋" --no-verify 或者手動 刪除.git/commit 目錄下的即可。
這樣是可以了,還有個問題就是:能不能做成一個無感知的、因為每次要手動執行才能使用。這樣也不方便,而且如果別人不執行的話,也不知道啊。