発生していた問題

当ブログでは各記事に更新日(.Lastmod)を表示している。この更新日はenableGitInfoを有効にし、Gitのコミット履歴から取得する設定にしていた。

enableGitInfo = true

[frontmatter]
  lastmod = [":git", "lastmod", "fileModTime", "date", "publishDate"]

ところが本番環境では、記事ごとに異なるはずの更新日が、すべて同じ日時(デプロイを実行した日時)になってしまう問題が発生していた。ローカルでhugo serverを実行した場合は正しい更新日が表示されるため、CI環境固有の問題であった。

原因

原因は、GitHub Actionsのpublish.ymlで使用していたactions/checkoutの設定にあった。

steps:
  - uses: actions/checkout@v2

actions/checkoutはデフォルトでfetch-depth: 1であり、直近1コミット分の履歴のみを取得するシャロークローンとなる。

enableGitInfogit logのようにGitのコミット履歴を辿り、各ファイルの最終更新コミットの日時を取得する仕組みである。履歴が1コミット分しか存在しないシャロークローンの環境では、すべてのファイルの最終更新コミットがcheckout時点のコミットと判定されてしまう。結果として、全記事の更新日がデプロイ実行時にpushされていた最新コミットの日時と同じ値になっていた。

page.GitInfo | Hugo でも、CI/CD環境ではシャロークローンによりenableGitInfoが誤ったGit情報を返す旨が説明されている。

解決方法

actions/checkout のオプションにfetch-depth: 0を指定し、全コミット履歴を取得するように変更する。

steps:
  - uses: actions/checkout@v2
    with:
      fetch-depth: 0

fetch-depth: 0を指定すると全履歴を取得したフルクローンになるため、enableGitInfoが各ファイルの最終更新コミットを正しく辿れるようになり、記事ごとに正しい更新日が表示されるようになった。

まとめ

enableGitInfo.GitInfoなど、Gitのコミット履歴を参照するHugoの機能をCI上でビルドする場合は、actions/checkoutのようなチェックアウトアクションがシャロークローンになっていないかを確認する必要がある。