Githubに画像を上げて自動的にwebpに変換するファイルホスティングサーバーを作る
お詫び
Qiitaの元記事にて、区切り線を「---」で書いている場所があり、これがZennの記法に干渉して一部うまく表示できない記事がある事を認識しています。
全ての記事を精査しきれていないため、お手数ですがお見かけの際は教えていただけると大変喜びます。
画像ファイルのアップロード先
ソースコード
使い方
リポジトリに画像ファイルを上げる
以上!
ymlでやっていること
- webpパッケージをインストール
- (今回はUbuntu:latestを使っているので
sudo apt install webp
。Macならbrew install webp
)
- (今回はUbuntu:latestを使っているので
- リポジトリ内のファイルを全てチェックして、見つけたファイルをwebpに変換する
- この時、webpに変換できなかったファイルは無視する(cwebpコマンドの挙動)
- (詳細は後述)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で条件処理
ほぼこちらを参考にしました。
デバッグの方法を書いてもらっていたのがとても助かりました。
- 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
を実施すると、元ファイルも履歴から削除できて多少軽量化できます。
Discussion