Lint only diff files
過去我們會在提交的時候運行代碼風格檢查,但隨著檔案越來越多,檢查的時間也越來越長。但其實每次提交改動的檔案數量不多,所以可以根據改動的檔案做檢查即可。目前透過 Github action 嘗試進行設定,建立 Pull Request 的時候執行。
PHP
首先根目錄有 phpcs.xml
的 PHP CodeSniffer 設定檔,並且只在 php 檔案有變更或者設定檔變更的情況下觸發。先透過 curl 下載 PHP CodeSniffer,然後利用 git diff
跟目標分支比對出此次修改的檔案名稱跟路徑,並且利用 --diff-filter=dr
過濾掉刪除的檔案跟只是更名的檔案,最後透過 egrep
過濾出 php 結尾的檔案。
git diff --name-only --diff-filter=dr \
${{ github.event.pull_request.base.sha }} |egrep '\.php$'
github.event.pull_request.base.sha
這個變數是目標分支的 SHA 值,通常是 master 分支的 SHA。但因為使用官方的 actions/checkout
checkout 分支,預設只會包含目前 Pull Request 這支分支,所以要加上 fetch-depth: 0
這個參數,才能夠取得其他分支,這樣一來才能取得 master 的 SHA。
綜合上述的說明,設計下方的 workflow:
name: Run lint
on:
pull_request:
# 只在底下檔案有變動的情況觸發
paths:
- "**.php"
- "phpcs.xml"
- ".github/workflows/php-lint.yaml"
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- run: |
curl -OL https://squizlabs.github.io/PHP_CodeSniffer/phpcs.phar
- run: |
php phpcs.phar --standard=./phpcs.xml $(git diff --diff-filter=dr --name-only ${{ github.event.pull_request.base.sha }} |egrep '\.php$')
網路上透過 github action phpcs
可以找到許多現成的 github action,功能更完善,包括整合機器人帳號可以自動提示等等。目前的訴求還很簡單,先簡單進行。
JavaScript
有 PHP 的例子之後,JS、TS 的部分就簡單多了。 .eslintrc.js
設定檔放置在根目錄,利用 npx 的方式執行 eslint,只檢查 ts, js 檔案的變更。 package.json
要先包含 eslint
的安裝。
name: Run lint
on:
pull_request:
paths:
- "**.ts"
- "**.js"
- ".eslintrc.js"
- ".github/workflows/js-lint.yaml"
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- run: |
npm install
npx eslint -c .eslintrc.js $(git diff --diff-filter=dr --name-only ${{ github.event.pull_request.base.sha }} |egrep '\.[tj]s$')
CSS
CSS 的部分使用 stylelint
依法泡製,只檢查 css 檔案的變更。package.json
要先包含 stylelint
的安裝。
name: Run lint
on:
pull_request:
paths:
- "**.css"
- ".stylelintrc.json"
- ".github/workflows/css-lint.yaml"
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- run: |
npm install
npx stylelint -c .stylelintrc.json $(git diff --diff-filter=dr --name-only ${{ github.event.pull_request.base.sha }} |egrep '\.css$')
無差異情況的修正
由於 egrep
在沒有檔案差異的情況下,會回傳非零的代碼,這會導致執行中斷。所以需要在後面加上 || true
,並且判斷只有在檔案內容有的時候才進行檢查。
git diff --name-only ${{ github.event.pull_request.base.sha }} |egrep '\.php$' > .list.txt || true
# 有檔案內容才進行檢查
[ -s ./.list.txt ] && phpcs --standard=./phpcs.xml --file-list=./.list.txt
話說
話說上面的這三個工具其實都支援 cache 的使用,所以本地端檢查即是檢查全部,只要啟用快取速度上都挺快的。主要是 CI/CD 的環境沒有特別去維護快取內容所以預設都是重新檢查。因此這樣的改動才發揮它的價值。