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

Blog

リポジトリ内のpng画像のファイルに対し、圧縮してファイルサイズを減らすことができるかチェックする、GitHub Actions(action-png-size-lint)を作りました。

The GitHub Action is that check file size if png images can be reduced. - chick-p/action-png-size-lint
GitHub

このアクションでは、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-lint@v0
        with:
          image-paths: |
            fixtures/**/*.png
          limit: 90

変更した画像だけをチェックする(2022年8月27日追記)

ユースケースとして変更したファイルだけチェックすることが想定されます。
image-pathsに指定したパスのpng画像がチェック対象になるため、ワークフロー側でファイルだけに絞り込んでimage-pathsに渡すと、変更したファイルだけをチェックできます。

lint.yml
on:
  pull_request:
    paths:
      - "*.png"

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
        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-lint@v0
        with:
          image-paths: ${{ env.CHANGED_FILES }}
          limit: 90

今後実装したい機能

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

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