png 画像のファイルサイズを節約できるかをチェックする GitHub Actions を作った

Last Updated on August 27, 2022
Blog
August 24, 2022

リポジトリ内の 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 の使い方

GitHub Actions のステップに次のアクションを指定します。
入力には次の 2 つの変数を設定します。

  • image-paths:チェック対象の画像ファイルのパス
  • limit:CI を落とす、ファイルのサイズ削減が可能な割合のしきい値
    たとえば「90」を指定すると、元のファイルサイズの 90% よりもサイズを小さくできそうであればエラーになります。
      - uses: chick-p/action-png-size-lint@v0
        with:
          image-paths: |
            fixtures/**/*.png
          limit: 90

今後実装したい機能

変更した画像だけをチェックする

最初のバージョンでは、image-paths に指定したパスの png 画像がすべて対象です。
ただ、ユースケースとしては、変更したファイルだけチェックすることが想定されるため、コミット差分を見て変更したファイルだけをチェックするようにしたいです。

2022年8月27日追記

ワークフロー側で変更のあったファイルだけに絞り込んで image-paths に渡せば、変更したファイルだけをチェックできます。

lint.yml
    steps:
      - uses: actions/checkout@v3
        with:
          fetch-depth: 100
      - run: |
          echo 'CHANGED_FILES<<EOF' >> $GITHUB_ENV
          git diff ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }} --diff-filter=AM --name-only >> $GITHUB_ENV
          echo 'EOF' >> $GITHUB_ENV
      - uses: chick-p/action-png-size-lint@v0
        with:
          image-paths: ${{ env.CHANGED_FILES }}
          limit: 90

除外対象を指定できるようにする

GitHub Actions の on.pull_request.paths-ignore のように除外対象を指定できるようにしたいです。