📝

Githubに画像を上げて自動的にwebpに変換するファイルホスティングサーバーを作る

2023/08/29に公開

https://qiita.com/items/06a4acf9459e28add367


お詫び

Qiitaの元記事にて、区切り線を「---」で書いている場所があり、これがZennの記法に干渉して一部うまく表示できない記事がある事を認識しています。
全ての記事を精査しきれていないため、お手数ですがお見かけの際は教えていただけると大変喜びます。


画像ファイルのアップロード先

https://github.com/shimajima-eiji/__Backup_Images

ソースコード

https://github.com/shimajima-eiji/__Backup_Images/blob/main/.github/workflows/convert_webp.yml

使い方

リポジトリに画像ファイルを上げる
以上!

ymlでやっていること

  1. webpパッケージをインストール
    1. (今回はUbuntu:latestを使っているのでsudo apt install webp。Macならbrew install webp)
  2. リポジトリ内のファイルを全てチェックして、見つけたファイルをwebpに変換する
    1. この時、webpに変換できなかったファイルは無視する(cwebpコマンドの挙動)
  3. (詳細は後述)webp変換したらpush、変換していないなら何もしない

ソースコードは実際に運用しているスクリプトなので、チェックロジックをバシバシ入れていますが、やっている事は上記の通りです。
エッセンスを抽出するとcwebp "(from)" -o "(to)"の部分。

2022/01/11 追記。もっと簡単で直感的な方法

ymlはコマンドの集まりではなく、一つのshellファイルとみなして考えたほうがよさそうです。
Github Actionsの仕様を考えていましたが、保守性や教育コストを考えるとこちらの方がシンプルでした。

(中略)
# 説明のため、echoにしたが実際は処理がいっぱい
- name: sample
  run: echo 0  >file2webp.log

# webp変換した場合(結果が0以外)のみ処理する
- name: Commit files
  run: |
    if [ $(tail -n 1 file2webp.log) -ne 0 ]
    then
      rm file2webp.log  # 先にログファイルを消さないと、ログファイルもpushしてしまう
      git config --global user.email "${{ secrets.EMAIL }}"
      git config --global user.name "${{ secrets.USER ​}}"
      ​git add -A
      ​git commit -m "[Update]converted webp by Github Actions"
      ​git pull
      ​git push
      ​echo "[COMPLETE] convert to webp."
    ​else
      ​echo "[SKIP] No convert."
    ​fi

これなら、GithubActionsを知らなくてもif文で処理できます。
GithubActionsで変数を持たせると制御が分かりにくいので、今回のようにファイルに書き出して捨てた方が直感的でした。

(非推奨)webp変換判定をGithubActionに渡す

まず、これがとんでもなく難しかったです。
まずshellの実行結果を受け取る必要がありますが、

  • shellファイルは戻り値を持たない(実行結果は受け取れる)  → 0で正常終了、0以外で異常終了。ただし255件を超えると予期せぬ挙動が起こる可能性がある
  • 出力を実行結果にする方法がある → 他の出力が欲しいので使えない

という、強烈な問題があります。

次に、shellの結果を受け取れたとしても、Github Actionsで条件判定する方法とはまた別の話なので、これらを解決する方法が必要になりました。

shellの結果を受け取る

急遽、shellスクリプト側に件数を出力する処理を追加しました。
GithubActionsのログに表示をさせたいのと、255件を超える数値を条件処理に使いたいのでどちらも満たせるのがteeコマンドです。
シンプルに0であればfalse、0以外であればtrueにして渡す方法もありましたが、shell側に責任を持たせるのは違うので、せめて意味のあるものとしてwebp変換した数を出力させるぐらいはやらせる事にしました。
shell側ができる精一杯の譲歩です。

Github Actionsで条件処理

https://qiita.com/ljourm/items/556f5ccc8425891865de

ほぼこちらを参考にしました。
デバッグの方法を書いてもらっていたのがとても助かりました。

- name: output step context
  run: echo $CONTEXT
  env:
    CONTEXT: ${{ toJSON(steps.check_something) }}

この時の条件処理で欲しいのは「webp変換をしたファイルがあるのかどうか」だけなので、teeで作ったファイルをtail -n 1で取得すれば件数だけ取れるので、あとはtrue(success)=0 / false(failure)=0以外で取得すれば良いです。
従って、

steps:
# (中略)
  # webpに変換したファイル数を取得(残念ながら仕様のため変換0でtrue / 変換したら1以上になりfalse)
  # 0/1〜を出力しているのはcurlしたスクリプトの最終出力で件数を表示している
  - name: result check
    id: result
    run: tail -n 1 file2webp.log
    continue-on-error: true
# (中略)
# webp変換した場合のみ処理する
  - name: Commit files
    if: steps.check_something.outcome == 'failure'
    run: ...

上記の方法で取得できます。
後は生成したファイルのrawを取ったり、ダウンロードをすれば良いです。[1]

リポジトリの軽量化について

ここまでにリポジトリに画像を上げたらwebpに変換してくれる上、ファイルホスティングもしてくれるWebサーバーが手軽に作れます。
もし元ファイルが不要なら、

git pull
git filter-branch --tree-filter "rm -fr ${元ファイルのpath}" HEAD
git reflog expire --expire=now --all
git gc --aggressive --prune=now
git push -f

を実施すると、元ファイルも履歴から削除できて多少軽量化できます。

注釈

脚注
  1. 【作成したwebpファイルをダウンロードする】WEBP変換ツールとかがあるので、こちらを使った方が楽です。 ↩︎

GitHubで編集を提案

Discussion