png 画像のファイルサイズを節約できるかをチェックする GitHub Actions を作った
リポジトリ内の png 画像のファイルに対し、圧縮してファイルサイズを減らすことができるかチェックする、GitHub Actions(action-png-size-lint)を作りました。
このアクションでは、zopflipng を使って png ファイルの圧縮後のサイズを算出し、ファイルサイズを減らせるようであればエラーで CI を落とします。
モチベーション
GitHub.com では、ひとつのリポジトリのサイズを 5GB 未満にすることを推奨しています。
リポジトリのサイズが大きくなると、リポジトリのクローンなどの Git の操作に時間がかかります。
たとえばブログのようなデータを管理する場合、リポジトリのサイズが大きくなる要因のひとつとして、たくさんの画像ファイルを管理することが考えられます。
できればコミットするときに圧縮済みの画像ファイルをコミットしたいところですが、つい圧縮作業をするのを忘れてしまいます。
そのため、Pull Request を作成した段階でファイルサイズを減らすことができるかを確認できるようにしたいと考えました。
関連する GitHub Actions
今回のアクションと同じように、画像ファイルを圧縮できる GitHub Actions には、calibreapp/image-actions があります。
calibreapp/image-actions は、その名のとおりオープンソースの電子書籍ビューアーである calibre を使っています。
今回のアクションと calibreapp/image-actions との大きな違いは、次の 2 つです。
- image-actions では png 形式以外の画像ファイルにも対応している
- エラーで CI を落とすのではなく、圧縮した画像ファイルをコミットする
今回作ったアクションでは、圧縮後のファイルをコミットせずにエラーで落とすようにしました。
なぜなら、コミットを作ってしまうとリポジトリサイズの削減には貢献しないからです。
圧縮したファイルを含むコミットを作ると、リポジトリには圧縮前と後の 2 つのコミットが存在することになります。
Squash してコミットをまとめれば良いのですが、CI にそこまでさせるには強力すぎではと考えました。
Actions の使い方
ディレクトリの画像パスを [object Object] に指定する
GitHub Actions のステップに次のアクションを指定します。
入力には次の 2 つの変数を設定します。
image-paths
:チェック対象の画像ファイルのパスlimit
:CI を落とす、ファイルのサイズ削減が可能な割合のしきい値
たとえば「90」を指定すると、元のファイルサイズの 90% よりもサイズを小さくできそうであればエラーになります。
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: chick-p/action-png-size-[email protected]
with:
image-paths: |
fixtures/**/*.png
limit: 90
変更した画像だけをチェックする(2022年8月27日追記)
ユースケースとして変更したファイルだけチェックすることが想定されます。image-paths
に指定したパスの png 画像がチェック対象になるため、ワークフロー側でファイルだけに絞り込んで image-paths
に渡すと、変更したファイルだけをチェックできます。
on:
pull_request:
paths:
- "*.png"
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/[email protected]
with:
fetch-depth: 100
- name: "Diff files"
run: |
{
echo 'CHANGED_FILES<<EOF'
git diff ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }} --diff-filter=AM --name-only
echo 'EOF'
} >> "$GITHUB_ENV"
- uses: chick-p/action-png-size-[email protected]
with:
image-paths: ${{ env.CHANGED_FILES }}
limit: 90
今後実装したい機能
除外対象を指定できるようにする
GitHub Actions の on.pull_request.paths-ignore
のように除外対象を指定できるようにしたいです。