2021年5月2日 星期日

[Git 文章收集] 提升程式碼品質:使用 Pre-Commit (Git Hooks)

 Source From Here

Preface
在團隊協作開發中,程式碼品質是一個非常需要重視的問題,除了比較進階的重構以外,有沒有什麼自動檢查的方法可以提升程式碼品質呢?答案是有的,就是今天要討論的 pre-commit。

在程式碼 commit 進 branch 之前,如果能在 local 端阻擋一些低級失誤,就可以大大提升開發品質,在專案中使用 pre-commit 有以下好處:
* 自動化檢查程式碼排版規範快速又有效率(如 python PEP8)
* 低級的問題不會進到 code review
---- 多一點時間檢查程式邏輯,而不是基本錯誤(如排版)。
---- 人工檢查程式碼的時間很寶貴,減少人工即是增進效率。
* 低級的問題不會進到 CI/CD pipeline
---- pipeline 應該多一點綠勾勾,而不是滿滿 debug 的痕跡。

這次示範的 pre-commit 設定是基於 python 的 pre-commit framework:pre-commit。市面上的 pre-commit framework 其實不少,例如 js 的 Husky,或是自己撰寫 git hook 的 script 也是可以的。那就廢話不多說,開始介紹吧!

一、Pre-commit 基本使用
以 framework 設置 pre-commit 非常簡單,官方文件 淺顯易懂,只需要 pre-commit 的基本程式,再加上一個 yaml 設定檔即可完成!

1. Pre-commit 安裝
如下安裝工具:
# pip3 install pre-commit
# pre-commit install
pre-commit installed at .git/hooks/pre-commit

接著還需要:
* 撰寫配置文件 .pre-commit-config.yaml
* 產生一個新 commit (需要的套件安裝會和第一次 commit 時的檢查一起完成。)


2. Pre-commit 設定檔與使用流程
需要設定的只有 .pre-commit-config.yaml 這個 config 檔,將它置於專案下(也就是和 .git 同一層)即可,他的基礎格式如下:
  1. repos:  
  2. -   repo: https://github.com/pre-commit/pre-commit-hooks  
  3.     rev: v1.2.3  
  4.     hooks:  
  5.     -   ...  
一個實際使用的 .pre-commit-config.yaml 範例:
  1. repos:  
  2. -   repo: https://github.com/pre-commit/pre-commit-hooks  
  3.     rev: v2.2.3  
  4.     hooks:  
  5.     -   id: flake8  
  6.     -   id: detect-aws-credentials  
  7.     -   id: detect-private-key  
  8.     -   id: check-added-large-files  
  9.     -   id: check-merge-conflict  
  10.     -   id: check-json  
  11.     -   id: check-yaml  
  12. -   repo: https://github.com/ambv/black  
  13.     rev: stable  
  14.     hooks:  
  15.     - id: black  
  16.       language_version: python3.6  
  17. -   repo: https://github.com/Lucas-C/pre-commit-hooks-bandit  
  18.     rev: v1.0.4  
  19.     hooks:  
  20.     -   id: python-bandit-vulnerability-check  
  21.         args: [-l, --recursive, -x, tests]  
  22.         files: .py$  
  23. -   repo: https://github.com/asottile/reorder_python_imports  
  24.     rev: v1.6.1  
  25.     hooks:  
  26.     -   id: reorder-python-imports  
使用這個設定檔 commit 時的檢查訊息:


修改後再次 commit:


二、常用的 Git Hooks
Pre-commit 設置的本質上就是加上一個個 Git hooks,而市面上有很多 hooks 可以挑選,以目的來區分大抵上有幾種類別:

* 程式碼規範檢查
---- black:自動格式化 (formatter)
---- flake8:檢查程式碼不符合規範的地方 (checker, style & linting)。

* 安全檢查:
---- detect-aws-credentials
---- detect-private-key

* 格式檢查:
---- check-json
---- check-yaml

* 其他檢查:
---- check-added-large-files
---- check-merge-conflict

而每一個 hook 也可以針對各個 hook 需要的設定檔再做設定,例如 flake8 的客製化:
.flake8
  1. [flake8]  
  2. ignore = E203, E266, E501, W503, F403, F401  
  3. max-line-length = 79  
  4. max-complexity = 18  
  5. select = B,C,E,F,W,T4,B9  
  6. exclude =  
  7.     .git,  
  8.     __pycache__,  
  9.     build  
另一個常見的用法是用 hook 啟動 unit test,不過要當 test case 質量和數量到達一定程度時比較建議使用,不然測試常常壞掉,然後不得已常常下 --no-verify 參數繞過檢查,反而得不償失。

三、Pre-commit 的注意事項

1. Pre-commit 是一個用於自律的輕量本地端開發工具。
Pre-commit 不是強制性的,不是用來強硬擋下不符規範的 commit;其主要目的是更早的發現問題,有助於維持開發流程的健康狀態。
方法論設計理念上,pre-commit hooks 的作用域僅限 local,其他人不應該有權限限制你 local 的 git 指令,如強硬限制你必須使用的 hooks。急於 commit 可以使用 git commit --no-verify 繞過檢查,雖然這種作法有點不健康。

如果要強硬擋下的話應該使用 server 端的 pre-receive hook。Server 端的檢查雖然有強制性,但也有速度較慢、可能無法重現等缺點。

2. 在開發團隊中維護 hooks,在大量 repositories 中設定 pre-commit 的方法?
Git 2.9 之後有 "global" hooks 的功能,但還是不大適合用於所有 repositories 的設定。 由於存放 Git hooks 的 .git/hooks 目錄不會隨著專案複製,比較適合的做法還是另外開一個 repository 分享存放設定檔,讓團隊中的成員可以自行拷貝或連結進行設定,也比較方便追蹤 hooks 的更動。

Supplement
Getting Started with Python Pre-commit Hooks
Define rules to reject commits that don’t meet your requirements



沒有留言:

張貼留言

[Git 常見問題] error: The following untracked working tree files would be overwritten by merge

  Source From  Here 方案1: // x -----删除忽略文件已经对 git 来说不识别的文件 // d -----删除未被添加到 git 的路径中的文件 // f -----强制运行 #   git clean -d -fx 方案2: 今天在服务器上  gi...