こんにちは, またくです。

hugo でブログを書く時に, 手動でビルドするのが 😩 だったので, 自動でやってもらうことにしました。

ローカルの開発環境にて hugo を使ってブログを書く際に, hugo server -D とかでサーバーを立ち上げておけば, 記事の markdown ファイルを書いていくことで, 手元のブラウザで記事のプレビューを見ることができます。

そのため, 生成される完成形を手元でも確認できており, GitHub Pages で公開するためにビルドされた html ファイルを GitHub 上で再度確認するというステップをあまり踏んでないと思ったのがきっかけです。(1つの記事を 1 Pull request で管理)

単純にビルドを勝手にしてくれるならば, 書く内容に集中できる割合を増やすことができるというのもあります。

Circle CI

ひとまず, どこかの CI サービスを使うにあたり, 雑に hugo deploy 自動 とかで調べると, Circle CI を使ったものが色々出てきました。Circle CI にてデフォルトで使えるイメージには Go と Git が元々入っている状態だったので, Circle CI で良さそう!と思い, 使ってみることにしました。

記事が下書き状態でないかのチェック

記事の markdown の front matter 部分に draft = true がなければ良いので, それがないかを単純にチェックするスクリプトを test のステップに入れました。

#!/bin/bash
# check-draft.sh
if [ -n "$(git grep -l 'draft = true' content/)" ]; then
  exit 1
fi

これを設定している時に, 記事の下書きのステータスを true から false に変える hugo undraft というコマンドがあることに気付いてしまったのですが, そこまでこだわらなくて良いかなと思いました。

エラー無くビルドできるかの確認

test のステップにて, hugo コマンドを実行して, そのコマンドの返り値でテストということにしました。

記事を自動ビルドしてそれを GitHub Pages にデプロイ

master ブランチで CI サービスが動いている時に, GitHub Pages にデプロイするように, deployment の設定を記述して, 以下のスクリプトを実行させるようにしました。

#!/bin/bash -eux

# Set GIT_USER_NAME and GIT_USER_EMAIL in Circle CI project
if [ -z "${GIT_USER_NAME}" ]; then
  echo "Please set GIT_USER_NAME"
  exit 1
fi

if [ -z "${GIT_USER_EMAIL}" ]; then
  echo "Please set GIT_USER_EMAIL"
  exit 1
fi

git config --global user.name "${GIT_USER_NAME}"
git config --global user.email "${GIT_USER_EMAIL}"

cp -rf public/* docs/
if [ -n "$(git diff --name-only docs/)" ]; then
  git add docs/
  git commit -m ':rocket: Deployed from Circle CI [ci skip]'
  git push origin master
fi

hugo コマンドは test のステップにて実行しているので, 再度実行する必要はありませんでした。また, 僕は master ブランチのみで運用しているので, 単純に master ブランチに push するだけでした。

circle.yml

Circle CI の設定ファイルである circle.yml は以下のようになりました。

# circle.yml 

dependencies:
  # Install hugo before running Circle CI's build-test-deploy process
  pre:
    - go get github.com/spf13/hugo

machine:
  timezone: Asia/Tokyo

test:
  override:
    - ./scripts/check-draft.sh
    - hugo

deployment:
  production:
    branch: master
    commands:
      - ./scripts/push-to-github.sh


デプロイしたい対象は docs/ 以下なので, そこに変更があればリモートに push するようにしていますが, 記事の markdown やテーマファイルを全く変更していなくても, ビルドした際に hugo のバージョンのメタ情報の違いで html ファイルに差分が出てしまうこともあります。

とはいえ, 対して気にならないなと感じたので, シンプルに git diff --name-only docs/ の結果で変更があったらリモートに push するようにしました。

おわりに

これでブログを書く頻度が爆上げされるかどうかは別問題であってほしいです。