【Hugo + Netlify + GitHub Actions】静的サイトジェネレータで予約投稿する

 

Hugo 本ブログで使用している静的サイトジェネレータ
公式サイト
は WordPress などの動的なサイト生成ツールとは異なり、予約投稿機能がありません。

しかし、NetlifyGitHub Actions を使って予約投稿を実現できたので、その方法をご紹介します。

ほとんどはこちらのサイトと同じことをやっているのですが、

マークダウンファイル側や git まわりの準備も含めてお話したいと思います。

関連記事

静的サイトジェネレータとは?WordPress との違いは?

静的サイトジェネレータとは?WordPress との違いは?


GitHub Actions とは

GitHub Actions は、ソフトウェアのビルドやデプロイを自動化する CI(継続的インテグレーション)、CD(継続的デリバリ)のようなサービスです。

GitHub ユーザならプライベートリポジトリでも Free プランから利用でき、

実行時間が毎月2000分(Windows なら1000分、macOS なら200分)までなら無料で利用できます。

ちなみに私の場合は ワークフロー 実行条件と実行内容を表したもの の実行時間がだいたい0.5分なので、

macOS で一日12回実行しても大丈夫そうです。


Netlify でビルド用 URL を取得する

Netlify にアクセスして、Settings > Build & deploy > Build hooks > Add build hookとします。

Build hook 追加

Build hook nameのところには任意の名前をつけます。

ここではschedulerとします。

Branch to buildmasterのままで大丈夫です。

Saveを押すと、ビルドを引き起こす URL が得られます。

Build hook コマンド

展開すると下にコマンドが出てくるので、こちらをコピーします。


定期実行の内容を表す yml ファイルを作成する

ローカルの ルートディレクトリ 一番最初の階層のディレクトリ(フォルダ)

/.github/workflows/schedule.ymlを作成します(フォルダ名は変更不可、ファイル名は任意)。

これがワークフローを定義するファイルとなります。

/.github/workflows/schedule.yml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# 任意の名前
name: scheduler
 
# ワークフローを起動する条件
on:
  # スケジュールに基づいて起動する
  schedule:
    - cron: '0 3 2-31/2 * *'
 
# 実行するジョブ
jobs:
  # ジョブ名
  build:
    # ジョブを実行する環境を指定する
    runs-on: ubuntu-latest
 
    steps:
    - name: post build hooks
      # コマンドを実行する
      run: curl -X POST -d {} ${{ secrets.BUILD_HOOKS_URL }}

on.scheduleは、cron 構文というものを使用して指定した時間になると自動でjobsを行ってくれます。

ただし時間は UTC(協定世界時)なので、日本の時間から9時間引き算する必要があります。

cron の指定は(分[0-59]) (時[0-23]) (日[1-31]) (月[1-12]) (曜日[0-7])というふうに行い、

/2をつけるとステップ値を指定できます。

0 3 2-31/2 * *は、月や曜日に関係なく、偶数日の日本時間で正午に実行するという意味になります。

run:の行にはさきほどのコマンドをペーストしたのち、URL 部分を${{ secrets.xxx }}と書き換えます。

xxxの部分は任意の名前。ここではBUILD_HOOKS_URL。)

これは GitHub の Secrets から呼び出すことができます。

一度 push しておきましょう。

git add .
git commit -m "github actions: add workflow, scheduler"
git push origin master

GitHub の Secrets を設定する

GitHub のリポジトリにアクセスし、Settings > Secrets > Add a new secretから値を登録します。

GitHub Secrets

Nameにはさきほどの変数名(xxx)を入れ、Valueに Build hook の URL を入れます。

Add secretで登録すると、これで指定した時間に Netlify がビルドしてくれるようになります。

関連記事

【Hugo + Netlify】デプロイ時に CSS, JS が適用されない場合の対処法

【Hugo + Netlify】デプロイ時に CSS, JS が適用されない場合の対処法


予約投稿したい記事のマークダウンのフロントマターの日付を設定する

Netlify はデプロイをしてくれます。

デプロイは GitHub のリポジトリをもとに行われます。

つまり、あらかじめ公開したい記事を完成させた(draftfalseにした)状態で push しておく必要があります。

そのまま push すると公開されてしまうので、

フロントマター マークダウンファイルの先頭の、その記事に関する情報を書く部分 dateの日付を投稿したい日時に合わせます。

こうするとその日時になるまではいくら push しようがデプロイしようが、その日時がまだ存在しないので、

記事が存在しないものとして扱われて表示されません。

例えばある記事を翌日の20時に予約投稿したいなら、フロントマターのdateの部分をその日時に合わせてから push すれば、

翌日の20時以降にデプロイされたときにはじめて記事が出現するというわけです。

このデプロイの時刻を GitHub Actions で同じ日時に指定してやれば、

翌日の20時05分ぐらいにはうまくいけばちゃんと記事が公開されるはずです。

(たまにデプロイが失敗することもあるようですが…)


記事以外の場合

記事でない場合でも、時間によって操作を変えることができます。

Hugo にはnowという、地域の時間を返す関数が用意されています。

これを利用して、例えば時間帯によって条件分岐して表示させるものを変えることができます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
{{- /* 朝(06:00-11:59)のとき */ -}}
{{- if in (seq 6 11) (int (now.Format "15")) -}}
    おはよう!
{{- /* 昼(12:00-17:59)のとき */ -}}
{{- else if in (seq 12 17) (int (now.Format "15")) -}}
    こんにちは!
{{- /* 夜(18:00-05:59)のとき */ -}}
{{- else -}}
    こんばんは!
{{- end -}}

ワークフローのon.scheduleはこんな感じになります。

1
2
// 6:00, 12:00, 18:00 に実行
cron: '0 6-18/6 * * *'

これで夜だけ背景色やデザインを変える、なんてこともできちゃいますよ。

なお、記事の場合で今回のやり方がうまくいかない(未来の日付の投稿が表示されてしまう)場合でも、

.Site.RegularPagesをいじればおそらく実装は可能です。

関係各所の調整がちょっと面倒かもしれないですが。

たぶんこんな感じになるかと思います。
次のコードを必ず通る場所に置きます。
1
2
3
4
5
{{ range .Site.RegularPages }}
    {{ if .PublishDate.Before now }}
        {{ .Scratch.Add "existing_pages" (slice .) }}
    {{ end }}
{{ end }}

これ以外のすべての.Site.RegularPages

.Scratch.Get "existing_pages"に書き換えます。

関連記事

【Hugo】ブログの記事ページのサイドバーに固定目次を追加

【Hugo】ブログの記事ページのサイドバーに固定目次を追加


予約投稿機能がないのは静的サイトジェネレータの弱点のひとつですが、

比較的簡単に、ほとんどの場合無料で実現できてしまいます。

この記事が参考になったら幸いです。

では👋